Generación de texto a voz (TTS)

La API de Gemini puede transformar la entrada de texto en audio de uno o varios interlocutores con las capacidades de generación de texto a voz (TTS) de Gemini. La generación de texto a voz es controlable, lo que significa que puedes combinar metadatos de turnos estructurados (speech_metadata) y etiquetas de voz intercaladas para guiar el estilo, el acento, el ritmo y el tono del audio.

La capacidad de TTS difiere de la generación de voz que se proporciona a través de la API de Live, que está diseñada para entradas y salidas interactivas, no estructuradas y multimodales. Si bien la API de Live se destaca en contextos conversacionales dinámicos, la API de Gemini TTS está diseñada para situaciones que requieren una recitación de texto exacta con un control detallado sobre el estilo y el sonido, como la generación de podcasts o audiolibros.

En esta guía, se muestra cómo generar audio de un solo orador y de varios oradores a partir de texto con Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) y Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts).

Antes de comenzar

Asegúrate de usar un modelo de TTS de Gemini que aparezca en la sección Modelos compatibles y actualiza al SDK de IA generativa de Google más reciente (google-genai >= 2.25.0 para Python o @google/genai >= 2.24.0 para JavaScript/TypeScript) o usa la API de REST. Para obtener resultados óptimos, consulta Cuándo usar cada modelo y selecciona el mejor modelo para tu carga de trabajo.

Te recomendamos que pruebes los modelos de TTS de Gemini en AI Studio antes de comenzar a compilar.

TTS de un solo interlocutor

Para convertir texto en audio de un solo orador con los modelos de Gemini 3.8 TTS, pasa la transcripción literal en input, adjunta el diseño a nivel de turno con una anotación speech_metadata y configura tu voz en generation_config.speech_config. Puedes elegir una voz de las opciones de voz predefinidas, la biblioteca de voces extendida (GET /v1beta/voices), un ID de diseño de voz personalizado (voice_...) o un ID de replicación de voz (voice_... o voicekey_... sin estado opcional).

En este ejemplo, se guarda el audio de salida WAV predeterminado (audio/wav) del modelo directamente en un archivo:

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

En los SDK de Python y JavaScript, puedes recuperar los datos de audio generados con la propiedad de conveniencia interaction.output_audio, que devuelve el último bloque de audio generado (en las respuestas JSON de REST sin procesar, el audio codificado en Base64 se almacena en steps[].content[].data). Para obtener detalles sobre las propiedades de conveniencia, consulta la descripción general de las interacciones.

TTS con varios interlocutores

Para el diálogo con varios interlocutores, configura dos interlocutores en speech_config.speakers y pasa cada turno como un elemento de texto independiente con una anotación speech_metadata que especifique el speaker y el style opcional a nivel del turno. Ten en cuenta que speech_config acepta un array ([{"voice": "..."}]) para la generación de un solo interlocutor y un objeto ({"speakers": [...]}) para la generación de varios interlocutores:

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

Controla el estilo de voz con metadatos y etiquetas

Gemini 3.8 TTS trata el campo text estrictamente como una transcripción literal. Para controlar la entrega sin que se lean en voz alta las indicaciones de escena, divide tus instrucciones por alcance:

  • Publicación sostenida a nivel de turno (speech_metadata.style): Coloca las emociones, el estilo de publicación, la prosodia, el ritmo y el volumen que se aplican en todo un turno en el campo style (por ejemplo, "style": "whispered urgently", "style": "out of breath" o "style": "warm and enthusiastic").
  • Eventos puntuales (etiquetas intercaladas): Coloca ráfagas o pausas vocales momentáneas que no sean de voz directamente dentro de la transcripción con corchetes angulares (por ejemplo, "Wait... <short pause> did you hear that? <sigh>" o "Excuse me <cough> as I was saying...").

Consulta la Guía de instrucciones para conocer las prácticas recomendadas integrales.

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

Generación de voz en vivo

Puedes transmitir el audio generado a medida que se sintetiza configurando stream: true. A diferencia de las solicitudes unarias (que devuelven un archivo WAV completo con un encabezado RIFF), las solicitudes de transmisión devuelven fragmentos de PCM lineal sin encabezado, sin procesar, de 16 bits, con signo, little-endian (audio/l16, 24 kHz, mono) de forma predeterminada para que los fragmentos de audio se puedan reproducir o concatenar de forma continua sin encabezados de contenedor.

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

Formatos de salida de audio

Los modelos de TTS de Gemini 3.8 usan diferentes formatos de audio predeterminados según si la solicitud es unaria o de transmisión:

  • Solicitudes unarias (stream=False): Devuelven audio WAV (audio/wav) completo con un encabezado RIFF estándar (PCM de 24 kHz, mono, 16 bits con signo y orden de bytes little-endian). Puedes guardar los bytes de audio decodificados directamente en un archivo .wav sin anteponer manualmente un encabezado WAV.
  • Solicitudes de transmisión (stream=True): Muestra fragmentos de PCM lineal sin procesar sin encabezado (audio/l16) (PCM de 24 kHz, mono, little-endian con firma de 16 bits) de forma predeterminada para que los fragmentos se puedan transmitir o concatenar de forma continua sin encabezados de contenedor en cada fragmento.

Para solicitar una codificación de audio o una tasa de muestreo diferentes, configura mime_type y el sample_rate opcional dentro de response_format:

Formato Valor mime_type Descripción
WAV (unario predeterminado) "audio/wav" Archivo WAV sin comprimir con un encabezado RIFF (PCM little-endian firmado de 16 bits, mono, 24 kHz predeterminado). Es el valor predeterminado para las solicitudes unarias.
PCM sin procesar (L16) (predeterminado para transmisión) "audio/l16" Audio PCM lineal de 16 bits sin comprimir y sin encabezado, con signo y formato little-endian (24 kHz, mono). Es el valor predeterminado para las solicitudes de transmisión.
Mu-law "audio/mulaw" Audio codificado con ley mu G.711 de 8 bits (de uso frecuente en los sistemas de telefonía/IVR de Norteamérica y Japón).
Ley A "audio/alaw" Audio codificado con ley A de G.711 de 8 bits (de uso frecuente en sistemas de telefonía europeos e internacionales).

También puedes especificar sample_rate en hercios (por ejemplo, 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();

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

Opciones de voz

Gemini 3.8 TTS admite cuatro formas de seleccionar o crear voces:

  1. Voces de Studio precompiladas: 30 voces seleccionadas que se enumeran en la siguiente tabla.
  2. Biblioteca de voces extendida: Cientos de voces adicionales en varios idiomas, acentos y arquetipos de personajes a los que se puede acceder con client.voices.list() (GET /v1beta/voices).
  3. Diseño de voz: Genera un personaje vocal personalizado a partir de una descripción en lenguaje natural en Google AI Studio o con POST /v1beta/voices (type="prompted", que devuelve un ID de voice_... persistente y una vista previa de WAV de sample_audio en CreateVoice y GetVoice).
  4. Replicación de voz: Replica la voz de un orador a partir de audio de referencia y consentimiento en Google AI Studio o con POST /v1beta/voices (type="replicated", store=True persistente de forma predeterminada o store=False opcional sin estado).

Límites de voz personalizada y TTL

Tipo de voz Modo de almacenamiento Cuota o límite Retención (TTL)
Voces con estado (voice_..., replicadas o generadas con instrucciones) store=True 200 voces por proyecto (compartidas entre voces con instrucciones y replicadas) 1 año desde el último uso*
Claves de voz sin estado (voicekey_..., replicadas) store=False Administrado por el cliente 7 días

* Extensión del TTL: El período de retención de 1 año se restablece cada vez que la voz se usa de forma activa (ya sea para sintetizar voz con la voz o usarla como voz base para la remezcla). Las voces que no tengan actividad durante 1 año se borrarán automáticamente.

Voces prediseñadas

Zephyr: Brillante Puck: Alegre Charon: Informativa
Kore: Firme Fenrir: Inquieto Leda: Juvenil
Orus: Firme Aoede -- Breezy Callirrhoe: Tranquila
Autonoe: Brillo Enceladus: Respiración Iapetus: Claro
Umbriel: Relajado Algieba: Suave Despina: Suave
Erinome: Claro Algenib: Gravelly Rasalgethi: Informativa
Laomedeia: Alegre Achernar: Suave Alnilam: Firme
Schedar: Par Gacrux: Maduro Pulcherrima -- Reenviar
Achird: Amigable Zubenelgenubi: Casual Vindemiatrix: Voz amable
Sadachbia: Animada Sadaltager: Conocimiento Sulafat: Cálida

Biblioteca de voces y filtrado extendidos

Además de las 30 voces de estudio destacadas en la tabla anterior, la Biblioteca de voces extendida proporciona cientos de voces adicionales en diferentes idiomas, acentos regionales, personajes y dominios. Puedes explorar, filtrar y probar la biblioteca de voces completa de forma interactiva en Google AI Studio o consultarla de manera programática con client.voices.list() (GET /v1beta/voices, con google-genai 2.25.0+ / @google/genai 2.24.0+).

ListVoices devuelve tus voces almacenadas personalizadas (ordenadas de la más reciente a la más antigua) seguidas de las voces del catálogo precompiladas que coinciden con tus criterios de filtro. Cuando se pasan varios valores para un filtro de lista, se devuelven las voces que coinciden con cualquier valor de ese filtro (OR), mientras que los distintos parámetros de filtro se combinan con AND:

Parámetro Tipo Descripción
language_code list[str] Etiquetas de idioma BCP-47 (por ejemplo, ["en-US", "en-GB"]). Se realiza una coincidencia exacta que no distingue mayúsculas de minúsculas.
region_code list[str] Códigos de región ISO 3166-1 alpha-2 o UN M.49 (por ejemplo, ["US", "GB"]).
accent list[str] Descriptores de acento regional (por ejemplo, ["American", "British"])
gender list[str] Presentación de género percibida ("female", "male" o "neutral").
pitch list[str] Clasificación del tono vocal ("low", "medium" o "high").
persona list[str] Es el arquetipo de personaje o voz (por ejemplo, ["Warm, Friendly"], ["Narrator"]).
contexts (context en REST) list[str] Dominio de uso óptimo (por ejemplo, ["Audiobook", "Conversational", "News"]).
type (type_ en Python) list[str] Filtrar por fuente de voz: "prebuilt", "prompted" (Diseño de voz) o "replicated" (Replicación de voz)
search str Búsqueda de substring de texto libre que coincide sin distinguir mayúsculas de minúsculas con display_name y description.
page_size int Cantidad máxima de voces que se muestran por página (el valor predeterminado es 50 y el máximo es 1000).
page_token str Es el token de response.next_page_token para recuperar la siguiente página de resultados.

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"

Idiomas admitidos

Los modelos de TTS detectan el idioma de entrada automáticamente. Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) admite más de 130 idiomas, y Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) admite más de 100 idiomas:

Idioma TTS de Gemini 3.8 Flash Gemini 3.8 Flash-Lite TTS
Acehnés (escritura árabe) ✔️ ✔️
Afrikaans ✔️ ✔️
Akan ✔️ ✔️
Amárico ✔️ ✔️
Armenio ✔️ ✔️
Asamés ✔️ ✔️
Awadhi ✔️ ✔️
Balinés ✔️ ✔️
Bengalí ✔️ ✔️
Banjar (alfabeto árabe) ✔️ —
Banjar (alfabeto latino) ✔️ ✔️
Baskir ✔️ —
Euskara ✔️ ✔️
Bielorruso ✔️ ✔️
Bemba ✔️ —
Bhojpuri ✔️ ✔️
Bosnio ✔️ ✔️
Buginés ✔️ ✔️
Búlgaro ✔️ ✔️
Birmano ✔️ —
Cantonés ✔️ ✔️
Catalán ✔️ ✔️
Cebuano ✔️ ✔️
Kurdo ✔️ ✔️
Chatisgarí ✔️ ✔️
Chino (secuencia de comandos Hans) ✔️ ✔️
Chino (secuencia de comandos Hant) ✔️ ✔️
Tártaro de Crimea ✔️ —
Croata ✔️ ✔️
Checo ✔️ ✔️
Danés ✔️ ✔️
Holandés ✔️ ✔️
Diula ✔️ —
Dzongkha ✔️ —
Árabe egipcio ✔️ ✔️
Inglés ✔️ ✔️
Estonio ✔️ ✔️
Filipino ✔️ ✔️
Finlandés ✔️ —
Francés ✔️ ✔️
Gallego ✔️ ✔️
luganda ✔️ ✔️
Georgiano ✔️ ✔️
Alemán ✔️ ✔️
Griego ✔️ ✔️
Guaraní ✔️ —
Gujarati ✔️ ✔️
Criollo haitiano ✔️ ✔️
Mongol de Halh ✔️ ✔️
Hausa ✔️ ✔️
Hebreo ✔️ ✔️
Hindi ✔️ ✔️
Húngaro ✔️ ✔️
Islandés ✔️ ✔️
Igbo ✔️ —
Ilocano ✔️ ✔️
Indonesio ✔️ ✔️
Persa iraní ✔️ ✔️
Italiano ✔️ ✔️
Japonés ✔️ ✔️
Javanés ✔️ ✔️
Kabyle ✔️ —
Kamba ✔️ ✔️
Canarés ✔️ ✔️
Cachemir (escritura árabe) ✔️ ✔️
Cachemir (alfabeto Deva) ✔️ ✔️
Kazajo ✔️ ✔️
Jemer ✔️ ✔️
Kikuyu ✔️ ✔️
Kiñarwanda ✔️ ✔️
Congo ✔️ ✔️
Coreano ✔️ ✔️
Kirguís ✔️ ✔️
Laosiano ✔️ ✔️
Latgaliano ✔️ —
Lingala ✔️ ✔️
Lituano ✔️ —
Luxemburgués ✔️ —
Macedonio ✔️ ✔️
Magahi ✔️ ✔️
Maithili ✔️ ✔️
Malayalam ✔️ ✔️
Maltés ✔️ ✔️
Manipuri ✔️ ✔️
Maratí ✔️ ✔️
Minangkabau (escritura árabe) ✔️ ✔️
Minangkabau (alfabeto latino) ✔️ —
Mizo ✔️ ✔️
Nepalí (idioma individual) ✔️ ✔️
Fulfulde nigeriano ✔️ ✔️
Azerí del norte ✔️ ✔️
Sotho norteño ✔️ ✔️
Uzbeko septentrional ✔️ ✔️
Bokmål ✔️ ✔️
Noruego (Nynorsk) ✔️ ✔️
Nyanja ✔️ ✔️
Occitano ✔️ —
Odia (idioma individual) ✔️ ✔️
Pangasinán ✔️ —
Persa (Afganistán) ✔️ ✔️
Polaco ✔️ ✔️
Portugués ✔️ ✔️
Punyabí ✔️ ✔️
Rumano ✔️ ✔️
Ruso ✔️ ✔️
Santali ✔️ ✔️
Serbio ✔️ ✔️
Sindhi ✔️ —
Cingalés ✔️ ✔️
Eslovaco ✔️ ✔️
Esloveno ✔️ —
Somalí ✔️ —
Azerí del sur ✔️ ✔️
Pastún meridional ✔️ ✔️
Sesoto meridional ✔️ —
Español ✔️ ✔️
Árabe estándar (alfabeto árabe) ✔️ ✔️
Árabe estándar (alfabeto latino) ✔️ ✔️
Letón estándar ✔️ ✔️
Malayo estándar ✔️ ✔️
Suajili (idioma individual) ✔️ —
Suazi ✔️ —
Sueco ✔️ —
Tayiko ✔️ —
Tamil ✔️ ✔️
Telugu ✔️ ✔️
Tailandés ✔️ —
Tigrinya ✔️ —
Albanés tosk ✔️ —
Turco ✔️ ✔️
Uigur ✔️ —
Vietnamita ✔️ ✔️

Modelos compatibles

Modelo Orador único Varios oradores Diseño de voz Replicación de voz
TTS de Gemini 3.8 Flash (gemini-3.8-flash-tts) ✔️ ✔️ ✔️ ✔️
Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) ✔️ ✔️ ✔️ ✔️
Versión preliminar del TTS de Gemini 3.1 Flash ✔️ ✔️ — —
TTS de Gemini 2.5 Pro en versión preliminar ✔️ ✔️ — —

Cuándo usar cada modelo

Ambos modelos de TTS de Gemini 3.8 comparten el mismo esquema de API y formato de instrucciones, lo que te permite cambiar entre ellos con un solo cambio de parámetro:

  • Usa Gemini 3.8 Flash TTS (gemini-3.8-flash-tts) cuando la máxima fidelidad acústica, la actuación matizada y el control expresivo sean la principal prioridad. Es ideal para el trabajo creativo de nivel de estudio, los diálogos complejos con varios interlocutores, las etiquetas de ráfagas vocales intensas, las pronunciaciones difíciles, los dialectos regionales o minoritarios y las narraciones de formato largo que requieren una estabilidad sólida de la voz y el tono de la sala.
  • Usa Gemini 3.8 Flash-Lite TTS (gemini-3.8-flash-lite-tts) como tu reemplazo rápido y rentable para gemini-3.1-flash-tts-preview. Está optimizado para la producción masiva de gran volumen, las cascadas de agentes de voz conversacionales, las funciones de lectura en voz alta, la replicación de voz confiable y el habla cotidiana de un solo orador en los principales idiomas.

Guía de migración

Si migras de gemini-3.1-flash-tts-preview o modelos de Gemini TTS anteriores a Gemini 3.8 TTS, ten en cuenta lo siguiente:

  1. Mueve las instrucciones a nivel de turno a speech_metadata: Gemini 3.8 TTS trata el texto de entrada estrictamente como una transcripción literal. Mueve las instrucciones de entrega sostenida (style, como "whispering", "out of breath" o "speaking slowly") y las etiquetas de interlocutor (speaker) a anotaciones speech_metadata estructuradas en lugar de incorporar acotaciones en el texto de la transcripción.
  2. Usa etiquetas intercaladas entre corchetes angulares solo para eventos vocales puntuales: Mantén las vocalizaciones y pausas momentáneas que no sean de voz intercaladas en la transcripción con corchetes angulares (como <laugh>, <sigh>, <cough>, <breath> o <short pause>). Evita las etiquetas de efectos de sonido (como aplausos o golpes) y coloca los estilos de entrega en speech_metadata.style.
  3. Especifica speaker en cada turno de las solicitudes con varios interlocutores: Cada turno de una solicitud con varios interlocutores debe incluir de forma explícita speaker dentro de speech_metadata que coincida con uno de los interlocutores configurados.
  4. Diseña personas por adelantado con el diseño de voz: Reemplaza los bloques "Audio Profile" o "Director's Notes" de varios párrafos por una voz personalizada creada en Diseño de voz y, luego, lleva ese ID de voice_... a través de tus solicitudes de TTS con cadenas style mínimas o vacías.
  5. Ten en cuenta la salida WAV predeterminada (audio/wav) en las solicitudes unarias: A diferencia de gemini-3.1-flash-tts-preview y los modelos de TTS anteriores (que mostraban PCM sin procesar y sin encabezado audio/l16 de forma predeterminada), Gemini 3.8 TTS muestra audio WAV (audio/wav) con un encabezado RIFF estándar de forma predeterminada para las solicitudes unarias.
    • Si tu código antes unía bytes de PCM sin procesar en un encabezado WAV (por ejemplo, con el módulo wave de Python o ffmpeg), quita el wrapper de encabezado manual y escribe los bytes devueltos directamente en un archivo .wav.
    • Si tu canalización requiere audio PCM sin procesar, mu-law o A-law sin encabezado, establece de forma explícita response_format.mime_type en "audio/l16", "audio/mulaw" o "audio/alaw" (por ejemplo, {"response_format": {"type": "audio", "mime_type": "audio/l16"}} en la API de Interactions o AUDIO_L16 en generateContent). Consulta Formatos de salida de audio.

Guía de instrucciones

Los modelos de Gemini 3.8 TTS tratan el texto de entrada estrictamente como una transcripción literal. A diferencia de los modelos de vista previa anteriores, en los que las indicaciones de escena se incorporaban en texto sin formato, Gemini 3.8 TTS separa las indicaciones sostenidas a nivel de turno (speech_metadata) de las etiquetas vocales intercaladas en un momento determinado.

Campo de estilo en comparación con las etiquetas intercaladas

Divide tus instrucciones de rendimiento por alcance:

  • Entrega a nivel de turno (speech_metadata.style): Coloca atributos de entrega sostenida, como emoción, prosodia, ritmo general o estilo de entrega (como "whispering", "out of breath", "muttering" o "sarcastic"), en el campo style de speech_metadata. Para crear un personaje y un rendimiento estables en todos los turnos, diseña el arquetipo de antemano en Diseño de voz y usa style solo para ajustes opcionales a nivel de turno.
  • Eventos puntuales (etiquetas intercaladas): Coloca ráfagas vocales momentáneas que no sean de voz, respiraciones o pausas intercaladas en la transcripción con corchetes angulares (<cough>, <breath>, <sigh>, <short pause>). Usa corchetes angulares (<...>) para obtener la calidad de audio más alta y limítate a las vocalizaciones humanas en lugar de los efectos de sonido no vocales.
Alcance Dónde colocarlo Ejemplos
A nivel de turno (se mantiene durante todo el turno) speech_metadata.style "angry tone", "speaking rapidly", "out of breath", "whispers" y "sarcastic"
En un momento determinado (ocurre en una palabra específica) En línea en text (<...>) "<cough> Thank you all for coming tonight! <throat-clearing> As I was saying..."

Ritmo y pausas

Puedes controlar el ritmo y el silencio en tres niveles de detalle:

  • Puntuación y puntos suspensivos: Usa comas, guiones (--) y puntos suspensivos (...) para generar una vacilación natural en la conversación.
  • Etiquetas de pausa intercaladas: Inserta <short pause> o <long pause> en puntos exactos del guion en los que el interlocutor deba hacer una pausa: text Hold on, let me think... <short pause> Alright, I've got it.
  • Ritmo a nivel de turno: Establece "style": "speaking rapidly" o "style": "speaking slowly" en speech_metadata para controlar la velocidad de habla en todo el turno.

Prosodia y tono

Usa speech_metadata.style para controlar la prosodia, el tono y la inflexión en un turno (por ejemplo, "style": "high pitch, cheerful and excited inflection" o "style": "monotone and flat"). Si la emoción o la prosodia cambian a mitad del diálogo, divide el guion en turnos separados con valores de style distintos para cada turno.

Énfasis

Usa mayúsculas en palabras específicas de la transcripción, junto con signos de puntuación y etiquetas vocales intercaladas, para enfatizar naturalmente las palabras clave:

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

Ráfagas vocales y sonidos no verbales

Coloca las vocalizaciones humanas que no sean de voz intercaladas con corchetes angulares (<...>) en el punto exacto en el que debería producirse el sonido. Entre las etiquetas vocales recomendadas, se incluyen las siguientes:

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

Canales de retroalimentación y voces superpuestas

En los diálogos con varios interlocutores, encierra las reacciones de los oyentes entre caracteres de barra vertical (|reaction|) dentro del turno de un interlocutor para crear canales de retroalimentación naturales o superposiciones de voz sin interrumpir el turno de cada reacción.

  • Intercambios breves de retroalimentación: Agrega reacciones breves del oyente (|oh hmm|, |oh really?|, |absolutely|) dentro del turno del participante activo:
    • Turno 1 (orador A): "So the launch is Thursday |oh hmm| Are we actually ready?"
    • Turno 2 (orador 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."
  • Voz superpuesta y entrelazada: Usa varios segmentos de canalización para simular una voz simultánea o entrelazada entre dos interlocutores (funciona mejor con gemini-3.8-flash-tts):
    • Cuenta regresiva/coro simultáneos: "Let's surprise him on three |ok| ready?" seguido de "one. two. three. |happy| happy |birthday| birthday!"
    • Superposición total de oradores: "Hello |oh| there |my| it |goodness| must |gracious| be |would| almost |you| time |look| for |at that| dinner"

Coherencia entre las generaciones y qué evitar

Sigue estos lineamientos para mantener la identidad vocal estable en los diferentes turnos:

  • Diseña arquetipos por adelantado en el diseño de voz en lugar de usar largos bloques de estilo: Los párrafos de formato largo "Audio Profile" y las listas con múltiples viñetas "Director's Notes" que se transfirieron de modelos anteriores son la causa más común de la desviación de voz. Usa esa misma intuición creativa desde el principio en el diseño de voz para generar un personaje de voice_... personalizado persistente y, luego, lleva ese ID de voz a tus llamadas de TTS.
  • Confía en la referencia de voz para la estabilidad (omite las metainstrucciones): Los modelos de TTS de Gemini 3.8 se entrenan para anclarse primero en la referencia de audio. No incluyas instrucciones que le indiquen al modelo que mantenga la voz estable (como "do not switch speaker identity" o "maintain identical timbre"), ya que el texto adicional de la instrucción aumenta la desviación. Descarta las instrucciones de estilo innecesarias y deja que el modelo varíe de forma natural en torno al punto estable que proporciona la referencia de voz.
  • No intentes cambiar los rasgos inmutables del orador en style: Evita incluir cambios de edad, género, nombres o acento permanentes en speech_metadata.style. En su lugar, elige una voz regional de la biblioteca de voces extendida o crea una con el diseño de voz.
  1. Crea el personaje una vez: Crea tu personaje en Diseño de voz o selecciona una voz regional de la biblioteca de voces extendida que coincida con tu idioma de destino y tu personaje.
  2. Escribe transcripciones habladas naturales con disfluencias: Para lograr la máxima naturalidad, escribe la text como una transcripción hablada real, incluidas las disfluencias y las vacilaciones naturales de la conversación (por ejemplo, "Oh uh yeah I think... hm, so that's interesting").
  3. Primero, prueba el TTS simple: Sintetiza tu transcripción con un campo style vacío primero. La mayoría de las solicitudes no necesitan ninguna instrucción style.
  4. Agrega instrucciones style breves solo para realizar ajustes: Agrega una cadena style concisa (como "casual, friendly" o "muttering, then reassuring") solo para los turnos que necesitan un ajuste de entrega específico y reutiliza esa cadena corta exacta en todos los turnos cuando quieras una base coherente.

Agentes de voz y diálogo de varios turnos

Cuando crees agentes de voz conversacionales en tiempo real o aplicaciones de varios turnos, ten en cuenta lo siguiente:

  • Realiza una llamada de TTS por turno a medida que llegan los fragmentos de texto del LLM.
  • Permite que el voice configurado (precompilado, diseñado voice_... o replicado voice_... / voicekey_...) lleve la identidad del interlocutor en cada turno; nunca vuelvas a enviar un personaje largo en cada turno.
  • Deja vacío el campo style por turno o envía una cadena constante corta (como "casual, friendly") para toda la conversación.
  • Divide las respuestas largas de los agentes en turnos más cortos en lugar de buscar instrucciones de estilo más sólidas.

Limitaciones

  • Los modelos de TTS aceptan entradas solo de texto y generan salidas solo de audio.
  • La generación de varios interlocutores con una sola solicitud (speech_config.speakers) admite hasta 2 interlocutores con voces precompiladas. Para combinar voces diseñadas de forma personalizada (voice_...) o replicadas (voice_... / voicekey_...) en diálogos con varios personajes, sintetiza el turno de cada orador de forma individual. Debido a que las solicitudes unarias devuelven audio/wav con un encabezado RIFF de 44 bytes de forma predeterminada, solicita PCM sin procesar ({"type": "audio", "mime_type": "audio/l16"}) o quita el encabezado WAV de cada turno antes de concatenar los fotogramas de audio PCM de 24 kHz.
  • Límites de almacenamiento de voz personalizada y TTL:
    • Voces con estado (store=True, con instrucciones o replicadas): Un máximo de 200 voces por proyecto con un TTL de 1 año (tiempo de actividad).
    • Claves de voz sin estado (store=False, voicekey_...): TTL de 7 días (tiempo de actividad).
  • Revisa la sección Idiomas admitidos para conocer la cobertura de idiomas.

¿Qué sigue?