文字转语音生成 (TTS)

Gemini API 可以使用 Gemini 文字转语音 (TTS) 生成功能将文本输入转换为单人或多人语音。文字转语音生成是可控的,这意味着您可以结合使用结构化对话元数据 (speech_metadata) 和内嵌语音标记来指导音频的风格、口音、语速和语气。

TTS 功能不同于通过 Live API 提供的语音生成功能,后者专为交互式非结构化音频以及多模态输入和输出而设计。虽然 Live API 在动态对话上下文中表现出色,但通过 Gemini API 实现的 TTS 专为需要精确朗读文本并对风格和声音进行精细控制的场景而量身打造,例如播客或有声读物生成。

本指南将向您展示如何使用 Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) 和 Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) 从文本生成单人语音和多人语音。

准备工作

请确保您使用的是支持的模型部分中列出的 Gemini TTS 模型。为获得最佳结果,请查看何时使用哪种模型,以便为您的工作负载选择最佳模型。

在开始构建之前,您可能会发现在 AI Studio 中测试 Gemini TTS 模型很有用。

单说话者 TTS

如需使用 Gemini 3.8 TTS 模型将文本转换为单人语音,请在 parts[].text 中传递逐字转写内容,在 parts[].speech_metadata 中附加轮次级样式,并在 speechConfig.voiceConfig 中配置语音。您可以传递预构建的语音名称、扩展语音库 ID、自定义语音设计 ID (voice_...) 或语音复刻 ID(voice_... 或可选的无状态 voicekey_...)。

此示例将模型生成的输出音频保存到 WAV 文件中:

Python

from google import genai

client = genai.Client()

response = client.models.generate_content(
    model="gemini-3.8-flash-tts",
    contents=[{
        "role": "user",
        "parts": [{
            "text": "Have a wonderful day!",
            "speech_metadata": {"style": "cheerful and friendly"},
        }],
    }],
    config={
        "response_modalities": ["AUDIO"],
        "speech_config": {
            "voice_config": {"voice": "Kore"}
        },
    },
)

data = response.candidates[0].content.parts[0].inline_data.data
with open("out.wav", "wb") as f:
    f.write(data)

JavaScript

import {GoogleGenAI} from '@google/genai';
import * as fs from 'node:fs';

async function main() {
   const ai = new GoogleGenAI({});

   const response = await ai.models.generateContent({
      model: 'gemini-3.8-flash-tts',
      contents: [{
         role: 'user',
         parts: [{
            text: 'Have a wonderful day!',
            speechMetadata: { style: 'cheerful and friendly' },
         }],
      }],
      config: {
         responseModalities: ['AUDIO'],
         speechConfig: {
            voiceConfig: { voice: 'Kore' },
         },
      },
   });

   const data = response.candidates?.[0]?.content?.parts?.[0]?.inlineData?.data;
   const audioBuffer = Buffer.from(data, 'base64');

   fs.writeFileSync('out.wav', audioBuffer);
}
await main();

REST

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash-tts:generateContent" \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
        "contents": [{
          "role": "user",
          "parts": [{
            "text": "Have a wonderful day!",
            "speech_metadata": {
              "style": "cheerful and friendly"
            }
          }]
        }],
        "generationConfig": {
          "responseModalities": ["AUDIO"],
          "speechConfig": {
            "voiceConfig": {
              "voice": "Kore"
            }
          }
        }
    }' | jq -r '.candidates[0].content.parts[0].inlineData.data' | \
          base64 --decode > out.wav

多说话人 TTS

对于多说话人对话,请在 multiSpeakerVoiceConfig.speakerVoiceConfigs 中使用 prebuiltVoiceConfig 配置两个说话人,并将每个对话轮次作为单独的 part 传递,其中 speech_metadata 指定了 speaker 和可选的轮次级 style:

Python

from google import genai

client = genai.Client()

response = client.models.generate_content(
    model="gemini-3.8-flash-tts",
    contents=[{
        "role": "user",
        "parts": [
            {
                "text": "How's it going today Jane?",
                "speech_metadata": {
                    "speaker": "Joe",
                    "style": "cheerful and friendly",
                },
            },
            {
                "text": "Not too bad, how about you? Ready to test these new voices?",
                "speech_metadata": {
                    "speaker": "Jane",
                    "style": "calm and relaxed",
                },
            },
        ],
    }],
    config={
        "response_modalities": ["AUDIO"],
        "speech_config": {
            "multi_speaker_voice_config": {
                "speaker_voice_configs": [
                    {
                        "speaker": "Joe",
                        "voice_config": {
                            "prebuilt_voice_config": {"voice_name": "Puck"}
                        },
                    },
                    {
                        "speaker": "Jane",
                        "voice_config": {
                            "prebuilt_voice_config": {"voice_name": "Kore"}
                        },
                    },
                ]
            }
        },
    },
)

data = response.candidates[0].content.parts[0].inline_data.data
with open("out.wav", "wb") as f:
    f.write(data)

JavaScript

import {GoogleGenAI} from '@google/genai';
import * as fs from 'node:fs';

async function main() {
   const ai = new GoogleGenAI({});

   const response = await ai.models.generateContent({
      model: 'gemini-3.8-flash-tts',
      contents: [{
         role: 'user',
         parts: [
            {
               text: "How's it going today Jane?",
               speechMetadata: {
                  speaker: 'Joe',
                  style: 'cheerful and friendly',
               },
            },
            {
               text: 'Not too bad, how about you? Ready to test these new voices?',
               speechMetadata: {
                  speaker: 'Jane',
                  style: 'calm and relaxed',
               },
            },
         ],
      }],
      config: {
         responseModalities: ['AUDIO'],
         speechConfig: {
            multiSpeakerVoiceConfig: {
               speakerVoiceConfigs: [
                  {
                     speaker: 'Joe',
                     voiceConfig: {
                        prebuiltVoiceConfig: { voiceName: 'Puck' },
                     },
                  },
                  {
                     speaker: 'Jane',
                     voiceConfig: {
                        prebuiltVoiceConfig: { voiceName: 'Kore' },
                     },
                  },
               ],
            },
         },
      },
   });

   const data = response.candidates?.[0]?.content?.parts?.[0]?.inlineData?.data;
   const audioBuffer = Buffer.from(data, 'base64');

   fs.writeFileSync('out.wav', audioBuffer);
}

await main();

REST

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash-tts:generateContent" \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [{
      "role": "user",
      "parts": [
        {
          "text": "How'\''s it going today Jane?",
          "speech_metadata": {
            "speaker": "Joe",
            "style": "cheerful and friendly"
          }
        },
        {
          "text": "Not too bad, how about you? Ready to test these new voices?",
          "speech_metadata": {
            "speaker": "Jane",
            "style": "calm and relaxed"
          }
        }
      ]
    }],
    "generationConfig": {
      "responseModalities": ["AUDIO"],
      "speechConfig": {
        "multiSpeakerVoiceConfig": {
          "speakerVoiceConfigs": [
            {
              "speaker": "Joe",
              "voiceConfig": {
                "prebuiltVoiceConfig": { "voiceName": "Puck" }
              }
            },
            {
              "speaker": "Jane",
              "voiceConfig": {
                "prebuiltVoiceConfig": { "voiceName": "Kore" }
              }
            }
          ]
        }
      }
    }
  }' | jq -r '.candidates[0].content.parts[0].inlineData.data' | \
      base64 --decode > out.wav

使用元数据和标记控制语音风格

Gemini 3.8 TTS 会将 text 字段严格视为逐字转写内容。如需控制朗读效果,但不希望系统朗读舞台说明,请按范围拆分指令:

  • 持续的轮次级交付 (speech_metadata.style):将适用于整个轮次的情感、交付风格、韵律、节奏和音量放在 speech_metadata.style 中(例如 "style": "whispered urgently"、"style": "out of breath" 或 "style": "warm and enthusiastic")。
  • 时间点事件(内嵌标记):使用尖括号(例如 "Wait... <short pause> did you hear that? <sigh>" 或 "Excuse me <cough> as I was saying...")将短暂的非语音声音爆发或停顿直接放置在转写内容中。

如需了解全面的最佳实践,请参阅提示指南。

语音选项

Gemini 3.8 TTS 支持四种选择或创建语音的方式:

  1. 预建的 Studio 语音:下表中列出的 30 种精选语音。
  2. 扩展语音库:使用 client.voices.list() (GET /v1beta/voices) 可访问数百种其他语音,涵盖多种语言、口音和角色原型。
  3. 语音设计:在 Google AI Studio 中通过自然语言描述生成自定义声音角色,或使用 POST /v1beta/voices(type="prompted",返回持久性 voice_... ID 和 CreateVoice 和 GetVoice 中的 sample_audio WAV 预览)。
  4. 语音复刻:在 Google AI Studio 中或使用 POST /v1beta/voices(默认情况下为持久性 store=True,也可选择无状态 store=False)复制参考音频和同意音频中的说话者语音。type="replicated"

自定义语音限制和 TTL

语音类型 存储模式 配额 / 限制 保留期限 (TTL)
有状态语音(voice_...,提示或复制) store=True 每个项目 200 个声音(在提示声音和复制声音之间共享) 自上次使用起 1 年*
无状态语音键(voicekey_...,已复制) store=False 由客户端管理 7 天

* TTL 延期:每次积极使用该声音(通过该声音合成语音或将其用作混音的基础声音)时,1 年的保留期限都会重置。如果某个声音闲置 1 年,系统会自动将其删除。

预建语音

Zephyr - 明亮 Puck - 欢快 Charon - 信息丰富
Kore -- 坚定 Fenrir - 易兴奋 Leda - 青春
Orus - 公司 Aoede - Breezy Callirrhoe - 轻松
Autonoe - 明亮 Enceladus - 气声 Iapetus -- 清晰
Umbriel - 随和 Algieba - 平滑 Despina - 平滑
Erinome -- 清除 Algenib -- Gravelly Rasalgethi - 信息丰富
Laomedeia - 欢快 Achernar - 柔和 Alnilam - 坚定
Schedar - 均匀 Gacrux - 成熟 Pulcherrima - 转发
Achird - 友好 Zubenelgenubi - 休闲 Vindemiatrix - 柔和
Sadachbia - 活泼 Sadaltager - 知识渊博 Sulafat - 偏高

扩展的语音库和过滤功能

除了上表中列出的 30 种精选工作室语音外,扩展语音库还提供了数百种其他语音,涵盖多种语言、地区口音、角色人物和领域。您可以在 Google AI Studio 中以交互方式浏览、过滤和试听完整的语音库,也可以使用 client.voices.list()(GET /v1beta/voices,使用 google-genai 2.25.0+ / @google/genai 2.24.0+)以编程方式查询语音库。

ListVoices 会返回您的自定义存储语音(按最新到最旧的顺序排列),然后返回符合过滤条件的预构建目录语音。如果为列表过滤条件传递了多个值,系统会返回与该过滤条件中的任何值匹配的声音 (OR),而不同的过滤条件参数会与 AND 结合使用:

参数 类型 说明
language_code list[str] BCP-47 语言标记(例如 ["en-US", "en-GB"])。不区分大小写的完全匹配。
region_code list[str] ISO 3166-1 alpha-2 或联合国 M.49 地区代码(例如 ["US", "GB"])。
accent list[str] 区域口音描述符(例如 ["American", "British"])。
gender list[str] 感知到的性别表达("female"、"male" 或 "neutral")。
pitch list[str] 人声音调分类("low"、"medium" 或 "high")。
persona list[str] 声音角色或角色原型(例如 ["Warm, Friendly"]、["Narrator"])。
contexts(REST 中的 context) list[str] 最佳使用网域(例如 ["Audiobook", "Conversational", "News"])。
type(在 Python 中为 type_) list[str] 按语音来源过滤:"prebuilt"、"prompted"(语音设计)或 "replicated"(语音复刻)。
search str 自由文本子字符串搜索不区分大小写,可匹配 display_name 和 description。
page_size int 每页返回的声音数量上限(默认值为 50,最大值为 1000)。
page_token str 来自 response.next_page_token 的令牌,用于获取下一页结果。

Python

from google import genai

client = genai.Client()

# Filter the Voice Library by language, gender, pitch, domain context, and keyword
response = client.voices.list(
    language_code=["en-US", "en-GB"],
    gender=["female"],
    pitch=["medium", "low"],
    contexts=["Audiobook", "Conversational"],
    type_=["prebuilt"],
    search="warm",
    page_size=50,
)

for voice in response.voices or []:
    print(
        f"{voice.id} | {voice.display_name} ({voice.language_code},"
        f" {voice.accent}, {voice.gender}, pitch={voice.pitch}):"
        f" {voice.description}"
    )

JavaScript

import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI();

// Filter the Voice Library by language, gender, pitch, domain context, and keyword
const response = await ai.voices.list({
  language_code: ["en-US", "en-GB"],
  gender: ["female"],
  pitch: ["medium", "low"],
  contexts: ["Audiobook", "Conversational"],
  type: ["prebuilt"],
  search: "warm",
  page_size: 50,
});

for (const voice of response.voices ?? []) {
  console.log(
    `${voice.id} | ${voice.display_name} (${voice.language_code}, ${voice.accent}, ${voice.gender}, pitch=${voice.pitch}): ${voice.description}`
  );
}

REST

curl -G "https://generativelanguage.googleapis.com/v1beta/voices" \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  --data-urlencode "language_code=en-US" \
  --data-urlencode "language_code=en-GB" \
  --data-urlencode "gender=female" \
  --data-urlencode "pitch=medium" \
  --data-urlencode "context=Audiobook" \
  --data-urlencode "type=prebuilt" \
  --data-urlencode "search=warm" \
  --data-urlencode "page_size=50"

支持的语言

TTS 模型会自动检测输入语言。 Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) 支持超过 130 种语言,而 Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) 支持超过 100 种语言:

语言 Gemini 3.8 Flash TTS Gemini 3.8 Flash-Lite TTS
亚齐语(阿拉伯文字) ✔️ ✔️
南非荷兰语 ✔️ ✔️
阿坎语 ✔️ ✔️
阿姆哈拉语 ✔️ ✔️
亚美尼亚语 ✔️ ✔️
阿萨姆语 ✔️ ✔️
阿瓦德语 ✔️ ✔️
巴厘语 ✔️ ✔️
孟加拉语 ✔️ ✔️
班查语(阿拉伯文字) ✔️ —
班查语(拉丁文字) ✔️ ✔️
巴什基尔语 ✔️ —
巴斯克语 ✔️ ✔️
白俄罗斯语 ✔️ ✔️
奔巴语 ✔️ —
博杰普尔语 ✔️ ✔️
波斯尼亚语 ✔️ ✔️
布吉文 ✔️ ✔️
保加利亚语 ✔️ ✔️
缅甸语 ✔️ —
粤语 ✔️ ✔️
加泰罗尼亚语 ✔️ ✔️
宿务语 ✔️ ✔️
中部库尔德语 ✔️ ✔️
恰蒂斯加尔语 ✔️ ✔️
中文(汉字) ✔️ ✔️
中文(繁体) ✔️ ✔️
克里米亚鞑靼语 ✔️ —
克罗地亚语 ✔️ ✔️
捷克 ✔️ ✔️
丹麦语 ✔️ ✔️
荷兰语 ✔️ ✔️
迪尤拉语 ✔️ —
宗卡语 ✔️ —
阿拉伯语(埃及) ✔️ ✔️
英语 ✔️ ✔️
爱沙尼亚语 ✔️ ✔️
菲律宾语 ✔️ ✔️
芬兰语 ✔️ —
法语 ✔️ ✔️
加利西亚语 ✔️ ✔️
干达语 ✔️ ✔️
格鲁吉亚语 ✔️ ✔️
德语 ✔️ ✔️
希腊语 ✔️ ✔️
瓜拉尼人 ✔️ —
古吉拉特语 ✔️ ✔️
海地克里奥尔语 ✔️ ✔️
喀尔喀蒙古语 ✔️ ✔️
豪萨语 ✔️ ✔️
希伯来语 ✔️ ✔️
印地语 ✔️ ✔️
匈牙利语 ✔️ ✔️
冰岛语 ✔️ ✔️
伊博语 ✔️ —
伊洛果语 ✔️ ✔️
印度尼西亚语 ✔️ ✔️
伊朗波斯语 ✔️ ✔️
意大利语 ✔️ ✔️
日语 ✔️ ✔️
爪哇语 ✔️ ✔️
卡拜尔语 ✔️ —
卡姆巴语 ✔️ ✔️
卡纳达语 ✔️ ✔️
克什米尔语(阿拉伯文字) ✔️ ✔️
克什米尔语(梵文) ✔️ ✔️
哈萨克语 ✔️ ✔️
高棉语 ✔️ ✔️
吉库尤语 ✔️ ✔️
卢旺达语 ✔️ ✔️
刚果语 ✔️ ✔️
韩语 ✔️ ✔️
吉尔吉斯语 ✔️ ✔️
老挝语 ✔️ ✔️
拉特加莱语 ✔️ —
林加拉语 ✔️ ✔️
立陶宛语 ✔️ —
卢森堡语 ✔️ —
马其顿语 ✔️ ✔️
摩揭陀语 ✔️ ✔️
迈蒂利语 ✔️ ✔️
马拉雅拉姆语 ✔️ ✔️
马耳他语 ✔️ ✔️
曼尼普尔语 ✔️ ✔️
马拉地语 ✔️ ✔️
米南佳保语(阿拉伯文字) ✔️ ✔️
米南佳保语(拉丁文字) ✔️ —
米佐语 ✔️ ✔️
尼泊尔语(单独的语言) ✔️ ✔️
尼日利亚富拉语 ✔️ ✔️
阿塞拜疆北部 ✔️ ✔️
北索托语 ✔️ ✔️
乌兹别克北部 ✔️ ✔️
挪威博克马尔语 ✔️ ✔️
挪威语(尼诺斯克语) ✔️ ✔️
尼昂加语 ✔️ ✔️
奥克斯坦语 ✔️ —
奥里亚语(单个语言) ✔️ ✔️
邦阿西楠语 ✔️ —
波斯语(阿富汗) ✔️ ✔️
波兰语 ✔️ ✔️
葡萄牙语 ✔️ ✔️
旁遮普语 ✔️ ✔️
罗马尼亚语 ✔️ ✔️
俄语 ✔️ ✔️
桑塔利语 ✔️ ✔️
塞尔维亚语 ✔️ ✔️
信德语 ✔️ —
僧伽罗语 ✔️ ✔️
斯洛伐克语 ✔️ ✔️
斯洛文尼亚语 ✔️ —
索马里语 ✔️ —
南阿塞拜疆语 ✔️ ✔️
南部普什图语 ✔️ ✔️
南索托语 ✔️ —
西班牙语 ✔️ ✔️
标准阿拉伯语(阿拉伯文字) ✔️ ✔️
标准阿拉伯语(拉丁文字) ✔️ ✔️
标准拉脱维亚语 ✔️ ✔️
标准马来语 ✔️ ✔️
斯瓦希里语(单个语言) ✔️ —
斯瓦特语 ✔️ —
瑞典语 ✔️ —
塔吉克语 ✔️ —
泰米尔语 ✔️ ✔️
泰卢固语 ✔️ ✔️
泰语 ✔️ —
提格里尼亚语 ✔️ —
阿尔巴尼亚语托斯克方言 ✔️ —
土耳其语 ✔️ ✔️
维吾尔语 ✔️ —
越南语 ✔️ ✔️

支持的模型

模型 一位说话者 多说话人 语音设计 语音复刻
Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) ✔️ ✔️ ✔️ ✔️
Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) ✔️ ✔️ ✔️ ✔️
Gemini 3.1 Flash TTS 预览版 ✔️ ✔️ — —
Gemini 2.5 Pro 预览版 TTS ✔️ ✔️ — —

何时使用哪种模型

Gemini 3.8 TTS 模型具有完全相同的 API 架构和提示格式,因此您只需更改一个参数即可在它们之间切换:

  • 如果需要优先考虑最高声音保真度、细致的表演 和富有表现力的控制,请使用 Gemini 3.8 Flash TTS (gemini-3.8-flash-tts)。它非常适合工作室级创意工作、复杂的多人对话、大量人声爆发标记、难以发音的词语、区域性或少数民族方言,以及需要稳定的人声和环境音的长篇旁白。
  • 使用 Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) 作为 gemini-3.1-flash-tts-preview 的快速、经济高效的替代方案。它经过优化,可用于大批量生成内容、创建对话式语音智能体级联、实现大声朗读功能、可靠地进行语音复刻,以及处理主要语言的日常单人语音。

迁移指南

从之前的预览版模型(gemini-3.1-flash-tts-preview 或 gemini-2.5-pro-preview-tts)升级到 Gemini 3.8 TTS(gemini-3.8-flash-tts 或 gemini-3.8-flash-lite-tts)时,请查看以下五项主要变更:

  1. 将样式与转写内容分离:将持续的表演、语气、韵律和节奏说明(例如 "whispering"、"out of breath" 或 "speaking slowly")从纯文本移到 speech_metadata.style 中。 请务必将 text 严格保留为逐字转写内容加上内嵌的声乐标记。
  2. 使用语音设计预先设计角色:使用在语音设计中创建的自定义语音替换多段落 "Audio Profile" 或 "Director's Notes" 代码块,然后通过 TTS 请求传递该 voice_... ID,并使用最少的 style 字符串或空字符串。
  3. 使用结构化对话回合:对于多说话人对话,请为每个说话人回合传递一个 part(使用 speech_metadata.speaker),而不是将 Speaker: ... 前缀嵌入单个文本块中。
  4. 使用尖括号表示内嵌语音标记:使用尖括号(<laugh>、<sigh>、<cough>、<breath>、<short pause>)表示时间点上的人声和停顿。避免使用非人声音效标签(例如掌声或砰砰声)。
  5. 考虑单次请求的默认 WAV (AUDIO_WAV) 输出:与 gemini-3.1-flash-tts-preview(默认返回不含标头的原始 PCM AUDIO_L16)不同,Gemini 3.8 TTS 模型在单次请求中返回完整的 WAV (AUDIO_WAV) 音频,其中包含 RIFF 标头(24 kHz、单声道、16 位 PCM):
    • 如果您的代码之前将原始 PCM 字节封装在 WAV 标头中(例如,使用 Python 的 wave 模块或 Node 的 wav 软件包),请移除手动标头封装,并将解码后的音频字节直接写入 .wav 文件。
    • 如果现有流水线需要无标头的原始 PCM、mu-law 或 A-law 音频,请将 response_format.audio.mime_type 明确设置为 "AUDIO_L16"、"AUDIO_MULAW" 或 "AUDIO_ALAW"(例如,在 generateContent 中设置为 {"response_format": {"audio": {"mime_type": "AUDIO_L16"}}},或在 Interactions API 中设置为 {"response_format": {"type": "audio", "mime_type": "audio/l16"}})。请参阅音频输出格式。

提示指南

Gemini 3.8 TTS 模型将输入文本严格视为逐字转写内容。与之前将舞台说明嵌入纯文本中的预览模型不同,Gemini 3.8 TTS 将持续的回合级说明 (speech_metadata) 与时间点内嵌语音标记分开。

样式字段与内嵌标记

按范围拆分性能指令:

  • 回合级交付 (speech_metadata.style):将持续交付属性(例如情绪、韵律、整体节奏或交付风格(如 "whispering"、"out of breath"、"muttering" 或 "sarcastic"))放入 speech_metadata 的 style 字段中。为了在对话轮次中保持角色和性能的稳定性,请在语音设计中预先设计角色设定,并仅使用 style 进行可选的轮次级调整。
  • 时间点事件(内嵌标记):使用尖括号(<cough>、<breath>、<sigh>、<short pause>)将短暂的非语音声音爆发、呼吸或停顿内嵌在转写内容中。使用尖括号 (<...>) 可获得最高音质,并且应仅标记人声,而非非人声的音效。
范围 放置位置 示例
回合级(在整个回合中持续存在) speech_metadata.style "angry tone"、"speaking rapidly"、"out of breath"、"whispers"、"sarcastic"
时间点(在特定字词处发生) 内嵌在 text 中(<...>) "<cough> Thank you all for coming tonight! <throat-clearing> As I was saying..."

节奏和停顿

您可以从以下三个精细程度级别控制节奏和静音:

  • 标点符号和省略号:使用逗号、短划线 (--) 和省略号 (...) 来模拟自然对话中的犹豫。
  • 内嵌暂停标记:在脚本中说话者应暂停的确切位置插入 <short pause> 或 <long pause>: text Hold on, let me think... <short pause> Alright, I've got it.
  • 回合级语速:在 speech_metadata 中设置 "style": "speaking rapidly" 或 "style": "speaking slowly",以控制整个回合的说话速率。

韵律和音调

使用 speech_metadata.style 控制整个对话轮次的韵律、音调和语调(例如 "style": "high pitch, cheerful and excited inflection" 或 "style": "monotone and flat")。如果情绪或韵律在对话中发生变化,请将脚本拆分为单独的轮次,并为每个轮次指定不同的 style 值。

强调方式

在转写内容中将特定字词大写,并结合标点符号和内嵌语音标记,以便在关键字上自然地施加语音重音:

This is a VERY important point!
It was a VERY long day <sigh> ... nobody listens anymore.

爆发性发声和非语音声音

使用尖括号 (<...>) 将非语音的人声内嵌在声音应出现的准确位置。建议的人声标记包括:

<argh> <breath> <heavy breath> <exhales>
<cackle> <cheer> <chuckle>/<chuckles> <cough>
<cry> <gasp> <giggle> <groan>
<growl> <grunt> <grr> <hiss>
<laugh>/<laughter> <moan> <pant> <pff>/<phew>
<scream> <shout> <shriek> <sigh>/<sighs>
<sneeze> <snicker> <snort> <sob>
<throat-clearing> <tsk> <whimper> <whispers>/<whispering>
<yawn> <short pause> <long pause>

后通道和重叠语音

在多说话人对话中,将听者的反应用竖线字符 (|reaction|) 括起来,放在说话人的回合内,以创建自然的后通道或重叠的语音,而无需为每个反应另起一个回合。

  • 简短的后通道交流:在主动发言者的发言轮次中,添加简短的听众反应(|oh hmm|、|oh really?|、|absolutely|):
    • 第 1 轮(发言者 A): "So the launch is Thursday |oh hmm| Are we actually ready?"
    • 第 2 轮(演讲者 B): "Ready enough |oh really?| The last blocker cleared this morning."
    • 第 3 轮(演讲者 A): "Then let's ship it |absolutely| and watch the dashboards."
  • 重叠和交错的语音:使用多个竖线分隔符来模拟两位发言者同时或交错的语音(最好与 gemini-3.8-flash-tts 搭配使用):
    • 同步倒计时/合唱: "Let's surprise him on three |ok| ready?",然后是 "one. two. three. |happy| happy |birthday| birthday!"
    • 完全重叠的音箱: "Hello |oh| there |my| it |goodness| must |gracious| be |would| almost |you| time |look| for |at that| dinner"

各代之间的一致性以及应避免的事项

请遵循以下准则,以确保在对话轮次之间保持稳定的声音身份:

  • 在语音设计中提前设计角色,而不是使用长样式块: 长篇 "Audio Profile" 段落和多项目符号 "Director's Notes" 是从早期模型沿用下来的,也是导致语音漂移的最常见原因。 在语音设计中提前运用同样的创意直觉,生成持久的自定义 voice_... 人格,然后在 TTS 调用中沿用该语音 ID。
  • 依靠语音参考实现稳定性(省略元指令):Gemini 3.8 TTS 模型经过训练,可先锚定音频参考。 请勿添加指示模型保持声音稳定的指令(例如 "do not switch speaker identity" 或 "maintain identical timbre")- 额外的提示文本会增加漂移。舍弃不必要的风格指令,让模型在语音参考提供的稳定点附近自然变化。
  • 请勿尝试更改 style 中不可变的说话人特征:避免在 speech_metadata.style 中添加年龄、性别、姓名或永久性口音变化。 您可以从扩展语音库中选择一种地区性语音,也可以使用语音设计功能创建一种语音。
  1. 一次性打造角色:在语音设计中创建角色,或从扩展语音库中选择与目标语言和角色相符的区域性语音。
  2. 撰写包含语流不畅的自然口语转写内容:为了尽可能自然,请将 text 撰写为真实的口语转写内容,包括自然的对话语流不畅和犹豫(例如,"Oh uh yeah I think... hm, so that's interesting")。
  3. 先测试纯 TTS:先使用空的 style 字段合成脚本,大多数请求根本不需要 style 指令。
  4. 仅为调整添加简短的 style 提示:仅为需要进行特定投放调整的轮次添加简明的 style 字符串(例如 "casual, friendly" 或 "muttering, then reassuring"),并在需要保持一致基准时,在各个轮次中重复使用该简短字符串。

多轮对话和语音代理

构建实时对话式语音代理或多轮对话应用时:

  • 在 LLM 文本块到达时,每次轮次进行一次 TTS 调用。
  • 让配置的 voice(预构建、设计的 voice_... 或复制的 voice_... / voicekey_...)在对话轮次之间传递发言者的身份,而无需在每个轮次中重新发送长字符角色。
  • 将每轮对话的 style 字段留空,或为整个对话发送一个简短的常量字符串(例如 "casual, friendly")。
  • 将较长的智能体回答拆分为较短的对话轮次,而不是使用更强烈的风格提示。

流式语音生成

您可以一边合成音频,一边通过模型进行流式传输。与返回包含 RIFF 标头的完整 WAV 文件的单次请求不同,流式请求默认返回不含标头的原始 16 位有符号小端字节序线性 PCM(AUDIO_L16 / audio/L16;codec=pcm;rate=24000、24 kHz、单声道)块,因此音频块可以连续播放或串联,而无需容器标头:

Python

from google import genai

client = genai.Client()

response_stream = client.models.generate_content_stream(
    model="gemini-3.8-flash-tts",
    contents=[{
        "role": "user",
        "parts": [{
            "text": "Have a wonderful day!",
            "speech_metadata": {"style": "cheerful and friendly"},
        }],
    }],
    config={
        "response_modalities": ["AUDIO"],
        "speech_config": {
            "voice_config": {"voice": "Kore"}
        },
    },
)

for chunk in response_stream:
    try:
        data = chunk.candidates[0].content.parts[0].inline_data.data
        # data contains raw PCM bytes (24kHz, 1-channel, 16-bit)
    except (IndexError, AttributeError):
        pass

JavaScript

import {GoogleGenAI} from '@google/genai';

async function main() {
   const ai = new GoogleGenAI({});

   const responseStream = await ai.models.generateContentStream({
      model: 'gemini-3.8-flash-tts',
      contents: [{
         role: 'user',
         parts: [{
            text: 'Have a wonderful day!',
            speechMetadata: { style: 'cheerful and friendly' },
         }],
      }],
      config: {
         responseModalities: ['AUDIO'],
         speechConfig: {
            voiceConfig: { voice: 'Kore' },
         },
      },
   });

   for await (const chunk of responseStream) {
      const data = chunk.candidates?.[0]?.content?.parts?.[0]?.inlineData?.data;
      if (data) {
         const audioBuffer = Buffer.from(data, 'base64');
         // Process the audio buffer
      }
   }
}
await main();

REST

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash-tts:streamGenerateContent" \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
        "contents": [{
          "role": "user",
          "parts": [{
            "text": "Have a wonderful day!",
            "speech_metadata": {
              "style": "cheerful and friendly"
            }
          }]
        }],
        "generationConfig": {
          "responseModalities": ["AUDIO"],
          "speechConfig": {
            "voiceConfig": {
              "voice": "Kore"
            }
          }
        }
    }'

音频输出格式

Gemini 3.8 TTS 模型使用不同的默认音频格式,具体取决于请求是单次请求还是流式请求:

  • 一元请求 (models.generate_content):返回完整的 WAV (AUDIO_WAV) 音频,其中包含 RIFF 标头(24 kHz、单声道、16 位有符号小端字节序 PCM)。您可以将解码后的音频字节直接写入 .wav 文件,而无需手动添加 WAV 容器。
  • 流式传输请求(models.generate_content_stream / streamGenerateContent):默认返回无标头的原始线性 PCM (AUDIO_L16) 块(24 kHz、单声道、16 位有符号小端字节序 PCM),以便可以连续流式传输或串联块,而无需在每个块上添加容器标头。

您可以使用 generationConfig.responseFormat.audio 替换输出音频编码和采样率:

mimeType 值 格式 说明
"AUDIO_WAV" (一元默认) WAV (audio/wav) 包含 RIFF 标头的完整 WAV 文件(24 kHz、单声道、16 位 PCM)。
"AUDIO_L16" (流式默认) 线性 PCM (audio/l16) 无标头的原始 16 位有符号小端序线性 PCM。最适合流式传输、自定义音频流水线或串联多轮对话片段。
"AUDIO_MULAW" μ-law (audio/basic / audio/mulaw) G.711 μ-law 压扩音频。常用于北美和日本的电话系统 (8 kHz)。
"AUDIO_ALAW" A-law (audio/alaw) G.711 A-law 压扩音频。常用于欧洲和国际电话 (8 kHz)。

您还可以选择指定 sampleRate(例如 24000、16000 或 8000 Hz;默认值为 24000 Hz)。

以下示例请求以 24 kHz 采样率获取无标头的原始 16 位 PCM (AUDIO_L16):

Python

from google import genai

client = genai.Client()

response = client.models.generate_content(
    model="gemini-3.8-flash-tts",
    contents=[{
        "role": "user",
        "parts": [{
            "text": "Have a wonderful day!",
            "speech_metadata": {"style": "cheerful and friendly"},
        }],
    }],
    config={
        "response_modalities": ["AUDIO"],
        "response_format": {
            "audio": {
                "mime_type": "AUDIO_L16",
                "sample_rate": 24000,
            }
        },
        "speech_config": {
            "voice_config": {"voice": "Kore"}
        },
    },
)

data = response.candidates[0].content.parts[0].inline_data.data
with open("out.pcm", "wb") as f:
    f.write(data)

JavaScript

import {GoogleGenAI} from '@google/genai';
import * as fs from 'node:fs';

async function main() {
   const ai = new GoogleGenAI({});

   const response = await ai.models.generateContent({
      model: 'gemini-3.8-flash-tts',
      contents: [{
         role: 'user',
         parts: [{
            text: 'Have a wonderful day!',
            speechMetadata: { style: 'cheerful and friendly' },
         }],
      }],
      config: {
         responseModalities: ['AUDIO'],
         responseFormat: {
            audio: {
               mimeType: 'AUDIO_L16',
               sampleRate: 24000,
            },
         },
         speechConfig: {
            voiceConfig: { voice: 'Kore' },
         },
      },
   });

   const data = response.candidates?.[0]?.content?.parts?.[0]?.inlineData?.data;
   const audioBuffer = Buffer.from(data, 'base64');

   fs.writeFileSync('out.pcm', audioBuffer);
}
await main();

REST

curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash-tts:generateContent" \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
        "contents": [{
          "role": "user",
          "parts": [{
            "text": "Have a wonderful day!",
            "speech_metadata": {
              "style": "cheerful and friendly"
            }
          }]
        }],
        "generationConfig": {
          "responseModalities": ["AUDIO"],
          "responseFormat": {
            "audio": {
              "mimeType": "AUDIO_L16",
              "sampleRate": 24000
            }
          },
          "speechConfig": {
            "voiceConfig": {
              "voice": "Kore"
            }
          }
        }
    }' | jq -r '.candidates[0].content.parts[0].inlineData.data' | \
          base64 --decode > out.pcm

限制

  • TTS 模型接受纯文本输入,并生成纯音频输出。
  • 单次请求多说话人生成 (multiSpeakerVoiceConfig) 最多支持 2 位说话人,且使用预建语音。若要在多角色对话中组合自定义设计 (voice_...) 或复制 (voice_... / voicekey_...) 的声音,请单独合成每个说话者的发言。 由于一元请求默认返回带有 44 字节 RIFF 标头的 audio/wav,因此请请求原始 PCM (AUDIO_L16) 或从每个回合中剥离 WAV 标头,然后再连接 24 kHz PCM 音频帧。
  • 自定义语音存储空间限制和 TTL:
    • 有状态的声音(store=True,提示或复制):每个项目最多 200 个声音,1 年 TTL(存留时间)。
    • 无状态语音密钥(store=False、voicekey_...): 7 天的 TTL(存留时间)。
  • 如需了解语言覆盖范围,请参阅支持的语言部分。

后续步骤