# Gemini 3.8 Flash TTS API: 모델 선택·호출·비용

> 3.1 preview 후속은 Flash-Lite TTS, 연기·2인 대화는 Flash TTS입니다. 오디오 1분 $0.009~$0.0135(2026년 Standard), 2027년부터 2배입니다.

- URL: https://blog.laozhang.ai/ko/posts/gemini-3-8-flash-tts-api
- Published: 2026-09-30
- Updated: 2026-09-30
- Author: LaoZhang AI Team (https://blog.laozhang.ai/ko/about)
- Category: API 가이드
- Tags: Gemini 3.8 Flash TTS, Gemini API, 텍스트 음성 변환, 음성 생성, 음성 복제

---
Gemini API의 텍스트 음성 변환(TTS) 모델은 2026년 9월 22일자 API 변경 로그 기준으로 `gemini-3.8-flash-tts`와 `gemini-3.8-flash-lite-tts` 두 가지가 정식(GA) 상태입니다. 두 모델은 요청 형식과 프롬프트 규칙이 완전히 같아서 `model` 문자열만 바꾸면 서로 오갈 수 있습니다. 기본 선택은 단순합니다. `gemini-3.1-flash-tts-preview`나 2.5 TTS를 쓰던 코드는 Google이 공식 대체 모델로 지정한 Flash-Lite TTS로 옮기고, 캐릭터 연기·2인 대화의 맞장구·수십 분짜리 낭독처럼 표현력이 우선이면 Flash TTS를 씁니다. 사용자의 말에 실시간으로 대답하는 양방향 음성이 필요하면 TTS가 아니라 Live API입니다.

비용은 출력 오디오 1초 = 25 토큰 규칙으로 계산합니다. Standard 요금으로 오디오 1분에 Flash TTS $0.0135, Flash-Lite TTS $0.009이고, 2027년 1월 1일부터 두 모델 모두 2배가 됩니다. 무료 등급에서 Standard 요청이 무료이므로 결제 계정을 연결하기 전에 한국어 샘플을 만들어 볼 수 있습니다. 한국은 Gemini API와 Google AI Studio 지원 국가 목록에 들어 있고, 두 모델 모두 지원 언어 표에 Korean이 있습니다.

아래 코드는 2026년 9월 24일자 공식 음성 생성 문서의 Python·REST 예제를 한국어 대본에 맞게 고쳐 쓴 것입니다. 음질과 지연 시간 수치는 공개 문서에 없으므로, 도입 판단은 무료 등급에서 직접 만든 샘플로 해야 합니다.

## 어느 모델을 쓸지: Flash TTS, Flash-Lite TTS, 아니면 Live API

모델 페이지가 제시하는 용도 구분을 한국 개발자가 실제로 만드는 것 기준으로 옮기면 다음과 같습니다.

| 만들려는 것 | 선택 | 이유 |
|---|---|---|
| 오디오북, 스튜디오급 내레이션, 감정 변화가 큰 게임 대사 | `gemini-3.8-flash-tts` | 모델 페이지가 "최대 음성 충실도, 연기 뉘앙스, 방언"을 주 강점으로 명시 |
| 웃음·한숨 태그가 많은 연기, 2인 대화에서 맞장구와 겹치는 말 | `gemini-3.8-flash-tts` | 파이프 맞장구는 Flash TTS에서 가장 잘 동작한다고 문서가 명시 |
| 어려운 고유명사 발음, 지역 억양 | `gemini-3.8-flash-tts` | 모델 페이지의 Flash TTS 대표 용도 |
| 대량 생성, 음성 상담봇의 답변 읽기, 읽어주기 기능, 일상적인 단일 화자 | `gemini-3.8-flash-lite-tts` | "고처리량, 저지연, 비용 효율"이 주 강점; LLM 답변을 바로 읽어 주는 실시간 음성 에이전트가 대표 용도 |
| `gemini-3.1-flash-tts-preview`에서 옮기는 기존 코드 | `gemini-3.8-flash-lite-tts` | 변경 로그와 모델 페이지가 지정한 공식 대체 모델 |
| 음성 복제로 만든 목소리를 대량으로 쓰는 경우 | `gemini-3.8-flash-lite-tts` | 모델 페이지가 "안정적인 음성 복제"를 Flash-Lite 용도로 분류 |
| 사용자가 말하면 끼어들기 포함 실시간으로 대답하는 앱 | Live API | 두 TTS 모델 모두 Live API 미지원; TTS는 텍스트 입력·오디오 출력만 |
| 녹음을 텍스트로 바꾸는 작업 | Transcribe 모델 | TTS는 오디오 입력을 받지 않음 |

판단 순서는 이렇습니다. 먼저 Flash-Lite TTS로 대본을 돌려 보고, 연기가 밋밋하거나 2인 대화의 겹침이 필요할 때만 Flash TTS로 바꿉니다. 요청 형식이 같으므로 바꾸는 비용은 문자열 하나입니다. 지원 언어 수는 Flash TTS 130개 이상, Flash-Lite TTS 101개이며, 입력 언어는 자동 감지됩니다.

![만들려는 것에 따라 Flash-Lite TTS, Flash TTS, Live API 중 하나를 고르는 흐름도. 두 TTS 모델은 요청 형식이 같아 model 문자열만 바꾸면 된다](https://blog.laozhang.ai/posts/ko/gemini-3-8-flash-tts-api/img/tts-model-routing.webp)

양방향 음성은 [Gemini 3.1 Flash Live API 가이드](https://blog.laozhang.ai/ko/posts/gemini-3-1-flash-live-api)가, 음성을 텍스트로 바꾸는 쪽은 [Gemini 3.5 Transcribe API 가이드](https://blog.laozhang.ai/ko/posts/gemini-3-5-transcribe-api)가 다룹니다. 텍스트 생성 모델인 3.8 Flash와는 별개 모델이며, 그쪽은 [Gemini 3.8 Flash 출시 가이드](https://blog.laozhang.ai/ko/posts/gemini-3-comparison)를 보면 됩니다.

## 첫 요청: 단일 화자 음성을 WAV 파일로 저장

준비물은 [Google AI Studio API 키 발급](https://blog.laozhang.ai/ko/posts/google-ai-studio-api-key) 절차로 받은 키 하나와 `google-genai` SDK입니다. 음성 라이브러리 조회와 음성 디자인까지 쓰려면 SDK가 `google-genai` 2.25.0 이상, JavaScript는 `@google/genai` 2.24.0 이상이어야 합니다.

```bash
pip install -U google-genai
export GEMINI_API_KEY="발급받은 키"
```

요청은 Interactions API로 보냅니다. 대본은 `text`에 그대로 넣고, 말투는 `speech_metadata` 주석의 `style`에, 목소리는 `generation_config.speech_config`에 지정합니다.

```python
import base64
from google import genai

client = genai.Client()

interaction = client.interactions.create(
    model="gemini-3.8-flash-lite-tts",
    input=[{
        "type": "user_input",
        "content": [{
            "type": "text",
            "text": "안녕하세요. 오늘 배송 일정을 안내해 드리겠습니다.",
            "annotations": [{
                "type": "speech_metadata",
                "style": "warm and friendly",
            }],
        }],
    }],
    response_format={"type": "audio"},
    generation_config={
        "speech_config": [
            {"voice": "Kore"},
        ]
    },
)

with open("out.wav", "wb") as f:
    f.write(base64.b64decode(interaction.output_audio.data))
```

돌아오는 것은 `interaction.output_audio.data`에 담긴 base64 문자열이고, 디코딩하면 RIFF 헤더가 붙은 완성된 WAV 파일입니다. 24 kHz, 모노, 16비트 signed little-endian PCM이며 헤더는 44바이트입니다. 그래서 위 코드처럼 바이트를 그대로 `.wav`로 쓰면 바로 재생됩니다. 별도로 헤더를 붙이면 안 됩니다.

같은 요청을 curl로 보내면 오디오는 `steps[].content[].data`에 들어 있습니다.

```bash
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3.8-flash-lite-tts",
    "input": [{
      "type": "user_input",
      "content": [{
        "type": "text",
        "text": "안녕하세요. 오늘 배송 일정을 안내해 드리겠습니다.",
        "annotations": [{ "type": "speech_metadata", "style": "warm and friendly" }]
      }]
    }],
    "response_format": { "type": "audio" },
    "generation_config": { "speech_config": [ { "voice": "Kore" } ] }
  }' | jq -r '[.steps[] | select(.type=="model_output") | .content[] | select(.type=="audio")] | last | .data' \
  | base64 --decode > out.wav
```

`voice`에는 프리빌트 음성 이름 30개 중 하나(Kore, Puck, Charon, Zephyr 등), Extended Voice Library의 음성 ID, 음성 디자인으로 만든 `voice_...` ID, 음성 복제로 만든 `voice_...` 또는 `voicekey_...`를 넣을 수 있습니다. 라이브러리는 `client.voices.list()`에 `language_code=["ko-KR"]` 같은 필터를 주어 조회합니다.

### 2인 대화: conversational 모드

팟캐스트나 인터뷰 형식은 한 요청 안에서 화자 2명을 지정합니다. 턴마다 `speaker`를 반드시 적고, 그 이름이 `speech_config.speakers`에 등록된 화자와 일치해야 합니다. 화자 이름은 매칭용 라벨일 뿐 읽히지 않으며, 공식 예제는 모두 영문 이름을 씁니다.

```python
import base64
from google import genai

client = genai.Client()

interaction = client.interactions.create(
    model="gemini-3.8-flash-tts",
    input=[{
        "type": "user_input",
        "content": [
            {
                "type": "text",
                "text": "지난주에 말씀하신 그 앱, 드디어 출시됐다면서요? |네, 맞아요| 반응이 어때요?",
                "annotations": [{
                    "type": "speech_metadata",
                    "speaker": "Host",
                    "style": "curious and upbeat",
                }],
            },
            {
                "type": "text",
                "text": "<laugh> 솔직히 첫날은 서버가 버티나 보느라 잠을 못 잤어요.",
                "annotations": [{
                    "type": "speech_metadata",
                    "speaker": "Guest",
                    "style": "relaxed, a little tired",
                }],
            },
        ],
    }],
    response_format={"type": "audio"},
    generation_config={
        "speech_config": {
            "mode": "conversational",
            "speakers": [
                {"speaker": "Host", "voice": "Puck"},
                {"speaker": "Guest", "voice": "Kore"},
            ],
        }
    },
)

with open("dialogue.wav", "wb") as f:
    f.write(base64.b64decode(interaction.output_audio.data))
```

첫 턴의 `|네, 맞아요|`는 Host가 말하는 동안 Guest가 배경에서 넣는 맞장구입니다. 파이프 안에 1~3단어 정도의 짧은 반응을 넣으면 턴을 쪼개지 않고도 겹치는 말이 만들어지며, 문서는 이 기능이 Flash TTS에서 가장 잘 동작한다고 밝힙니다. 한 요청의 화자는 프리빌트 음성으로 2명까지입니다. 직접 만든 `voice_...` 음성 두 개를 대화에 쓰려면 턴별로 따로 합성해서 이어 붙여야 하는데, 방법은 아래 한도 표에서 다룹니다.

### 스트리밍: 헤더 없는 raw PCM 조각

음성 상담봇처럼 첫 소리가 빨리 나와야 하는 경우 `stream=True`를 붙입니다. 이때 돌아오는 것은 WAV가 아니라 헤더 없는 16비트 PCM 조각(`audio/l16`, 24 kHz 모노)입니다. 조각을 그대로 이어 붙이거나 재생 버퍼에 넣을 수 있도록 헤더를 뺀 것입니다.

```python
import base64
from google import genai

client = genai.Client()

stream = client.interactions.create(
    model="gemini-3.8-flash-lite-tts",
    input=[{
        "type": "user_input",
        "content": [{
            "type": "text",
            "text": "주문하신 상품은 내일 오후에 도착할 예정입니다.",
            "annotations": [{"type": "speech_metadata", "style": "calm"}],
        }],
    }],
    response_format={"type": "audio"},
    generation_config={"speech_config": [{"voice": "Kore"}]},
    stream=True,
)

with open("out.pcm", "wb") as f:
    for event in stream:
        if event.event_type == "step.delta" and event.delta.type == "audio":
            f.write(base64.b64decode(event.delta.data))
```

파일로 모은 raw PCM을 확인용으로 들어 보려면 샘플 레이트와 채널을 알려주며 WAV로 감쌉니다. 값은 문서가 명시한 24 kHz, 모노, 16비트입니다.

```bash
ffmpeg -f s16le -ar 24000 -ac 1 -i out.pcm out.wav
```

### 출력 형식 바꾸기

전화 IVR처럼 8 kHz μ-law가 필요하거나 단발 요청에서도 raw PCM을 원하면 `response_format`에 `mime_type`과 `sample_rate`를 지정합니다.

| `mime_type` | 형식 | 기본이 되는 경우 |
|---|---|---|
| `audio/wav` | RIFF 헤더가 있는 WAV, 16비트 PCM, 모노, 24 kHz | 단발 요청 기본값 |
| `audio/l16` | 헤더 없는 16비트 PCM, 모노, 24 kHz | 스트리밍 기본값 |
| `audio/mulaw` | 8비트 G.711 μ-law | 북미·일본 전화망 IVR용으로 문서가 예시 |
| `audio/alaw` | 8비트 G.711 A-law | 유럽·국제 전화망용으로 문서가 예시 |

`sample_rate`는 24000, 16000, 8000 같은 값을 헤르츠 단위로 넣습니다.

```python
response_format={"type": "audio", "mime_type": "audio/l16", "sample_rate": 16000}
```

## 한국어 대본에 연출 지시를 넣는 규칙

3.8 TTS는 `text` 필드를 글자 그대로 읽는 대본으로만 취급합니다. 이전 preview 모델에서 흔히 쓰던 "속삭이듯 말해: 안녕하세요"나 "화자 1: 안녕하세요" 같은 문구를 본문에 넣으면 그 지시까지 소리 내어 읽을 수 있습니다. 지시는 범위에 따라 두 곳으로 나눕니다.

- 턴 전체에 걸치는 감정·속도·음량·말투는 `speech_metadata.style`에 넣습니다. 문서 예시는 "whispered urgently", "out of breath", "speaking slowly", "sarcastic" 같은 짧은 영어 구문입니다.
- 특정 단어 위치에서 한 번 일어나는 소리(웃음, 한숨, 기침, 숨소리, 멈춤)는 대본 안에 꺾쇠 태그로 넣습니다. 대본이 한국어라도 태그는 영어로 유지하라고 문서가 명시합니다.

```text
잠깐만요... <short pause> 이거 들으셨어요? <sigh>
실례합니다 <cough> 아까 말씀드리던 대로요.
```

문서가 권장하는 태그는 breath, heavy breath, exhales, pant, sigh, laugh, chuckle, giggle, cackle, gasp, cough, sneeze, throat-clearing, sob, cry, groan, yawn, scream, shout, whispers, short pause, long pause 등이며 모두 사람이 내는 소리입니다. 박수나 문 닫는 소리 같은 효과음 태그는 피하라고 되어 있습니다.

한국어 대본에서 특히 신경 쓸 점이 세 가지 있습니다.

1. **강조** — 문서는 강조할 단어를 대문자로 쓰라고 하는데, 한국어에는 대소문자가 없습니다. 대신 문서가 함께 제시하는 다른 수단, 즉 쉼표·줄표·말줄임표로 호흡을 만들고, 강조 구간만 별도 턴으로 나눠 `style`을 달리 주는 방법을 씁니다.
2. **발음** — 영어 이름이나 신조어를 잘못 읽으면 단어 뒤에 국제 음성 기호(IPA)를 슬래시로 감싸 넣습니다. AI Studio 개발자 가이드의 예시는 `/niːv/` 같은 형태입니다. 어려운 발음은 모델 페이지가 Flash TTS 용도로 분류합니다.
3. **품질 확인** — 발표문에 실린 언어별 블라인드 선호 평가 결과에는 일본어, 브라질 포르투갈어, 베트남어, 아랍어, 멕시코 스페인어, 힌디어가 언급되고 한국어는 없습니다. 한국어 품질을 보여 주는 공식 수치가 없으므로, 실제 대본으로 무료 등급에서 두 모델을 각각 들어 보고 정하는 편이 확실합니다.

문서가 권하는 작업 순서도 한국어에 그대로 적용됩니다. `style`을 비운 채 먼저 합성해 보고(대부분의 요청은 지시가 필요 없다고 문서가 밝힙니다), 필요한 턴에만 짧은 문구를 추가하며, 같은 기준 말투는 같은 문자열을 재사용합니다. "목소리를 바꾸지 마"처럼 모델에게 안정성을 부탁하는 메타 문장은 오히려 흔들림을 키우므로 넣지 않습니다. 나이, 성별, 이름, 고정 억양은 `style`로 바꿀 수 없고, 음성 라이브러리에서 고르거나 음성 디자인으로 만들어야 합니다.

## 비용 계산: 오디오 1초 = 25 토큰

요금표의 각주가 기준입니다. 출력 오디오 토큰은 오디오 1초당 25 토큰이므로 1분은 1,500 토큰, 1시간은 90,000 토큰입니다. 비용 식은 다음과 같습니다.

```text
출력 비용 = 오디오 초 × 25 × (출력 단가 ÷ 1,000,000)
예) Flash TTS Standard 2026년: 60초 × 25 × (9.00 ÷ 1,000,000) = $0.0135
```

입력 텍스트 비용은 따로 더하지만 크기가 다릅니다. 1분 분량 대본이 200 토큰이라면 입력 단가 $0.50 기준 $0.0001로, 출력의 1% 미만입니다. 아래 표는 출력 오디오만 계산한 값이며, 1M 토큰당 단가에서 도출한 수치입니다.

| 요청 방식 | 모델 | 1분 (2026년) | 1시간 (2026년) | 1분 (2027년 1월 1일부터) | 1시간 (2027년) |
|---|---|---|---|---|---|
| Standard | Flash TTS | $0.0135 | $0.81 | $0.027 | $1.62 |
| Standard | Flash-Lite TTS | $0.009 | $0.54 | $0.018 | $1.08 |
| Batch / Flex | Flash TTS | $0.00675 | $0.405 | $0.0135 | $0.81 |
| Batch / Flex | Flash-Lite TTS | $0.0045 | $0.27 | $0.009 | $0.54 |
| Priority | Flash TTS | $0.0243 | $1.458 | $0.0486 | $2.916 |
| Priority | Flash-Lite TTS | $0.0162 | $0.972 | $0.0324 | $1.944 |

![오디오 1초 25 토큰에서 1분 1,500 토큰을 도출하고, Standard 기준 Flash TTS와 Flash-Lite TTS의 1분 비용이 2027년 1월 1일부터 2배가 되는 것을 3.1 preview와 비교한 막대 그래프](https://blog.laozhang.ai/posts/ko/gemini-3-8-flash-tts-api/img/tts-audio-cost.webp)

단가 원본은 이렇습니다. Standard 출력 오디오 1M 토큰당 Flash TTS $9.00, Flash-Lite TTS $6.00(2026년 12월 31일까지), 2027년 1월 1일부터 $18.00과 $12.00. Batch와 Flex는 Standard의 절반, Priority는 1.8배입니다. 입력 텍스트는 두 모델 모두 Standard $0.50, Batch·Flex $0.25, Priority $0.90이며 2027년에 역시 2배가 됩니다.

같은 방식으로 구모델을 계산하면 옮길 때의 절감폭이 보입니다. `gemini-3.1-flash-tts-preview`는 출력 $20.00이므로 1분에 $0.03, 1시간에 $1.80입니다. 2026년 요금으로 Flash-Lite TTS는 그 30%, Flash TTS는 45%이고, 2027년 요금이 적용된 뒤에도 각각 60%와 90%로 3.1 preview보다 쌉니다. `gemini-2.5-flash-preview-tts`는 출력 $10.00으로 1분 $0.015, `gemini-2.5-pro-preview-tts`는 $20.00으로 1분 $0.03입니다.

예를 들어 10시간 분량 오디오북을 Standard로 만들면 2026년 요금 기준 Flash TTS $8.10, Flash-Lite TTS $5.40이고, 마감이 급하지 않아 Batch로 돌리면 Flash-Lite TTS가 $2.70입니다. 이 값에는 컨텍스트 캐싱(입력 캐싱 1M 토큰당 $0.125, 저장 시간당 $0.50), 재시도, 마음에 안 들어 다시 만든 생성분, 세금과 카드 결제 수수료가 빠져 있습니다. 실제 오디오 길이는 모델의 말 속도에 따라 달라지므로, 청구 금액은 요청 후 반환되는 토큰 수로 맞춰 봐야 합니다.

### 무료 등급에서 먼저 테스트하기

두 모델 모두 무료 등급에서 Standard와 Priority 요청이 무료입니다. Batch와 Flex는 무료 등급에 없으므로 대량 저가 생성은 결제 계정을 연결해야 합니다. 무료 등급의 입력과 출력은 Google 제품 개선에 사용된다고 요금표에 명시되어 있고 유료 등급은 사용되지 않으므로, 고객 대본이나 복제한 목소리로 하는 테스트는 유료 등급에서 하는 것이 맞습니다.

무료 등급에서 분당 몇 번까지 요청할 수 있는지는 속도 제한 페이지에 3.8 TTS 항목이 없습니다. 2.5 TTS만 Batch 대기 토큰 표에 있을 뿐이고, 3.8 TTS의 RPM·TPM·RPD는 AI Studio의 속도 제한 화면에서 프로젝트별로 확인하라고 안내합니다. 확인 위치는 [Gemini API 무료 사용 한도 2026](https://blog.laozhang.ai/ko/posts/gemini-api-free-tier)에 정리되어 있습니다.

결제를 연결한 뒤에는 지출 기반 제한이 붙습니다. 10분 창 기준 Tier 1 $10, Tier 2 $50, Tier 3 $200을 넘기면 `429 RESOURCE_EXHAUSTED`가 돌아옵니다. Flash TTS Standard로 10분 안에 $10을 쓰려면 약 12시간 분량 오디오를 생성해야 하므로 단일 서비스에서 흔히 닿는 값은 아니지만, Batch 작업을 한 번에 넣을 때는 계산해 두어야 합니다. Tier 2는 누적 결제 $100과 첫 결제 후 3일, Tier 3는 $1,000과 30일이 조건입니다. 결제 연결과 카드 문제는 [Gemini API 키 구매 전 확인할 가격·결제·안전 경로](https://blog.laozhang.ai/ko/posts/gemini-api-pricing)에서 다룹니다.

## 3.1 preview·2.5 TTS에서 옮길 때 깨지는 다섯 지점

`gemini-3.1-flash-tts-preview`는 모델 목록에서 "Legacy TTS preview model"로 표시되며 3.8로 옮기라고 안내됩니다. 2.5 모델은 2026년 9월 18일 변경 로그에 따라 과거에 실제로 사용한 사용자에게만 접근이 허용됩니다. 지원 종료는 아니지만 새 프로젝트에서는 열리지 않으므로 `gemini-2.5-flash-preview-tts`나 `gemini-2.5-pro-preview-tts` 기반 코드도 같은 이유로 옮겨야 합니다.

모델 페이지가 적은 깨지는 지점은 다섯 가지입니다.

| # | 이전 방식 | 3.8에서 생기는 일 | 고치는 법 |
|---|---|---|---|
| 1 | "Say cheerfully: ..."처럼 대본 안에 지시를 섞음 | 지시문까지 소리 내어 읽을 수 있음 | `style`과 `speaker`를 `speech_metadata` 주석으로 이동 |
| 2 | 지시를 자유 텍스트나 효과음 태그로 표현 | 효과음 태그는 권장되지 않음 | 꺾쇠 태그는 순간적인 사람 소리에만, 속삭임 같은 말투는 `style`에 |
| 3 | 2인 대화에서 "Joe: ..." 접두어로 화자 구분 | 접두어를 읽거나 화자 매칭이 되지 않음 | 모든 턴에 등록된 이름과 일치하는 `speaker` 지정 |
| 4 | 긴 "Audio Profile", "Director's Notes" 블록으로 인물 설정 | 목소리 흔들림의 가장 흔한 원인이라고 문서가 명시 | 음성 디자인으로 `voice_...` 하나 만들고 `style`은 짧게 또는 비움 |
| 5 | raw PCM이 돌아온다고 보고 Python `wave`나 ffmpeg로 WAV 헤더를 붙임 | 단발 요청 기본이 WAV라 헤더가 두 번 붙음 | 헤더 래퍼 제거; raw PCM이 필요하면 `audio/l16` 명시 |

코드로 보면 다음과 같습니다. 첫 번째 블록은 3.1 preview 시절 흔한 형태이고, 두 번째가 3.8 형식입니다.

```python
# 이전: 3.1 preview 방식 — 3.8에서는 지시문이 읽히고 헤더가 이중으로 붙음
import base64
import wave

interaction = client.interactions.create(
    model="gemini-3.1-flash-tts-preview",
    input="Say cheerfully: 오늘도 좋은 하루 보내세요!",
    response_format={"type": "audio"},
    generation_config={"speech_config": [{"voice": "Kore"}]},
)
pcm = base64.b64decode(interaction.output_audio.data)
with wave.open("out.wav", "wb") as wf:
    wf.setnchannels(1)
    wf.setsampwidth(2)
    wf.setframerate(24000)
    wf.writeframes(pcm)
```

```python
# 이후: 3.8 방식 — 대본과 지시를 분리하고 WAV를 그대로 저장
interaction = client.interactions.create(
    model="gemini-3.8-flash-lite-tts",
    input=[{
        "type": "user_input",
        "content": [{
            "type": "text",
            "text": "오늘도 좋은 하루 보내세요!",
            "annotations": [{"type": "speech_metadata", "style": "cheerful"}],
        }],
    }],
    response_format={"type": "audio"},
    generation_config={"speech_config": [{"voice": "Kore"}]},
)
with open("out.wav", "wb") as f:
    f.write(base64.b64decode(interaction.output_audio.data))
```

GenerateContent API를 쓰는 코드라면 각 `part`에 `"speech_metadata": {"speaker": "...", "style": "..."}`를 붙이는 형태로 같은 원칙이 적용된다고 모델 페이지가 적고 있지만, 전체 예제는 Interactions API 기준만 공개되어 있습니다.

Go로 작업한다면 주의할 점이 하나 더 있습니다. 음성 생성 문서의 Go 예제는 아직 `gemini-3.1-flash-tts-preview`와 "Say cheerfully:" 인라인 지시, 수동 `saveWaveFile` 래퍼를 그대로 쓰고 있어 3.8 형식이 아닙니다. Go SDK에서는 REST 요청 형태를 기준으로 구조체를 맞추고, 그 예제의 헤더 래퍼는 가져오지 않아야 합니다.

## 한도와 실패 경계

부딪히기 전에 알아 두어야 할 값들입니다. 출처는 모델 페이지와 음성 생성 문서의 제한 항목입니다.

| 항목 | 한도 또는 동작 | 넘으면 생기는 일 | 대응 |
|---|---|---|---|
| 입력 토큰 | 요청당 8,192 | 긴 대본은 거부 | 장이나 단락 단위로 나누어 요청 |
| 출력 토큰 | 요청당 16,384 (API 서빙 한도) | 25 토큰/초 규칙으로 환산하면 약 655초, 약 10.9분 상당 | 10분 넘는 낭독은 나누어 생성 후 이어 붙임 |
| 한 요청의 화자 수 | 프리빌트 음성으로 2명까지 | 3명 이상, 또는 `voice_...` 음성 조합은 한 요청으로 불가 | 화자별 턴을 따로 합성; 단발 요청은 WAV라 44바이트 헤더를 떼거나 `audio/l16`으로 받아 24 kHz PCM을 이어 붙임 |
| 저장형 커스텀 음성 | 프로젝트당 200개, 보관 1년 (디자인·복제 합산) | 초과 생성 불가 | `voices.delete()`로 정리, 임시 음성은 저장하지 않음 |
| 무저장 음성 키 `voicekey_...` | 7일 | 만료 후 사용 불가 | 서버 저장을 피해야 하는 경우에만 사용하고 갱신 절차 마련 |
| 인라인 태그 언어 | 한국어 대본에도 영어 태그 | 한글 태그는 문서가 보장하지 않음 | 위 권장 태그 목록만 사용 |
| 단발 vs 스트리밍 출력 | 단발 WAV, 스트리밍 raw PCM | 스트리밍 조각을 `.wav`로 저장하면 헤더 없는 파일 | 스트리밍은 PCM으로 처리하거나 재생 시 형식 지정 |
| 지원하지 않는 기능 | Live API, 함수 호출, 구조화 출력, 사고(thinking), 검색 그라운딩, 이미지 생성 | 모델 페이지에 "지원 안 함"으로 표시 | 텍스트 생성은 다른 모델에서 하고 결과 대본만 TTS에 전달 |
| 모델 버전 | 날짜 스냅샷 없음, `gemini-3.8-flash-tts`와 `gemini-3.8-flash-lite-tts`만 | 특정 버전 고정 불가 | 출력 변화를 감지하는 회귀 샘플 유지 |
| 지역 | 한국은 지원 국가 목록에 포함, 18세 이상, 계정 연령 확인 필요 | 미지원 지역에서는 AI Studio 접근 불가 | Colab은 사용자가 아니라 인스턴스 위치 기준으로 판정 |
| Vertex AI / Cloud TTS | 2026년 9월 30일 기준 Google Cloud Text-to-Speech 문서의 Gemini-TTS 목록에 3.8 항목 없음 | 기업용 경로는 "Gemini Enterprise를 통해 곧 제공" 단계 | 당장은 Gemini API 키 경로만 사용 |

## 음성 디자인과 음성 복제: 한국 사용자 조건

두 3.8 모델 모두 음성 디자인(Voice design)과 음성 복제(Voice replication)를 지원하며, 둘 다 `POST /v1beta/voices` 엔드포인트로 만듭니다. 만들어진 `voice_...` ID는 위 TTS 요청의 `voice` 자리에 그대로 넣습니다.

음성 디자인은 화자가 누구인지(나이, 음색, 음높이, 억양, 기본 말 속도)를 설명해서 새 목소리를 만드는 기능입니다. 일시적인 감정은 `style`의 몫이므로 설명에 넣지 않습니다. 공식 예시는 모두 영어 설명이며, 생성 응답에는 바로 들어 볼 수 있는 `sample_audio`(WAV)가 함께 옵니다.

```python
from google import genai

client = genai.Client()

voice = client.voices.create(
    store=True,
    voice={
        "model": "gemini-3.8-flash-tts",
        "type": "prompted",
        "display_name": "차분한 30대 안내 음성",
        "gender": "female",
        "language_code": "ko-KR",
        "prompted": {
            "input": "A calm, clear woman in her mid-30s with a neutral Seoul accent, "
                     "medium pitch, measured pace, like a public transit announcer."
        },
    },
)
print(voice.id)  # voice_... 를 speech_config의 voice에 사용
```

음성 복제는 같은 성인 화자의 녹음 두 개가 필요합니다. 복제할 목소리의 깨끗한 발화 10~30초(`source_audio`)와, 그 화자가 동의문을 그대로 읽은 녹음(`consent_audio`)입니다. 동의문은 30개 로케일 중 하나여야 하며 한국어(ko-KR) 문장은 다음과 같습니다.

> 나는 이 음성의 소유자이며 구글이 이 음성을 사용하여 음성 합성 모델을 생성할 것을 허용합니다.

두 녹음은 같은 마이크, 같은 공간에서 하고 24 kHz 모노 16비트 WAV로 변환해 보내는 것이 권장됩니다. 동의 녹음의 화자가 참조 음성의 화자와 일치하는지 검증하며, 생성된 모든 오디오에는 SynthID 워터마크가 들어갑니다. 발표문 각주에 따르면 AI Studio 화면에서의 음성 복제는 일리노이, 텍사스, EEA, 영국, 스위스, 인도에서 제공되지 않는데, 이 목록에 한국은 없습니다.

`store=True`로 만든 음성은 프로젝트당 200개, 1년 보관 한도를 디자인 음성과 나눠 씁니다. 생체 정보를 서버에 남기지 않아야 하는 경우 `store=False`로 만들면 `voicekey_...` 문자열이 돌아오고, 이를 클라이언트가 보관하며 7일 안에 써야 합니다.

## 자주 묻는 질문

**Gemini 3.8 TTS는 무료로 쓸 수 있나요?**
무료 등급에서 Standard와 Priority 요청은 무료이며, 두 3.8 TTS 모델 모두 해당됩니다. 대신 무료 등급의 입력·출력은 Google 제품 개선에 사용되고, Batch와 Flex는 무료 등급에 없으며, 3.8 TTS의 분당·일당 요청 한도는 AI Studio에서 프로젝트별로 확인해야 합니다. AI Studio 화면에서 무료로 되는 범위는 [Google AI Studio 무료, 어디까지 되고 언제 돈이 드나](https://blog.laozhang.ai/ko/posts/ai-studio-complete-access-guide)에 있습니다.

**Vertex AI나 Google Cloud Text-to-Speech에서 3.8 TTS를 쓸 수 있나요?**
2026년 9월 30일 기준 Cloud Text-to-Speech 문서의 Gemini-TTS 모델 목록에는 3.1 preview와 2.5 계열만 있고 3.8은 없습니다. 발표문은 기업용 API 경로를 "Gemini Enterprise를 통해 곧 제공"이라고만 적었습니다. 현재 공개된 경로는 Gemini API 키를 쓰는 `generativelanguage.googleapis.com`뿐입니다.

**2.5 TTS를 그대로 써도 되나요?**
2026년 9월 18일부터 2.5 모델은 과거에 실제 사용한 적이 있는 사용자에게만 열립니다. 지원 종료는 아니지만 새 프로젝트에서는 쓸 수 없고, 요금도 2.5 Flash TTS 출력 $10.00, 2.5 Pro TTS $20.00으로 3.8 Flash-Lite TTS의 $6.00보다 비쌉니다. 옮기는 기준은 위 다섯 지점과 같습니다.

**화자 3명짜리 대본은 어떻게 만드나요?**
한 요청에는 프리빌트 음성 2명까지만 들어갑니다. 3명 이상이거나 디자인·복제 음성을 섞으려면 화자별 턴을 각각 합성한 뒤 이어 붙입니다. 단발 요청은 WAV로 오므로 각 턴에서 44바이트 RIFF 헤더를 떼거나 처음부터 `audio/l16`으로 받아 24 kHz PCM을 연결하고, 마지막에 한 번만 WAV 헤더를 붙입니다.

**한국어 대본에 섞인 영어 이름을 잘못 읽으면 어떻게 하나요?**
해당 단어 뒤에 국제 음성 기호를 슬래시로 감싸 넣습니다. 그래도 안 되면 Flash TTS로 바꿔 봅니다. 어려운 발음은 모델 페이지가 Flash TTS의 대표 용도로 분류하고 있습니다.
