Gemini API 可使用 Gemini 文字轉語音 (TTS) 生成功能,將文字輸入內容轉換為單人或多人語音。文字轉語音生成功能可控,也就是說,您可以結合結構化回合中繼資料 (speech_metadata) 和內嵌語音標記,引導音訊的風格、口音、速度和語氣。
TTS 功能與Live API 提供的語音生成功能不同,後者專為互動式非結構化音訊,以及多模態輸入和輸出內容而設計。Live API 擅長處理動態對話情境,而 Gemini API 的 TTS 則適用於需要準確朗讀文字,並精細控制風格和聲音的情境,例如生成 Podcast 或有聲書。
本指南說明如何使用 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 模型將文字轉換為單人語音,請在 input 中傳遞逐字稿,使用 speech_metadata 註解附加回合層級的樣式,並在 generation_config.speech_config 中設定語音。您可以從預先建構的語音選項、擴充語音庫 (GET /v1beta/voices)、自訂語音設計 ID (voice_...) 或語音複製 ID (voice_... 或選用的無狀態 voicekey_...) 中選擇語音。
這個範例會將模型預設的 WAV 輸出音訊 (audio/wav) 直接儲存至檔案:
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": "Have a wonderful day!",
"annotations": [{
"type": "speech_metadata",
"style": "cheerful 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))
JavaScript
import * as fs from 'node:fs';
import {GoogleGenAI} from '@google/genai';
async function main() {
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
model: 'gemini-3.8-flash-tts',
input: [{
type: 'user_input',
content: [{
type: 'text',
text: 'Have a wonderful day!',
annotations: [{
type: 'speech_metadata',
style: 'cheerful and friendly',
}],
}],
}],
response_format: { type: 'audio' },
generation_config: {
speech_config: [
{ voice: 'Kore' },
],
},
});
const audioBuffer = Buffer.from(interaction.output_audio.data, 'base64');
fs.writeFileSync('out.wav', audioBuffer);
}
await main();
Go
package main
import (
"context"
"encoding/base64"
"encoding/binary"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func saveWaveFile(filename string, pcmData []byte) error {
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
sampleRate := uint32(24000)
numChannels := uint16(1)
bitsPerSample := uint16(16)
byteRate := sampleRate * uint32(numChannels) * uint32(bitsPerSample/8)
blockAlign := numChannels * (bitsPerSample / 8)
dataSize := uint32(len(pcmData))
f.WriteString("RIFF")
binary.Write(f, binary.LittleEndian, uint32(36+dataSize))
f.WriteString("WAVEfmt ")
binary.Write(f, binary.LittleEndian, uint32(16))
binary.Write(f, binary.LittleEndian, uint16(1))
binary.Write(f, binary.LittleEndian, numChannels)
binary.Write(f, binary.LittleEndian, sampleRate)
binary.Write(f, binary.LittleEndian, byteRate)
binary.Write(f, binary.LittleEndian, blockAlign)
binary.Write(f, binary.LittleEndian, bitsPerSample)
f.WriteString("data")
binary.Write(f, binary.LittleEndian, dataSize)
_, err = f.Write(pcmData)
return err
}
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
generationConfig := &interactions.GenerationConfig{
SpeechConfig: genai.Ptr(interactions.NewSpeechConfigUnion([]interactions.SpeechConfig{
{Voice: genai.Ptr("Kore")},
})),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.1-flash-tts-preview"),
Input: interactions.NewInteractionsInput("Say cheerfully: Have a wonderful day!"),
ResponseFormat: genai.Ptr(interactions.NewCreateModelInteractionResponseFormat(
interactions.NewResponseFormat(interactions.AudioResponseFormat{}),
)),
GenerationConfig: generationConfig,
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputAudio != nil && res.Interaction.OutputAudio.Data != nil {
pcmBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputAudio.Data)
if err != nil {
log.Fatal(err)
}
if err := saveWaveFile("out.wav", pcmBytes); err != nil {
log.Fatal(err)
}
}
}
REST
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-tts",
"input": [{
"type": "user_input",
"content": [{
"type": "text",
"text": "Have a wonderful day!",
"annotations": [{
"type": "speech_metadata",
"style": "cheerful and friendly"
}]
}]
}],
"response_format": {
"type": "audio"
},
"generation_config": {
"speech_config": [
{ "voice": "Kore" }
]
}
}'
您可以使用 interaction.output_audio 屬性擷取生成的音訊資料,該屬性會傳回最後生成的音訊區塊。如要瞭解便利性屬性,請參閱「互動總覽」。
多位說話者 TTS
如果是多位說話者的對話,請在 speech_config.speakers 中設定兩位說話者,並將每一輪對話當做個別文字項目傳遞,並附上 speech_metadata 註解,指定 speaker 和選用的輪次層級 style。使用 "mode": "conversational" 進行自然輪流對話:
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": "How's it going today Jane?",
"annotations": [{
"type": "speech_metadata",
"speaker": "Joe",
"style": "cheerful and friendly",
}],
},
{
"type": "text",
"text": "Not too bad, how about you? Ready to test these new voices?",
"annotations": [{
"type": "speech_metadata",
"speaker": "Jane",
"style": "calm and relaxed",
}],
},
],
}],
response_format={"type": "audio"},
generation_config={
"speech_config": {
"mode": "conversational",
"speakers": [
{"speaker": "Joe", "voice": "Puck"},
{"speaker": "Jane", "voice": "Kore"},
],
}
},
)
with open("out.wav", "wb") as f:
f.write(base64.b64decode(interaction.output_audio.data))
JavaScript
import * as fs from 'node:fs';
import {GoogleGenAI} from '@google/genai';
async function main() {
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
model: 'gemini-3.8-flash-tts',
input: [{
type: 'user_input',
content: [
{
type: 'text',
text: "How's it going today Jane?",
annotations: [{
type: 'speech_metadata',
speaker: 'Joe',
style: 'cheerful and friendly',
}],
},
{
type: 'text',
text: 'Not too bad, how about you? Ready to test these new voices?',
annotations: [{
type: 'speech_metadata',
speaker: 'Jane',
style: 'calm and relaxed',
}],
},
],
}],
response_format: { type: 'audio' },
generation_config: {
speech_config: {
mode: 'conversational',
speakers: [
{ speaker: 'Joe', voice: 'Puck' },
{ speaker: 'Jane', voice: 'Kore' },
],
},
},
});
const audioBuffer = Buffer.from(interaction.output_audio.data, 'base64');
fs.writeFileSync('out.wav', audioBuffer);
}
await main();
Go
package main
import (
"context"
"encoding/base64"
"encoding/binary"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func saveWaveFile(filename string, pcmData []byte) error {
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
sampleRate := uint32(24000)
numChannels := uint16(1)
bitsPerSample := uint16(16)
byteRate := sampleRate * uint32(numChannels) * uint32(bitsPerSample/8)
blockAlign := numChannels * (bitsPerSample / 8)
dataSize := uint32(len(pcmData))
f.WriteString("RIFF")
binary.Write(f, binary.LittleEndian, uint32(36+dataSize))
f.WriteString("WAVEfmt ")
binary.Write(f, binary.LittleEndian, uint32(16))
binary.Write(f, binary.LittleEndian, uint16(1))
binary.Write(f, binary.LittleEndian, numChannels)
binary.Write(f, binary.LittleEndian, sampleRate)
binary.Write(f, binary.LittleEndian, byteRate)
binary.Write(f, binary.LittleEndian, blockAlign)
binary.Write(f, binary.LittleEndian, bitsPerSample)
f.WriteString("data")
binary.Write(f, binary.LittleEndian, dataSize)
_, err = f.Write(pcmData)
return err
}
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
prompt := "TTS the following conversation between Joe and Jane:\n" +
"Joe: How's it going today Jane?\n" +
"Jane: Not too bad, how about you?"
generationConfig := &interactions.GenerationConfig{
SpeechConfig: genai.Ptr(interactions.NewSpeechConfigUnion([]interactions.SpeechConfig{
{Speaker: genai.Ptr("Joe"), Voice: genai.Ptr("Kore")},
{Speaker: genai.Ptr("Jane"), Voice: genai.Ptr("Puck")},
})),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.1-flash-tts-preview"),
Input: interactions.NewInteractionsInput(prompt),
ResponseFormat: genai.Ptr(interactions.NewCreateModelInteractionResponseFormat(
interactions.NewResponseFormat(interactions.AudioResponseFormat{}),
)),
GenerationConfig: generationConfig,
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputAudio != nil && res.Interaction.OutputAudio.Data != nil {
pcmBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputAudio.Data)
if err != nil {
log.Fatal(err)
}
if err := saveWaveFile("out.wav", pcmBytes); err != nil {
log.Fatal(err)
}
}
}
REST
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-tts",
"input": [{
"type": "user_input",
"content": [
{
"type": "text",
"text": "How'\''s it going today Jane?",
"annotations": [{
"type": "speech_metadata",
"speaker": "Joe",
"style": "cheerful and friendly"
}]
},
{
"type": "text",
"text": "Not too bad, how about you? Ready to test these new voices?",
"annotations": [{
"type": "speech_metadata",
"speaker": "Jane",
"style": "calm and relaxed"
}]
}
]
}],
"response_format": {
"type": "audio"
},
"generation_config": {
"speech_config": {
"mode": "conversational",
"speakers": [
{ "speaker": "Joe", "voice": "Puck" },
{ "speaker": "Jane", "voice": "Kore" }
]
}
}
}'
使用中繼資料和標記控制語音風格
Gemini 3.8 TTS 會將 text 欄位視為逐字稿。如要控制朗讀方式,但不要朗讀舞台指示,請依範圍劃分指令:
- 持續的輪流層級傳遞 (
speech_metadata.style):將適用於整個輪流的語氣、傳遞風格、韻律、節奏和音量放在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...")。
如需完整最佳做法,請參閱提示指南。
Go
package main
import (
"context"
"log"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
transcriptRes, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.8-flash"),
Input: interactions.NewInteractionsInput(
"Generate a short transcript around 100 words that reads " +
"like it was clipped from a podcast by excited herpetologists. " +
"The hosts names are Dr. Anya and Liam.",
),
}),
})
if err != nil {
log.Fatal(err)
}
var transcript string
if transcriptRes.Interaction.OutputText != nil {
transcript = *transcriptRes.Interaction.OutputText
}
generationConfig := &interactions.GenerationConfig{
SpeechConfig: genai.Ptr(interactions.NewSpeechConfigUnion([]interactions.SpeechConfig{
{Speaker: genai.Ptr("Dr. Anya"), Voice: genai.Ptr("Kore")},
{Speaker: genai.Ptr("Liam"), Voice: genai.Ptr("Puck")},
})),
}
ttsRes, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.1-flash-tts-preview"),
Input: interactions.NewInteractionsInput(transcript),
ResponseFormat: genai.Ptr(interactions.NewCreateModelInteractionResponseFormat(
interactions.NewResponseFormat(interactions.AudioResponseFormat{}),
)),
GenerationConfig: generationConfig,
}),
})
if err != nil {
log.Fatal(err)
}
_ = ttsRes
}
串流語音生成
您可以設定 stream: true,在生成音訊時串流播放。與一元要求不同 (會傳回含有 RIFF 標頭的完整 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-tts",
input=[{
"type": "user_input",
"content": [{
"type": "text",
"text": "Have a wonderful day!",
"annotations": [{
"type": "speech_metadata",
"style": "cheerful and friendly",
}],
}],
}],
response_format={"type": "audio"},
generation_config={
"speech_config": [
{"voice": "Kore"},
]
},
stream=True,
)
for event in stream:
if event.event_type == "step.delta":
if event.delta.type == "audio":
audio_data = base64.b64decode(event.delta.data)
# Process the audio chunk (e.g. play it or write to a file)
JavaScript
import {GoogleGenAI} from '@google/genai';
async function main() {
const client = new GoogleGenAI({});
const stream = await client.interactions.create({
model: 'gemini-3.8-flash-tts',
input: [{
type: 'user_input',
content: [{
type: 'text',
text: 'Have a wonderful day!',
annotations: [{
type: 'speech_metadata',
style: 'cheerful and friendly',
}],
}],
}],
response_format: { type: 'audio' },
generation_config: {
speech_config: [
{ voice: 'Kore' },
],
},
stream: true,
});
for await (const event of stream) {
if (event.event_type === 'step.delta') {
if (event.delta.type === 'audio') {
const audioBuffer = Buffer.from(event.delta.data, 'base64');
// Process the audio buffer
}
}
}
}
await main();
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
--no-buffer \
-d '{
"model": "gemini-3.8-flash-tts",
"input": [{
"type": "user_input",
"content": [{
"type": "text",
"text": "Have a wonderful day!",
"annotations": [{
"type": "speech_metadata",
"style": "cheerful and friendly"
}]
}]
}],
"response_format": {
"type": "audio"
},
"generation_config": {
"speech_config": [
{ "voice": "Kore" }
]
},
"stream": true
}'
音訊輸出格式
Gemini 3.8 TTS 模型會根據要求是 unary 或串流,使用不同的預設音訊格式:
- 一元要求 (
stream=False):傳回完整的 WAV (audio/wav) 音訊,並附上標準 RIFF 標頭 (24 kHz、單聲道、16 位元帶正負號的小端序 PCM)。您可以直接將解碼後的音訊位元組儲存至.wav檔案,不必手動預先加入 WAV 標頭。 - 串流要求 (
stream=True):預設傳回無標頭的原始線性 PCM (audio/l16) 區塊 (24 kHz、單聲道、16 位元帶正負號的小端序 PCM),因此區塊可以持續串流或串連,每個區塊都不含容器標頭。
如要要求使用其他音訊編碼或取樣率,請在 response_format 內設定 mime_type 和選用的 sample_rate:
| 格式 | mime_type值 |
說明 |
|---|---|---|
| WAV (一元預設值) | "audio/wav" |
未壓縮的 WAV 檔案,並包含 RIFF 標頭 (16 位元帶正負號的小端序 PCM、單聲道、預設為 24 kHz)。一元要求的預設值。 |
| 原始 PCM (L16) (串流預設) | "audio/l16" |
未壓縮、無標頭的 16 位元帶正負號小端序線性 PCM 音訊 (24 kHz,單聲道)。串流要求的預設值。 |
| Mu-law | "audio/mulaw" |
8 位元 G.711 mu-law 編碼音訊 (常用於北美和日本的電話/IVR 系統)。 |
| A-law | "audio/alaw" |
8 位元 G.711 A-law 編碼音訊 (常用於歐洲和國際電話系統)。 |
你也可以指定以赫茲為單位的 sample_rate (例如 24000、16000 或 8000)。
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": "Have a wonderful day!",
"annotations": [{
"type": "speech_metadata",
"style": "cheerful and friendly",
}],
}],
}],
response_format={
"type": "audio",
"mime_type": "audio/l16", # "audio/wav" (default), "audio/l16", "audio/mulaw", or "audio/alaw"
"sample_rate": 24000,
},
generation_config={
"speech_config": [
{"voice": "Kore"},
]
},
)
with open("out.pcm", "wb") as f:
f.write(base64.b64decode(interaction.output_audio.data))
JavaScript
import * as fs from 'node:fs';
import {GoogleGenAI} from '@google/genai';
async function main() {
const client = new GoogleGenAI({});
const interaction = await client.interactions.create({
model: 'gemini-3.8-flash-tts',
input: [{
type: 'user_input',
content: [{
type: 'text',
text: 'Have a wonderful day!',
annotations: [{
type: 'speech_metadata',
style: 'cheerful and friendly',
}],
}],
}],
response_format: {
type: 'audio',
mime_type: 'audio/l16', // 'audio/wav' (default), 'audio/l16', 'audio/mulaw', or 'audio/alaw'
sample_rate: 24000,
},
generation_config: {
speech_config: [
{ voice: 'Kore' },
],
},
});
const audioBuffer = Buffer.from(interaction.output_audio.data, 'base64');
fs.writeFileSync('out.pcm', audioBuffer);
}
await main();
Go
package main
import (
"context"
"encoding/base64"
"log"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
generationConfig := &interactions.GenerationConfig{
SpeechConfig: genai.Ptr(interactions.NewSpeechConfigUnion([]interactions.SpeechConfig{
{Voice: genai.Ptr("Kore")},
})),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-3.1-flash-tts-preview"),
Input: interactions.NewInteractionsInput("Say cheerfully: Have a wonderful day!"),
ResponseFormat: genai.Ptr(interactions.NewCreateModelInteractionResponseFormat(
interactions.NewResponseFormat(interactions.AudioResponseFormat{}),
)),
GenerationConfig: generationConfig,
Stream: genai.Ptr(true),
}),
})
if err != nil {
log.Fatal(err)
}
stream := res.InteractionSSEStreamEvent
defer stream.Close()
for stream.Next() {
event := stream.Value()
if stepDelta := event.GetDataStepDelta(); stepDelta != nil {
if audioDelta := stepDelta.GetDeltaAudio(); audioDelta != nil && audioDelta.Data != nil {
audioData, err := base64.StdEncoding.DecodeString(*audioDelta.Data)
if err != nil {
log.Fatal(err)
}
// Process the audio chunk (e.g. play it or write to a file)
_ = audioData
}
}
}
if err := stream.Err(); err != nil {
log.Fatal(err)
}
}
REST
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-tts",
"input": [{
"type": "user_input",
"content": [{
"type": "text",
"text": "Have a wonderful day!",
"annotations": [{
"type": "speech_metadata",
"style": "cheerful and friendly"
}]
}]
}],
"response_format": {
"type": "audio",
"mime_type": "audio/l16",
"sample_rate": 24000
},
"generation_config": {
"speech_config": [
{ "voice": "Kore" }
]
}
}'
語音選項
Gemini 3.8 TTS 支援四種選取或建立語音的方式:
- 預建的 Studio 語音:下表列出 30 種精選語音。
- 擴充語音庫:提供數百種其他語言、口音和角色原型,可使用
client.voices.list()(GET /v1beta/voices) 存取。 - 語音設計:在 Google AI Studio 中,透過自然語言描述生成自訂語音角色,或使用
POST /v1beta/voices(type="prompted",這會傳回持續性voice_...ID 和sample_audioWAV 預覽,位於CreateVoice和GetVoice)。 - 語音複製:在 Google AI Studio 中,或使用
POST /v1beta/voices(type="replicated"、預設為持續性store=True或選用的無狀態store=False),從參考和同意音訊複製講者的聲音。
自訂語音限制和存留時間
| 語音類型 | 儲存模式 | 配額 / 限制 | 保留時間 (TTL) |
|---|---|---|---|
有狀態語音 (voice_...,提示或複製) |
store=True |
每個專案 200 個聲音 (提示和複製的聲音共用) | 1 年 |
無狀態語音金鑰 (voicekey_...,已複製) |
store=False |
用戶端管理 | 7 天 |
預先建構的聲音
| Zephyr - Bright | Puck - Upbeat | Charon - 實用 |
| 韓國 -- Firm | Fenrir - 興奮 | Leda - 年輕 |
| Orus -- Firm | Aoede -- Breezy | Callirrhoe - 隨和 |
| Autonoe -- Bright | Enceladus -- Breathy | Iapetus -- Clear |
| Umbriel -- Easy-going | Algieba -- Smooth | Despina -- Smooth |
| Erinome -- Clear | Algenib - Gravelly | Rasalgethi -- 實用資訊 |
| Laomedeia - Upbeat | Achernar -- Soft | Alnilam - Firm |
| Schedar -- Even | Gacrux -- Mature | Pulcherrima - Forward |
| Achird - 友善 | Zubenelgenubi -- Casual | Vindemiatrix -- Gentle |
| Sadachbia -- Lively | 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 或 UN 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) 支援 101 種語言:
| 語言 | 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 TTS 模型遷移至 Gemini 3.8 TTS:
- 將回合層級的指示移至
speech_metadata:Gemini 3.8 TTS 會將輸入文字嚴格視為逐字稿。將持續傳送指令 (style,例如"whispering"、"out of breath"或"speaking slowly") 和發言者標籤 (speaker) 移至結構化speech_metadata註解,而不是將舞台指示嵌入轉錄稿文字。 - 只針對特定時間點的聲音事件使用角括號內嵌標記:使用角括號 (例如
<laugh>、<sigh>、<cough>、<breath>或<short pause>),將短暫的非語音發聲和停頓內嵌在轉錄稿中。請避免使用音效標記 (例如掌聲或重擊聲),並將傳達方式放在speech_metadata.style中。 - 在多位說話者要求中,為每個輪流發言指定
speaker:多位說話者要求中的每個輪流發言,都必須在speech_metadata內明確包含speaker,且與其中一位已設定的說話者相符。 - 預先使用 Voice 設計設計角色:以 Voice 設計建立自訂語音,然後將多段落
"Audio Profile"或"Director's Notes"區塊替換為該語音,並透過 TTS 要求傳送voice_...ID,搭配最少或空白的style字串。 - 單元要求預設會輸出 WAV (
audio/wav) 格式:與gemini-3.1-flash-tts-preview和更早的 TTS 模型不同 (預設會傳回無標頭的原始 PCMaudio/l16),Gemini 3.8 TTS 預設會傳回具有標準 RIFF 標頭的 WAV 音訊 (audio/wav),以供單元要求使用。- 如果您的程式碼先前將原始 PCM 位元組包裝在 WAV 標頭中 (例如使用 Python 的
wave模組或ffmpeg),請移除手動標頭包裝函式,並將傳回的位元組直接寫入.wav檔案。 - 如果管道需要無標頭的原始 PCM、mu-law 或 A-law 音訊,請將
response_format明確設為"audio/l16"、"audio/mulaw"或"audio/alaw"。請參閱「音訊輸出格式」。
- 如果您的程式碼先前將原始 PCM 位元組包裝在 WAV 標頭中 (例如使用 Python 的
提示指南
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."
- 第 1 輪 (講者 A):
- 重疊和交錯的語音:使用多個管道區隔,模擬兩位講者同時或交錯說話 (最適合搭配
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中加入年齡、性別、姓名或永久口音變化。請改為從擴充語音庫中選擇區域性語音,或使用「語音設計」建立語音。
建議工作流程
- 建立角色一次:在「語音設計」中建立角色,或從擴充語音庫中選取符合目標語言和角色的區域語音。
- 撰寫自然口語轉錄稿,包含語病:為求盡可能自然,請撰寫
text時,包含自然對話中的語病和猶豫 (例如"Oh uh yeah I think... hm, so that's interesting")。 - 先測試一般 TTS:先使用空白的
style欄位合成轉錄稿,大多數要求完全不需要style指令。 - 只為微調新增簡短
style提示:只為需要特定傳送調整的輪次新增簡潔的style字串 (例如"casual, friendly"或"muttering, then reassuring"),並在需要一致基準時,在各輪次重複使用該簡短字串。
多輪對話和語音代理程式
建構即時對話式語音代理或多輪應用程式時:
- 在 LLM 文字區塊抵達時,每回合進行一次 TTS 呼叫。
- 讓已設定的
voice(預先建構、設計voice_...或複製voice_.../voicekey_...) 在對話輪流進行時,持續傳達說話者的身分,不必在每一輪都重新傳送長篇的角色設定。 - 將每回合的
style欄位留空,或為整段對話傳送一個簡短的常數字串 (例如"casual, friendly")。 - 將服務專員的長篇回覆分成較短的回覆,而不是使用更強烈的風格提示。
限制
- TTS 模型只接受文字輸入,並只生成音訊輸出內容。
- 單一要求多位說話者生成 (
multiSpeakerVoiceConfig/ multi-speakerspeakers) 最多支援 2 位說話者使用預建語音。 如要在多個角色的對話中結合自訂設計 (voice_...) 或複製 (voicekey_...) 的聲音,請分別合成每個說話者的語音,然後串連 24 kHz PCM 音訊影格。 - 自訂語音儲存空間限制和存留時間:
- 有狀態的聲音 (
store=True、提示或複製):每個專案最多 200 個聲音,存留時間 (TTL) 為 1 年。 - 無狀態語音金鑰 (
store=False、voicekey_...): 7 天 TTL (存留時間)。
- 有狀態的聲音 (
- 如要瞭解支援的語言,請參閱「支援的語言」一節。
後續步驟
- 使用語音設計,以自然語言建立自訂聲音角色。
- 在語音複製功能中複製現有語音。
- 在 Gemini 3.8 Flash TTS 和 Gemini 3.8 Flash-Lite TTS 模型頁面上比較模型規格。
- 使用 Live API 探索互動式雙向音訊。