Pembuatan text-to-speech (TTS)

Gemini API dapat mengubah input teks menjadi audio satu pembicara atau beberapa pembicara menggunakan kemampuan pembuatan text-to-speech (TTS) Gemini. Pembuatan text-to-speech dapat dikontrol, yang berarti Anda dapat menggabungkan metadata giliran terstruktur (speech_metadata) dan tag vokal inline untuk memandu gaya, aksen, kecepatan, dan nada audio.

Kemampuan TTS berbeda dengan pembuatan ucapan yang disediakan melalui Live API, yang dirancang untuk audio interaktif, tidak terstruktur, serta input dan output multimodal. Meskipun Live API unggul dalam konteks percakapan dinamis, TTS melalui Gemini API disesuaikan untuk skenario yang memerlukan pembacaan teks yang tepat dengan kontrol yang mendetail atas gaya dan suara, seperti pembuatan podcast atau buku audio.

Panduan ini menunjukkan cara membuat audio satu penutur dan multi-penutur dari teks menggunakan Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) dan Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts).

Sebelum memulai

Pastikan Anda menggunakan model TTS Gemini yang tercantum di bagian Model yang didukung, dan upgrade ke Google GenAI SDK terbaru (google-genai >= 2.25.0 untuk Python atau @google/genai >= 2.24.0 untuk JavaScript/TypeScript) atau gunakan REST API. Untuk hasil yang optimal, tinjau Kapan harus menggunakan model tertentu guna memilih model terbaik untuk workload Anda.

Anda mungkin perlu menguji model Gemini TTS di AI Studio sebelum mulai membangun.

TTS satu penutur

Untuk mengonversi teks menjadi audio satu penutur dengan model TTS Gemini 3.8, teruskan transkrip verbatim di input, lampirkan gaya tingkat giliran menggunakan anotasi speech_metadata, dan konfigurasikan suara Anda di generation_config.speech_config. Anda dapat memilih suara dari Opsi suara bawaan, Extended Voice Library (GET /v1beta/voices), ID Desain suara kustom (voice_...), atau ID Replikasi suara (voice_..., atau voicekey_... stateless opsional).

Contoh ini menyimpan audio output WAV default (audio/wav) dari model langsung ke file:

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();

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" }
      ]
    }
  }' | jq -r '[.steps[] | select(.type=="model_output") | .content[] | select(.type=="audio")] | last | .data' | base64 --decode > out.wav

Di SDK Python dan JavaScript, Anda dapat mengambil data audio yang dihasilkan dengan menggunakan properti praktis interaction.output_audio, yang menampilkan blok audio terakhir yang dihasilkan (dalam respons JSON REST mentah, audio berenkode base64 disimpan di steps[].content[].data). Untuk mengetahui detail tentang properti praktis, lihat Ringkasan interaksi.

TTS multi-penutur

Untuk dialog multi-pembicara, konfigurasikan dua pembicara di speech_config.speakers dan teruskan setiap giliran sebagai item teks terpisah dengan anotasi speech_metadata yang menentukan speaker dan style tingkat giliran opsional. Perhatikan bahwa speech_config menerima array ([{"voice": "..."}]) untuk pembuatan satu penutur dan objek ({"speakers": [...]}) untuk pembuatan multi-penutur:

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": {
            "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: {
            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();

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" }
        ]
      }
    }
  }'

Mengontrol gaya ucapan dengan metadata dan tag

Gemini 3.8 TTS memperlakukan kolom text secara ketat sebagai transkrip verbatim. Untuk mengontrol penyampaian tanpa membacakan petunjuk panggung, bagi petunjuk Anda berdasarkan cakupan:

  • Penayangan tingkat giliran yang berkelanjutan (speech_metadata.style): Masukkan emosi, gaya penayangan, prosodi, kecepatan, dan volume yang berlaku di seluruh giliran dalam kolom style (misalnya, "style": "whispered urgently", "style": "out of breath", atau "style": "warm and enthusiastic").
  • Peristiwa pada waktu tertentu (tag inline): Tempatkan jeda atau letupan vokal non-ucapan sesaat langsung di dalam transkrip menggunakan tanda kurung sudut (misalnya, "Wait... <short pause> did you hear that? <sigh>" atau "Excuse me <cough> as I was saying...").

Lihat Panduan perintah untuk mengetahui praktik terbaik yang komprehensif.

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": "Wait... <short pause> look under that fallen log! Is that a blue-spotted salamander?",
                "annotations": [{
                    "type": "speech_metadata",
                    "speaker": "Dr. Anya",
                    "style": "whispered urgently",
                }],
            },
            {
                "type": "text",
                "text": "<gasp> No way! <laugh> We've been searching for this species all season!",
                "annotations": [{
                    "type": "speech_metadata",
                    "speaker": "Liam",
                    "style": "warm and enthusiastic",
                }],
            },
        ],
    }],
    response_format={"type": "audio"},
    generation_config={
        "speech_config": {
            "speakers": [
                {"speaker": "Dr. Anya", "voice": "Kore"},
                {"speaker": "Liam", "voice": "Puck"},
            ],
        }
    },
)

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: 'Wait... <short pause> look under that fallen log! Is that a blue-spotted salamander?',
               annotations: [{
                  type: 'speech_metadata',
                  speaker: 'Dr. Anya',
                  style: 'whispered urgently',
               }],
            },
            {
               type: 'text',
               text: "<gasp> No way! <laugh> We've been searching for this species all season!",
               annotations: [{
                  type: 'speech_metadata',
                  speaker: 'Liam',
                  style: 'warm and enthusiastic',
               }],
            },
         ],
      }],
      response_format: { type: 'audio' },
      generation_config: {
         speech_config: {
            speakers: [
               { speaker: 'Dr. Anya', voice: 'Kore' },
               { speaker: 'Liam', voice: 'Puck' },
            ],
         },
      },
   });

   if (interaction.output_audio?.data) {
      const audioBuffer = Buffer.from(interaction.output_audio.data, 'base64');
      fs.writeFileSync('out.wav', audioBuffer);
   }
}

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" \
  -d '{
    "model": "gemini-3.8-flash-tts",
    "input": [{
      "type": "user_input",
      "content": [
        {
          "type": "text",
          "text": "Wait... <short pause> look under that fallen log! Is that a blue-spotted salamander?",
          "annotations": [{
            "type": "speech_metadata",
            "speaker": "Dr. Anya",
            "style": "whispered urgently"
          }]
        },
        {
          "type": "text",
          "text": "<gasp> No way! <laugh> We'\''ve been searching for this species all season!",
          "annotations": [{
            "type": "speech_metadata",
            "speaker": "Liam",
            "style": "warm and enthusiastic"
          }]
        }
      ]
    }],
    "response_format": {
      "type": "audio"
    },
    "generation_config": {
      "speech_config": {
        "speakers": [
          { "speaker": "Dr. Anya", "voice": "Kore" },
          { "speaker": "Liam", "voice": "Puck" }
        ]
      }
    }
  }'

Pembuatan ucapan streaming

Anda dapat melakukan streaming audio yang dihasilkan saat audio tersebut disintesis dengan menetapkan stream: true. Tidak seperti permintaan unary (yang menampilkan file WAV lengkap dengan header RIFF), permintaan streaming menampilkan potongan PCM linear 16-bit bertanda tangan little-endian tanpa header (audio/l16, 24 kHz, mono) secara default sehingga potongan audio dapat diputar atau digabungkan secara terus-menerus tanpa header container.

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
  }'

Format output audio

Model TTS Gemini 3.8 menggunakan format audio default yang berbeda, bergantung pada apakah permintaan bersifat unary atau streaming:

  • Permintaan unary (stream=False): Menampilkan audio WAV (audio/wav) lengkap dengan header RIFF standar (24 kHz, mono, PCM little-endian bertanda 16-bit). Anda dapat menyimpan byte audio yang didekode langsung ke file .wav tanpa menambahkan header WAV secara manual.
  • Permintaan streaming (stream=True): Menampilkan potongan PCM Linear mentah tanpa header (audio/l16) (PCM little-endian bertanda 16-bit, mono, 24 kHz) secara default sehingga potongan dapat di-streaming atau digabungkan secara terus-menerus tanpa header penampung di setiap potongan.

Untuk meminta encoding audio atau frekuensi sampel yang berbeda, konfigurasikan mime_type dan sample_rate opsional di dalam response_format:

Format Nilai mime_type Deskripsi
WAV (default unary) "audio/wav" File WAV tanpa kompresi dengan header RIFF (PCM little-endian bertanda 16-bit, mono, default 24 kHz). Default untuk permintaan unary.
PCM mentah (L16) (default streaming) "audio/l16" Audio PCM linear little-endian bertanda 16-bit tanpa kompresi dan tanpa header (24 kHz, mono). Default untuk permintaan streaming.
Mu-law "audio/mulaw" Audio berenkode mu-law G.711 8-bit (umum digunakan dalam sistem telefoni/IVR di Amerika Utara dan Jepang).
A-law "audio/alaw" Audio berenkode G.711 A-law 8-bit (umumnya digunakan dalam sistem telepon Eropa dan internasional).

Anda juga dapat menentukan sample_rate dalam Hertz (misalnya, 24000, 16000, atau 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();

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" }
      ]
    }
  }'

Pilihan suara

Gemini 3.8 TTS mendukung empat cara untuk memilih atau membuat suara:

  1. Suara studio bawaan: 30 suara pilihan yang tercantum dalam tabel berikut.
  2. Extended Voice Library: Ratusan suara tambahan dalam berbagai bahasa, aksen, dan arketipe karakter yang dapat diakses menggunakan client.voices.list() (GET /v1beta/voices).
  3. Desain suara: Buat persona vokal kustom dari deskripsi bahasa alami di Google AI Studio atau menggunakan POST /v1beta/voices (type="prompted", yang menampilkan ID voice_... persisten dan pratinjau WAV sample_audio di CreateVoice dan GetVoice).
  4. Replikasi suara: Replikasi suara pembicara dari audio referensi dan izin di Google AI Studio atau menggunakan POST /v1beta/voices (type="replicated", store=True persisten secara default atau store=False stateless opsional).

Batas suara kustom dan TTL

Jenis suara Mode penyimpanan Kuota / batas Retensi (TTL)
Suara stateful (voice_..., dipromosikan atau direplikasi) store=True 200 suara per project (dibagikan ke seluruh suara yang diminta dan direplikasi) 1 tahun sejak penggunaan terakhir*
Kunci suara stateless (voicekey_..., direplikasi) store=False Dikelola klien 7 hari

* Perpanjangan TTL: Jendela retensi 1 tahun direset setiap kali suara digunakan secara aktif (baik dengan menyintesis ucapan dengan suara tersebut atau menggunakannya sebagai suara dasar untuk remix). Suara yang tidak memiliki aktivitas selama 1 tahun akan otomatis dihapus.

Suara bawaan

Zephyr -- Bright Puck -- Ceria Charon -- Informatif
Kore -- Firm Fenrir -- Mudah Terangsang Leda -- Muda
Orus -- Keras Aoede -- Breezy Callirrhoe -- Santai
Autonoe -- Terang Enceladus -- Breathy Iapetus -- Clear
Umbriel -- Santai Algieba -- Halus (Smooth) Despina -- Smooth
Erinome -- Clear Algenib -- Berbatu Rasalgethi -- Informatif
Laomedeia -- Ceria Achernar -- Lembut Alnilam -- Firm
Schedar -- Even Gacrux -- Matang Pulcherrima -- Spontan
Achird -- Ramah Zubenelgenubi -- Kasual Vindemiatrix -- Lembut
Sadachbia -- Lively Sadaltager -- Berpengetahuan Luas Sulafat -- Hangat

Library Suara dan pemfilteran yang diperluas

Selain 30 suara studio unggulan dalam tabel sebelumnya, Pustaka Suara yang Diperluas menyediakan ratusan suara tambahan dalam berbagai bahasa, aksen regional, persona karakter, dan domain. Anda dapat menjelajahi, memfilter, dan mendengarkan Voice Library lengkap secara interaktif di Google AI Studio, atau membuat kueri secara terprogram menggunakan client.voices.list() (GET /v1beta/voices, menggunakan google-genai 2.25.0+ / @google/genai 2.24.0+).

ListVoices menampilkan suara tersimpan kustom Anda (diurutkan dari yang terbaru terlebih dahulu), diikuti dengan suara katalog bawaan yang cocok dengan kriteria filter Anda. Jika beberapa nilai diteruskan untuk filter daftar, suara yang cocok dengan nilai apa pun dalam filter tersebut akan ditampilkan (OR), sedangkan parameter filter yang berbeda digabungkan dengan AND:

Parameter Jenis Deskripsi
language_code list[str] Tag bahasa BCP-47 (misalnya, ["en-US", "en-GB"]). Pencocokan persis yang tidak peka huruf besar/kecil.
region_code list[str] Kode wilayah ISO 3166-1 alpha-2 atau UN M.49 (misalnya, ["US", "GB"]).
accent list[str] Deskripsi aksen regional (misalnya, ["American", "British"]).
gender list[str] Presentasi gender yang terlihat ("female", "male", atau "neutral").
pitch list[str] Klasifikasi nada suara ("low", "medium", atau "high").
persona list[str] Persona vokal atau arketipe karakter (misalnya, ["Warm, Friendly"], ["Narrator"]).
contexts (context di REST) list[str] Domain penggunaan yang optimal (misalnya, ["Audiobook", "Conversational", "News"]).
type (type_ di Python) list[str] Filter menurut sumber suara: "prebuilt", "prompted" (Desain suara), atau "replicated" (Replikasi suara).
search str Penelusuran substring teks bebas yang dicocokkan tanpa peka huruf besar/kecil dengan display_name dan description.
page_size int Jumlah maksimum suara yang ditampilkan per halaman (default 50, maksimum 1000).
page_token str Token dari response.next_page_token untuk mengambil halaman hasil berikutnya.

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"

Bahasa yang didukung

Model TTS mendeteksi bahasa input secara otomatis. Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) mendukung lebih dari 130 bahasa, dan Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) mendukung lebih dari 100 bahasa:

Language Gemini 3.8 Flash TTS Gemini 3.8 Flash-Lite TTS
Aceh (Aksara Arab) ✔️ ✔️
Afrika ✔️ ✔️
Akan ✔️ ✔️
Amharik ✔️ ✔️
Armenia ✔️ ✔️
Assam ✔️ ✔️
Awadhi ✔️ ✔️
Bali ✔️ ✔️
Bangla ✔️ ✔️
Banjar (aksara Arab) ✔️ —
Banjar (skrip Latn) ✔️ ✔️
Bashkir ✔️ —
Basque ✔️ ✔️
Belarusian ✔️ ✔️
Bemba ✔️ —
Bhojpuri ✔️ ✔️
Bosnia ✔️ ✔️
Bugis ✔️ ✔️
Bulgaria ✔️ ✔️
Burma ✔️ —
Kanton ✔️ ✔️
Katalan ✔️ ✔️
Cebuano ✔️ ✔️
Kurdi Tengah ✔️ ✔️
Chhattisgarhi ✔️ ✔️
China (skrip Hans) ✔️ ✔️
China (skrip Hant) ✔️ ✔️
Crimean Tatar ✔️ —
Kroasia ✔️ ✔️
Ceko ✔️ ✔️
Denmark ✔️ ✔️
Belanda ✔️ ✔️
Dyula ✔️ —
Dzongkha ✔️ —
Arab Mesir ✔️ ✔️
Inggris ✔️ ✔️
Estonia ✔️ ✔️
Filipino ✔️ ✔️
Finlandia ✔️ —
Prancis ✔️ ✔️
Galisia ✔️ ✔️
Ganda ✔️ ✔️
Georgia ✔️ ✔️
Jerman ✔️ ✔️
Yunani ✔️ ✔️
Guarani ✔️ —
Gujarat ✔️ ✔️
Kreol Haiti ✔️ ✔️
Halh Mongolia ✔️ ✔️
Hausa ✔️ ✔️
Ibrani ✔️ ✔️
Hindi ✔️ ✔️
Hungaria ✔️ ✔️
Islandia ✔️ ✔️
Igbo ✔️ —
Iloko ✔️ ✔️
Indonesia ✔️ ✔️
Persia Iran ✔️ ✔️
Italia ✔️ ✔️
Jepang ✔️ ✔️
Jawa ✔️ ✔️
Kabyle ✔️ —
Kamba ✔️ ✔️
Kannada ✔️ ✔️
Kashmir (skrip Arab) ✔️ ✔️
Kashmir (aksara Deva) ✔️ ✔️
Kazak ✔️ ✔️
Khmer ✔️ ✔️
Kikuyu ✔️ ✔️
Kinyarwanda ✔️ ✔️
Kongo ✔️ ✔️
Korea ✔️ ✔️
Kirgiz ✔️ ✔️
Laos ✔️ ✔️
Latgalia ✔️ —
Lingala ✔️ ✔️
Lituania ✔️ —
Luksemburg ✔️ —
Makedonia ✔️ ✔️
Magahi ✔️ ✔️
Maithili ✔️ ✔️
Malayalam ✔️ ✔️
Malta ✔️ ✔️
Manipuri ✔️ ✔️
Marathi ✔️ ✔️
Minangkabau (aksara Arab) ✔️ ✔️
Minangkabau (skrip Latn) ✔️ —
Mizo ✔️ ✔️
Nepali (bahasa individu) ✔️ ✔️
Fulfulde Nigeria ✔️ ✔️
Azerbaijan Utara ✔️ ✔️
Sotho Utara ✔️ ✔️
Uzbek Utara ✔️ ✔️
Bokmål Norwegia ✔️ ✔️
Nynorsk Norwegia ✔️ ✔️
Nyanja ✔️ ✔️
Occitan ✔️ —
Odia (bahasa individual) ✔️ ✔️
Pangasinan ✔️ —
Persia (Afganistan) ✔️ ✔️
Polandia ✔️ ✔️
Portugis ✔️ ✔️
Punjabi ✔️ ✔️
Rumania ✔️ ✔️
Rusia ✔️ ✔️
Santali ✔️ ✔️
Serbia ✔️ ✔️
Sindhi ✔️ —
Sinhala ✔️ ✔️
Slovakia ✔️ ✔️
Slovenia ✔️ —
Somali ✔️ —
Azerbaijan Selatan ✔️ ✔️
Pashto Selatan ✔️ ✔️
Sotho Selatan ✔️ —
Spanyol ✔️ ✔️
Arab Standar (aksara Arab) ✔️ ✔️
Arab Standar (skrip Latn) ✔️ ✔️
Latvia Standar ✔️ ✔️
Melayu Standar ✔️ ✔️
Swahili (bahasa individual) ✔️ —
Swati ✔️ —
Swedia ✔️ —
Tajik ✔️ —
Tamil ✔️ ✔️
Telugu ✔️ ✔️
Thai ✔️ —
Tigrinya ✔️ —
Tosk Albania ✔️ —
Turki ✔️ ✔️
Uyghur ✔️ —
Vietnam ✔️ ✔️

Model yang didukung

Model Satu penutur Multi-penutur Desain suara Replikasi suara
Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) ✔️ ✔️ ✔️ ✔️
Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) ✔️ ✔️ ✔️ ✔️
Pratinjau Gemini 3.1 Flash TTS ✔️ ✔️ — —
Gemini 2.5 Pro Preview TTS ✔️ ✔️ — —

Kapan harus menggunakan model tertentu

Kedua model TTS Gemini 3.8 memiliki skema API dan format perintah yang sama persis, sehingga Anda dapat beralih di antara keduanya dengan satu perubahan parameter:

  • Gunakan Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) jika fidelitas akustik maksimum, akting bernuansa, dan kontrol ekspresif menjadi prioritas utama. Model ini ideal untuk karya kreatif tingkat studio, dialog kompleks dengan banyak pembicara, tag burst vokal yang berat, pengucapan yang sulit, dialek regional atau minoritas, dan narasi panjang yang memerlukan stabilitas suara dan nada ruang yang sangat kuat.
  • Gunakan Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) sebagai pengganti gemini-3.1-flash-tts-preview yang cepat dan hemat biaya. API ini dioptimalkan untuk produksi massal bervolume tinggi, rangkaian agen suara percakapan, fitur baca lisan, replikasi suara yang andal, dan ucapan satu penutur sehari-hari dalam bahasa utama.

Panduan migrasi

Jika Anda bermigrasi dari model Gemini TTS gemini-3.1-flash-tts-preview atau yang lebih lama ke Gemini 3.8 TTS:

  1. Pindahkan petunjuk tingkat giliran ke speech_metadata: Gemini 3.8 TTS memperlakukan teks input secara ketat sebagai transkrip verbatim. Pindahkan petunjuk pengiriman berkelanjutan (style—seperti "whispering", "out of breath", atau "speaking slowly") dan label pembicara (speaker) ke dalam anotasi speech_metadata terstruktur, bukan menyematkan petunjuk panggung dalam teks transkrip.
  2. Gunakan tag inline tanda kurung sudut hanya untuk peristiwa vokal pada waktu tertentu: Pertahankan vokalisasi dan jeda non-ucapan sesaat secara inline dalam transkrip menggunakan tanda kurung sudut (seperti <laugh>, <sigh>, <cough>, <breath>, atau <short pause>). Hindari tag efek suara (seperti tepuk tangan atau bunyi gedebuk) dan masukkan gaya penyampaian dalam speech_metadata.style.
  3. Tentukan speaker di setiap giliran dalam permintaan multi-pembicara: Setiap giliran dalam permintaan multi-pembicara harus secara eksplisit menyertakan speaker di dalam speech_metadata yang cocok dengan salah satu pembicara yang dikonfigurasi.
  4. Desain persona di awal dengan Voice design: Ganti blok "Audio Profile" atau "Director's Notes" multi-paragraf dengan suara kustom yang dibuat di Voice design, lalu bawa ID voice_... tersebut melalui permintaan TTS Anda dengan string style minimal atau kosong.
  5. Perhitungkan output WAV (audio/wav) default pada permintaan unary: Tidak seperti gemini-3.1-flash-tts-preview dan model TTS sebelumnya (yang menampilkan PCM audio/l16 mentah tanpa header secara default), TTS Gemini 3.8 menampilkan audio WAV (audio/wav) dengan header RIFF standar secara default untuk permintaan unary.
    • Jika kode Anda sebelumnya menggabungkan byte PCM mentah dalam header WAV (misalnya, menggunakan modul wave Python atau ffmpeg), hapus wrapper header manual dan tulis byte yang ditampilkan langsung ke file .wav.
    • Jika pipeline Anda memerlukan audio PCM, mu-law, atau A-law mentah tanpa header, tetapkan response_format.mime_type secara eksplisit ke "audio/l16", "audio/mulaw", atau "audio/alaw" (misalnya, {"response_format": {"type": "audio", "mime_type": "audio/l16"}} di Interactions API, atau AUDIO_L16 di generateContent). Lihat Format output audio.

Panduan menulis perintah

Model Gemini 3.8 TTS memperlakukan teks input secara ketat sebagai transkrip verbatim. Tidak seperti model pratinjau sebelumnya yang menyematkan petunjuk panggung dalam teks biasa, Gemini 3.8 TTS memisahkan petunjuk tingkat giliran yang berkelanjutan (speech_metadata) dari tag vokal inline pada titik waktu tertentu.

Kolom gaya versus tag inline

Pisahkan petunjuk performa Anda berdasarkan cakupan:

  • Penyampaian tingkat giliran (speech_metadata.style): Masukkan atribut penyampaian berkelanjutan—seperti emosi, prosodi, kecepatan keseluruhan, atau gaya penyampaian (seperti "whispering", "out of breath", "muttering", atau "sarcastic")—ke dalam kolom style dari speech_metadata. Untuk membuat karakter dan performa yang stabil di seluruh giliran, desain persona di awal dalam Desain suara dan gunakan style hanya untuk penyesuaian opsional di tingkat giliran.
  • Peristiwa pada waktu tertentu (tag inline): Tempatkan letupan vokal non-ucapan, napas, atau jeda sesaat secara inline di dalam transkrip menggunakan tanda kurung sudut (<cough>, <breath>, <sigh>, <short pause>). Gunakan tanda kurung sudut (<...>) untuk kualitas audio tertinggi, dan gunakan vokalisasi manusia, bukan efek suara non-vokal.
Cakupan Tempat penempatan Contoh
Tingkat giliran (dipertahankan di seluruh giliran) speech_metadata.style "angry tone", "speaking rapidly", "out of breath", "whispers", "sarcastic"
Point-in-time (terjadi pada kata tertentu) Inline di text (<...>) "<cough> Thank you all for coming tonight! <throat-clearing> As I was saying..."

Kecepatan dan jeda

Anda dapat mengontrol ritme dan keheningan pada tiga tingkat perincian:

  • Tanda baca dan elipsis: Gunakan koma, tanda hubung (--), dan elipsis (...) untuk keraguan percakapan yang alami.
  • Tag jeda inline: Sisipkan <short pause> atau <long pause> di titik yang tepat dalam skrip tempat pembicara harus menjeda: text Hold on, let me think... <short pause> Alright, I've got it.
  • Kecepatan tingkat giliran: Tetapkan "style": "speaking rapidly" atau "style": "speaking slowly" di speech_metadata untuk mengontrol kecepatan bicara di seluruh giliran.

Prosodi dan nada

Gunakan speech_metadata.style untuk mengontrol prosodi, nada, dan infleksi di seluruh giliran bicara (misalnya, "style": "high pitch, cheerful and excited inflection" atau "style": "monotone and flat"). Jika emosi atau prosodi berubah di tengah dialog, pisahkan skrip menjadi giliran bicara terpisah dengan nilai style yang berbeda untuk setiap giliran bicara.

Penekanan

Gunakan huruf kapital untuk kata-kata tertentu dalam transkrip, yang dikombinasikan dengan tanda baca dan tag vokal inline, untuk memberikan penekanan vokal yang alami pada kata-kata kunci:

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

Suara vokal dan suara non-ucapan

Tempatkan vokalisasi manusia non-ucapan secara inline menggunakan tanda kurung sudut (<...>) pada titik yang tepat di mana suara tersebut seharusnya muncul. Tag vokal yang direkomendasikan meliputi:

<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>

Backchannel dan ucapan yang tumpang tindih

Dalam dialog multi-pembicara, sertakan reaksi pendengar dalam karakter pipa (|reaction|) di dalam giliran pembicara untuk membuat saluran belakang yang alami atau ucapan yang tumpang-tindih tanpa memecah menjadi giliran terpisah per reaksi.

  • Pertukaran saluran belakang singkat: Susun reaksi singkat pendengar (|oh hmm|, |oh really?|, |absolutely|) di dalam giliran pembicara aktif:
    • Giliran 1 (Pembicara A): "So the launch is Thursday |oh hmm| Are we actually ready?"
    • Giliran 2 (Pembicara B): "Ready enough |oh really?| The last blocker cleared this morning."
    • Giliran 3 (Pembicara A): "Then let's ship it |absolutely| and watch the dashboards."
  • Ucapan yang tumpang-tindih dan berselang-seling: Gunakan beberapa segmen pipa untuk mensimulasikan ucapan simultan atau berselang-seling antara dua penutur (berfungsi paling baik dengan gemini-3.8-flash-tts):
    • Hitung mundur/paduan suara simultan: "Let's surprise him on three |ok| ready?" diikuti dengan "one. two. three. |happy| happy |birthday| birthday!"
    • Tumpang-tindih penuh pembicara: "Hello |oh| there |my| it |goodness| must |gracious| be |would| almost |you| time |look| for |at that| dinner"

Konsistensi di seluruh generasi dan hal yang harus dihindari

Ikuti panduan berikut untuk menjaga identitas vokal tetap stabil di seluruh giliran:

  • Desain persona di awal dalam desain Suara, bukan blok gaya yang panjang: Paragraf "Audio Profile" yang panjang dan "Director's Notes" dengan banyak poin yang dibawa dari model sebelumnya adalah penyebab paling umum dari penyimpangan suara. Gunakan intuisi kreatif yang sama di awal dalam Desain suara untuk menghasilkan persona voice_... kustom yang persisten, lalu gunakan ID suara tersebut dalam panggilan TTS Anda.
  • Mengandalkan referensi suara untuk stabilitas (menghilangkan meta-petunjuk): Model TTS Gemini 3.8 dilatih untuk berfokus pada referensi audio terlebih dahulu. Jangan sertakan petunjuk yang meminta model untuk menjaga kestabilan suara (seperti "do not switch speaker identity" atau "maintain identical timbre")—teks perintah tambahan meningkatkan penyimpangan. Hapus petunjuk gaya yang tidak diperlukan dan biarkan model bervariasi secara alami di sekitar titik stabil yang disediakan oleh referensi suara.
  • Jangan mencoba mengubah karakteristik pembicara yang tidak dapat diubah di style: Hindari memasukkan usia, gender, nama, atau perubahan aksen permanen di speech_metadata.style. Sebagai gantinya, pilih suara regional dari Extended Voice Library atau buat suara dengan Voice design.
  1. Buat karakter sekali: Buat karakter Anda di Voice design atau pilih suara regional dari Extended Voice Library yang sesuai dengan bahasa target dan persona Anda.
  2. Tulis transkrip lisan yang alami dengan disfluensi: Untuk kealamian maksimum, tulis text sebagai transkrip lisan yang sebenarnya—termasuk disfluensi dan keraguan percakapan yang alami (misalnya, "Oh uh yeah I think... hm, so that's interesting").
  3. Uji TTS biasa terlebih dahulu: Sintesiskan transkrip Anda dengan kolom style kosong terlebih dahulu—sebagian besar permintaan tidak memerlukan petunjuk style sama sekali.
  4. Tambahkan perintah style singkat hanya untuk penyesuaian: Tambahkan string style yang ringkas (seperti "casual, friendly" atau "muttering, then reassuring") hanya untuk giliran yang memerlukan penyesuaian pengiriman tertentu, dan gunakan kembali string singkat yang sama di seluruh giliran jika Anda menginginkan dasar pengukuran yang konsisten.

Dialog multi-giliran dan agen suara

Saat membangun agen suara percakapan real-time atau aplikasi multi-giliran:

  • Lakukan satu panggilan TTS per giliran saat potongan teks LLM tiba.
  • Biarkan voice yang dikonfigurasi (voice_... bawaan, yang didesain, atau voice_... / voicekey_... yang direplikasi) membawa identitas pembicara di seluruh giliran—jangan pernah mengirim ulang persona karakter yang panjang di setiap giliran.
  • Biarkan kolom style per giliran kosong, atau kirim satu string konstanta pendek (seperti "casual, friendly") untuk seluruh percakapan.
  • Membagi respons agen yang panjang menjadi giliran yang lebih pendek daripada menggunakan perintah gaya yang lebih kuat.

Batasan

  • Model TTS menerima input khusus teks dan menghasilkan output khusus audio.
  • Pembuatan multi-pembicara dengan satu permintaan (speech_config.speakers) mendukung hingga 2 pembicara menggunakan suara bawaan. Untuk menggabungkan suara yang didesain khusus (voice_...) atau direplikasi (voice_... / voicekey_...) dalam dialog multi-karakter, sintesiskan setiap giliran bicara secara terpisah. Karena permintaan unary menampilkan audio/wav dengan header RIFF 44 byte secara default, minta PCM mentah ({"type": "audio", "mime_type": "audio/l16"}) atau hapus header WAV dari setiap giliran sebelum menggabungkan frame audio PCM 24 kHz.
  • Batas penyimpanan suara kustom dan TTL:
    • Suara stateful (store=True, dipicu atau direplikasi): Maksimum 200 suara per project dengan TTL 1 tahun (time-to-live).
    • Kunci suara stateless (store=False, voicekey_...): TTL 7 hari (time-to-live).
  • Tinjau bagian Bahasa yang didukung untuk mengetahui cakupan bahasa.

Langkah berikutnya