Generazione di sintesi vocale (TTS)

L'API Gemini può trasformare l'input di testo in audio con uno o più parlanti utilizzando le funzionalità di generazione di sintesi vocale (TTS) di Gemini. La generazione di sintesi vocale è controllabile, il che significa che puoi combinare i metadati strutturati del turno (speech_metadata) e i tag vocali incorporati per guidare lo stile, l'accento, il ritmo e il tono dell'audio.

La funzionalità TTS è diversa dalla generazione vocale fornita tramite l'API Live, progettata per input e output multimodali e audio interattivi e non strutturati. Mentre l'API Live eccelle in contesti conversazionali dinamici, la sintesi vocale tramite l'API Gemini è pensata per scenari che richiedono una recitazione esatta del testo con un controllo preciso su stile e suono, come la generazione di podcast o audiolibri.

Questa guida mostra come generare audio con una o più voci a partire da un testo utilizzando Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) e Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts).

Prima di iniziare

Assicurati di utilizzare un modello Gemini TTS elencato nella sezione Modelli supportati. Per risultati ottimali, consulta la sezione Quando utilizzare un modello per selezionare il modello migliore per il tuo carico di lavoro.

Prima di iniziare a creare, ti consigliamo di testare i modelli Gemini TTS in AI Studio.

TTS con un solo speaker

Per convertire il testo in audio con una sola voce utilizzando i modelli Gemini 3.8 TTS, passa la trascrizione letterale in input, allega lo stile a livello di turno utilizzando un'annotazione speech_metadata e configura la voce in generation_config.speech_config. Puoi scegliere una voce tra le opzioni vocali predefinite, la libreria vocale estesa (GET /v1beta/voices), un ID progettazione vocale personalizzato (voice_...) o un ID replica vocale (voice_... o voicekey_... stateless facoltativo).

Questo esempio salva l'audio di output WAV predefinito (audio/wav) dal modello direttamente in un 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();

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

Puoi recuperare i dati audio generati utilizzando la proprietà interaction.output_audio, che restituisce l'ultimo blocco audio generato. Per informazioni dettagliate sulle proprietà di convenienza, consulta la panoramica delle interazioni.

TTS multilocutore

Per i dialoghi con più interlocutori, configura due speaker in speech_config.speakers e passa ogni turno come elemento di testo separato con un'annotazione speech_metadata che specifica speaker e style facoltativo a livello di turno. Usa "mode": "conversational" per una cadenza naturale di alternanza dei turni:

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

Controllare lo stile del parlato con metadati e tag

Gemini 3.8 TTS considera il campo text esclusivamente come una trascrizione letterale. Per controllare la recitazione senza che le indicazioni di regia vengano lette ad alta voce, dividi le istruzioni per ambito:

  • Pronuncia sostenuta a livello di turno (speech_metadata.style): inserisci emozioni, stile di pronuncia, prosodia, ritmo e volume che si applicano a un intero turno nel campo style (ad esempio, "style": "whispered urgently", "style": "out of breath" o "style": "warm and enthusiastic").
  • Eventi puntuali (tag in linea): inserisci brevi interruzioni o pause vocali non verbali direttamente all'interno della trascrizione utilizzando le parentesi angolari (ad esempio, "Wait... <short pause> did you hear that? <sigh>" o "Excuse me <cough> as I was saying...").

Consulta la guida ai prompt per best practice complete.

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
}

Generazione di sintesi vocale in streaming

Puoi riprodurre in streaming l'audio generato durante la sintesi impostando stream: true. A differenza delle richieste unarie (che restituiscono un file WAV completo con un'intestazione RIFF), le richieste di streaming restituiscono blocchi PCM lineare little-endian a 16 bit non elaborati senza intestazione (audio/l16, 24 kHz, mono) per impostazione predefinita, in modo che i blocchi audio possano essere riprodotti o concatenati continuamente senza intestazioni del contenitore.

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

Formati di uscita audio

I modelli Gemini 3.8 TTS utilizzano formati audio predefiniti diversi a seconda che la richiesta sia unaria o di streaming:

  • Richieste unarie (stream=False): restituiscono audio WAV (audio/wav) completo con un'intestazione RIFF standard (24 kHz, mono, PCM little-endian con segno a 16 bit). Puoi salvare i byte audio decodificati direttamente in un file .wav senza anteporre manualmente un'intestazione WAV.
  • Richieste di streaming (stream=True): restituisci blocchi PCM lineare non elaborato senza intestazione (audio/l16) (24 kHz, mono, PCM little-endian firmato a 16 bit) per impostazione predefinita, in modo che i blocchi possano essere trasmessi in streaming o concatenati continuamente senza intestazioni del contenitore su ogni blocco.

Per richiedere una codifica audio o una frequenza di campionamento diversa, configura mime_type e sample_rate facoltativo all'interno di response_format:

Formato Valore mime_type Descrizione
WAV (impostazione predefinita unaria) "audio/wav" File WAV non compresso con un'intestazione RIFF (PCM little-endian signed a 16 bit, mono, 24 kHz predefinito). Valore predefinito per le richieste unarie.
PCM non elaborato (L16) (impostazione predefinita per lo streaming) "audio/l16" Audio PCM lineare a 16 bit signed little-endian non compresso e senza intestazione (24 kHz, mono). Valore predefinito per le richieste di streaming.
Mu-law "audio/mulaw" Audio codificato G.711 mu-law a 8 bit (di uso comune nei sistemi di telefonia/IVR nordamericani e giapponesi).
A-law "audio/alaw" Audio codificato G.711 A-law a 8 bit (di uso comune nei sistemi di telefonia europei e internazionali).

Puoi anche specificare sample_rate in hertz (ad esempio, 24000, 16000 o 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" }
      ]
    }
  }'

Opzioni vocali

Gemini 3.8 TTS supporta quattro modi per selezionare o creare voci:

  1. Voci di studio predefinite:30 voci selezionate elencate nella tabella seguente.
  2. Libreria di voci estesa:centinaia di voci aggiuntive in diverse lingue, accenti e archetipi di personaggi accessibili tramite client.voices.list() (GET /v1beta/voices).
  3. Progettazione della voce: genera una persona vocale personalizzata da una descrizione in linguaggio naturale in Google AI Studio o utilizzando POST /v1beta/voices (type="prompted", che restituisce un ID voice_... persistente e un'anteprima sample_audio WAV in CreateVoice e GetVoice).
  4. Replica vocale: replica la voce di un oratore dall'audio di riferimento e di consenso in Google AI Studio o utilizzando POST /v1beta/voices (type="replicated", store=True persistente per impostazione predefinita o store=False stateless facoltativo).

Limiti e TTL della voce personalizzata

Tipo di voce Modalità di archiviazione Quota / limite Conservazione (TTL)
Voci stateful (voice_..., richieste o replicate) store=True 200 voci per progetto (condivise tra le voci richieste e replicate) 1 anno
Chiavi vocali stateless (voicekey_..., replicate) store=False Gestita dal cliente 7 giorni

Voci predefinite

Zephyr - Luminoso Puck - Upbeat Caronte -- Istruttiva
Kore -- Azienda Fenrir: eccitabile Leda - Giovane
Orus -- Azienda Aoede - Breezy Callirrhoe: informale
Autonoe -- Luminoso Enceladus - Soffio Iapetus -- Cancella
Umbriel: tranquillo Algieba -- Fluido Despina -- Smooth
Erinome -- Sereno Algenib - Gravelly Rasalgethi - Informativa
Laomedeia - Upbeat Achernar - Soft Alnilam -- Firm
Schedar - Even Gacrux -- Per adulti Pulcherrima -- Forward
Achird: amichevole Zubenelgenubi - Informale Vindemiatrix - Gentle
Sadachbia: Vivace Sadaltager - Competente Sulafat: calda

Libreria di voci estesa e filtri

Oltre alle 30 voci di studio in primo piano nella tabella precedente, la Extended Voice Library offre centinaia di voci aggiuntive in varie lingue, accenti regionali, personaggi e domini. Puoi sfogliare, filtrare e provare l'intera libreria di voci in modo interattivo in Google AI Studio oppure interrogarla in modo programmatico utilizzando client.voices.list() (GET /v1beta/voices, utilizzando google-genai 2.25.0+ / @google/genai 2.24.0+).

ListVoices restituisce le voci personalizzate memorizzate (ordinate dalla più recente) seguite dalle voci del catalogo predefinite che corrispondono ai criteri di filtro. Quando vengono passati più valori per un filtro elenco, vengono restituite le voci corrispondenti a qualsiasi valore del filtro (OR), mentre i parametri di filtro distinti si combinano con AND:

Parametro Tipo Descrizione
language_code list[str] Tag lingua BCP-47 (ad esempio, ["en-US", "en-GB"]). Corrispondenza esatta senza distinzione tra maiuscole e minuscole.
region_code list[str] Codice o codici regione ISO 3166-1 alpha-2 o UN M.49 (ad esempio, ["US", "GB"]).
accent list[str] Descrittore o descrittori dell'accento regionale (ad esempio, ["American", "British"]).
gender list[str] Presentazione del genere percepito ("female", "male" o "neutral").
pitch list[str] Classificazione del tono vocale ("low", "medium" o "high").
persona list[str] Personaggio vocale o archetipo del personaggio (ad esempio, ["Warm, Friendly"], ["Narrator"]).
contexts (context in REST) list[str] Dominio di utilizzo ottimale (ad esempio, ["Audiobook", "Conversational", "News"]).
type (type_ in Python) list[str] Filtra per fonte della voce: "prebuilt", "prompted" (Progettazione vocale) o "replicated" (Replica vocale).
search str La ricerca di sottostringhe di testo libero è stata eseguita senza distinzione tra maiuscole e minuscole sia per display_name che per description.
page_size int Numero massimo di voci restituite per pagina (valore predefinito 50, massimo 1000).
page_token str Token di response.next_page_token per recuperare la pagina successiva dei risultati.

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"

Lingue supportate

I modelli di sintesi vocale rilevano automaticamente la lingua di input. Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) supporta 130 lingue e Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) supporta 101 lingue:

Lingua Gemini 3.8 Flash TTS Gemini 3.8 Flash-Lite TTS
Accinese (alfabeto arabo) ✔️ ✔️
Afrikaans ✔️ ✔️
Akan ✔️ ✔️
Amarico ✔️ ✔️
Armeno ✔️ ✔️
Assamese ✔️ ✔️
Awadhi ✔️ ✔️
Balinese ✔️ ✔️
Bengalese ✔️ ✔️
Banjar (caratteri arabi) ✔️ —
Banjar (alfabeto latino) ✔️ ✔️
Bashkir ✔️ —
Basco ✔️ ✔️
Bielorusso ✔️ ✔️
Bemba ✔️ —
Bhojpuri ✔️ ✔️
Bosniaco ✔️ ✔️
Buginese ✔️ ✔️
Bulgaro ✔️ ✔️
Birmano ✔️ —
Cantonese ✔️ ✔️
Catalano ✔️ ✔️
Cebuano ✔️ ✔️
Curdo centrale ✔️ ✔️
Chhattisgarhi ✔️ ✔️
Cinese (caratteri Hans) ✔️ ✔️
Cinese (caratteri Hant) ✔️ ✔️
Tataro di Crimea ✔️ —
Croato ✔️ ✔️
Ceco ✔️ ✔️
Danese ✔️ ✔️
Olandese ✔️ ✔️
Diula ✔️ —
Dzongkha ✔️ —
Arabo (Egitto) ✔️ ✔️
Inglese ✔️ ✔️
Estone ✔️ ✔️
Filippino ✔️ ✔️
Finlandese ✔️ —
Francese ✔️ ✔️
Galiziano ✔️ ✔️
ganda ✔️ ✔️
Georgiano ✔️ ✔️
Tedesco ✔️ ✔️
Greek ✔️ ✔️
Guarani ✔️ —
Gujarati ✔️ ✔️
Creolo haitiano ✔️ ✔️
Halh mongolo ✔️ ✔️
Hausa ✔️ ✔️
Ebraico ✔️ ✔️
Hindi ✔️ ✔️
Ungherese ✔️ ✔️
Islandese ✔️ ✔️
Igbo ✔️ —
Ilocano ✔️ ✔️
Indonesiano ✔️ ✔️
Persiano iraniano ✔️ ✔️
Italiano ✔️ ✔️
Giapponese ✔️ ✔️
Giavanese ✔️ ✔️
Kabyle ✔️ —
Kamba ✔️ ✔️
Kannada ✔️ ✔️
Kashmiri (scrittura araba) ✔️ ✔️
Kashmiri (Deva script) ✔️ ✔️
Kazako ✔️ ✔️
Khmer ✔️ ✔️
Kikuyu ✔️ ✔️
Kinyarwanda ✔️ ✔️
Kongo ✔️ ✔️
Coreano ✔️ ✔️
Kirgizo ✔️ ✔️
Lao ✔️ ✔️
Letgallo ✔️ —
Lingala ✔️ ✔️
Lituano ✔️ —
Lussemburghese ✔️ —
Macedone ✔️ ✔️
Magahi ✔️ ✔️
Maithili ✔️ ✔️
Malayalam ✔️ ✔️
Maltese ✔️ ✔️
Manipuri ✔️ ✔️
Marathi ✔️ ✔️
Minangkabau (scrittura araba) ✔️ ✔️
Minangkabau (latino) ✔️ —
Mizo ✔️ ✔️
Nepalese (lingua individuale) ✔️ ✔️
Fulfulde nigeriano ✔️ ✔️
Azerbaigian settentrionale ✔️ ✔️
Sotho del nord ✔️ ✔️
Uzbeko settentrionale ✔️ ✔️
Norvegese bokmål ✔️ ✔️
Norvegese (Nynorsk) ✔️ ✔️
Nyanja ✔️ ✔️
Occitano ✔️ —
Odia (lingua individuale) ✔️ ✔️
Pangasinan ✔️ —
Persiano (Afghanistan) ✔️ ✔️
Polacco ✔️ ✔️
Portoghese ✔️ ✔️
Punjabi ✔️ ✔️
Rumeno ✔️ ✔️
Russo ✔️ ✔️
Santali ✔️ ✔️
Serbo ✔️ ✔️
Sindhi ✔️ —
Singalese ✔️ ✔️
Slovacco ✔️ ✔️
Sloveno ✔️ —
Somalo ✔️ —
Azerbaigiano meridionale ✔️ ✔️
Pashto meridionale ✔️ ✔️
Sotho del sud ✔️ —
Spagnolo ✔️ ✔️
Arabo standard (caratteri arabi) ✔️ ✔️
Arabo standard (alfabeto latino) ✔️ ✔️
Lettone standard ✔️ ✔️
Malese standard ✔️ ✔️
Swahili (singola lingua) ✔️ —
Swati ✔️ —
Svedese ✔️ —
Tagico ✔️ —
Tamil ✔️ ✔️
Telugu ✔️ ✔️
Thailandese ✔️ —
Tigrinya ✔️ —
Albanese tosk ✔️ —
Uiguro ✔️ —

Modelli supportati

Modello Unico relatore Più relatori Progettazione vocale Replica vocale
Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) ✔️ ✔️ ✔️ ✔️
Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) ✔️ ✔️ ✔️ ✔️
Anteprima di Gemini 3.1 Flash TTS ✔️ ✔️ — —
Gemini 2.5 Pro Preview TTS ✔️ ✔️ — —

Quando utilizzare un modello o l'altro

Entrambi i modelli Gemini 3.8 TTS condividono lo stesso schema dell'API e formato di prompt, consentendoti di passare da uno all'altro con una sola modifica del parametro:

  • Utilizza Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) quando la massima fedeltà acustica, l'interpretazione ricca di sfumature e il controllo espressivo sono la priorità assoluta. È ideale per lavori creativi di qualità professionale, dialoghi complessi tra più persone, tag di burst vocali pesanti, pronunce difficili, dialetti regionali o di minoranze e narrazioni di lunga durata che richiedono una stabilità assoluta della voce e del tono della stanza.
  • Utilizza Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) come sostituto rapido ed economico di gemini-3.1-flash-tts-preview. È ottimizzato per la produzione di grandi volumi, le cascate di agenti vocali conversazionali, le funzionalità di lettura ad alta voce, la replica vocale affidabile e la sintesi vocale quotidiana con un solo oratore nelle principali lingue.

Guida alla migrazione

Se esegui la migrazione da modelli Gemini TTS gemini-3.1-flash-tts-preview o precedenti a Gemini 3.8 TTS:

  1. Sposta le indicazioni a livello di svolta in speech_metadata: Gemini 3.8 TTS tratta il testo di input rigorosamente come una trascrizione letterale. Sposta le istruzioni di consegna sostenuta (style, ad esempio "whispering", "out of breath" o "speaking slowly") e le etichette di chi parla (speaker) in annotazioni speech_metadata strutturate anziché incorporare le indicazioni di scena nel testo della trascrizione.
  2. Utilizza i tag in linea tra parentesi angolari solo per gli eventi vocali puntuali: mantieni le vocalizzazioni e le pause momentanee non verbali in linea nella trascrizione utilizzando le parentesi angolari (ad esempio <laugh>, <sigh>, <cough>, <breath> o <short pause>). Evita i tag degli effetti sonori (ad esempio applausi o tonfi) e inserisci gli stili di pronuncia in speech_metadata.style.
  3. Specifica speaker a ogni turno nelle richieste multilingue:ogni turno in una richiesta multilingue deve includere esplicitamente speaker all'interno di speech_metadata corrispondente a uno degli oratori configurati.
  4. Progetta le buyer persona in anticipo con la progettazione vocale:sostituisci i blocchi di più paragrafi "Audio Profile" o "Director's Notes" con una voce personalizzata creata in Progettazione vocale, quindi riporta l'ID voice_... nelle richieste TTS con stringhe style minime o vuote.
  5. Tieni conto dell'output WAV (audio/wav) predefinito nelle richieste unarie:a differenza di gemini-3.1-flash-tts-preview e dei modelli TTS precedenti (che restituivano PCM non elaborato senza intestazione audio/l16 per impostazione predefinita), Gemini 3.8 TTS restituisce audio WAV (audio/wav) con un'intestazione RIFF standard per impostazione predefinita per le richieste unarie.
    • Se in precedenza il codice racchiudeva i byte PCM non elaborati in un'intestazione WAV (ad esempio, utilizzando il modulo wave di Python o ffmpeg), rimuovi il wrapper dell'intestazione manuale e scrivi i byte restituiti direttamente in un file .wav.
    • Se la pipeline richiede audio PCM non elaborato, mu-law o A-law senza intestazione, imposta esplicitamente response_format su "audio/l16", "audio/mulaw" o "audio/alaw". Consulta Formati di uscita audio.

Guida ai prompt

I modelli Gemini 3.8 TTS trattano il testo di input rigorosamente come una trascrizione letterale. A differenza dei modelli di anteprima precedenti in cui le indicazioni sceniche erano incorporate nel testo normale, la sintesi vocale di Gemini 3.8 separa le indicazioni di turno sostenute (speech_metadata) dai tag vocali incorporati puntuali.

Campo Stile e tag in linea

Dividi le istruzioni sul rendimento per ambito:

  • Turn-level delivery (speech_metadata.style): inserisci gli attributi di delivery sostenuta, come emozione, prosodia, ritmo generale o stile di delivery (ad esempio "whispering", "out of breath", "muttering" o "sarcastic"), nel campo style di speech_metadata. Per creare un personaggio e una performance stabili nel tempo, progetta la persona in anticipo in Voice design e utilizza style solo per modifiche facoltative a livello di turno.
  • Eventi puntuali (tag in linea): inserisci brevi interruzioni vocali non verbali, respiri o pause in linea all'interno della trascrizione utilizzando le parentesi angolari (<cough>, <breath>, <sigh>, <short pause>). Utilizza le parentesi angolari (<...>) per ottenere la massima qualità audio e concentrati sulle vocalizzazioni umane anziché sugli effetti sonori non vocali.
Ambito Dove posizionare Esempi
Svolta per svolta (mantenuta durante la svolta) speech_metadata.style "angry tone", "speaking rapidly", "out of breath", "whispers", "sarcastic"
Point-in-time (si verifica in una parola specifica) Inline in text (<...>) "<cough> Thank you all for coming tonight! <throat-clearing> As I was saying..."

Pacing e pause

Puoi controllare il ritmo e il silenzio a tre livelli di granularità:

  • Punteggiatura e puntini di sospensione:utilizza virgole, trattini (--) e puntini di sospensione (...) per simulare le esitazioni naturali di una conversazione.
  • Tag di pausa in linea:inserisci <short pause> o <long pause> nei punti esatti del copione in cui un oratore deve fare una pausa: text Hold on, let me think... <short pause> Alright, I've got it.
  • Ritmo a livello di turno:imposta "style": "speaking rapidly" o "style": "speaking slowly" in speech_metadata per controllare la velocità di pronuncia durante l'intero turno.

Prosodia e intonazione

Utilizza speech_metadata.style per controllare la prosodia, il tono e l'inflessione in un turno (ad esempio, "style": "high pitch, cheerful and excited inflection" o "style": "monotone and flat"). Se l'emozione o la prosodia cambia a metà del dialogo, dividi il copione in turni separati con valori style distinti per ogni turno.

Enfasi

Metti in maiuscolo parole specifiche nella trascrizione, combinate con punteggiatura e tag vocali in linea, per enfatizzare naturalmente le parole chiave:

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

Esplosioni vocali e suoni non vocali

Inserisci le vocalizzazioni umane non verbali in linea utilizzando le parentesi angolari (<...>) nel punto esatto in cui deve verificarsi il suono. I tag vocali consigliati includono:

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

Canali secondari e voci sovrapposte

Nel dialogo tra più oratori, racchiudi le reazioni dell'ascoltatore tra caratteri pipe (|reaction|) all'interno del turno di un oratore per creare backchannel naturali o sovrapposizioni di parlato senza interrompere un turno separato per reazione.

  • Scambi brevi nel backchannel:inserisci brevi reazioni degli ascoltatori (|oh hmm|, |oh really?|, |absolutely|) all'interno del turno dell'oratore attivo:
    • Turno 1 (Speaker A): "So the launch is Thursday |oh hmm| Are we actually ready?"
    • Turno 2 (Speaker B): "Ready enough |oh really?| The last blocker cleared this morning."
    • Turno 3 (Speaker A): "Then let's ship it |absolutely| and watch the dashboards."
  • Discorso sovrapposto e alternato: utilizza più segmenti di pipe per simulare un discorso simultaneo o alternato tra due oratori (funziona meglio con gemini-3.8-flash-tts):
    • Simultaneous countdown/chorus: "Let's surprise him on three |ok| ready?" followed by "one. two. three. |happy| happy |birthday| birthday!"
    • Sovrapposizione completa degli speaker: "Hello |oh| there |my| it |goodness| must |gracious| be |would| almost |you| time |look| for |at that| dinner"

Coerenza tra le generazioni e cosa evitare

Segui queste linee guida per mantenere stabile l'identità vocale durante i turni:

  • Progetta le buyer persona in anticipo nella progettazione vocale anziché in lunghi blocchi di stile: i paragrafi "Audio Profile" in formato lungo e gli elenchi puntati multipli "Director's Notes" riportati dai modelli precedenti sono la causa più comune di deriva della voce. Utilizza la stessa intuizione creativa in anticipo nella progettazione della voce per generare una persona voice_... personalizzata persistente, quindi riporta l'ID voce nelle chiamate TTS.
  • Affidati al riferimento vocale per la stabilità (ometti le metainstruzioni): I modelli TTS Gemini 3.8 sono addestrati ad ancorarsi prima al riferimento audio. Non includere istruzioni che indicano al modello di mantenere la voce costante (ad esempio "do not switch speaker identity" o "maintain identical timbre"). Il testo del prompt aggiuntivo aumenta la deriva. Elimina le istruzioni di stile non necessarie e lascia che il modello vari naturalmente intorno al punto stabile fornito dal riferimento vocale.
  • Non tentare di modificare le caratteristiche immutabili del relatore in style: evita di inserire età, genere, nomi o modifiche permanenti dell'accento in speech_metadata.style. Scegli invece una voce regionale dalla raccolta di voci estese o creane una con Progettazione vocale.
  1. Crea il personaggio una sola volta: crea il tuo personaggio in Progettazione della voce o seleziona una voce regionale dalla raccolta di voci estesa che corrisponda alla lingua e alla personalità di destinazione.
  2. Scrivi trascrizioni naturali con disfluenze:per ottenere la massima naturalezza, scrivi il text come una vera trascrizione del parlato, includendo disfluenze e esitazioni naturali (ad esempio, "Oh uh yeah I think... hm, so that's interesting").
  3. Per prima cosa, prova la sintesi vocale standard: sintetizza la trascrizione con un campo style vuoto. La maggior parte delle richieste non richiede alcuna istruzione style.
  4. Aggiungi prompt brevi style solo per modifiche:aggiungi una stringa style concisa (ad esempio "casual, friendly" o "muttering, then reassuring") solo per i turni che richiedono una modifica specifica della pubblicazione e riutilizza la stessa stringa breve nei vari turni quando vuoi una base di riferimento coerente.

Agenti vocali e di dialogo multi-turno

Quando crei agenti vocali conversazionali in tempo reale o applicazioni multi-turno:

  • Effettua una chiamata TTS per turno all'arrivo dei blocchi di testo LLM.
  • Consenti al voice configurato (predefinito, progettato voice_... o replicato voice_... / voicekey_...) di mantenere l'identità dell'oratore durante i turni, senza inviare di nuovo una persona con un lungo carattere a ogni turno.
  • Lascia vuoto il campo style per turno o invia una breve stringa costante (ad esempio "casual, friendly") per l'intera conversazione.
  • Dividi le risposte lunghe dell'agente in turni più brevi anziché ricorrere a prompt di stile più efficaci.

Limitazioni

  • I modelli TTS accettano input solo di testo e generano output solo audio.
  • La generazione di più speaker con una sola richiesta (multiSpeakerVoiceConfig / multi-speaker speakers) supporta fino a 2 speaker che utilizzano voci predefinite. Per combinare voci progettate su misura (voice_...) o replicate (voicekey_...) nel dialogo di più personaggi, sintetizza il turno di ogni oratore individualmente e concatena i frame audio PCM a 24 kHz.
  • Limiti di archiviazione e TTL della voce personalizzata:
    • Voci con stato (store=True, richieste o replicate): massimo 200 voci per progetto con un TTL di 1 anno (durata).
    • Chiavi vocali stateless (store=False, voicekey_...): TTL di 7 giorni (durata).
  • Consulta la sezione Lingue supportate per informazioni sulla copertura linguistica.

Passaggi successivi