Generowanie tekstu na mowę (TTS)

Interfejs Gemini API może przekształcać tekst na mowę jednego lub wielu rozmówców, korzystając z funkcji zamiany tekstu na mowę (TTS) w Gemini. Generowanie zamiany tekstu na mowę jest kontrolowane, co oznacza, że możesz łączyć uporządkowane metadane tury (speech_metadata) i wbudowane tagi głosowe, aby określać styl, akcent, tempo i ton dźwięku.

Funkcja TTS różni się od generowania mowy za pomocą interfejsu Live API, który jest przeznaczony do interaktywnych, nieustrukturyzowanych danych audio oraz multimodalnych danych wejściowych i wyjściowych. Interfejs Live API sprawdza się w dynamicznych kontekstach konwersacyjnych, a TTS za pomocą interfejsu Gemini API jest dostosowany do scenariuszy, które wymagają dokładnego odczytania tekstu z precyzyjną kontrolą stylu i dźwięku, takich jak generowanie podcastów lub audiobooków.

Z tego przewodnika dowiesz się, jak generować dźwięk z jednym lub wieloma mówcami na podstawie tekstu za pomocą Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) i Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts).

Zanim zaczniesz

Upewnij się, że używasz modelu Gemini TTS wymienionego w sekcji Obsługiwane modele, i przejdź na najnowszą wersję pakietu Google GenAI SDK (google-genai >= 2.25.0 w przypadku Pythona lub @google/genai >= 2.24.0 w przypadku JavaScriptu/TypeScriptu) lub użyj interfejsu REST API. Aby uzyskać optymalne wyniki, zapoznaj się z artykułem Kiedy używać którego modelu, aby wybrać najlepszy model dla swojego zadania.

Zanim zaczniesz tworzyć, warto przetestować modele Gemini TTS w AI Studio.

TTS z jednym głosem

Aby przekonwertować tekst na dźwięk z jednym rozmówcą za pomocą modeli TTS Gemini 3.8, przekaż dosłowną transkrypcję w input, dołącz styl na poziomie tury za pomocą adnotacji speech_metadata i skonfiguruj głos w generation_config.speech_config. Możesz wybrać głos z gotowych opcji głosu, rozszerzonej biblioteki głosów (GET /v1beta/voices), niestandardowego identyfikatora projektu głosu (voice_...) lub identyfikatora replikacji głosu (voice_... lub opcjonalnie bezstanowego voicekey_...).

W tym przykładzie domyślny plik audio WAV (audio/wav) z modelu jest zapisywany bezpośrednio w pliku:

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

W pakietach SDK dla Pythona i pakietach JavaScript SDK możesz pobrać wygenerowane dane audio, korzystając z właściwości interaction.output_audio, która zwraca ostatni wygenerowany blok audio (w nieprzetworzonych odpowiedziach REST JSON zakodowany w base64 dźwięk jest przechowywany w steps[].content[].data). Szczegółowe informacje o właściwościach znajdziesz w omówieniu interakcji.

Zamiana tekstu na mowę z wieloma rozmówcami

W przypadku dialogu z wieloma rozmówcami skonfiguruj 2 rozmówców w speech_config.speakers i przekaż każdą wypowiedź jako osobny element tekstowy z adnotacją speech_metadata określającą speaker i opcjonalną style na poziomie wypowiedzi. Zwróć uwagę, że speech_config akceptuje tablicę ([{"voice": "..."}]) w przypadku generowania głosu jednego rozmówcy i obiekt ({"speakers": [...]}) w przypadku generowania głosów wielu rozmówców:

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

Kontrolowanie stylu mowy za pomocą metadanych i tagów

Gemini 3.8 TTS traktuje pole text ściśle jako dosłowną transkrypcję. Aby kontrolować sposób odczytywania bez odczytywania na głos wskazówek scenicznych, podziel instrukcje według zakresu:

  • Stałe dostarczanie na poziomie tury (speech_metadata.style): umieść emocje, styl dostarczania, prozodię, tempo i głośność, które mają zastosowanie w całej turze, w polu style (np. "style": "whispered urgently", "style": "out of breath" lub "style": "warm and enthusiastic").
  • Zdarzenia w określonym momencie (tagi wbudowane): umieść krótkie dźwięki inne niż mowa lub pauzy bezpośrednio w transkrypcji, używając nawiasów ostrych (np. "Wait... <short pause> did you hear that? <sigh>" lub "Excuse me <cough> as I was saying...").

Więcej sprawdzonych metod znajdziesz w przewodniku po promptach.

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

Generowanie mowy strumieniowej

Możesz przesyłać strumieniowo wygenerowany dźwięk podczas jego syntezy, ustawiając stream: true. W przeciwieństwie do żądań jednoargumentowych (które zwracają kompletny plik WAV z nagłówkiem RIFF) żądania strumieniowe domyślnie zwracają fragmenty nieprzetworzonego 16-bitowego liniowego PCM ze znakiem w formacie little-endian (audio/l16, 24 kHz, mono) bez nagłówka, dzięki czemu fragmenty audio można odtwarzać lub łączyć w sposób ciągły bez nagłówków kontenera.

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

Formaty wyjścia audio

Modele Gemini 3.8 TTS używają różnych domyślnych formatów audio w zależności od tego, czy żądanie jest jednorazowe czy strumieniowe:

  • Żądania jednoargumentowe (stream=False): zwracają pełny dźwięk WAV (audio/wav) ze standardowym nagłówkiem RIFF (24 kHz, mono, 16-bitowy, ze znakiem, little-endian PCM). Możesz zapisać zdekodowane bajty audio bezpośrednio w pliku .wav bez ręcznego dodawania nagłówka WAV.
  • Żądania strumieniowe (stream=True): domyślnie zwracają nieprzetworzone fragmenty Linear PCM bez nagłówka (audio/l16) (24 kHz, mono, 16-bitowy PCM ze znakiem, little-endian), dzięki czemu fragmenty mogą być przesyłane strumieniowo lub łączone w sposób ciągły bez nagłówków kontenera w każdym fragmencie.

Aby poprosić o inne kodowanie dźwięku lub inną częstotliwość próbkowania, skonfiguruj mime_type i opcjonalnie sample_rate w response_format:

Format Wartość mime_type Opis
WAV (domyślny format jednoargumentowy) "audio/wav" Nieskompresowany plik WAV z nagłówkiem RIFF (16-bitowy, podpisany, PCM w formacie little-endian, mono, domyślnie 24 kHz). Domyślna wartość dla żądań jednoargumentowych.
Raw PCM (L16) (domyślny format strumieniowania) "audio/l16" Nieskompresowany, bez nagłówka, 16-bitowy, ze znakiem, little-endian, liniowy dźwięk PCM (24 kHz, mono). Domyślna wartość dla żądań strumieniowania.
Mu-law "audio/mulaw" 8-bitowy dźwięk zakodowany w standardzie G.711 mu-law (powszechnie używany w systemach telefonicznych/IVR w Ameryce Północnej i Japonii).
A-law "audio/alaw" 8-bitowy dźwięk zakodowany za pomocą kodeka G.711 A-law (powszechnie używany w europejskich i międzynarodowych systemach telefonicznych).

Możesz też podać wartość sample_rate w hercach (np. 24000, 16000 lub 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" }
      ]
    }
  }'

Opcje głosowe

Gemini 3.8 TTS obsługuje 4 sposoby wybierania lub tworzenia głosów:

  1. Gotowe głosy studyjne: 30 wyselekcjonowanych głosów wymienionych w tabeli poniżej.
  2. Rozszerzona biblioteka głosów: setki dodatkowych głosów w różnych językach, z różnymi akcentami i archetypami postaci, które są dostępne za pomocą client.voices.list() (GET /v1beta/voices).
  3. Projektowanie głosu: wygeneruj niestandardową osobowość głosową na podstawie opisu w języku naturalnym w Google AI Studio lub za pomocą POST /v1beta/voices (type="prompted", która zwraca trwały identyfikator voice_... i podgląd WAV sample_audio w CreateVoice i GetVoice).
  4. Replikacja głosu: Replikacja głosu mówcy na podstawie dźwięku referencyjnego i dźwięku, na którego wykorzystanie uzyskano zgodę, w Google AI Studio lub za pomocą POST /v1beta/voices (type="replicated", domyślnie trwałe store=True lub opcjonalne bezstanowe store=False).

Limity i TTL głosów niestandardowych

Rodzaj głosu Tryb przechowywania Limit Przechowywanie (TTL)
Głosy stanowe (voice_..., wygenerowane na podstawie promptu lub replikowane) store=True 200 głosów na projekt (współdzielonych między głosami wygenerowanymi na podstawie promptów i głosami replikowanymi). 1 rok od ostatniego użycia*
Klucze głosowe bezstanowe (voicekey_..., replikowane) store=False Zarządzane przez klienta 7 dni

* Przedłużenie okresu ważności TTL: 1-roczny okres przechowywania jest resetowany za każdym razem, gdy głos jest aktywnie używany (do syntezy mowy lub jako głos bazowy do remiksowania). Głosy, które nie były używane przez rok, są automatycznie usuwane.

Gotowe głosy

Zephyr – jasny Puck – Upbeat Charon – zawiera przydatne informacje
Kore – firma Fenrir – pobudliwy Leda – młodzieńczy
Orus – Firm Aoede – Breezy Callirrhoe – Easy-going
Autonoe – jasny Enceladus -- Breathy Iapetus – Clear
Umbriel – spokojny Algieba – gładki Despina – gładki
Erinome – Clear Algenib – żwirowy Rasalgethi – Zawiera przydatne informacje
Laomedeia – optymistyczny Achernar – Soft Alnilam – Firm
Schedar – Even Gacrux – Mature Pulcherrima – Przekaż dalej
Achird – przyjazny Zubenelgenubi – zwykły Vindemiatrix – delikatny
Sadachbia – Lively Sadaltager – kompetentny Sulafat – ciepły

Rozszerzona biblioteka głosów i filtrowanie

Oprócz 30 głosów studyjnych wymienionych w tabeli powyżej rozszerzona biblioteka głosów zawiera setki dodatkowych głosów w różnych językach, z różnymi akcentami regionalnymi, postaciami i domenami. Możesz przeglądać, filtrować i odsłuchiwać całą bibliotekę głosów interaktywnie w Google AI Studio lub wysyłać do niej zapytania programowo za pomocą client.voices.list() (GET /v1beta/voices, używając google-genai w wersji 2.25.0 lub nowszej / @google/genai w wersji 2.24.0 lub nowszej).

ListVoices zwraca niestandardowe zapisane głosy (uporządkowane od najnowszych), a następnie głosy z gotowego katalogu, które pasują do kryteriów filtra. Jeśli w przypadku filtra listy przekazywanych jest kilka wartości, zwracane są głosy pasujące do dowolnej wartości w tym filtrze (OR), a różne parametry filtra są łączone za pomocą znaku AND:

Parametr Typ Opis
language_code list[str] Tagi języka BCP-47 (np. ["en-US", "en-GB"]). Dopasowanie ścisłe, wielkość liter nie jest rozróżniana.
region_code list[str] Kod regionu w formacie ISO 3166-1 alfa-2 lub UN M.49 (np. ["US", "GB"]).
accent list[str] Deskryptory akcentu regionalnego (np. ["American", "British"]).
gender list[str] Postrzegana płeć ("female", "male" lub "neutral").
pitch list[str] Klasyfikacja wysokości głosu ("low", "medium" lub "high").
persona list[str] osobowość wokalna lub archetyp postaci (np. ["Warm, Friendly"], ["Narrator"]);
contexts (context w REST) list[str] Optymalna domena użytkowania (np. ["Audiobook", "Conversational", "News"]).
type (type_ w Pythonie) list[str] Filtruj według źródła głosu: "prebuilt", "prompted" (Projektowanie głosu) lub "replicated" (Replikacja głosu).
search str Wyszukiwanie podłańcucha w dowolnym tekście bez rozróżniania wielkości liter w polach display_name i description.
page_size int Maksymalna liczba głosów zwracanych na stronę (domyślnie 50, maksymalnie 1000).
page_token str Token z response.next_page_token, aby pobrać następną stronę wyników.

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"

Obsługiwane języki

Modele TTS automatycznie wykrywają język wejściowy. Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) obsługuje ponad 130 języków, a Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) obsługuje ponad 100 języków:

Język Gemini 3.8 Flash TTS Gemini 3.8 Flash-Lite TTS
aceh (alfabet arabski), ✔️ ✔️
afrikaans ✔️ ✔️
akan ✔️ ✔️
amharski ✔️ ✔️
ormiański ✔️ ✔️
asamski ✔️ ✔️
awadhi ✔️ ✔️
balijski ✔️ ✔️
bengalski ✔️ ✔️
banjar (alfabet arabski) ✔️ –
banjar (alfabet łaciński) ✔️ ✔️
baszkirski ✔️ –
baskijski ✔️ ✔️
białoruski ✔️ ✔️
bemba ✔️ –
bhodźpuri ✔️ ✔️
bośniacki ✔️ ✔️
Bugiński ✔️ ✔️
bułgarski ✔️ ✔️
birmański ✔️ –
kantoński ✔️ ✔️
kataloński ✔️ ✔️
cebuański ✔️ ✔️
centralny kurdyjski ✔️ ✔️
ćhattisgarhi ✔️ ✔️
chiński (pismo han) ✔️ ✔️
chiński (pismo tradycyjne) ✔️ ✔️
krymsko-tatarski ✔️ –
chorwacki ✔️ ✔️
czeski ✔️ ✔️
duński ✔️ ✔️
niderlandzki ✔️ ✔️
diula ✔️ –
dzongkha ✔️ –
arabski egipski ✔️ ✔️
angielski ✔️ ✔️
estoński ✔️ ✔️
filipiński ✔️ ✔️
fiński ✔️ –
francuski ✔️ ✔️
galicyjski ✔️ ✔️
luganda ✔️ ✔️
gruziński ✔️ ✔️
niemiecki ✔️ ✔️
grecki ✔️ ✔️
guarani ✔️ –
gudżarati ✔️ ✔️
kreolski haitański ✔️ ✔️
chałcha-mongolski ✔️ ✔️
hausa ✔️ ✔️
hebrajski ✔️ ✔️
hindi ✔️ ✔️
węgierski ✔️ ✔️
islandzki ✔️ ✔️
igbo ✔️ –
iloko ✔️ ✔️
indonezyjski ✔️ ✔️
perski (Iran) ✔️ ✔️
włoski ✔️ ✔️
japoński ✔️ ✔️
jawajski ✔️ ✔️
Kabyle ✔️ –
kamba ✔️ ✔️
kannada ✔️ ✔️
kaszmirski (alfabet arabski), ✔️ ✔️
kaszmirski (pismo dewanagari) ✔️ ✔️
kazachski ✔️ ✔️
khmerski ✔️ ✔️
kikuyu ✔️ ✔️
ruanda-rundi ✔️ ✔️
kongo ✔️ ✔️
koreański ✔️ ✔️
kirgiski ✔️ ✔️
laotański ✔️ ✔️
łatgalski ✔️ –
lingala ✔️ ✔️
litewski ✔️ –
luksemburski ✔️ –
macedoński ✔️ ✔️
magahi ✔️ ✔️
maithili ✔️ ✔️
malajalam ✔️ ✔️
maltański ✔️ ✔️
manipuri, ✔️ ✔️
marathi ✔️ ✔️
minangkabau (pismo arabskie) ✔️ ✔️
Minangkabau (alfabet łaciński) ✔️ –
mizo ✔️ ✔️
nepalski (język) ✔️ ✔️
fulfulde (Nigeria) ✔️ ✔️
północnoazerbejdżański ✔️ ✔️
sotho północny ✔️ ✔️
uzbecki (północny) ✔️ ✔️
norweski bokmål ✔️ ✔️
norweski (Nynorsk) ✔️ ✔️
njandża ✔️ ✔️
oksytański ✔️ –
orija (język indywidualny) ✔️ ✔️
pangasinan ✔️ –
perski (Afganistan) ✔️ ✔️
polski ✔️ ✔️
portugalski ✔️ ✔️
pendżabski ✔️ ✔️
rumuński ✔️ ✔️
rosyjski ✔️ ✔️
santali ✔️ ✔️
serbski ✔️ ✔️
sindhi ✔️ –
syngaleski ✔️ ✔️
słowacki ✔️ ✔️
słoweński ✔️ –
somalijski ✔️ –
południowoazerski ✔️ ✔️
paszto południowy ✔️ ✔️
sotho południowy ✔️ –
hiszpański ✔️ ✔️
standardowy arabski (pismo arabskie) ✔️ ✔️
standardowy arabski (alfabet łaciński) ✔️ ✔️
standardowy łotewski, ✔️ ✔️
standardowy malajski ✔️ ✔️
suahili (język) ✔️ –
suazi ✔️ –
szwedzki ✔️ –
tadżycki ✔️ –
tamilski ✔️ ✔️
telugu ✔️ ✔️
tajski ✔️ –
tigrinia ✔️ –
albański (toskijski) ✔️ –
turecki ✔️ ✔️
ujgurski ✔️ –
wietnamski ✔️ ✔️

Obsługiwane modele

Model Pojedynczy rozmówca Wielu rozmówców Projektowanie głosu Replikacja głosu
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 (wersja testowa) ✔️ ✔️ – –
Wersja testowa Gemini 2.5 Pro TTS ✔️ ✔️ – –

Kiedy używać którego modelu

Oba modele Gemini 3.8 TTS mają ten sam schemat interfejsu API i format promptów, co pozwala na przełączanie się między nimi przez zmianę jednego parametru:

  • Używaj Gemini 3.8 Flash TTS (gemini-3.8-flash-tts), gdy najważniejsza jest maksymalna wierność akustyczna, niuansowana gra i ekspresyjna kontrola. Idealnie nadaje się do pracy kreatywnej na poziomie studyjnym, złożonych dialogów z wieloma rozmówcami, trudnych tagów wokalnych, trudnej wymowy, dialektów regionalnych lub mniejszościowych oraz długich narracji wymagających stabilnego głosu i tonu pomieszczenia.
  • Używaj Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) jako szybkiego i ekonomicznego zamiennika gemini-3.1-flash-tts-preview. Jest zoptymalizowany pod kątem masowej produkcji, kaskad agentów głosowych, funkcji czytania na głos, niezawodnej replikacji głosu i codziennej mowy jednego rozmówcy w głównych językach.

Przewodnik po migracji

Jeśli przechodzisz z modelu gemini-3.1-flash-tts-preview lub wcześniejszych modeli Gemini TTS na Gemini 3.8 TTS:

  1. Przenieś wskazówki dojazdu do speech_metadata: Gemini 3.8 TTS traktuje tekst wejściowy ściśle jako transkrypcję dosłowną. Przenieś instrukcje dotyczące sposobu wypowiedzi (style – np. "whispering", "out of breath" lub "speaking slowly") i etykiety rozmówców (speaker) do uporządkowanych adnotacji speech_metadata, zamiast umieszczać didaskalia w tekście transkrypcji.
  2. Używaj tagów w nawiasach ostrokątnych tylko w przypadku zdarzeń głosowych w danym momencie: zachowaj chwilowe wokalizacje i pauzy w transkrypcji, używając nawiasów ostrokątnych (np. <laugh>, <sigh>, <cough>, <breath> lub <short pause>). Unikaj tagów efektów dźwiękowych (takich jak oklaski lub uderzenia) i umieszczaj style dostawy w speech_metadata.style.
  3. Określ speaker w każdej turze w żądaniach z wieloma rozmówcami: każda tura w żądaniu z wieloma rozmówcami musi wyraźnie zawierać speaker wewnątrz speech_metadata, pasujący do jednego ze skonfigurowanych rozmówców.
  4. Zaprojektuj persony z wyprzedzeniem za pomocą funkcji Voice design: zastąp wieloakapitowe bloki "Audio Profile" lub "Director's Notes" niestandardowym głosem utworzonym w Voice design, a następnie przekaż ten identyfikator voice_... w żądaniach TTS z minimalnymi lub pustymi ciągami znaków style.
  5. Uwzględnij domyślne dane wyjściowe WAV (audio/wav) w przypadku żądań jednoargumentowych: w przeciwieństwie do modeli TTS gemini-3.1-flash-tts-preview i wcześniejszych (które domyślnie zwracały nieprzetworzone dane PCM audio/l16 bez nagłówka) Gemini 3.8 TTS domyślnie zwraca dźwięk WAV (audio/wav) ze standardowym nagłówkiem RIFF w przypadku żądań jednoargumentowych.
    • Jeśli Twój kod wcześniej opakowywał surowe bajty PCM w nagłówek WAV (np. za pomocą modułu wave w Pythonie lub ffmpeg), usuń ręczny wrapper nagłówka i zapisz zwrócone bajty bezpośrednio w pliku .wav.
    • Jeśli Twój potok wymaga dźwięku PCM bez nagłówka, mu-law lub A-law, ustaw parametr response_format.mime_type na "audio/l16", "audio/mulaw" lub "audio/alaw" (np. {"response_format": {"type": "audio", "mime_type": "audio/l16"}} w interfejsie Interactions API lub AUDIO_L16 w generateContent). Więcej informacji znajdziesz w sekcji Formaty wyjściowe audio.

Przewodnik po promptach

Modele TTS Gemini 3.8 traktują tekst wejściowy ściśle jako dosłowną transkrypcję. W przeciwieństwie do wcześniejszych modeli podglądu, w których wskazówki sceniczne były osadzone w zwykłym tekście, Gemini 3.8 TTS oddziela ciągłe wskazówki na poziomie tury (speech_metadata) od wbudowanych tagów głosowych.

Pole stylu a tagi wbudowane

Podziel instrukcje dotyczące wydajności według zakresu:

  • Sposób wypowiedzi na poziomie tury (speech_metadata.style): umieść atrybuty sposobu wypowiedzi, takie jak emocje, prozodia, ogólne tempo lub styl wypowiedzi (np. "whispering", "out of breath", "muttering" lub "sarcastic"), w polu style obiektu speech_metadata. Aby stworzyć stabilną postać i zachować spójność między turami, zaprojektuj ją z wyprzedzeniem w sekcji Projekt głosu, a parametr style wykorzystuj tylko do opcjonalnych poprawek na poziomie tury.
  • Zdarzenia w określonym momencie (tagi wbudowane): umieszczaj krótkie, niewerbalne dźwięki wokalne, oddechy lub przerwy w transkrypcji za pomocą nawiasów ostrych (<cough>, <breath>, <sigh>, <short pause>). Używaj nawiasów ostrych (<...>) w przypadku najwyższej jakości dźwięku i skup się na ludzkich dźwiękach wokalnych, a nie na niewokalnych efektach dźwiękowych.
Zakres Gdzie umieścić Przykłady
Na poziomie tury (utrzymywany przez całą turę) speech_metadata.style "angry tone", "speaking rapidly", "out of breath", "whispers", "sarcastic"
W określonym momencie (występuje przy konkretnym słowie). Wbudowane w text (<...>) "<cough> Thank you all for coming tonight! <throat-clearing> As I was saying..."

Tempo i przerwy

Rytm i ciszę możesz kontrolować na 3 poziomach szczegółowości:

  • Interpunkcja i wielokropki: używaj przecinków, myślników (--) i wielokropków (...), aby uzyskać naturalne wahanie w rozmowie.
  • Wbudowane tagi pauzy: wstaw <short pause> lub <long pause> w dokładnych miejscach w skrypcie, w których lektor powinien zrobić przerwę:text Hold on, let me think... <short pause> Alright, I've got it.
  • Tempo na poziomie tury: ustaw "style": "speaking rapidly" lub "style": "speaking slowly" w speech_metadata, aby kontrolować tempo mowy w całej turze.

Prozodia i ton

Używaj parametru speech_metadata.style, aby kontrolować prozodię, wysokość głosu i fleksję w trakcie wypowiedzi (np. "style": "high pitch, cheerful and excited inflection" lub "style": "monotone and flat"). Jeśli emocje lub prozodia zmieniają się w trakcie dialogu, podziel skrypt na osobne wypowiedzi z różnymi wartościami style dla każdej z nich.

Wyróżnienie

Używaj wielkich liter w przypadku konkretnych słów w transkrypcji w połączeniu ze znakami interpunkcyjnymi i tagami wokalnymi w tekście, aby w naturalny sposób podkreślać kluczowe słowa:

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

Wykrzyknienia i dźwięki inne niż mowa

Wstawiaj w tekście niewerbalne dźwięki wydawane przez ludzi, używając nawiasów ostrych (<...>) w dokładnym miejscu, w którym powinien pojawić się dźwięk. Zalecane tagi wokalne:

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

Potwierdzenia i nakładające się wypowiedzi

W dialogach z wieloma mówcami umieść reakcje słuchaczy w znakach potoku (|reaction|) w wypowiedzi mówcy, aby utworzyć naturalne kanały zwrotne lub nakładające się wypowiedzi bez dzielenia ich na osobne wypowiedzi dla każdej reakcji.

  • Krótkie reakcje: dodaj krótkie reakcje słuchacza (|oh hmm|, |oh really?|, |absolutely|) w trakcie wypowiedzi aktywnego rozmówcy:
    • Turn 1 (Speaker A): "So the launch is Thursday |oh hmm| Are we actually ready?"
    • Turn 2 (Speaker B): "Ready enough |oh really?| The last blocker cleared this morning."
    • Turn 3 (Speaker A): "Then let's ship it |absolutely| and watch the dashboards."
  • Nakładające się i przeplatające się wypowiedzi: użyj wielu segmentów z kreską pionową, aby symulować jednoczesne lub przeplatające się wypowiedzi 2 osób (najlepiej działa z gemini-3.8-flash-tts):
    • Jednoczesne odliczanie i refren: "Let's surprise him on three |ok| ready?", a potem "one. two. three. |happy| happy |birthday| birthday!"
    • Pełne nakładanie się wypowiedzi: "Hello |oh| there |my| it |goodness| must |gracious| be |would| almost |you| time |look| for |at that| dinner"

Spójność między generowanymi treściami i czego unikać

Aby zachować stabilność tożsamości głosowej w różnych turach, postępuj zgodnie z tymi wytycznymi:

  • Zaprojektuj persony z wyprzedzeniem w ramach projektowania głosu, zamiast używać długich bloków stylu: długie akapity "Audio Profile" i wypunktowania "Director's Notes" przeniesione z wcześniejszych modeli są najczęstszą przyczyną dryfu głosu. Wykorzystaj tę samą intuicję twórczą w projektowaniu głosu, aby wygenerować trwałą niestandardową postać voice_..., a następnie używaj tego identyfikatora głosu w wywołaniach TTS.
  • Polegaj na stabilności głosu referencyjnego (pomiń metainstrukcje): modele Gemini 3.8 TTS są trenowane tak, aby najpierw zakotwiczyć się na nagraniu referencyjnym. Nie dołączaj instrukcji, które nakazują modelowi utrzymywanie stałego głosu (np. "do not switch speaker identity" lub "maintain identical timbre") – dodatkowy tekst prompta zwiększa dryf. Usuń niepotrzebne instrukcje dotyczące stylu i pozwól modelowi na naturalne zmiany wokół stabilnego punktu zapewnianego przez odniesienie głosowe.
  • Nie próbuj zmieniać niezmiennych cech rozmówcy w tagu style: unikaj umieszczania w tagu speech_metadata.style wieku, płci, imion i nazwisk ani trwałych zmian akcentu. Zamiast tego wybierz głos regionalny z rozszerzonej biblioteki głosów lub utwórz go za pomocą funkcji Projektowanie głosu.
  1. Utwórz postać raz: utwórz postać w Voice design lub wybierz głos regionalny z rozszerzonej biblioteki głosów, który pasuje do wybranego języka i osobowości.
  2. Twórz naturalne transkrypcje mówione z elementami niepłynności: aby uzyskać maksymalną naturalność, zapisuj text jako prawdziwą transkrypcję mówioną, w tym naturalne elementy niepłynności i wahania (np. "Oh uh yeah I think... hm, so that's interesting").
  3. Najpierw przetestuj zwykły TTS: najpierw dokonaj syntezy transkrypcji za pomocą pustego pola style  – większość żądań nie wymaga żadnych instrukcji style.
  4. Dodawaj krótkie prompty style tylko w przypadku drobnych zmian: dodawaj zwięzły ciąg znaków style (np. "casual, friendly" lub "muttering, then reassuring") tylko w przypadku tur, które wymagają konkretnej zmiany w dostarczaniu, i używaj tego samego krótkiego ciągu znaków w różnych turach, gdy chcesz uzyskać spójną wartość bazową.

Rozmowy wieloetapowe i agenty głosowe

Podczas tworzenia agentów głosowych działających w czasie rzeczywistym lub aplikacji wieloetapowych:

  • Wykonuj 1 wywołanie TTS na turę, gdy docierają fragmenty tekstu z LLM.
  • Niech skonfigurowany voice (gotowy, zaprojektowany voice_... lub zreplikowany voice_... / voicekey_...) przenosi tożsamość rozmówcy między turami – nigdy nie wysyłaj ponownie długiej persony w każdej turze.
  • Pozostaw pole style puste lub wyślij jeden krótki ciąg stały (np. "casual, friendly") dla całej rozmowy.
  • Podziel długie odpowiedzi agenta na krótsze tury, zamiast używać bardziej rygorystycznych promptów dotyczących stylu.

Ograniczenia

  • Modele TTS akceptują tylko tekstowe dane wejściowe i generują tylko dźwiękowe dane wyjściowe.
  • Generowanie wielu rozmówców w ramach jednego żądania (speech_config.speakers) obsługuje maksymalnie 2 rozmówców korzystających z gotowych głosów. Aby połączyć niestandardowe (voice_...) lub replikowane (voice_... / voicekey_...) głosy w dialogu z wieloma postaciami, zsyntetyzuj wypowiedź każdego rozmówcy osobno. Żądania jednoargumentowe domyślnie zwracają audio/wav z 44-bajtowym nagłówkiem RIFF, dlatego przed połączeniem ramek audio PCM 24 kHz poproś o nieprzetworzony format PCM ({"type": "audio", "mime_type": "audio/l16"}) lub usuń nagłówek WAV z każdej tury.
  • Limity miejsca na dane i TTL w przypadku głosu niestandardowego:
    • Głosy z zachowaniem stanu (store=True, na podstawie promptu lub replikowane): maksymalnie 200 głosów na projekt z rocznym czasem życia danych (TTL).
    • Bezstanowe klucze głosowe (store=False, voicekey_...): 7-dniowy TTL (czas życia danych).
  • W sekcji Obsługiwane języki znajdziesz informacje o zakresie językowym.

Co dalej?