Генерация речи из текста (TTS)

API Gemini позволяет преобразовывать текстовый ввод в аудиозапись с одним или несколькими говорящими, используя возможности генерации речи (TTS) Gemini. Генерация речи управляема , то есть вы можете комбинировать структурированные метаданные реплик ( speech_metadata ) и встроенные голосовые теги для управления стилем , акцентом , темпом и тоном аудиозаписи.

Функция преобразования текста в речь (TTS) отличается от генерации речи, предоставляемой через Live API , которая предназначена для интерактивного, неструктурированного аудио и многомодальных входных и выходных данных. В то время как Live API превосходно подходит для динамичных разговорных контекстов, TTS через Gemini API разработана для сценариев, требующих точного воспроизведения текста с тонкой настройкой стиля и звучания, таких как создание подкастов или аудиокниг.

В этом руководстве показано, как создавать аудиозаписи с одним или несколькими говорящими из текста с помощью Gemini 3.8 Flash TTS ( gemini-3.8-flash-tts ) и Gemini 3.8 Flash-Lite TTS ( gemini-3.8-flash-lite-tts ).

Прежде чем начать

Убедитесь, что вы используете модель Gemini TTS, указанную в разделе «Поддерживаемые модели» . Для достижения оптимальных результатов ознакомьтесь с разделом «Когда использовать ту или иную модель» , чтобы выбрать наиболее подходящую модель для вашей рабочей нагрузки.

Возможно, вам будет полезно протестировать модели Gemini TTS в AI Studio, прежде чем приступать к разработке.

Синхронизация речи и речи с одним динамиком

Для преобразования текста в аудиозапись одного говорящего с использованием моделей Gemini 3.8 TTS передайте дословную расшифровку на input , добавьте стилизацию уровня реплики с помощью аннотации speech_metadata и настройте свой голос в generation_config.speech_config . Вы можете выбрать голос из предустановленных вариантов , расширенной библиотеки голосов ( GET /v1beta/voices ), пользовательского идентификатора дизайна голоса ( voice_... ) или идентификатора репликации голоса ( voice_... , или, при необходимости, stateless voicekey_... ).

В этом примере аудиофайл, сохраненный по умолчанию в формате WAV ( audio/wav ), сохраняется непосредственно в файл из модели:

Python

import base64
from google import genai

client = genai.Client()

interaction = client.interactions.create(
    model="gemini-3.8-flash-tts",
    input=[{
        "type": "user_input",
        "content": [{
            "type": "text",
            "text": "Have a wonderful day!",
            "annotations": [{
                "type": "speech_metadata",
                "style": "cheerful and friendly",
            }],
        }],
    }],
    response_format={"type": "audio"},
    generation_config={
        "speech_config": [
            {"voice": "Kore"},
        ]
    },
)

with open("out.wav", "wb") as f:
    f.write(base64.b64decode(interaction.output_audio.data))

JavaScript

import * as fs from 'node:fs';
import {GoogleGenAI} from '@google/genai';

async function main() {
   const client = new GoogleGenAI({});

   const interaction = await client.interactions.create({
      model: 'gemini-3.8-flash-tts',
      input: [{
         type: 'user_input',
         content: [{
            type: 'text',
            text: 'Have a wonderful day!',
            annotations: [{
               type: 'speech_metadata',
               style: 'cheerful and friendly',
            }],
         }],
      }],
      response_format: { type: 'audio' },
      generation_config: {
         speech_config: [
            { voice: 'Kore' },
         ],
      },
   });

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

Идти

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

ОТДЫХ

curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3.8-flash-tts",
    "input": [{
      "type": "user_input",
      "content": [{
        "type": "text",
        "text": "Have a wonderful day!",
        "annotations": [{
          "type": "speech_metadata",
          "style": "cheerful and friendly"
        }]
      }]
    }],
    "response_format": {
      "type": "audio"
    },
    "generation_config": {
      "speech_config": [
        { "voice": "Kore" }
      ]
    }
  }'

Вы можете получить сгенерированные аудиоданные, используя свойство interaction.output_audio , которое возвращает последний сгенерированный аудиоблок. Подробную информацию об удобных свойствах см. в обзоре взаимодействий .

Многоканальное синтезирование речи

Для диалога с несколькими говорящими настройте двух говорящих в speech_config.speakers и передавайте каждый ход как отдельный текстовый элемент с аннотацией speech_metadata , указывающей speaker и, при необходимости, style уровня хода. Используйте "mode": "conversational" для естественного ритма обмена репликами:

Python

import base64
from google import genai

client = genai.Client()

interaction = client.interactions.create(
    model="gemini-3.8-flash-tts",
    input=[{
        "type": "user_input",
        "content": [
            {
                "type": "text",
                "text": "How's it going today Jane?",
                "annotations": [{
                    "type": "speech_metadata",
                    "speaker": "Joe",
                    "style": "cheerful and friendly",
                }],
            },
            {
                "type": "text",
                "text": "Not too bad, how about you? Ready to test these new voices?",
                "annotations": [{
                    "type": "speech_metadata",
                    "speaker": "Jane",
                    "style": "calm and relaxed",
                }],
            },
        ],
    }],
    response_format={"type": "audio"},
    generation_config={
        "speech_config": {
            "mode": "conversational",
            "speakers": [
                {"speaker": "Joe", "voice": "Puck"},
                {"speaker": "Jane", "voice": "Kore"},
            ],
        }
    },
)

with open("out.wav", "wb") as f:
    f.write(base64.b64decode(interaction.output_audio.data))

JavaScript

import * as fs from 'node:fs';
import {GoogleGenAI} from '@google/genai';

async function main() {
   const client = new GoogleGenAI({});

   const interaction = await client.interactions.create({
      model: 'gemini-3.8-flash-tts',
      input: [{
         type: 'user_input',
         content: [
            {
               type: 'text',
               text: "How's it going today Jane?",
               annotations: [{
                  type: 'speech_metadata',
                  speaker: 'Joe',
                  style: 'cheerful and friendly',
               }],
            },
            {
               type: 'text',
               text: 'Not too bad, how about you? Ready to test these new voices?',
               annotations: [{
                  type: 'speech_metadata',
                  speaker: 'Jane',
                  style: 'calm and relaxed',
               }],
            },
         ],
      }],
      response_format: { type: 'audio' },
      generation_config: {
         speech_config: {
            mode: 'conversational',
            speakers: [
               { speaker: 'Joe', voice: 'Puck' },
               { speaker: 'Jane', voice: 'Kore' },
            ],
         },
      },
   });

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

await main();

Идти

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

ОТДЫХ

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

Управляйте стилем речи с помощью метаданных и тегов.

Система преобразования text поле строго как дословную расшифровку. Чтобы управлять воспроизведением без зачитывания сценических указаний вслух, разделите инструкции по объему:

  • Устойчивая манера речи на протяжении всего реплики ( speech_metadata.style ): В поле style укажите эмоции, стиль речи, просодию, темп и громкость, которые применяются ко всей реплике (например, "style": "whispered urgently" , "style": "out of breath" или "style": "warm and enthusiastic" ).
  • Встроенные теги для обозначения событий в определенный момент времени: размещайте короткие неречевые голосовые всплески или паузы непосредственно внутри транскрипта, используя угловые скобки (например, "Wait... <short pause> did you hear that? <sigh>" или "Excuse me <cough> as I was saying..." ).

Для получения исчерпывающей информации о передовых методах см. руководство по использованию подсказок .

Идти

package main

import (
    "context"
    "log"

    "google.golang.org/genai"
    "google.golang.org/genai/interactions/models/interactions"
    "google.golang.org/genai/interactions/models/operations"
)

func main() {
    ctx := context.Background()
    client, err := genai.NewClient(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }

    transcriptRes, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
        Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
            Model: interactions.Model("gemini-3.8-flash"),
            Input: interactions.NewInteractionsInput(
                "Generate a short transcript around 100 words that reads " +
                    "like it was clipped from a podcast by excited herpetologists. " +
                    "The hosts names are Dr. Anya and Liam.",
            ),
        }),
    })
    if err != nil {
        log.Fatal(err)
    }

    var transcript string
    if transcriptRes.Interaction.OutputText != nil {
        transcript = *transcriptRes.Interaction.OutputText
    }

    generationConfig := &interactions.GenerationConfig{
        SpeechConfig: genai.Ptr(interactions.NewSpeechConfigUnion([]interactions.SpeechConfig{
            {Speaker: genai.Ptr("Dr. Anya"), Voice: genai.Ptr("Kore")},
            {Speaker: genai.Ptr("Liam"), Voice: genai.Ptr("Puck")},
        })),
    }

    ttsRes, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
        Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
            Model: interactions.Model("gemini-3.1-flash-tts-preview"),
            Input: interactions.NewInteractionsInput(transcript),
            ResponseFormat: genai.Ptr(interactions.NewCreateModelInteractionResponseFormat(
                interactions.NewResponseFormat(interactions.AudioResponseFormat{}),
            )),
            GenerationConfig: generationConfig,
        }),
    })
    if err != nil {
        log.Fatal(err)
    }
    _ = ttsRes
}

Генерация потокового речи

Вы можете передавать сгенерированный звук в режиме реального времени по мере его синтеза, установив stream: true . В отличие от унарных запросов (которые возвращают полный WAV-файл с заголовком RIFF), потоковые запросы по умолчанию возвращают необработанные 16-битные знаковые линейные PCM-фрагменты в формате little-endian ( audio/l16 , 24 кГц, моно) без заголовков, поэтому аудиофрагменты можно воспроизводить или объединять непрерывно без заголовков контейнера.

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

ОТДЫХ

curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  -H "Content-Type: application/json" \
  --no-buffer \
  -d '{
    "model": "gemini-3.8-flash-tts",
    "input": [{
      "type": "user_input",
      "content": [{
        "type": "text",
        "text": "Have a wonderful day!",
        "annotations": [{
          "type": "speech_metadata",
          "style": "cheerful and friendly"
        }]
      }]
    }],
    "response_format": {
      "type": "audio"
    },
    "generation_config": {
      "speech_config": [
        { "voice": "Kore" }
      ]
    },
    "stream": true
  }'

Форматы вывода звука

В моделях Gemini 3.8 TTS используются разные форматы аудио по умолчанию в зависимости от того, является ли запрос односторонним или потоковым:

  • Унарные запросы ( stream=False ): Возвращают полный WAV-файл ( audio/wav ) со стандартным заголовком RIFF (24 кГц, моно, 16-битный знаковый PCM в формате little-endian). Вы можете сохранить декодированные аудиобайты непосредственно в файл .wav без ручного добавления заголовка WAV.
  • Запросы потоковой передачи ( stream=True ): По умолчанию возвращают необработанные фрагменты линейного PCM ( audio/l16 ) без заголовков (24 кГц, моно, 16-битный знаковый PCM в формате little-endian), чтобы фрагменты можно было передавать или объединять непрерывно без заголовков контейнера для каждого фрагмента.

Чтобы запросить другое кодирование звука или частоту дискретизации, укажите параметры mime_type и необязательный sample_rate в response_format :

Формат значение mime_type Описание
WAV (унарный формат по умолчанию) "audio/wav" Несжатый WAV-файл с заголовком RIFF (16-битный знаковый PCM в формате little-endian, моно, по умолчанию 24 кГц). По умолчанию для унарных запросов.
Необработанный PCM (L16) (потоковое воспроизведение по умолчанию) "audio/l16" Несжатый, без заголовка, 16-битный знаковый линейный PCM-аудио в формате little-endian (24 кГц, моно). По умолчанию для потоковых запросов.
Му-лоу "audio/mulaw" 8-битное аудио, закодированное по стандарту G.711 mu-law (широко используется в североамериканских и японских системах телефонии/IVR).
Закон "audio/alaw" 8-битное аудио, закодированное по стандарту G.711 A-law (широко используется в европейских и международных телефонных системах).

Также можно указать sample_rate в Герцах (например, 24000 , 16000 или 8000 ).

Python

import base64
from google import genai

client = genai.Client()

interaction = client.interactions.create(
    model="gemini-3.8-flash-tts",
    input=[{
        "type": "user_input",
        "content": [{
            "type": "text",
            "text": "Have a wonderful day!",
            "annotations": [{
                "type": "speech_metadata",
                "style": "cheerful and friendly",
            }],
        }],
    }],
    response_format={
        "type": "audio",
        "mime_type": "audio/l16",  # "audio/wav" (default), "audio/l16", "audio/mulaw", or "audio/alaw"
        "sample_rate": 24000,
    },
    generation_config={
        "speech_config": [
            {"voice": "Kore"},
        ]
    },
)

with open("out.pcm", "wb") as f:
    f.write(base64.b64decode(interaction.output_audio.data))

JavaScript

import * as fs from 'node:fs';
import {GoogleGenAI} from '@google/genai';

async function main() {
   const client = new GoogleGenAI({});

   const interaction = await client.interactions.create({
      model: 'gemini-3.8-flash-tts',
      input: [{
         type: 'user_input',
         content: [{
            type: 'text',
            text: 'Have a wonderful day!',
            annotations: [{
               type: 'speech_metadata',
               style: 'cheerful and friendly',
            }],
         }],
      }],
      response_format: {
         type: 'audio',
         mime_type: 'audio/l16', // 'audio/wav' (default), 'audio/l16', 'audio/mulaw', or 'audio/alaw'
         sample_rate: 24000,
      },
      generation_config: {
         speech_config: [
            { voice: 'Kore' },
         ],
      },
   });

   const audioBuffer = Buffer.from(interaction.output_audio.data, 'base64');
   fs.writeFileSync('out.pcm', audioBuffer);
}
await main();

Идти

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

ОТДЫХ

curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3.8-flash-tts",
    "input": [{
      "type": "user_input",
      "content": [{
        "type": "text",
        "text": "Have a wonderful day!",
        "annotations": [{
          "type": "speech_metadata",
          "style": "cheerful and friendly"
        }]
      }]
    }],
    "response_format": {
      "type": "audio",
      "mime_type": "audio/l16",
      "sample_rate": 24000
    },
    "generation_config": {
      "speech_config": [
        { "voice": "Kore" }
      ]
    }
  }'

Варианты голосового управления

Система синтеза речи Gemini 3.8 TTS поддерживает четыре способа выбора или создания голосов:

  1. Предварительно созданные студийные тембры: 30 тщательно отобранных тембров, перечисленных в следующей таблице.
  2. Расширенная библиотека голосов: сотни дополнительных голосов на разных языках, с разными акцентами и архетипами персонажей, доступных с помощью client.voices.list() ( GET /v1beta/voices ).
  3. Разработка голоса : Создайте пользовательский голосовой образ на основе описания на естественном языке в Google AI Studio или используя POST /v1beta/voices ( type="prompted" , что возвращает постоянный идентификатор voice_... и предварительный просмотр WAV- sample_audio в CreateVoice и GetVoice ).
  4. Воспроизведение голоса : Воспроизведите голос говорящего из эталонного и полученного в результате согласия аудиофайла в Google AI Studio или с помощью POST /v1beta/voices ( type="replicated" , persistent store=True по умолчанию или необязательно stateless store=False ).

Настраиваемые ограничения на количество голосовых вызовов и TTL.

Тип голоса Режим хранения Квота / лимит Время хранения (TTL)
Голоса, выражающие состояние ( voice_... , подсказанные или воспроизведенные) store=True 200 голосов на проект (обмениваются между предложенными и повторяющимися голосами). 1 год
Бессостоятельные голосовые клавиши ( voicekey_... , реплицированные) store=False Управление осуществляется клиентом 7 дней

Предварительно настроенные голоса

Зефир -- Яркий Пакоптимистичный Харонинформативный
Коре -- Фирма ФенрирВозбудимый ЛедаЮная
ОрусФирма Аоэде -- Бризи Каллирродобродушный
АвтоноеЯркое ЭнцеладХрипловатый ЯпетЯсный
Умбриэльдобродушный Алгиеба -- Гладкая Деспина -- Гладкая
Эрином -- Чистый Алгениб -- Грейвли Расалгетиинформативный
Лаомедеяоптимистичная АхернарМягкий Альнилам -- Фирма
Шедардаже Гакруксзрелый Пульчеррима -- Нападающий
АхирдДружелюбный Зубенельгенуби -- Повседневный Виндемиатрикс -- Нежная
Садахбия -- Оживлённый Садалтагерзнающий специалист Сулафат -- Теплый

Расширенная голосовая библиотека и фильтрация

Помимо 30 представленных в предыдущей таблице студийных голосов, расширенная библиотека голосов содержит сотни дополнительных голосов на разных языках, с различными региональными акцентами, для разных персонажей и в разных областях. Вы можете просматривать, фильтровать и прослушивать всю библиотеку голосов в интерактивном режиме в Google AI Studio или запрашивать ее программно с помощью client.voices.list() ( GET /v1beta/voices , using google-genai 2.25.0+ / @google/genai 2.24.0+).

ListVoices возвращает ваши пользовательские сохраненные голоса (в порядке возрастания), за которыми следуют предварительно созданные голоса из каталога, соответствующие критериям фильтра. Если для фильтра списка передается несколько значений, возвращаются голоса, соответствующие любому значению в этом фильтре ( OR ), а различные параметры фильтра объединяются с помощью AND :

Параметр Тип Описание
language_code list[str] Языковые теги BCP-47 (например, ["en-US", "en-GB"] ). Точное совпадение без учета регистра.
region_code list[str] Код(ы) региона ISO 3166-1 alpha-2 или UN M.49 (например, ["US", "GB"] ).
accent list[str] Описание регионального акцента (например, ["American", "British"] ).
gender list[str] Воспринимаемая гендерная идентичность ( "female" , "male" или "neutral" ).
pitch list[str] Классификация высоты вокала ( "low" , "medium" или "high" ).
persona list[str] Голосовой образ или архетип персонажа (например, ["Warm, Friendly"] , ["Narrator"] ).
contexts ( context в REST) list[str] Оптимальная область применения (например, ["Audiobook", "Conversational", "News"] ).
type ( type_ в Python) list[str] Фильтрация по источнику голоса: "prebuilt" , "prompted" ( проектирование голоса ) или "replicated" ( репликация голоса ).
search str Поиск подстроки в свободном тексте с учетом регистра как по имени display_name , так и description .
page_size int Максимальное количество голосов, возвращаемых на странице (по умолчанию 50 , максимум 1000 ).
page_token str Используйте токен из response.next_page_token для получения следующей страницы результатов.

Python

from google import genai

client = genai.Client()

# Filter the Voice Library by language, gender, pitch, domain context, and keyword
response = client.voices.list(
    language_code=["en-US", "en-GB"],
    gender=["female"],
    pitch=["medium", "low"],
    contexts=["Audiobook", "Conversational"],
    type_=["prebuilt"],
    search="warm",
    page_size=50,
)

for voice in response.voices or []:
    print(
        f"{voice.id} | {voice.display_name} ({voice.language_code},"
        f" {voice.accent}, {voice.gender}, pitch={voice.pitch}):"
        f" {voice.description}"
    )

JavaScript

import { GoogleGenAI } from "@google/genai";

const ai = new GoogleGenAI();

// Filter the Voice Library by language, gender, pitch, domain context, and keyword
const response = await ai.voices.list({
  language_code: ["en-US", "en-GB"],
  gender: ["female"],
  pitch: ["medium", "low"],
  contexts: ["Audiobook", "Conversational"],
  type: ["prebuilt"],
  search: "warm",
  page_size: 50,
});

for (const voice of response.voices ?? []) {
  console.log(
    `${voice.id} | ${voice.display_name} (${voice.language_code}, ${voice.accent}, ${voice.gender}, pitch=${voice.pitch}): ${voice.description}`
  );
}

ОТДЫХ

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"

Поддерживаемые языки

Модели синтеза речи автоматически определяют язык ввода. Gemini 3.8 Flash TTS ( gemini-3.8-flash-tts ) поддерживает 130 языков , а Gemini 3.8 Flash-Lite TTS ( gemini-3.8-flash-lite-tts ) — 101 язык .

Язык Gemini 3.8 Flash TTS Gemini 3.8 Flash-Lite TTS
Ачехский (арабский алфавит) ✔️ ✔️
африкаанс ✔️ ✔️
Акан ✔️ ✔️
амхарский ✔️ ✔️
армянский ✔️ ✔️
ассамский ✔️ ✔️
Авадхи ✔️ ✔️
балийский ✔️ ✔️
Бенгальский ✔️ ✔️
Банджар (арабская письменность) ✔️
Банджар (лат.) ✔️ ✔️
Башкир ✔️
Баскский ✔️ ✔️
белорусский ✔️ ✔️
Бемба ✔️
Бходжпури ✔️ ✔️
боснийский ✔️ ✔️
Бугинский ✔️ ✔️
болгарский ✔️ ✔️
бирманский ✔️
кантонский ✔️ ✔️
каталанский ✔️ ✔️
Себуано ✔️ ✔️
Центральный Курдский ✔️ ✔️
Чхаттисгархи ✔️ ✔️
Китайский (Гансовский алфавит) ✔️ ✔️
Китайский (хантийский алфавит) ✔️ ✔️
Крымский татарин ✔️
хорватский ✔️ ✔️
чешский ✔️ ✔️
датский ✔️ ✔️
Голландский ✔️ ✔️
Дьюла ✔️
Дзонгкха ✔️
египетский арабский ✔️ ✔️
Английский ✔️ ✔️
эстонский ✔️ ✔️
филиппинский ✔️ ✔️
финский ✔️
Французский ✔️ ✔️
галисийский ✔️ ✔️
Ганда ✔️ ✔️
грузинский ✔️ ✔️
немецкий ✔️ ✔️
греческий ✔️ ✔️
Гуарани ✔️
гуджарати ✔️ ✔️
гаитянский креольский ✔️ ✔️
Халх Монгольский ✔️ ✔️
Хауса ✔️ ✔️
иврит ✔️ ✔️
хинди ✔️ ✔️
венгерский ✔️ ✔️
исландский ✔️ ✔️
Игбо ✔️
Илоко ✔️ ✔️
индонезийский ✔️ ✔️
иранский персидский ✔️ ✔️
итальянский ✔️ ✔️
японский ✔️ ✔️
яванский ✔️ ✔️
Кабиль ✔️
Камба ✔️ ✔️
Каннада ✔️ ✔️
Кашмирский (арабский алфавит) ✔️ ✔️
Кашмирский (письмо Дева) ✔️ ✔️
казахский ✔️ ✔️
кхмерский ✔️ ✔️
Кикую ✔️ ✔️
Киньяруанда ✔️ ✔️
Конго ✔️ ✔️
корейский ✔️ ✔️
кыргызы ✔️ ✔️
Лао ✔️ ✔️
Латгальский ✔️
Лингала ✔️ ✔️
литовский ✔️
люксембургский ✔️
македонский ✔️ ✔️
Магахи ✔️ ✔️
Майтхили ✔️ ✔️
Малаялам ✔️ ✔️
мальтийский ✔️ ✔️
Манипури ✔️ ✔️
маратхи ✔️ ✔️
Минангкабау (арабская письменность) ✔️ ✔️
Минангкабау (лат.) ✔️
Мизо ✔️ ✔️
Непальский (отдельный язык) ✔️ ✔️
Нигерийский Фульфульде ✔️ ✔️
Северный Азербайджан ✔️ ✔️
Северный Сото ✔️ ✔️
Северный узбек ✔️ ✔️
Норвежский букмол ✔️ ✔️
Норвежский Нюнорск ✔️ ✔️
Ньянджа ✔️ ✔️
окситанский ✔️
Одиа (отдельный язык) ✔️ ✔️
Пангасинан ✔️
Персидский (Афганистан) ✔️ ✔️
польский ✔️ ✔️
португальский ✔️ ✔️
Пенджаби ✔️ ✔️
румынский ✔️ ✔️
Русский ✔️ ✔️
Сантали ✔️ ✔️
сербский ✔️ ✔️
Синдхи ✔️
сингальский ✔️ ✔️
словацкий ✔️ ✔️
словенский ✔️
сомалийский ✔️
Южный Азербайджан ✔️ ✔️
Южный пушту ✔️ ✔️
Южный Сото ✔️
испанский ✔️ ✔️
Стандартный арабский язык (арабская письменность) ✔️ ✔️
Стандартный арабский язык (лат. алфавит) ✔️ ✔️
Стандартный латышский ✔️ ✔️
Стандартный малайский ✔️ ✔️
Суахили (отдельный язык) ✔️
Свати ✔️
шведский ✔️
Таджик ✔️
тамильский ✔️ ✔️
телугу ✔️ ✔️
Тайский ✔️
тигринья ✔️
Тоск Албанский ✔️
уйгурский ✔️

Поддерживаемые модели

Модель Один динамик Многоканальный Дизайн голоса репликация голоса
Gemini 3.8 Flash TTS ( gemini-3.8-flash-tts ) ✔️ ✔️ ✔️ ✔️
Gemini 3.8 Flash-Lite TTS ( gemini-3.8-flash-lite-tts ) ✔️ ✔️ ✔️ ✔️
Gemini 3.1 Flash TTS Preview ✔️ ✔️
Gemini 2.5 Pro Preview TTS ✔️ ✔️

Когда использовать ту или иную модель

Обе модели Gemini 3.8 TTS используют одну и ту же схему API и формат подсказок, что позволяет переключаться между ними всего одним изменением параметра:

  • Используйте Gemini 3.8 Flash TTS ( gemini-3.8-flash-tts ), когда приоритетными являются максимальная акустическая точность, тонкая игра актеров и выразительный контроль. Он идеально подходит для студийной работы, сложных диалогов с участием нескольких говорящих, интенсивных вокальных вставок, сложных произношений, региональных или национальных диалектов, а также длинных повествований, требующих безупречного голоса и стабильности акустики помещения.
  • Используйте Gemini 3.8 Flash-Lite TTS ( gemini-3.8-flash-lite-tts ) в качестве быстрой и экономичной замены для gemini-3.1-flash-tts-preview . Он оптимизирован для обработки больших объемов данных, каскадирования голосовых агентов, функций чтения вслух, надежного воспроизведения голоса и повседневной речи одного говорящего на основных языках.

Руководство по миграции

Если вы переходите с gemini-3.1-flash-tts-preview или более ранних моделей Gemini TTS на Gemini 3.8 TTS:

  1. Переместите указания уровня реплики в speech_metadata : Gemini 3.8 TTS обрабатывает входной текст строго как дословную расшифровку. Переместите указания продолжительности речи ( style — например, "whispering" , "out of breath" или "speaking slowly" ) и метки говорящего ( speaker ) в структурированные аннотации speech_metadata а не встраивайте указания уровня речи в текст расшифровки.
  2. Используйте теги в угловых скобках только для отдельных голосовых событий: короткие неречевые вокализации и паузы следует размещать непосредственно в транскрипте с помощью угловых скобок (например <laugh> , <sigh> , <cough> , <breath> или <short pause> ). Избегайте тегов звуковых эффектов (например, аплодисменты или глухие удары) и указывайте стили подачи в файле speech_metadata.style .
  3. В запросах с несколькими говорящими необходимо явно указывать speaker в каждом раунде: в каждом раунде запроса с несколькими говорящими необходимо явно указывать speaker в speech_metadata соответствующего одному из настроенных говорящих.
  4. Создавайте портреты пользователей заранее с помощью Voice Design: замените многоабзацные блоки "Audio Profile" или "Director's Notes" пользовательским голосом, созданным в Voice Design , а затем используйте этот идентификатор voice_... в запросах TTS с минимальными или пустыми строками style .
  5. Учитывайте вывод WAV-файлов по умолчанию ( audio/wav ) при унарных запросах: в отличие от gemini-3.1-flash-tts-preview и более ранних моделей TTS (которые по умолчанию возвращали необработанный PCM- audio/l16 без заголовка), Gemini 3.8 TTS по умолчанию возвращает WAV-аудиофайлы ( audio/wav ) со стандартным заголовком RIFF для унарных запросов.
    • Если в вашем коде ранее необработанные PCM-байты были упакованы в заголовок WAV (например, с помощью модуля wave в Python или ffmpeg ), удалите эту ручную упаковку заголовка и запишите полученные байты непосредственно в файл .wav .
    • Если ваш конвейер обработки данных требует необработанного аудио в формате PCM, mu-law или A-law без заголовка, явно установите response_format в значение "audio/l16" , "audio/mulaw" или "audio/alaw" . См. раздел " Форматы вывода аудио" .

Руководство по подсказкам

В моделях Gemini 3.8 TTS входной текст обрабатывается строго как дословная расшифровка . В отличие от более ранних предварительных моделей, где указания на реплики были встроены в обычный текст, Gemini 3.8 TTS отделяет подробные указания на уровне реплик ( speech_metadata ) от встроенных голосовых тегов на определенный момент времени.

Поле стиля против строчных тегов

Разделите инструкции по производительности по областям применения:

  • Стиль речи на уровне реплик ( speech_metadata.style ): Укажите атрибуты продолжительности речи — такие как эмоции, просодия, общий темп или стиль речи (например, "whispering" , "out of breath" , "muttering" или "sarcastic" ) — в поле style файла speech_metadata . Для создания стабильного персонажа и исполнения на протяжении реплик, разработайте образ заранее в разделе «Дизайн голоса» и используйте style только для необязательных корректировок на уровне реплик.
  • Встроенные теги для обозначения отдельных моментов времени: вставляйте короткие неречевые голосовые всплески, вдохи или паузы непосредственно в транскрипт, используя угловые скобки ( <cough> , <breath> , <sigh> , <short pause> ). Используйте угловые скобки ( <...> ) для обеспечения наилучшего качества звука и отдавайте предпочтение человеческим вокализациям, а не неречевым звуковым эффектам.
Объем Где разместить Примеры
Уровень управляемости на повороте (поддерживается на протяжении всего поворота) speech_metadata.style "angry tone" , "speaking rapidly" , "out of breath" , "whispers" , "sarcastic"
Момент времени (события, произошедшие в конкретное время) Встроенный text ( <...> ) "<cough> Thank you all for coming tonight! <throat-clearing> As I was saying..."

Темп и паузы

Вы можете управлять ритмом и тишиной на трех уровнях детализации:

  • Пунктуация и многоточие: Используйте запятые, тире ( -- ) и многоточие ( ... ) для естественной разговорной нерешительности.
  • Встроенные теги паузы: Вставьте <short pause> или <long pause> именно в тех местах сценария, где говорящий должен сделать паузу: text Hold on, let me think... <short pause> Alright, I've got it.
  • Темп речи на протяжении всего хода: установите параметр "style": "speaking rapidly" или "style": "speaking slowly" в speech_metadata , чтобы контролировать темп речи на протяжении всего хода.

Просодия и высота звука

Используйте speech_metadata.style для управления просодией, высотой тона и интонацией в течение диалога (например, "style": "high pitch, cheerful and excited inflection" или "style": "monotone and flat" ). Если эмоция или просодия меняются в середине диалога, разделите сценарий на отдельные реплики с различными значениями style для каждой реплики.

Акцент

Используйте заглавные буквы в отдельных словах транскрипта, сочетая их с пунктуацией и встроенными голосовыми метками, чтобы естественно расставить ударения на ключевых словах:

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

Вокальные всплески и неречевые звуки

Размещайте неречевые человеческие вокализации в строке, используя угловые скобки ( <...> ), точно в том месте, где должен звучать звук. Рекомендуемые вокальные теги включают:

<argh> <breath> <heavy breath> <exhales>
<cackle> <cheer> <chuckle> / <chuckles> <cough>
<cry> <gasp> <giggle> <groan>
<growl> <grunt> <grr> <hiss>
<laugh> / <laughter> <moan> <pant> <pff> / <phew>
<scream> <shout> <shriek> <sigh> / <sighs>
<sneeze> <snicker> <snort> <sob>
<throat-clearing> <tsk> <whimper> <whispers> / <whispering>
<yawn> <short pause> <long pause>

Обратные каналы связи и наложение речи

В диалогах с несколькими говорящими используйте символы конвейера ( |reaction| ) для обозначения реакций слушателей внутри реплики говорящего, чтобы создать естественные обратные каналы или наложение речи без необходимости создавать отдельную реплику для каждой реакции.

  • Короткие обмены репликами: Встраивайте короткие реакции слушателей ( |oh hmm| , |oh really?| , |absolutely| ) в реплику активного говорящего:
    • Первый ход (говорящий А): "So the launch is Thursday |oh hmm| Are we actually ready?"
    • Поворот 2 (говорящий B): "Ready enough |oh really?| The last blocker cleared this morning."
    • Третий ход (говорящий А): "Then let's ship it |absolutely| and watch the dashboards."
  • Перекрывающаяся и чередующаяся речь: Используйте несколько сегментов конвейера для имитации одновременной или чередующейся речи двух говорящих (лучше всего работает с gemini-3.8-flash-tts ):
    • Обратный отсчет/припев: "Let's surprise him on three |ok| ready?" затем "one. two. three. |happy| happy |birthday| birthday!"
    • Полное наложение реплик говорящих: "Hello |oh| there |my| it |goodness| must |gracious| be |would| almost |you| time |look| for |at that| dinner"

Последовательность в разных поколениях и чего следует избегать

Следуйте этим рекомендациям, чтобы сохранить стабильность вокальной идентичности на протяжении всего выступления:

  • При разработке голосового дизайна сначала создавайте портреты пользователей, а не длинные стилистические блоки: длинные абзацы "Audio Profile" и многопунктные "Director's Notes" перенесенные из более ранних моделей, являются наиболее распространенной причиной смещения голоса. Используйте ту же творческую интуицию на начальном этапе разработки голосового дизайна , чтобы создать постоянный пользовательский voice_... а затем используйте этот идентификатор голоса во всех ваших TTS-вызовах.
  • Для обеспечения стабильности используйте эталонный голос (опустите мета-инструкции): модели синтеза речи Gemini 3.8 обучены сначала ориентироваться на аудиоэталонный сигнал. Не включайте инструкции, указывающие модели на необходимость поддерживать стабильный голос (например "do not switch speaker identity" или "maintain identical timbre" ) — лишний текст подсказок увеличивает дрейф. Удалите ненужные указания на стиль и позвольте модели естественным образом изменять свой голос вокруг стабильной точки, обеспечиваемой эталонным голосом.
  • Не пытайтесь изменять неизменяемые характеристики говорящего в style : избегайте указания возраста, пола, имен или постоянных изменений акцента в speech_metadata.style . Вместо этого выберите региональный голос из расширенной библиотеки голосов или создайте его с помощью инструмента проектирования голоса .
  1. Создайте персонажа один раз: настройте голос персонажа в разделе «Озвучивание» или выберите региональный голос из расширенной библиотеки голосов, соответствующий вашему целевому языку и образу.
  2. Пишите естественные устные транскрипции с учетом неплавности речи: для максимальной естественности записывайте text как реальную устную транскрипцию, включая естественные разговорные неплавности и паузы (например, "Oh uh yeah I think... hm, so that's interesting" ).
  3. Сначала протестируйте обычный TTS: сначала синтезируйте свою расшифровку с пустым полем style — большинству запросов вообще не нужны указания style .
  4. Добавляйте короткие style подсказки только для внесения изменений: используйте лаконичную style строку (например, "casual, friendly" или "muttering, then reassuring" ) только для реплик, требующих конкретной корректировки подачи, и используйте эту же короткую строку для разных реплик, если вам нужен единый базовый уровень.

Многоходовые диалоги и голосовые агенты

При создании голосовых агентов для диалогового взаимодействия в реальном времени или многошаговых приложений:

  • Совершайте один вызов TTS за ход по мере поступления текстовых фрагментов LLM.
  • Пусть настроенный voice (предварительно созданный, разработанный voice_... или реплицированный voice_... / voicekey_... ) передает личность говорящего между ходами — никогда не отправляйте длинный текст с именем персонажа каждый ход.
  • Оставьте поле style для каждого хода пустым или отправьте одну короткую постоянную строку (например, "casual, friendly" ) для всего разговора.
  • Разделите длинные ответы агентов на более короткие реплики, вместо того чтобы использовать более сложные стилистические приемы.

Ограничения

  • Модели TTS принимают только текстовый ввод и выдают только аудиовывод.
  • Генерация многоголосого диалога по одному запросу ( multiSpeakerVoiceConfig / multi-speaker speakers ) поддерживает до 2 говорящих с использованием предварительно созданных голосов. Для объединения специально разработанных ( voice_... ) или дублированных ( voicekey_... ) голосов в многосимвольном диалоге синтезируйте реплики каждого говорящего по отдельности и объединяйте аудиокадры PCM с частотой 24 кГц.
  • Настраиваемые ограничения на объем хранилища голосовых данных и значение TTL:
    • Голоса с сохранением состояния ( store=True , с запросом или репликацией): Максимум 200 голосов на проект с временем жизни ( TTL) 1 год .
    • Бессостоятельные голосовые ключи ( store=False , voicekey_... ): 7-дневное время жизни (TTL ).
  • Для получения информации о поддерживаемых языках ознакомьтесь с разделом «Поддерживаемые языки».

Что дальше?

  • Создавайте индивидуальные голосовые образы на основе естественного языка с помощью функции Voice Design .
  • Воспроизведите голос существующего говорящего в функции «Воспроизведение голоса» .
  • Сравните технические характеристики моделей Gemini 3.8 Flash TTS и Gemini 3.8 Flash-Lite TTS на страницах соответствующих товаров.
  • Изучите возможности интерактивного двунаправленного звука с помощью Live API .