리턴제로 API로 음성인식 결과를 보정하고 인사이트 만들기

RTZR STT API로 음성 파일을 텍스트로 전사한 뒤, 전사 결과를 보정하고 인사이트를 만드는 Python 예제입니다.

리턴제로 API로 음성인식 결과를 보정하고 인사이트 만들기

by Hazel

음성 파일을 텍스트로 바꾸면 회의나 상담 내용을 다시 듣는 시간을 줄일 수 있습니다. 하지만 실제 녹음에는 청소기 소리, 도로 소음, 주변 사람의 목소리처럼 음성인식을 방해하는 소리가 자주 섞입니다. 이런 환경에서는 짧은 단어가 빠지거나 비슷한 발음의 다른 단어로 바뀌기도 합니다.

전사가 끝난 뒤에도 할 일은 남습니다. 긴 전사문에서 대화의 목적과 중요한 조건, 다음 행동을 찾으려면 내용을 처음부터 다시 읽어야 합니다. 전사 오류를 한 번 더 확인하고 대화의 제목과 핵심 내용까지 함께 얻을 수 있다면, 녹음 파일을 검토하는 흐름도 훨씬 단순해집니다.

이번 튜토리얼에서는 리턴제로(RTZR) STT OpenAPI로 기본 전사, 전사 결과 보정, 인사이트 생성을 실행하는 Python CLI를 만들어보겠습니다. 이어서 소음이 섞인 한국어 음성과 구조화된 대화 데이터를 이용해 다음 내용을 확인합니다.

  • 전사 결과 보정은 기본 STT에서 잘못 인식한 표현을 어떻게 바꾸는가?
  • 같은 음원에서 RTZR 보정 결과는 다른 한국어 지원 STT 모델의 결과와 어떻게 다른가?
  • 인사이트는 전사 결과를 기반으로 지정한 관점의 정보를 제대로 추출하는가?

1. 목표

만들어볼 것

이번 예제에서 사용하는 기능은 세 가지입니다.

기능 하는 일 확인할 결과
기본 STT 음성을 발화 단위의 텍스트로 변환 기본 전사문
전사 결과 보정 오디오를 다시 확인해 전사 오류를 교정 보정 전사문
인사이트 지정한 관점에 따라 전사 내용에서 정보를 추출 제목, 분류, 내용

전사 결과 보정은 오디오를 근거로 텍스트 오류를 교정하는 기능입니다. 수정할 내용이 없는 발화는 기본 결과와 같을 수 있고, 잘못 인식된 표현은 보정 결과에서 달라질 수 있습니다.

인사이트는 전사 결과를 기반으로 지정한 관점의 정보를 추출하는 기능입니다. 결과에는 제목과 내용, 일상, 문의, 업무, 스팸 중 하나의 분류가 포함됩니다. 프롬프트를 추가하면 상담의 요청 사항이나 회의의 결정 사항처럼 필요한 내용에 초점을 맞출 수도 있습니다.

💡 Enterprise 기능

전사 결과 보정과 인사이트는 Enterprise 기능입니다. 계정에 해당 기능이 활성화되어 있는지 확인하고, 사용할 수 없다면 Enterprise 도입을 문의해 주세요.

코드의 전체 흐름은 다음과 같습니다.

음성 파일
  ↓
RTZR STT API에 전사 요청
  ↓
RTZR STT API가 결과 반환
  ├─ 기본 전사 결과
  ├─ 인사이트 요청 시 제목·분류·내용 포함
  └─ 보정 요청 시 보정 결과 별도 조회 가능
  ↓
CLI가 결과 가공·저장

결과 미리보기

CLI를 실행하면 기본적으로 다음과 같은 결과 디렉터리가 만들어집니다.

outputs/<음원명>-<UTC 실행시각>/
├── transcript.txt  # 화자별 최종 전사문
├── response.json   # 기본 전사 API 응답
├── insight.txt     # 인사이트 기능 사용 시 생성
└── refined.json    # 보정 기능 사용 시 생성

RTZR API는 전사와 인사이트 결과를 JSON으로 반환합니다. 예제 CLI는 그중 발화별 화자 ID와 전사 텍스트를 모아 transcript.txt를 만들고, 인사이트의 제목·분류·내용을 insight.txt로 만듭니다. response.jsonrefined.json은 후속 분석에 사용할 수 있도록 원본 JSON 응답을 그대로 남긴 파일입니다.

2. 프로젝트 준비

프로젝트 구조

예제 프로젝트의 주요 파일은 다음과 같습니다.

c1-test/
├── src/rtzr_transcribe/
│   ├── cli.py          # 실행 옵션과 결과 저장
│   ├── client.py       # 인증, 전사 요청, polling
│   ├── config.py       # API 요청 설정과 환경 변수
│   ├── formatters.py   # JSON 응답을 TXT로 변환
│   └── io.py           # 입력 검사와 파일 저장
├── tests/
├── .env.example
├── pyproject.toml
└── uv.lock

예제는 Python 3.10 이상에서 실행되며, 패키지와 가상 환경 관리는 uv를 사용합니다. 저장소를 내려받은 뒤 다음 명령으로 의존성을 설치합니다.

uv sync --locked
cp -n .env.example .env

.env에는 RTZR 개발자 사이트에서 발급받은 Client ID와 Client Secret을 입력합니다.

RTZR_CLIENT_ID=발급받은_CLIENT_ID
RTZR_CLIENT_SECRET=발급받은_CLIENT_SECRET
RTZR_BASE_URL=https://openapi.vito.ai

이 예제는 RTZR 파일 STT API가 지원하는 mp4, m4a, mp3, amr, flac, wav 형식의 파일을 받습니다.

3. RTZR STT API 호출하기

API 요청 흐름

먼저 인증 API로 access token을 발급받고 음성 파일을 업로드하면, API는 transcribe_id를 반환합니다. 클라이언트는 이 ID로 처리 상태를 주기적으로 조회하고, 상태가 completed가 되면 최종 JSON 응답을 받습니다.

RTZR_CLIENT_ID / RTZR_CLIENT_SECRET
  ↓
access token 발급
  ↓
음성 파일 전사 요청
  ↓
transcribe_id 수신
  ↓
5초 간격으로 완료 여부 조회
  ↓
기본·보정 결과 JSON 저장

기본 전사 결과는 GET /v1/transcribe/{TRANSCRIBE_ID}로 조회합니다. 인사이트를 요청했다면 같은 응답의 results.insight에 결과가 포함됩니다. 보정 결과는 기본 전사와 별도로 GET /v1/transcribe/{TRANSCRIBE_ID}?result=refined에서 조회합니다.

기본 STT 실행하기

음성 파일 경로만 전달하면 기본 STT를 실행합니다.

이하 일반 실행 예제에서는 음성 파일명을 sample.wav로 통일합니다. 실행할 때는 sample.wav를 실제로 사용할 파일명이나 경로로 바꿔 주세요.

uv run --locked rtzr-transcribe sample.wav

이 예제의 기본 전사 설정

음성 파일만 전달하면 아래 설정으로 전사를 요청합니다. 모델과 언어, 도메인은 예제 코드에서 고정하고, 필요한 부가 기능만 실행 옵션으로 켤 수 있게 구성했습니다.

항목 기본 설정 필요할 때
음성인식 모델 sommers 예제 코드에서 고정
언어 한국어 (ko) 예제 코드에서 고정
도메인 일반 (GENERAL) 예제 코드에서 고정
화자 분리 사용, 화자 수 자동 예측 인원을 알면 --speaker-count 2처럼 지정
전사 결과 보정 사용하지 않음 --refinement로 활성화
인사이트 사용하지 않음 --insight로 활성화

💡 별도로 지정하지 않아도 적용되는 처리

이 예제는 다음 항목을 요청에 직접 넣지 않고 RTZR 파일 STT API의 기본값을 사용합니다.

따라서 , 같은 머뭇거림이나 불필요한 반복 표현은 전사 결과에서 제거될 수 있습니다.

전사 결과 보정 사용하기

--refinement를 추가하면 기본 전사에 이어 보정 결과가 준비될 때까지 기다립니다.

uv run --locked rtzr-transcribe sample.wav --refinement

기본 응답은 response.json, 보정 응답은 refined.json에 저장됩니다. 사용자가 바로 읽는 transcript.txt에는 보정된 전사문을 저장합니다.

인사이트 사용하기

--insight를 추가하면 기본 전사 응답에 제목과 분류, 내용이 함께 반환됩니다. 다음 예제에서는 중요한 요청과 후속 조치가 드러나도록 관점을 지정했습니다.

uv run --locked rtzr-transcribe sample.wav \
  --insight \
  --insight-prompt "대화의 핵심 내용과 중요한 요청, 후속 조치를 정리해 주세요."

CLI는 response.jsonresults.insight를 읽어 insight.txt도 함께 만듭니다. 프롬프트를 생략하면 프로젝트에 정의된 기본 지시문을 사용하고, 빈 문자열을 명시하면 인사이트 기능은 사용하되 별도의 지시문은 API에 보내지 않습니다.

보정과 인사이트가 모두 필요하다면 두 옵션을 함께 사용할 수 있습니다.

uv run --locked rtzr-transcribe sample.wav --refinement --insight

4. 소음 환경에서 전사 결과 보정하기

데이터

보정 실험에는 AI Hub의 소음 환경 음성인식 데이터를 사용합니다. 이 데이터는 주변 소음이 혼합된 음성과 전사 라벨을 함께 제공합니다.

이번 비교에는 01_01_000606_210809_SN.wav 한 건을 사용했습니다. 파일 전체를 입력한 뒤, 전사 결과에서 차이가 나타난 표현을 발췌했습니다.

RTZR 보정 전후 살펴보기

음원 앞부분에서는 도로에서 고라니를 본 경험을 이야기합니다. 아래는 같은 구간의 연속된 네 발화를 그대로 발췌한 것으로, 주요 변경 부분을 굵게 표시했습니다.

기본 전사

도로 위를 진짜 무겁자처럼 막 뛰어다녀요. 아니, 근데 걔네는 법을 모르니까 무법자일 수밖에 없죠.

근데 새끼 고라이가 진짜 귀엽게 생기긴 했어요, 되게 귀엽더라고요.

걔네가 막 깡총깡총 뛰어다니는데 집으로 데려가고 싶기도 했어요.

근데 걔네가 밤에는 정말 차에 진짜 졸진을 한다고 그러더라고요. 걔네가 진짜 위험하다고 그런 소리를 많이 들었어요.

보정 결과

도로 위를 진짜 무법자처럼 막 뛰어다녀요. 아니, 근데 걔네는 법을 모르니까 무법자일 수밖에 없죠.

근데 새끼 고라니가 진짜 귀엽게 생기긴 했어요. 되게 귀엽더라고요.

걔네가 막 깡총깡총 뛰어다니는데 집으로 데려가고 싶기도 했어요.

근데 걔네가 밤에는 정말 차에 진짜 돌진을 한다고 그러더라고요. 걔네가 진짜 위험하다고 그런 소리를 많이 들었어요.

보정 결과에서는 잘못 인식된 단어가 올바르게 수정되었습니다.

  • 무겁자처럼무법자처럼
  • 고라이가고라니가
  • 졸진을돌진을

다른 공개 모델의 결과와 비교하기

각 모델의 추론 코드와 실행 설정은 모델 추론 예제를 참고하세요.

비교에는 OpenAI의 Whisper large-v3-turbo, Alibaba Qwen 팀의 Qwen3-ASR-1.7B, NVIDIA의 Nemotron 3.5 ASR 0.6B, Microsoft의 VibeVoice-ASR를 사용했습니다. 같은 음원의 전사 결과를 RTZR 기본·보정 결과와 함께 살펴봤습니다.

앞서 살펴본 표현 중 일부와 다른 개선 사례를 함께 골라, 같은 음원의 핵심 표현을 표로 모았습니다. 단어 단위로 대응하기 어려운 경우에는 해당 대목의 표현을 조금 길게 발췌했습니다.

정답 표현 Whisper large-v3-turbo Qwen3-ASR-1.7B Nemotron 3.5 ASR 0.6B VibeVoice-ASR RTZR 기본 STT RTZR 보정 STT
무법자처럼 무겁자처럼 무섭더라고 무엇자처럼 엄마 언니를 진짜 못 잡혀 무겁자처럼 무법자처럼
다 큰 고라니 다크는 고라니 다 큰 보라니고요 다크는 고란이고 닭도 고라니가 다크롱 고라니 다 큰 고라니
이목이 집중이 될 것 같은데 이목이 집중이 될 것 같은데 무기 집중해 그러더라고요 대목이 집중이 될 것 같은데 의무기 집중이 될 것 같은데 이 집중이 될 것 같은데 이목이 집중이 될 것 같은데
손을 파닥 거린 거고요 손을 파닥버린 거고요 소를 파닥거리고요 손을 끄닥거리거고요 손을 파닥거린 거고요 손을 파닥버린 거고요 손을 파닥거린 거고요
킥라니 킹남 킹라니 킹나니 킹란이라는 킹라니 킥라니
킥보드 타는 사람들이 슈퍼드 타는 사람들이 킴보드 타는 사람들이 축구듯하는 사람들이 킥보드 타는 사람들이 킥보드 찾는 사람들이 킥보드 타는 사람들이

RTZR 기본 전사의 이 집중이는 보정 후 이목이 집중이로 바뀌었습니다. 같은 대목을 Whisper는 정확히 인식했지만, Qwen·Nemotron·VibeVoice는 각각 무기, 대목이, 의무기로 다르게 인식했습니다. 반면 VibeVoice도 손을 파닥거린 거고요, 킥보드 타는 사람들이는 올바르게 인식했습니다. 표에 제시한 사례에서 RTZR 보정 결과는 정답 표현의 의미와 일치했습니다.

이 결과는 특정 음원에서 확인한 사례이며 모델의 전체 성능을 의미하지 않습니다.

5. 대화에서 인사이트 추출하기

데이터

인사이트 실험에는 한국어 합성 대화로 구성된 Wi-Fi의 Korean Full-Duplex Synthetic Dataset Preview를 사용합니다.

각 대화에는 발화 원문과 화자, 시작·종료 시각 외에도 대화의 주제(topic)와 사용자 목적(user_goal)이 포함되어 있습니다. 이를 기준으로 인사이트가 대화의 핵심을 담았는지 확인합니다.

이번에는 prod_0031838 데이터를 사용합니다. 이 대화의 메타데이터는 다음과 같습니다.

{
  "topic": "국제배송 통관 문의",
  "user_goal": "관세나 부가세를 어디서 결제하는지도 확인하고 싶다"
}

인사이트 실행하기

살펴볼 음원은 고객과 상담원이 대화하는 2인 음성이므로 화자 수를 2명으로 지정했습니다. 별도의 인사이트 프롬프트는 입력하지 않고 CLI에 정의된 기본 지시문을 사용합니다.

uv run --locked rtzr-transcribe sample.wav \
  --speaker-count 2 \
  --insight

생성된 transcript.txt에서 핵심 부분만 옮기면 다음과 같습니다.

화자 1: 국제 배송 통관 처리 방법과 관세, 부가세, 결제 위치를 알려주세요.
화자 2: 통관 절차는 배송사와 세관에서 진행되며, 관세와 부가세는 결제 시 자동 계산됩니다.
화자 1: 결제는 어디서 하나요? 카드로 가능한가요?
화자 2: 결제는 배송 완료 후 안내되는 링크에서 카드로 가능합니다.
화자 1: 통관 지연 시 추가 비용이 발생하나요?
화자 2: 지연 시 보관료가 부과될 수 있으나, 관세나 부가세는 변동 없습니다.

[중략]

화자 1: 부가세 포함 가격이 맞나요?
화자 2: 네, 상품 가격에 부가세가 포함되어 있습니다.
화자 1: 결제 후 환불은 어떻게 되나요?
화자 2: 환불은 카드사 정책에 따라 처리되며 관세는 환급되지 않습니다.
화자 1: 감사합니다. 대략적인 범위만 알고 싶어요.
화자 2: 관세와 부가세는 상품 가격의 10 에서 20% 내외로 예상됩니다.

생성된 insight.txt의 내용은 다음과 같습니다.

제목: 국제 배송 통관 절차 및 관세·부가세 안내 문의
분류: 문의
내용: 고객이 국제 배송의 통관 처리 방법, 관세·부가세, 결제 방식 등에 대해 문의하였으며, 주요 내용은 다음과 같다. 통관 절차는 배송사와 세관이 진행하며, 관세와 부가세는 결제 시 자동 계산된다. 결제는 배송 완료 후 안내되는 링크를 통해 카드로 가능하다. 관세 납부 기한은 통관 완료 후 일반적으로 3일 이내이며, 관세·부가세는 상품 가격의 10~20% 내외로 예상된다. 통관 지연 시 보관료가 부과될 수 있으나 관세·부가세는 변동 없다. 배송 추적은 배송사 앱 또는 웹사이트에서 실시간 조회 가능하다. 환불 시 관세는 환급되지 않으며, 부가세는 상품 가격에 포함되어 있다.

대화에서는 국제 배송의 통관 절차와 관세·부가세 결제 방법을 묻고, 지연 시 추가 비용, 배송 추적, 납부 기한, 환불과 예상 비용 범위를 차례로 확인합니다. 인사이트 결과는 여러 발화에 흩어진 조건을 한 문단에 모았고, 제목과 문의 분류도 데이터셋의 주제와 사용자 목적에 맞습니다.

6. 마무리

이번 튜토리얼에서는 하나의 Python CLI로 음성을 전사하고, 보정과 인사이트 기능을 적용한 뒤 결과를 JSON과 TXT로 저장해보았습니다.

전사 결과 보정은 기본 전사의 발화 시간·화자 구조를 유지하면서 잘못 인식된 표현을 바로잡는 데 활용할 수 있습니다. 인사이트는 대화를 제목·분류·내용으로 정리해 주요 내용과 후속 조치를 파악하는 데 도움을 줍니다. 두 기능을 함께 사용하면 음성을 텍스트로 옮기는 것에서 나아가, 전사문을 검수하고 내용을 정리하는 작업까지 이어갈 수 있습니다.

전체 예제 코드는 아래에서 확인할 수 있습니다.

python-tutorial/stt-refinement-insight at main · rtzr/python-tutorial
Contribute to rtzr/python-tutorial development by creating an account on GitHub.

데이터 출처


Great! You’ve successfully signed up.

Welcome back! You've successfully signed in.

You've successfully subscribed to 기업을 위한 음성 AI - 리턴제로 blog.

Success! Check your email for magic link to sign-in.

Success! Your billing info has been updated.

Your billing was not updated.