오디오 전사

오디오 전사

Gemini API는 Gemini 3.5 Transcribe 모델(gemini-3.5-transcribe)을 사용해 오디오 파일의 음성을 텍스트로 변환해요. Gemini의 오디오 이해 능력을 기반으로 자동 언어 식별, 화자 분리(diarization), 단어 수준 타임스탬프, 커스텀 어휘 힌트와 함께 정확한 전사를 제공해요. 또한 비유창성 제거와 스마트 서식을 갖춘 스마트 전사 모드도 제공해요.

오디오 파일을 전사하려면 오디오를 업로드하고 gemini-3.5-transcribe에 전달하세요.

from google import genai

client = genai.Client()

audio_file = client.files.upload(file="path/to/sample.mp3")

response = client.models.generate_content(
    model="gemini-3.5-transcribe",
    contents=[audio_file],
)

print(response.text)
import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI({});

const audioFile = await ai.files.upload({
  file: "path/to/sample.mp3",
  mimeType: "audio/mp3",
});

const response = await ai.models.generateContent({
  model: "gemini-3.5-transcribe",
  contents: [audioFile],
});

console.log(response.text);
# First upload the file via the Files API, then pass its URI:
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-transcribe:generateContent" \
  -H "x-goog-api-key: *** \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {
        "parts": [
          {
            "fileData": {
              "fileUri": "YOUR_FILE_URI",
              "mimeType": "audio/mp3"
            }
          }
        ]
      }
    ]
  }'

출처: 원문

본문

개요

Gemini 3.5 Transcribe는 음성-텍스트 작업에 최적화되어 있어요. 다양한 억양, 배경 소음, 다중 언어 대화를 처리해요.

주요 기능은 다음과 같아요.

  • 자동 음성 인식(ASR): 85개 이상의 로케일에서 언어를 자동 감지해요. 수동 구성 없이 문장 내 및 문장 간 코드 스위칭을 처리해요.
  • 커스텀 어휘: 최대 1,000개의 구문을 전달해 도메인 특정 용어, 약어, 고유명사 쪽으로 인식을 편향시켜요.
  • 화자 분리: 여러 화자를 구별하고 음성 세그먼트를 개별 라벨에 할당해요.
  • 단어 수준 타임스탬프: 인식된 각 단어에 대한 정확한 시작/종료 시간 오프셋을 생성해요.
  • 스마트 전사: 비유창성, 필러 단어, 반복을 정리하고 구조화된 서식을 적용해요.
  • 서식 및 정규화: 대문자화, 구두점, 역텍스트 정규화를 적용해요(예: "twenty six million dollars"를 "$26M"으로 변환).

일반 오디오 추론이나 오디오 콘텐츠에 대한 질의응답은 오디오 이해를 사용하세요. 텍스트-음성 오디오 합성은 텍스트 음성 변환을 사용하세요.

언어 감지 및 힌트

기본적으로 모델은 사용된 언어를 자동 감지해요. 화자가 코드를 전환하면 언어 간에 동적으로 전환해요.

자동 감지를 사용하려면 language_codes를 생략하거나 빈 목록을 제공하세요.

from google import genai
from google.genai import types

client = genai.Client()

response = client.models.generate_content(
    model="gemini-3.5-transcribe",
    contents=[audio_file],
    config=types.GenerateContentConfig(
        audio_transcription_config=types.AudioTranscriptionConfig(
            language_codes=[],
        )
    ),
)
const response = await ai.models.generateContent({
  model: "gemini-3.5-transcribe",
  contents: [audioFile],
  config: {
    audioTranscriptionConfig: {
      languageCodes: [],
    },
  },
});
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-transcribe:generateContent" \
  -H "x-goog-api-key: *** \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {
        "parts": [
          {
            "fileData": {
              "fileUri": "YOUR_FILE_URI",
              "mimeType": "audio/mp3"
            }
          }
        ]
      }
    ],
    "generationConfig": {
      "audioTranscriptionConfig": {
        "languageCodes": []
      }
    }
  }'

언어를 미리 알고 있다면 전사 정확도를 높이기 위해 language_codes에 BCP-47 언어 코드를 지정하세요(지원 언어 참조).

config = types.GenerateContentConfig(
    audio_transcription_config=types.AudioTranscriptionConfig(
        language_codes=["es-ES"],
    )
)
const config = {
  audioTranscriptionConfig: {
    languageCodes: ["es-ES"],
  },
};
{
  "generationConfig": {
    "audioTranscriptionConfig": {
      "languageCodes": ["es-ES"]
    }
  }
}

커스텀 어휘

custom_vocabulary 배열에 최대 1,000개의 용어를 제공해 음성 모델을 흔하지 않은 단어, 기술 전문 용어, 브랜드 이름, 고유명사 쪽으로 유도할 수 있어요(일반적으로 최대 100개 용어에서 최상의 결과).

from google import genai
from google.genai import types

client = genai.Client()

response = client.models.generate_content(
    model="gemini-3.5-transcribe",
    contents=[audio_file],
    config=types.GenerateContentConfig(
        audio_transcription_config=types.AudioTranscriptionConfig(
            custom_vocabulary=["Gemini", "Kubernetes", "BigQuery"],
        )
    ),
)
const response = await ai.models.generateContent({
  model: "gemini-3.5-transcribe",
  contents: [audioFile],
  config: {
    audioTranscriptionConfig: {
      customVocabulary: ["Gemini", "Kubernetes", "BigQuery"],
    },
  },
});
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-transcribe:generateContent" \
  -H "x-goog-api-key: *** \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {
        "parts": [
          {
            "fileData": {
              "fileUri": "YOUR_FILE_URI",
              "mimeType": "audio/mp3"
            }
          }
        ]
      }
    ],
    "generationConfig": {
      "audioTranscriptionConfig": {
        "customVocabulary": ["Gemini", "Kubernetes", "BigQuery"]
      }
    }
  }'

화자 분리

화자 분리는 녹음의 서로 다른 목소리를 식별하고 각 세그먼트에 spk_1 또는 spk_2 같은 화자 식별자를 태그해요. 최대 8명의 화자를 지원해요(3명 이상 화자에 대한 귀속은 실험적).

diarization을 True로 설정해 분리를 활성화하세요.

from google import genai
from google.genai import types

client = genai.Client()

response = client.models.generate_content(
    model="gemini-3.5-transcribe",
    contents=[audio_file],
    config=types.GenerateContentConfig(
        audio_transcription_config=types.AudioTranscriptionConfig(
            diarization=True,
        )
    ),
)
const response = await ai.models.generateContent({
  model: "gemini-3.5-transcribe",
  contents: [audioFile],
  config: {
    audioTranscriptionConfig: {
      diarization: true,
    },
  },
});
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-transcribe:generateContent" \
  -H "x-goog-api-key: *** \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {
        "parts": [
          {
            "fileData": {
              "fileUri": "YOUR_FILE_URI",
              "mimeType": "audio/mp3"
            }
          }
        ]
      }
    ],
    "generationConfig": {
      "audioTranscriptionConfig": {
        "diarization": true
      }
    }
  }'

단어 수준 타임스탬프

단어 수준 타임스탬프는 오디오 스트림에서 인식된 모든 단어에 대한 정확한 시작 및 종료 오프셋을 제공해요.

word_timestamp를 True로 설정해 타임스탬프를 활성화하세요.

from google import genai
from google.genai import types

client = genai.Client()

response = client.models.generate_content(
    model="gemini-3.5-transcribe",
    contents=[audio_file],
    config=types.GenerateContentConfig(
        audio_transcription_config=types.AudioTranscriptionConfig(
            word_timestamp=True,
        )
    ),
)
const response = await ai.models.generateContent({
  model: "gemini-3.5-transcribe",
  contents: [audioFile],
  config: {
    audioTranscriptionConfig: {
      wordTimestamp: true,
    },
  },
});
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-transcribe:generateContent" \
  -H "x-goog-api-key: *** \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {
        "parts": [
          {
            "fileData": {
              "fileUri": "YOUR_FILE_URI",
              "mimeType": "audio/mp3"
            }
          }
        ]
      }
    ],
    "generationConfig": {
      "audioTranscriptionConfig": {
        "wordTimestamp": true
      }
    }
  }'

단일 요청에서 diarization과 word_timestamp를 결합해 화자 라벨과 단어 타임스탬프를 모두 받을 수 있어요.

config = types.GenerateContentConfig(
    audio_transcription_config=types.AudioTranscriptionConfig(
        diarization=True,
        word_timestamp=True,
    )
)
const config = {
  audioTranscriptionConfig: {
    diarization: true,
    wordTimestamp: true,
  },
};
{
  "generationConfig": {
    "audioTranscriptionConfig": {
      "diarization": true,
      "wordTimestamp": true
    }
  }
}

전사 모드

Gemini 3.5 Transcribe는 mode 매개변수를 통해 두 가지 전사 모드를 지원해요.

  • VERBATIM(기본값): 말한 모든 것을 단어 그대로 정확한 전사를 반환하며, 원시 필러 단어("um", "uh", "like", "you know"), 반복, 일시 정지, 잘못된 시작을 보존해요. 타임스탬프나 화자 분리를 사용할 때 필요해요.
  • SMART(스마트 전사): 지능적인 후처리를 적용해 읽기에 최적화된 전사를 만들어요. 비유창성 제거: 대화형 필러 단어, 더듬거림, 잘못된 시작을 제거해요. 인라인 자기 수정: 말로 한 수정을 직접 해결해요(예: "Let's meet on Tuesday, actually no, Wednesday at two" → "Let's meet on Wednesday at 2:00 PM"). 자동 구조화 서식: 구어적 생각을 단락, 번호 목록, 글머리 기호, 서식 있는 날짜, 통화, 숫자로 자동 구조화해요. 문법 정리: 자연스러운 구두점, 문장 대/소문자, 흐름을 적용해요.
구어 오디오 VERBATIM 출력 SMART(스마트 전사) 출력
"Um, so for the meeting, I think we should, uh, invite Alice and, wait no, Bob and Carol." "Um so for the meeting I think we should uh invite Alice and wait no Bob and Carol." "For the meeting, I think we should invite Bob and Carol."
"First item review budget second item finalize timeline third item send recap" "first item review budget second item finalize timeline third item send recap" "1. Review budget 2. Finalize timeline 3. Send recap"
from google import genai
from google.genai import types

client = genai.Client()

response = client.models.generate_content(
    model="gemini-3.5-transcribe",
    contents=[audio_file],
    config=types.GenerateContentConfig(
        audio_transcription_config=types.AudioTranscriptionConfig(
            mode="SMART",
        )
    ),
)
print(response.text)
const response = await ai.models.generateContent({
  model: "gemini-3.5-transcribe",
  contents: [audioFile],
  config: {
    audioTranscriptionConfig: {
      mode: "SMART",
    },
  },
});
console.log(response.text);
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-transcribe:generateContent" \
  -H "x-goog-api-key: *** \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {
        "parts": [
          {
            "fileData": {
              "fileUri": "YOUR_FILE_URI",
              "mimeType": "audio/mp3"
            }
          }
        ]
      }
    ],
    "generationConfig": {
      "audioTranscriptionConfig": {
        "mode": "SMART"
      }
    }
  }'

전사 출력 파싱

전체 전사 텍스트는 response.text로 반환돼요.

word_timestamp 또는 diarization이 활성화되면 API는 후보 파트에 첨부된 상세한 단어 수준 주석과 화자 라벨도 반환해요.

다음은 단어 타임스탬프와 화자 턴을 추출하고 반복 처리하는 방법이에요.

def extract_word_transcriptions(response):
    words = []
    for candidate in getattr(response, "candidates", []) or []:
        content = getattr(candidate, "content", None)
        for part in getattr(content, "parts", []) or []:
            transcription = getattr(part, "audio_transcription", None)
            if transcription:
                speaker = getattr(transcription, "speaker_label", "")
                for word_info in getattr(transcription, "words", []) or []:
                    word = getattr(word_info, "word", "")
                    start = getattr(word_info, "start_offset", "")
                    end = getattr(word_info, "end_offset", "")
                    words.append({
                        "word": word,
                        "speaker": speaker,
                        "start_offset": start,
                        "end_offset": end,
                    })
    return words

words = extract_word_transcriptions(response)

for w in words:
    speaker = f"[{w['speaker']}] " if w["speaker"] else ""
    timing = f"({w['start_offset']} -> {w['end_offset']}) " if w["start_offset"] and w["end_offset"] else ""
    print(f"{speaker}{timing}{w['word']}")
function extractWordTranscriptions(response) {
  const words = [];
  for (const candidate of response.candidates ?? []) {
    for (const part of candidate.content?.parts ?? []) {
      const transcription = part.audioTranscription;
      if (transcription) {
        const speaker = transcription.speakerLabel ?? "";
        for (const wordInfo of transcription.words ?? []) {
          words.push({
            word: wordInfo.word ?? "",
            speaker: speaker,
            startOffset: wordInfo.startOffset ?? "",
            endOffset: wordInfo.endOffset ?? "",
          });
        }
      }
    }
  }
  return words;
}

const words = extractWordTranscriptions(response);

for (const w of words) {
  const speaker = w.speaker ? `[${w.speaker}] ` : "";
  const timing = (w.startOffset && w.endOffset) ? `(${w.startOffset} -> ${w.endOffset}) ` : "";
  console.log(`${speaker}${timing}${w.word}`);
}
{
  "candidates": [
    {
      "content": {
        "parts": [
          {
            "audioTranscription": {
              "speakerLabel": "spk_1",
              "words": [
                {
                  "word": "Hello",
                  "startOffset": "0.100s",
                  "endOffset": "0.450s"
                },
                {
                  "word": "world",
                  "startOffset": "0.500s",
                  "endOffset": "0.850s"
                }
              ]
            }
          }
        ],
        "role": "model"
      },
      "finishReason": "STOP"
    }
  ]
}

지원 언어

Gemini 3.5 Transcribe는 다음 언어와 BCP-47 언어 코드를 지원해요.

언어 BCP-47 코드 언어 BCP-47 코드
아프리칸스어 af-ZA 일본어 ja-JP
암하라어 am-ET 자바어 jv-ID
아랍어(이집트) ar-EG 카부베르디아누 kea-CV
아르메니아어 hy-AM 칸나다어 kn-IN
아삼어 as-IN 카자흐어 kk-KZ
아제르바이잔어 az-AZ 한국어 ko-KR
벨라루스어 be-BY 키르기스어 ky-KG
벵골어(방글라데시) bn-BD 라트비아어 lv-LV
벵골어(인도) bn-IN 링갈라어 ln-CD
보스니아어 bs-BA 리투아니아어 lt-LT
불가리아어 bg-BG 마케도니아어 mk-MK
불가리아어(아로마니아어) rup-BG 말레이어 ms-MY
버마어 my-MM 말라얄람어 ml-IN
광둥어(번체) yue-Hant-HK 몰타어 mt-MT
카탈루냐어 ca-ES 중국어 북경어(간체) cmn-Hans-CN
세부아노어 ceb 마라티어 mr-IN
중부 크메르어 km-KH 몽골어 mn-MN
크로아티아어 hr-HR 네팔어 ne-NP
체코어 cs-CZ 노르웨이어 nb-NO
덴마크어 da-DK 오리야어 or-IN
네덜란드어 nl-NL 폴란드어 pl-PL
영어(영국) en-GB 포르투갈어(브라질) pt-BR
영어(인도) en-IN 포르투갈어(포르투갈) pt-PT
영어(미국) en-US 펀자브어 pa-IN
에스토니아어 et-EE 펀자브어(구르무키 문자) pa-Guru-IN
페르시아어 fa-IR 루마니아어 ro-RO
필리핀어 fil-PH 러시아어 ru-RU
핀란드어 fi-FI 세르비아어 sr-RS
프랑스어 fr-FR 신디어(아랍 문자) sd-Arab-IN
갈리시아어 gl-ES 슬로바키아어 sk-SK
조지아어 ka-GE 슬로베니아어 sl-SI
독일어 de-DE 스페인어(라틴 아메리카) es-419
그리스어 el-GR 스페인어(미국) es-US
구자라트어 gu-IN 스와힐리어(케냐) sw-KE
하우사어 ha-NG 스웨덴어 sv-SE
히브리어 he-IL 타지크어 tg-TJ
힌디어 hi-IN 텔루구어 te-IN
헝가리어 hu-HU 태국어 th-TH
아이슬란드어 is-IS 터키어 tr-TR
인도 영어 en-IN 우크라이나어 uk-UA
인도네시아어 id-ID 우즈베크어 uz-UZ
이탈리아어 it-IT 베트남어 vi-VN

지원 오디오 형식

Gemini 3.5 Transcribe는 다음 오디오 형식 MIME 유형을 지원해요.

  • WAV - audio/wav
  • MP3 - audio/mp3
  • AIFF - audio/aiff
  • AAC - audio/aac
  • OGG - audio/ogg
  • FLAC - audio/flac
  • MPEG - audio/mpeg
  • M4A - audio/m4a
  • L16 - audio/l16
  • Opus - audio/opus
  • ALAW - audio/alaw
  • MULAW - audio/mulaw
  • WebM - audio/webm

지원되는 MIME 유형과 매개변수 스키마의 전체 목록은 Interactions API 참조를 참조하세요.

매개변수 참조

GenerateContentConfig의 audio_transcription_config 객체 내 필드를 설정해 전사를 구성하세요.

필드 유형 설명
language_codes 문자열 배열 BCP-47 언어 코드(예: ["en-US"]). 생략하거나 비우면([]) 모델이 언어를 자동 감지하고 코드 스위칭을 처리해요.
custom_vocabulary 문자열 배열 음성 인식을 편향시킬 최대 1,000개의 커스텀 용어, 약어, 고유명사. 화자 분리 및 단어 수준 타임스탬프와 호환되지 않아요.
word_timestamp Boolean 단어 시작/종료 오프셋을 포함하려면 True로 설정. 생략하거나 False면 단어 타임스탬프가 반환되지 않아요. 커스텀 어휘와 호환되지 않아요.
diarization Boolean 서로 다른 화자를 식별하고 라벨링하려면 True로 설정. 커스텀 어휘와 호환되지 않아요.
mode String 전사 모드. 지원 값: "VERBATIM"(기본값) 및 "SMART". 타임스탬프 및 분리와 호환되지 않아요.

모범 사례

  • 깨끗한 오디오 제공: 오디오 녹음에 명확한 음성 분리가 있고 심한 클리핑을 피하세요.
  • 언어를 알 때 언어 힌트 제공: 오디오 언어를 미리 안다면 language_codes를 지정해 정확도를 극대화하세요.
  • 커스텀 어휘를 목표화: custom_vocabulary에는 흔한 일상 단어보다 고유한 도메인 용어, 브랜드 이름, 고유명사만 포함하세요.
  • 큰 녹음에는 Files API 사용: 몇 초보다 긴 파일은 client.files.upload로 업로드하고 반환된 파일을 모델 콘텐츠로 전달하세요.

제한 사항

  • 오디오 길이: 표준 단항 요청은 최대 1시간의 오디오 파일을 지원해요. 화자 분리나 단어 수준 타임스탬프 같은 기능을 활성화하면 오디오 처리가 30분으로 제한돼요.
  • 단어 수준 타임스탬프: 단어 수준 타임스탬프를 활성화하면 전반적인 전사 정확도가 저하될 수 있어요.
  • 화자 분리: 화자 분리는 최대 8명의 화자를 지원해요. 3명 이상의 화자에 대한 귀속은 실험적이에요.
  • 커스텀 어휘: custom_vocabulary에는 최대 1,000개의 용어를 제공할 수 있지만, 일반적으로 최대 100개 용어에서 최상의 결과를 얻어요. custom_vocabulary를 화자 분리 또는 단어 수준 타임스탬프와 결합할 수 없어요. API는 두 기능 중 하나와 함께 custom_vocabulary를 지정한 요청을 거부해요.
  • 모드 호환성: 스마트 전사(mode: "SMART")는 word_timestamp 또는 diarization과 결합할 수 없어요.

다음 단계

  • Live 전사 가이드로 Live API를 사용해 실시간 오디오를 스트리밍해 보세요.
  • 오디오 이해를 탐색해 오디오 콘텐츠를 분석, 요약, 질의해 보세요.
  • 텍스트 음성 변환으로 텍스트에서 오디오를 합성하는 방법을 알아보세요.
  • 모델 가격과 토큰 한도는 가격 페이지를 확인하세요.
  • 미디어 파일 업로드 및 관리에 대한 자세한 내용은 Files API 가이드를 확인하세요.

더 알아보기 (Learn more)