# Gemini 3.5 Transcribe API 가이드: 녹음 전사와 실시간 자막 구현

> 녹음 파일의 화자·단어 시각은 gemini-3.5-transcribe로, 말하는 동안 바뀌는 자막은 gemini-3.5-transcribe-live로 처리합니다. 자주 충돌하는 설정을 분리하고 확정 텍스트와 미완료 결과를 구별해 저장합니다.

- URL: https://blog.laozhang.ai/ko/posts/gemini-3-5-transcribe-api
- Published: 2026-08-27
- Updated: 2026-10-07
- Author: LaoZhang AI Team (https://blog.laozhang.ai/ko/about)
- Topic: API 가이드
- Tags: Gemini 3.5 Transcribe, Gemini API, 음성 텍스트 변환, Live API, 오디오 전사

---
Gemini 3.5 Transcribe로 녹음 파일을 텍스트로 바꾸려면 `gemini-3.5-transcribe`와 **Interactions API**를 사용합니다. 말하는 동안 자막을 표시하려면 `gemini-3.5-transcribe-live`와 **Live API**를 사용합니다. 화자 구분과 단어 단위 타임스탬프는 녹음 파일 경로에서만 지원합니다. 따라서 실시간 자막과 화자별 회의록이 모두 필요하다면 Live로 자막을 표시하고, 저장한 녹음을 파일 모델로 다시 처리하는 구성이 맞습니다. [모델별 지원 기능](https://ai.google.dev/gemini-api/docs/models/gemini-3.5-transcribe)

접속 경로를 고른 다음에는 출력 목적에 맞게 설정을 나눠야 합니다. 녹음 요청에서 `custom_vocabulary`는 화자 구분이나 단어 시각과 함께 사용할 수 없습니다. 전문 용어를 우선할지, 화자·시각이 붙은 기록을 우선할지 선택하고, Live에서는 임시 자막을 계속 덧붙이지 말고 현재 표시만 교체합니다.

## 녹음 파일과 실시간 자막의 모델 선택

두 모델은 음성을 텍스트로 바꾸는 전용 모델입니다. 음성으로 답하는 대화형 Live Agent, TTS, 실시간 음성 번역, 오디오에 관한 질문에 답하는 일반 Gemini 모델과는 용도가 다릅니다. 전사 뒤 요약이나 업무 도구 실행이 필요하면 별도 처리 단계를 연결합니다. 현재 전용 Transcribe 모델은 네이티브 함수 호출을 지원하지 않습니다. [현재 모델 문서](https://ai.google.dev/gemini-api/docs/models/gemini-3.5-transcribe)

| 필요한 결과 | 모델·API | 입력과 주요 제한 |
|---|---|---|
| 녹음이 끝난 뒤 전체 텍스트 | `gemini-3.5-transcribe` · Interactions API | 오디오 파일, 최대 1시간 |
| 화자별 기록 또는 단어 시각 | 같은 녹음 모델 | 해당 기능을 사용하면 최대 30분 |
| 발화 중 갱신되는 자막 | `gemini-3.5-transcribe-live` · Live API | 16kHz 단일 채널 raw PCM, 세션당 최대 10분 |
| 실시간 표시와 사후 화자별 기록 | Live 처리 후 녹음 모델로 재처리 | 두 요청의 출력과 비용을 각각 관리 |

이 표의 길이와 기능은 [Gemini Developer API 모델 문서](https://ai.google.dev/gemini-api/docs/models/gemini-3.5-transcribe)의 조건입니다. 두 경로 모두 언어 자동 감지와 언어 전환을 지원하며 한국어 코드 `ko-KR`도 지원 목록에 있습니다. 한국어 지원이 모든 지역·계정의 이용 가능성을 뜻하지는 않습니다.

![녹음 파일용 Interactions API와 실시간 자막용 Live API의 입력과 활용을 비교한 그림](https://blog.laozhang.ai/posts/ko/gemini-3-5-transcribe-api/img/api-comparison.webp)

모델 ID에는 문서에 적힌 문자열을 그대로 사용합니다. 검색에서 보이는 `gemini-3.5-transcribe-live-preview`를 Developer API의 별칭으로 추정하면 안 됩니다. Enterprise 문서의 모델 경로와 이 글의 Developer API 경로도 구별해야 합니다.

공개 상태의 표현에는 공식 자료 간 차이가 있습니다. 2026년 10월 6일 확인한 [변경 기록](https://ai.google.dev/gemini-api/docs/changelog#august-26-2026)은 8월 26일 두 모델의 GA를 기록하지만, [출시 발표](https://blog.google/innovation-and-ai/models-and-research/gemini-models/gemini-3-5-transcribe/)에는 public preview라는 표현이 남아 있습니다. 이 글은 현재 모델·요청 문서를 기준으로 구현을 설명하며, 그 표기만으로 특정 계정의 접속 성공이나 서비스 안정성을 보장하지 않습니다.

## 녹음 요청: 기본 전사부터 연결하고 설정을 하나씩 선택합니다

파일 경로는 **Files API 업로드 → 반환된 URI를 Interactions API에 전달 → 완료 상태와 결과 저장** 순서입니다. `generateContent`나 일반 음성 대화 API로 바꾸지 않습니다. 아래는 [공식 전사 가이드](https://ai.google.dev/gemini-api/docs/transcribe)의 요청 구조에 맞춘 Python 예시입니다. 사용자가 준비한 `google-genai` 환경과 서버 측 인증이 전제이며, SDK 호출·파일 업로드는 이 글을 작성하면서 실행하지 않았습니다.

```python
import json
from google import genai


def recorded_config(profile):
    if profile == "basic":
        return {"language_codes": ["ko-KR"]}
    if profile == "terms":
        return {
            "language_codes": ["ko-KR"],
            "custom_vocabulary": ["BigQuery", "라오장"],
        }
    if profile == "annotated":
        return {
            "language_codes": ["ko-KR"],
            "mode": {
                "type": "verbatim",
                "diarization_mode": "speaker",
                "timestamp_granularities": ["word"],
            },
        }
    if profile == "readable":
        return {"language_codes": ["ko-KR"], "mode": "smart"}
    raise ValueError("Unknown profile")


# Choose basic, terms, annotated, or readable before calling the API.
profile = "basic"
client = genai.Client()
audio_file = client.files.upload(file="sample.mp3")
interaction = client.interactions.create(
    model="gemini-3.5-transcribe",
    input=[{
        "type": "audio",
        "uri": audio_file.uri,
        "mime_type": audio_file.mime_type,
    }],
    generation_config={
        "transcription_config": recorded_config(profile),
    },
)
result = interaction.model_dump(mode="json")
with open("transcript.json", "w", encoding="utf-8") as target:
    json.dump(result, target, ensure_ascii=False, indent=2)
print("status:", result.get("status"))
print(interaction.output_text)
```

첫 요청에서는 `basic`을 선택하고 파일 MIME 유형, 반환 상태, 빈 출력 여부를 확인합니다. `status`가 `completed`인지 확인한 뒤 원음과 결과가 맞는지도 확인해야 합니다. 비어 있지 않은 텍스트만으로 올바른 전사를 판정할 수는 없습니다. 언어를 자동 감지하려면 `language_codes`를 생략하거나 빈 배열로 둡니다.

다른 설정은 결과의 용도에 따라 선택합니다.

| 설정 | 얻으려는 결과 | 함께 넣지 않는 기능 |
|---|---|---|
| `terms` | 이름·제품명 등 사용자 지정 어휘를 알려 준 전사 | 화자 구분, 단어 타임스탬프 |
| `annotated` | `verbatim` 텍스트와 화자·단어 시각 주석 | `custom_vocabulary`, `smart` |
| `readable` | 추임새와 자기 수정을 정리한 읽기 쉬운 텍스트 | 화자 구분, 단어 타임스탬프 |

이 예시는 필요한 설정을 선택할 수 있도록 분리한 것입니다. `custom_vocabulary`와 화자·시각 설정을 같은 요청에 넣는 방식은 현재 API에서 거부됩니다. 녹음 모델의 `smart`는 `"mode": "smart"`라는 문자열이며, `{"type": "smart"}`가 아닙니다. 구조를 지정하는 객체의 `type`은 위 예시처럼 `verbatim`입니다. [모드와 어휘 설정](https://ai.google.dev/gemini-api/docs/transcribe)

사용자 지정 어휘는 최대 1,000개 항목을 지원하지만, Google은 보통 100개 이하의 목록에서 좋은 결과를 얻는다고 안내합니다. 이는 서로 다른 두 조건입니다. 허용 개수를 채우기보다 중요한 이름과 용어부터 넣습니다. 화자는 최대 8명까지 표기할 수 있지만 **3명 이상은 실험적 지원**이며, 단어 시각을 요청하면 전사 정확도가 낮아질 수 있습니다. 이 기능이 필요한 녹음은 30분 제한도 함께 적용합니다. [기능별 제약](https://ai.google.dev/gemini-api/docs/models/gemini-3.5-transcribe)

## 화자와 단어 시각은 원본 JSON의 주석까지 저장합니다

`output_text`는 합쳐진 텍스트입니다. 자막 동기화, 발언 위치로 이동, 화자별 기록이 필요하면 그 값만 저장하지 말고 `steps[].content[].annotations[]`의 `word_info`도 보존합니다. 단어의 텍스트, 화자, 시작·종료 시각은 각각 `text`, `speaker`, `start_offset`, `end_offset`에 들어갑니다. 시각은 `"0.100s"` 같은 Duration 문자열입니다. [단어 주석 응답 구조](https://ai.google.dev/gemini-api/docs/transcribe)

아래 함수는 앞에서 저장한 JSON을 읽어 주석을 추출합니다. `0s`도 유효한 시작점으로 처리하고, 없는 화자나 시각을 추정해서 채우지 않습니다. 원본 `annotation`을 함께 남기므로 추출 결과를 원본과 대조할 수 있습니다.

```python
import json
import re
from decimal import Decimal


def offset_seconds(value):
    if value is None:
        return None
    if not isinstance(value, str) or not re.fullmatch(r"\d+(?:\.\d+)?s", value):
        raise ValueError(f"Invalid audio offset: {value!r}")
    return Decimal(value[:-1])


def collect_words(result):
    words = []
    for step in result.get("steps") or []:
        for content in step.get("content") or []:
            for annotation in content.get("annotations") or []:
                if annotation.get("type") != "word_info":
                    continue
                start = offset_seconds(annotation.get("start_offset"))
                end = offset_seconds(annotation.get("end_offset"))
                if start is not None and end is not None and end < start:
                    raise ValueError("End precedes start")
                words.append({
                    "text": annotation.get("text"),
                    "speaker": annotation.get("speaker"),
                    "start_seconds": None if start is None else str(start),
                    "end_seconds": None if end is None else str(end),
                    "annotation": dict(annotation),
                })
    return words


with open("transcript.json", encoding="utf-8") as source:
    result = json.load(source)
with open("words.json", "w", encoding="utf-8") as target:
    json.dump(collect_words(result), target, ensure_ascii=False, indent=2)
```

빈 배열은 “말이 없었다”는 판정이 아닙니다. 요청한 설정, 완료 상태, 주석 존재 여부를 함께 확인해야 합니다. 화자 라벨 역시 실명이나 확인된 신원을 뜻하지 않습니다. 여러 사람이 겹쳐 말한 구간은 원음을 들어 판정합니다.

위 시각은 제출한 오디오를 기준으로 해석합니다. 녹음을 여러 파일로 잘랐다면 각 파일의 원본 시작 위치를 별도로 보관해 전체 시각으로 환산합니다. 겹쳐 말한 단어를 무조건 하나의 시간 순서로 펴거나, 타임스탬프가 없는데 임의의 SRT 시간을 붙이면 원음과의 관계가 사라집니다. Live 결과에는 이 녹음 모델의 화자·단어 주석이 제공되지 않습니다.

## Live 구현: WAV에서 PCM을 읽고 자막과 종료 상태를 나눕니다

Live 전사는 `response_modalities=["TEXT"]`와 `input_audio_transcription`을 사용합니다. 입력은 **16비트 signed PCM, 16kHz, 단일 채널, little-endian** 바이트입니다. 100ms 분량은 1,600개 샘플, 즉 3,200바이트입니다. MP3나 WebM/Opus를 PCM이라고 표시하는 것만으로 변환되지는 않습니다. WAV도 헤더가 포함된 컨테이너이므로 파일 전체 바이트 대신 PCM 프레임을 읽어 보내야 합니다. [Live 전사 입력과 이벤트](https://ai.google.dev/gemini-api/docs/live-api/live-transcribe)

다음 예시는 마이크 없이 `sample-16k-mono.wav`를 읽는 서버 측 프로그램입니다. 준비한 WAV가 조건에 맞지 않으면 연결 전에 중단합니다. 임시 텍스트와 확정 텍스트를 별도로 유지하며, 오디오 EOF 뒤에는 5초까지만 수신을 기다립니다. 5초와 최대 9분이라는 값은 예시의 애플리케이션 정책이며 서버의 확정 지연 보장이 아닙니다. 실제 모델의 세션 제한은 10분입니다.

```python
import asyncio
import json
import wave
from google import genai
from google.genai import types


def check_wav(path):
    with wave.open(path, "rb") as source:
        if (source.getnchannels(), source.getsampwidth(),
                source.getframerate(), source.getcomptype()) != (1, 2, 16000, "NONE"):
            raise ValueError("Expected uncompressed 16-bit mono WAV at 16000 Hz")
        frames = source.getnframes()
        if not 0 < frames <= 16000 * 9 * 60:
            raise ValueError("This example accepts audio up to 9 minutes")


def pcm_chunks(path):
    with wave.open(path, "rb") as source:
        while True:
            chunk = source.readframes(1600)
            if not chunk:
                return
            if len(chunk) % 2:
                raise ValueError("Incomplete 16-bit PCM sample")
            yield chunk


class Captions:
    def __init__(self):
        self.final = []
        self.preview = ""

    def consume(self, content):
        if content is None:
            return
        final = getattr(content, "input_transcription", None)
        interim = getattr(content, "interim_input_transcription", None)
        if final is not None and final.text:
            # The sequence number belongs to this application.
            self.final.append({"sequence": len(self.final), "text": final.text})
            self.preview = ""
        if interim is not None and interim.text is not None:
            self.preview = interim.text


async def receive_segments(session, captions):
    while True:
        received = False
        async for message in session.receive():
            received = True
            captions.consume(message.server_content)
        # receive() may end at a turn boundary; wait for subsequent turns.
        if not received:
            return "receive-ended"


async def finish_receiver(receiver, timeout=5):
    try:
        return await asyncio.wait_for(asyncio.shield(receiver), timeout=timeout)
    except asyncio.TimeoutError:
        return "drain-timeout"
    finally:
        if not receiver.done():
            receiver.cancel()
        await asyncio.gather(receiver, return_exceptions=True)


async def transcribe_wav(path):
    check_wav(path)
    captions = Captions()
    status = "input-not-finished"
    error = None
    client = genai.Client()
    config = types.LiveConnectConfig(
        response_modalities=["TEXT"],
        input_audio_transcription=types.AudioTranscriptionConfig(
            language_codes=["ko-KR"],
        ),
    )
    try:
        async with client.aio.live.connect(
            model="gemini-3.5-transcribe-live", config=config,
        ) as session:
            receiver = asyncio.create_task(receive_segments(session, captions))
            try:
                for chunk in pcm_chunks(path):
                    if receiver.done():
                        receiver.result()
                        raise RuntimeError("Receiver ended before audio EOF")
                    await session.send_realtime_input(
                        audio=types.Blob(data=chunk, mime_type="audio/pcm;rate=16000"),
                    )
                    await asyncio.sleep(len(chunk) / 32000)
                await session.send_realtime_input(audio_stream_end=True)
                status = await finish_receiver(receiver)
            finally:
                if not receiver.done():
                    receiver.cancel()
                await asyncio.gather(receiver, return_exceptions=True)
    except Exception as exc:
        status = "error"
        error = f"{type(exc).__name__}: {exc}"
    return {
        "status": status, "error": error,
        "final_segments": captions.final, "uncommitted_preview": captions.preview,
    }


if __name__ == "__main__":
    result = asyncio.run(transcribe_wav("sample-16k-mono.wav"))
    with open("live-result.json", "w", encoding="utf-8") as target:
        json.dump(result, target, ensure_ascii=False, indent=2)
```

`interim_input_transcription`은 아직 바뀔 수 있는 자막이므로 `preview`를 교체합니다. `input_transcription`은 확정된 발화 조각이므로 `final_segments`에 추가합니다. 한 이벤트에 두 필드가 있으면 이 예시는 확정 조각을 먼저 저장하고 임시 필드를 다음 화면 상태로 보존합니다. `server_content`가 없는 이벤트도 처리합니다. 같은 문장이 두 번 확정돼도 그대로 남깁니다. 사람이 실제로 반복한 말까지 전역 텍스트 중복 제거로 지우면 안 됩니다.

`sequence`는 이 프로그램이 붙인 순번입니다. 서버가 제공한 발화 ID나 시간 정보가 아니며, 재연결을 넘나드는 중복 방지를 보장하지 않습니다. 확정 텍스트도 사람이 원음과 대조한 정답과는 다릅니다.

EOF에서 보내는 `audio_stream_end=True`는 오디오 입력의 끝을 알립니다. WebSocket이 즉시 닫히거나 모든 결과가 도착했다는 뜻은 아닙니다. `drain-timeout`이나 `error`일 때는 받은 확정 조각을 보관하되 전체 녹음이 완성된 기록으로 표시하지 않습니다. 남은 `uncommitted_preview`를 확정 기록에 합치지 말고 미완료 상태로 보여 줍니다. `receive-ended`도 이 예시의 수신 종료 관찰값이며, 서버가 전체 파일의 처리를 보증한 별도 상태는 아닙니다.

예시는 기본 자동 VAD를 사용합니다. 수동 활동 감지를 선택한다면 자동 감지를 끄고 `activity_start`·`activity_end`를 처리하는 별도 흐름으로 구현해야 합니다. Live의 모드 값은 `SMART`·`VERBATIM` 대문자 열거형이므로, 녹음 요청의 소문자 `"smart"`를 그대로 옮기지 않습니다. Live의 입력 설정은 [해당 경로의 문서](https://ai.google.dev/gemini-api/docs/live-api/live-transcribe)를 기준으로 맞춥니다.

![Live 자막을 표시하고 녹음 파일에서 화자와 단어 시각을 다시 얻는 처리 흐름](https://blog.laozhang.ai/posts/ko/gemini-3-5-transcribe-api/img/hybrid-pipeline.webp)

브라우저·모바일 직접 연결에는 장기 API 키를 포함하지 않습니다. 신뢰할 수 있는 서버에서 클라이언트를 인증한 뒤 제한된 단기 토큰을 발급하는 흐름을 사용합니다. 현재 [단기 토큰 문서](https://ai.google.dev/gemini-api/docs/live-api/ephemeral-tokens)는 Live API의 `v1beta`만 대상으로 하며, 기본값은 새 세션 시작 기한 1분, 연결에서 메시지를 보낼 수 있는 기한 30분, 사용 횟수 1회입니다. **토큰의 30분이 Transcribe 세션의 10분 제한을 늘리지는 않습니다.** 토큰도 추출될 수 있으므로 모델·설정 제약과 서버 측 접근 제어가 필요합니다.

긴 방송은 세션 전환을 미리 설계합니다. 연결이 끊긴 지점과 저장한 오디오 위치를 기록하고, 미완료 구간은 녹음 모델로 재처리할 수 있게 둡니다. 이 예시는 자동 재연결이나 무손실 복구를 구현하지 않으므로 그러한 보장을 제공하지 않습니다.

## 가격: 분당 숫자는 추정치이고 청구 기준은 토큰입니다

2026년 10월 6일 확인한 [Gemini Developer API 전용 가격표](https://ai.google.dev/gemini-api/docs/pricing#gemini-3.5-transcribe)의 유료 요율은 다음과 같습니다. 통화는 미국 달러(USD)입니다.

| 경로 | 오디오 입력 100만 토큰당 | 텍스트 출력 100만 토큰당 | 공식 분당 추정 합계 |
|---|---:|---:|---:|
| 녹음 Transcribe | 2달러 | 12달러 | 약 0.005달러 |
| Live Transcribe | 3.50달러 | 21달러 | 약 0.009달러 |

가격표의 가정은 오디오 초당 25토큰, 출력 분당 175토큰입니다. 일반 오디오 모델의 다른 토큰 환산율을 이 전용 모델에 적용하면 비용이 달라집니다. 이 가정으로 반올림 전 값을 계산하면 녹음은 분당 `1,500 × 2 / 1,000,000 + 175 × 12 / 1,000,000 = 0.0051`달러, Live는 `0.008925`달러입니다. 100시간, 즉 6,000분이면 각각 **30.60달러와 53.55달러**입니다. 공식 표의 반올림된 분당 수치로 계산한 약 30달러·54달러와 구별해야 합니다.

실제 사용량이 있으면 `입력 오디오 토큰 × 입력 요율 / 1,000,000 + 출력 텍스트 토큰 × 출력 요율 / 1,000,000`으로 계산합니다. 위 100시간 예시는 공식 가정을 대입한 예산 계산이며 실제 청구 내역이 아닙니다. 미디어 변환·저장·재처리·후속 요약·사람의 교정, 세금과 환율도 포함하지 않습니다. Live와 녹음 후처리를 함께 쓰면 두 처리의 비용을 각각 더해야 합니다.

무료 등급에는 입력·출력 무료가 표시돼 있지만, 계정별 한도나 지역 조건까지 없어지는 것은 아닙니다. 전용 모델에서 Batch 할인을 전제로 비용을 줄이는 계산도 하지 않습니다. [모델 지원 기능](https://ai.google.dev/gemini-api/docs/models/gemini-3.5-transcribe)과 현재 가격표에서 사용할 수 있는 경로를 확인합니다.

## 파일 보관과 데이터 이용 조건은 따로 확인합니다

Files API는 업로드한 파일을 자동으로 48시간 뒤 삭제하며 파일당 최대 2GB, 프로젝트당 최대 20GB 저장 한도가 있습니다. 업로드한 파일을 API에서 다시 다운로드할 수 없으므로 원음 보관을 원격 URI에 맡기지 않습니다. Files API가 무료라는 설명도 전사 모델 추론이 무료라는 뜻은 아닙니다. [Files API 수명과 한도](https://ai.google.dev/gemini-api/docs/files)

파일의 48시간 수명은 Interactions 결과나 서비스 로그의 보관 기한과 같지 않습니다. 파일을 삭제했다고 전사 결과와 모든 제공자 기록이 동시에 사라진다고 설명해서도 안 됩니다.

[Gemini API 이용약관](https://ai.google.dev/gemini-api/terms)은 일반적인 무료 서비스에 제출한 콘텐츠와 출력이 제품·모델 개선에 사용될 수 있고 사람이 검토할 수 있다고 설명하며, 민감하거나 기밀인 정보와 개인정보를 제출하지 말라고 안내합니다. 활성 Cloud Billing이 연결된 프로젝트의 유료 API 서비스에서는 프롬프트·응답을 제품 개선에 사용하지 않지만, 보안·오용 방지·법적 의무를 위한 제한된 처리는 남습니다. 이는 보관 기간이 0이거나 조직의 개인정보 요구를 자동으로 충족한다는 보장이 아닙니다.

EEA·스위스·영국에는 무료 할당량을 포함한 데이터 이용 예외와 해당 지역 사용자에게 API 클라이언트를 제공할 때의 유료 서비스 조건이 있습니다. 가격표의 단순한 Yes/No만으로 그 예외를 덮지 않습니다. 한국어를 쓴다는 이유만으로 사용자의 거주 지역이나 적법한 업로드 권한을 판단하지도 않습니다. 고객 통화·내부 회의라면 동의, 조직 정책, 실제 프로젝트의 서비스 조건을 확인한 뒤 처리합니다.

## 한국어 도입 검증에서 확인할 것

한국어 검증은 원음과 사람이 작성한 기준 전사를 대조하는 방식으로 진행합니다. 실제 서비스에서 나타나는 빠른 말, 한영 혼용, 숫자·금액·이름, 전화 음질, 원거리 마이크, 겹치는 발화를 포함하고 오류가 업무에 미치는 영향을 확인합니다. 화자·시각이 필요한 경우 일반 텍스트 정확도와 별도로 잘못된 화자 배정, 단어 시작·끝 위치를 확인합니다. Live에서는 첫 임시 자막과 확정 자막의 지연, 수정 빈도, 세션 종료 전후의 누락도 기록합니다.

이 글의 예시에서 실제로 실행한 검증은 네트워크 없는 로컬 검사입니다. 요청 설정 생성 함수의 조합, 합성 JSON의 `word_info` 추출, `0s` 처리와 잘못된 시각 거부, 합성 WAV의 PCM 프레임 길이, 임시·확정 자막 상태와 반복 발화 보존, EOF 뒤 시간 제한·예외 처리, 위 가격 계산을 확인했습니다. Google SDK를 불러오거나 클라이언트를 만들지 않았고, 실제 업로드·모델 호출·한국어 인식 품질·청구·운영 지연은 시험하지 않았습니다.

이 구분을 유지하면 도입 판단이 명확해집니다. 먼저 비민감 오디오로 자신의 계정에서 연결과 응답 구조를 확인하고, 필요한 설정으로 원음 대조를 진행합니다. 실시간 화자·단어 시각, 10분을 넘는 단일 Live 세션, Transcribe 자체의 함수 호출이 필수라면 현재 전용 API의 기능 범위와 맞지 않습니다.

## 자주 묻는 질문

### 사용자 지정 어휘와 화자 구분을 한 번에 켤 수 있나요?

현재 녹음 API에서는 함께 사용할 수 없습니다. `custom_vocabulary`는 화자 구분이나 단어 타임스탬프와 호환되지 않습니다. 용어를 알려 주는 요청과 `verbatim` 화자·시각 요청을 목적에 따라 선택합니다. [전사 설정 제약](https://ai.google.dev/gemini-api/docs/transcribe)

### MP3를 Live API에 그대로 보내도 되나요?

안 됩니다. 녹음 파일 경로에서는 MP3 같은 지원 형식을 사용할 수 있지만 Live는 16비트·16kHz·단일 채널 raw PCM을 요구합니다. 압축을 풀고 필요한 채널·샘플레이트로 변환해야 하며 MIME 이름만 바꿔서는 해결되지 않습니다. [녹음 형식](https://ai.google.dev/gemini-api/docs/transcribe), [Live 입력 형식](https://ai.google.dev/gemini-api/docs/live-api/live-transcribe)

### 임시 자막이 사라지면 전사 내용도 잃은 건가요?

임시 자막은 계속 수정되는 표시 상태입니다. 확정 이벤트가 오면 별도 기록에 추가합니다. 종료나 오류 뒤 임시 텍스트가 남았는데 확정 이벤트가 없다면 그 부분은 미완료로 표시합니다. 같은 확정 문장이 반복됐다는 이유만으로 지우지 않습니다.

### 파일을 48시간 뒤 삭제하니 기밀 회의도 무료로 올려도 되나요?

파일 자동 삭제만으로 그렇게 판단할 수 없습니다. 일반 무료 서비스의 데이터 이용과 사람의 검토 조건, 지역 예외, 유료 프로젝트 조건은 별도로 적용됩니다. 기밀·개인정보는 동의와 조직 정책, 이용약관에 맞는 처리 경로를 먼저 확인합니다. [Files API](https://ai.google.dev/gemini-api/docs/files), [데이터 이용약관](https://ai.google.dev/gemini-api/terms)

## 참고 자료

이 글이 링크한 외부 페이지를 본문에 나온 순서대로 정리했습니다. 마지막 업데이트: 2026-10-07.

- [모델별 지원 기능](https://ai.google.dev/gemini-api/docs/models/gemini-3.5-transcribe) (ai.google.dev)
- [변경 기록](https://ai.google.dev/gemini-api/docs/changelog) (ai.google.dev)
- [출시 발표](https://blog.google/innovation-and-ai/models-and-research/gemini-models/gemini-3-5-transcribe/) (blog.google)
- [공식 전사 가이드](https://ai.google.dev/gemini-api/docs/transcribe) (ai.google.dev)
- [Live 전사 입력과 이벤트](https://ai.google.dev/gemini-api/docs/live-api/live-transcribe) (ai.google.dev)
- [단기 토큰 문서](https://ai.google.dev/gemini-api/docs/live-api/ephemeral-tokens) (ai.google.dev)
- [Gemini Developer API 전용 가격표](https://ai.google.dev/gemini-api/docs/pricing) (ai.google.dev)
- [Files API 수명과 한도](https://ai.google.dev/gemini-api/docs/files) (ai.google.dev)
- [Gemini API 이용약관](https://ai.google.dev/gemini-api/terms) (ai.google.dev)
