Транскрипция в реальном времени с помощью Gemini Live API

API Gemini Live поддерживает транскрипцию речи в текст в реальном времени с низкой задержкой, используя модель gemini-3.5-transcribe-live . Подключаясь к API Live через WebSockets или используя SDK Google Gen AI, вы можете передавать непрерывный аудиопоток и получать поэтапную транскрипцию текста в реальном времени по мере произнесения речи.

Благодаря использованию API Gemini Live, такие платформы для разработчиков, как Agora , Fishjam , LiveKit , Pipecat , Vercel и Vision Agents, позволяют разработчикам с легкостью создавать и развертывать высокопроизводительные голосовые интерфейсы. Эти платформы управляют сложной инфраструктурой потоковой передачи мультимедиа в реальном времени, позволяя разработчикам полностью сосредоточиться на создании пользовательского опыта.

Живой агент против живой транскрипции

Хотя оба приложения используют двунаправленное потоковое соединение Live API, Live Transcription работает как специализированный конвейер распознавания речи с низкой задержкой, а не как диалоговый агент.

Особенность Живой агент Транскрипция в прямом эфире
Основная роль Разговорный помощник, который слушает, рассуждает и отвечает. Конвейер преобразования речи в текст в реальном времени, который расшифровывает входящий аудиосигнал.
Способность ответа Аудио- и текстовая речь ( response_modalities=["AUDIO"] ). Потоковая передача текстовых транскрипций ( response_modalities=["TEXT"] ).
Стиль взаимодействия Пошаговый диалог с обнаружением пауз и прерываний. Непрерывная обработка потока данных во время выступления докладчика.
Поддерживаемые функции Вызов функций, поиск в Google, системные инструкции. Смещение речи ( custom_vocabulary ), определение языка, ручная и гибридная обработка речи, интеллектуальная транскрипция.
Входной поток Мультимодальный: аудио, видео, изображения, текст. Аудиовход (необработанный 16-битный PCM).

Начать

Следующие примеры демонстрируют, как открыть сеанс двусторонней потоковой передачи с помощью gemini-3.5-transcribe-live и получать транскрипции в реальном времени.

Python

import asyncio
from google import genai
from google.genai import types

client = genai.Client()
model = "gemini-3.5-transcribe-live"

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    input_audio_transcription=types.AudioTranscriptionConfig(
        language_codes=[],  # Automatic language detection
    ),
)

async def main():
    async with client.aio.live.connect(model=model, config=config) as session:
        print("Session established with Live Transcription")

        # Receive transcription events
        async for response in session.receive():
            server_content = response.server_content
            if server_content and server_content.input_transcription:
                print("Transcript:", server_content.input_transcription.text)

if __name__ == "__main__":
    asyncio.run(main())

JavaScript

import { GoogleGenAI, Modality } from '@google/genai';

const ai = new GoogleGenAI({});
const model = 'gemini-3.5-transcribe-live';

const config = {
  responseModalities: [Modality.TEXT],
  inputAudioTranscription: {
    languageCodes: [], // Automatic language detection
  },
};

async function main() {
  const session = await ai.live.connect({
    model: model,
    config: config,
    callbacks: {
      onopen: () => console.log('Connected to Live Transcription'),
      onmessage: (message) => {
        const content = message.serverContent;
        if (content?.inputTranscription) {
          console.log('Transcript:', content.inputTranscription.text);
        }
      },
      onerror: (e) => console.error('Error:', e.message),
      onclose: (e) => console.log('Connection closed:', e.reason),
    },
  });
}

main();

Веб-сокеты

const API_KEY = "YOUR_API_KEY";
const MODEL_NAME = "gemini-3.5-transcribe-live";
const WS_URL = `wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent?key=${API_KEY}`;

const websocket = new WebSocket(WS_URL);

websocket.onopen = () => {
  console.log('WebSocket connected');

  const setupMessage = {
    setup: {
      model: `models/${MODEL_NAME}`,
      generationConfig: {
        responseModalities: ['TEXT'],
      },
      inputAudioTranscription: {
        languageCodes: []
      }
    }
  };
  websocket.send(JSON.stringify(setupMessage));
};

websocket.onmessage = (event) => {
  const response = JSON.parse(event.data);
  const content = response.serverContent;
  if (content?.inputTranscription) {
    console.log('Transcript:', content.inputTranscription.text);
  }
};

Предварительные и окончательные транскрипции

При передаче аудиопотоков в Live API сервер отправляет два взаимодополняющих поля транскрипции в server_content :

  • interim_input_transcription : частичные гипотезы с низкой задержкой, обновляемые во время активной речи говорящего. Эти частичные обновления происходят быстро с минимальной задержкой. Используйте interim_input_transcription для отображения адаптивных субтитров в реальном времени или предварительного просмотра субтитров.
  • input_transcription : окончательная расшифровка, которая выводится, когда говорящий делает паузу, реплика завершается или речь заканчивается. После вывода этот текст представляет собой авторитетную расшифровку данного фрагмента речи, выполненную моделью. В режиме интеллектуальной расшифровки это будет включать очищенный и отформатированный ответ.

Следующий пример демонстрирует, как отображать промежуточные фрагменты в потоковом режиме и фиксировать окончательные стенограммы:

Python

async def receive_transcripts(session):
    async for response in session.receive():
        server_content = response.server_content
        if not server_content:
            continue

        # Real-time interim hypothesis (updates dynamically as user speaks)
        if server_content.interim_input_transcription:
            interim_text = server_content.interim_input_transcription.text
            print(f"\r[Interim] {interim_text}", end="", flush=True)

        # Finalized transcript (emitted on speech completion)
        if server_content.input_transcription:
            final_text = server_content.input_transcription.text
            print(f"\n[Final] {final_text}")

JavaScript

onmessage: (message) => {
  const content = message.serverContent;
  if (!content) return;

  if (content.interimInputTranscription) {
    // Update live subtitle preview on screen
    renderInterimPreview(content.interimInputTranscription.text);
  }

  if (content.inputTranscription) {
    // Append final committed transcript to chat history
    commitFinalTranscript(content.inputTranscription.text);
  }
};

Веб-сокеты

websocket.onmessage = (event) => {
  const response = JSON.parse(event.data);
  const content = response.serverContent;
  if (content?.interimInputTranscription) {
    console.log('[Interim]:', content.interimInputTranscription.text);
  }
  if (content?.inputTranscription) {
    console.log('[Final]:', content.inputTranscription.text);
  }
};

Отправка аудио

Передача аудиофрагментов по активному соединению в виде необработанного 16-битного PCM-аудио.

  • Аудиоформат: 16-битный PCM-файл с частотой 16 кГц (моно, little-endian).
  • Размер блока: Отправляйте аудиофайлы блоками по 100 мс (от 1024 до 2048 кадров).
  • MIME-тип: audio/pcm;rate=16000 (или соответствующая частота дискретизации).

Python

# Stream a raw PCM audio chunk
await session.send_realtime_input(
    audio=types.Blob(
        data=audio_chunk_bytes,
        mime_type="audio/pcm;rate=16000"
    )
)

# Signal the end of the audio stream when finished
await session.send_realtime_input(audio_stream_end=True)

JavaScript

// Send base64-encoded PCM audio chunk
session.sendRealtimeInput({
  audio: {
    data: audioChunkBase64,
    mimeType: 'audio/pcm;rate=16000'
  }
});

// Signal stream end
session.sendRealtimeInput({
  audioStreamEnd: true
});

Веб-сокеты

// Send base64-encoded PCM audio chunk
websocket.send(JSON.stringify({
  realtimeInput: {
    audio: {
      data: audioChunkBase64,
      mimeType: 'audio/pcm;rate=16000'
    }
  }
}));

// Signal stream end
websocket.send(JSON.stringify({
  realtimeInput: {
    audioStreamEnd: true
  }
}));

Функции транскрипции

Автоматическое определение языка

По умолчанию, если опустить language_codes или установить language_codes=[] включится автоматическое определение языка. Модель динамически определяет язык речи в различных фрагментах текста, включая многоязычные разговоры и переключение кодов.

Python

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    input_audio_transcription=types.AudioTranscriptionConfig(
        language_codes=[],
    ),
)

JavaScript

const config = {
  responseModalities: [Modality.TEXT],
  inputAudioTranscription: {
    languageCodes: [],
  },
};

Веб-сокеты

const setupMessage = {
  setup: {
    model: 'models/gemini-3.5-transcribe-live',
    generationConfig: {
      responseModalities: ['TEXT'],
    },
    inputAudioTranscription: {
      languageCodes: [],
    },
  },
};
websocket.send(JSON.stringify(setupMessage));

Подсказка по конкретному языку

Укажите явные языковые коды BCP-47 (например, ["es-ES"] для испанского или ["fr-FR"] для французского), чтобы сместить распознавание в сторону конкретных языков (см. Поддерживаемые языки ).

Python

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    input_audio_transcription=types.AudioTranscriptionConfig(
        language_codes=["es-ES"],
    ),
)

JavaScript

const config = {
  responseModalities: [Modality.TEXT],
  inputAudioTranscription: {
    languageCodes: ['es-ES'],
  },
};

Веб-сокеты

const setupMessage = {
  setup: {
    model: 'models/gemini-3.5-transcribe-live',
    generationConfig: {
      responseModalities: ['TEXT'],
    },
    inputAudioTranscription: {
      languageCodes: ['es-ES'],
    },
  },
};
websocket.send(JSON.stringify(setupMessage));

Смещение в сторону пользовательской лексики

Предоставьте список из до 1000 фраз, имен собственных, названий брендов или технических терминов в custom_vocabulary , чтобы сместить распознавание речи в сторону конкретной терминологии (наилучшие результаты обычно достигаются при использовании до 100 терминов).

Python

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    input_audio_transcription=types.AudioTranscriptionConfig(
        language_codes=[],
        custom_vocabulary=["Gemini", "Kubernetes", "BigQuery"],
    ),
)

JavaScript

const config = {
  responseModalities: [Modality.TEXT],
  inputAudioTranscription: {
    languageCodes: [],
    customVocabulary: ['Gemini', 'Kubernetes', 'BigQuery'],
  },
};

Веб-сокеты

const setupMessage = {
  setup: {
    model: 'models/gemini-3.5-transcribe-live',
    generationConfig: {
      responseModalities: ['TEXT'],
    },
    inputAudioTranscription: {
      languageCodes: [],
      customVocabulary: ['Gemini', 'Kubernetes', 'BigQuery'],
    },
  },
};
websocket.send(JSON.stringify(setupMessage));

Интеллектуальная транскрипция

Настройте форматирование выходных данных транскрипции, используя параметр mode в input_audio_transcription :

  • VERBATIM (по умолчанию) : Создает точную буквальную транскрипцию всего произнесенного, сохраняя слова-паразиты («ум», «э», «типа»), повторения и ложные начала.
  • SMART (Smart transcription) : Улучшает и структурирует транскрипцию для повышения читабельности:

    • Удаление невнятной речи : удаляет слова-паразиты, заикание и ложные начала.
    • Встроенная самокоррекция : автоматически исправляет голосовые исправления.
    • Структурированное форматирование : автоматически форматирует списки, маркированные списки, числа, даты и разрывы абзацев.
    • Грамматика и регистр : Применяется естественное написание заглавных букв и пунктуация.

Python

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    input_audio_transcription=types.AudioTranscriptionConfig(
        mode="SMART",
    ),
)

JavaScript

const config = {
  responseModalities: [Modality.TEXT],
  inputAudioTranscription: {
    mode: 'SMART',
  },
};

Веб-сокеты

const setupMessage = {
  setup: {
    model: 'models/gemini-3.5-transcribe-live',
    generationConfig: {
      responseModalities: ['TEXT'],
    },
    inputAudioTranscription: {
      mode: 'SMART',
    },
  },
};
websocket.send(JSON.stringify(setupMessage));

Стратегии обнаружения голосовой активности (VAD)

Автоматический ВАД (по умолчанию)

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

Гибридный ВАД

Hybrid VAD сочетает автоматическое определение начала речи на стороне сервера с определением конца речи на стороне клиента для завершения реплики без задержки:

  1. Автоматическая обработка VAD на стороне сервера остается включенной для точного определения начала речи с помощью аудиодополнения в префиксе, предотвращая усечение слов в начале речи.
  2. Обнаружение тишины клиентским устройством VAD : Когда локальное устройство VAD обнаруживает, что говорящий перестал говорить, клиент немедленно отправляет сигнал audio_stream_end .
  3. Быстрая окончательная обработка : Сервер обрабатывает audio_stream_end как немедленный запрос на завершение трансляции, минуя стандартное время ожидания на стороне сервера и возвращая окончательную расшифровку с минимальной задержкой.
  4. Резервный вариант : Если клиентский VAD не срабатывает, серверный VAD автоматически заменяет его.

Python

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    input_audio_transcription=types.AudioTranscriptionConfig(),
)

async with client.aio.live.connect(model=model, config=config) as session:
    # Stream audio chunks...
    await session.send_realtime_input(
        audio=types.Blob(data=chunk, mime_type="audio/pcm;rate=16000")
    )

    # When client-side VAD detects end of speech, send audio_stream_end:
    await session.send_realtime_input(audio_stream_end=True)

JavaScript

const config = {
  responseModalities: [Modality.TEXT],
  inputAudioTranscription: {},
};

// Stream audio...
session.sendRealtimeInput({
  audio: { data: chunkBase64, mimeType: 'audio/pcm;rate=16000' }
});

// When client VAD detects end of speech, send audioStreamEnd:
session.sendRealtimeInput({
  audioStreamEnd: true
});

Веб-сокеты

const setupMessage = {
  setup: {
    model: 'models/gemini-3.5-transcribe-live',
    generationConfig: {
      responseModalities: ['TEXT'],
    },
    inputAudioTranscription: {},
  },
};
websocket.send(JSON.stringify(setupMessage));

// Stream audio...
websocket.send(JSON.stringify({
  realtimeInput: {
    audio: { data: chunkBase64, mimeType: 'audio/pcm;rate=16000' }
  }
}));

// When client VAD detects end of speech, send audioStreamEnd:
websocket.send(JSON.stringify({
  realtimeInput: {
    audioStreamEnd: true
  }
}));

Ручной VAD (Push-to-Talk)

Для интерфейсов раций или кнопок "говори-подключи" полностью отключите автоматическое управление VAD и явно контролируйте границы поворотов с помощью activity_start и activity_end :

Python

config = types.LiveConnectConfig(
    response_modalities=["TEXT"],
    realtime_input_config=types.RealtimeInputConfig(
        automatic_activity_detection=types.AutomaticActivityDetection(
            disabled=True
        )
    ),
    input_audio_transcription=types.AudioTranscriptionConfig(),
)

async with client.aio.live.connect(model=model, config=config) as session:
    # Button pressed: signal speech start
    await session.send_realtime_input(activity_start=types.ActivityStart())

    # Stream audio chunks...
    await session.send_realtime_input(audio=types.Blob(data=chunk, mime_type="audio/pcm;rate=16000"))

    # Button released: signal speech end
    await session.send_realtime_input(activity_end=types.ActivityEnd())

JavaScript

const config = {
  responseModalities: [Modality.TEXT],
  realtimeInputConfig: {
    automaticActivityDetection: {
      disabled: true,
    },
  },
  inputAudioTranscription: {},
};

// Signal speech start
session.sendRealtimeInput({ activityStart: {} });

// Stream audio...

// Signal speech end
session.sendRealtimeInput({ activityEnd: {} });

Веб-сокеты

const setupMessage = {
  setup: {
    model: 'models/gemini-3.5-transcribe-live',
    generationConfig: {
      responseModalities: ['TEXT'],
    },
    realtimeInputConfig: {
      automaticActivityDetection: {
        disabled: true,
      },
    },
    inputAudioTranscription: {},
  },
};
websocket.send(JSON.stringify(setupMessage));

// Button pressed: signal speech start
websocket.send(JSON.stringify({
  realtimeInput: {
    activityStart: {},
  },
}));

// Stream audio...
websocket.send(JSON.stringify({
  realtimeInput: {
    audio: { data: chunkBase64, mimeType: 'audio/pcm;rate=16000' },
  },
}));

// Button released: signal speech end
websocket.send(JSON.stringify({
  realtimeInput: {
    activityEnd: {},
  },
}));

Временные токены в клиентских приложениях

Для приложений, работающих по принципу «клиент-сервер» (например, мобильных или веб-приложений, передающих потоковое видео непосредственно с микрофона), используйте временные токены , чтобы избежать раскрытия ключа API в клиентском коде.

Перед установлением клиентского соединения создайте на сервере временный токен с ограниченными правами доступа:

Python

import datetime
from google import genai

client = genai.Client()
expire_time = datetime.datetime.now(tz=datetime.timezone.utc) + datetime.timedelta(minutes=30)

token = client.auth_tokens.create(
    config={
        "uses": 1,
        "expire_time": expire_time,
        "live_connect_constraints": {
            "model": "gemini-3.5-transcribe-live",
            "config": {
                "response_modalities": ["TEXT"],
                "input_audio_transcription": {
                    "language_codes": [],
                },
            },
        },
    }
)

JavaScript

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

const client = new GoogleGenAI({});
const expireTime = new Date(Date.now() + 30 * 60 * 1000).toISOString();

const token = await client.authTokens.create({
  config: {
    uses: 1,
    expireTime: expireTime,
    liveConnectConstraints: {
      model: 'gemini-3.5-transcribe-live',
      config: {
        responseModalities: ['TEXT'],
        inputAudioTranscription: {
          languageCodes: [],
        },
      },
    },
  },
});

ОТДЫХ

curl -X POST "https://generativelanguage.googleapis.com/v1beta/auth_tokens" \
  -H "x-goog-api-key: ${GEMINI_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "uses": 1,
    "expireTime": "YYYY-MM-DDTHH:MM:SSZ",
    "liveConnectConstraints": {
      "model": "models/gemini-3.5-transcribe-live",
      "config": {
        "responseModalities": ["TEXT"],
        "inputAudioTranscription": {
          "languageCodes": []
        }
      }
    }
  }'

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

В Gemini 3.5 Transcribe Live поддерживаются следующие языки и языковые коды BCP-47:

Язык Код BCP-47 Язык Код BCP-47
африкаанс af-ZA японский ja-JP
амхарский am-ET яванский jv-ID
Арабский (Египет) ar-EG Кабувердиану kea-CV
армянский hy-AM Каннада kn-IN
ассамский as-IN казахский kk-KZ
азербайджанский az-AZ корейский ko-KR
белорусский be-BY кыргызы ky-KG
Бенгальский (Бангладеш) bn-BD латышский lv-LV
Бенгальский (Индия) bn-IN Лингала ln-CD
боснийский bs-BA литовский lt-LT
болгарский bg-BG македонский mk-MK
Болгарский (арумынский) rup-BG малайский ms-MY
бирманский my-MM Малаялам ml-IN
Кантонский (традиционный) yue-Hant-HK мальтийский mt-MT
каталанский ca-ES Китайский язык (упрощенный) cmn-Hans-CN
Себуано ceb маратхи mr-IN
Центральный кхмерский km-KH монгольский mn-MN
хорватский hr-HR непальский ne-NP
чешский cs-CZ норвежский nb-NO
датский da-DK Ория or-IN
Голландский nl-NL польский pl-PL
Английский (Великобритания) en-GB Португальский (Бразилия) pt-BR
Английский (Индия) en-IN Португальский (Португалия) pt-PT
Английский (США) en-US Пенджаби pa-IN
эстонский et-EE Пенджабский (письмо гурмукхи) pa-Guru-IN
фарси fa-IR румынский ro-RO
филиппинский fil-PH Русский ru-RU
финский fi-FI сербский sr-RS
Французский fr-FR Синдхи (арабское письмо) sd-Arab-IN
галисийский gl-ES словацкий sk-SK
грузинский ka-GE словенский sl-SI
немецкий de-DE Испанский (Латинская Америка) es-419
греческий el-GR Испанский (США) es-US
гуджарати gu-IN Суахили (Кения) sw-KE
Хауса ha-NG шведский sv-SE
иврит he-IL Таджик tg-TJ
хинди hi-IN телугу te-IN
венгерский hu-HU Тайский th-TH
исландский is-IS турецкий tr-TR
индийский английский en-IN украинский uk-UA
индонезийский id-ID узбекский uz-UZ
итальянский it-IT вьетнамский vi-VN

Справочник параметров

Настройте транскрипцию в реальном времени, используя поля в input_audio_transcription и realtime_input_config :

Параметр Тип Описание
language_codes Массив строк Языковые коды BCP-47 (например, ["en-US"] ). Если они опущены или пусты ( [] ), модель автоматически определяет язык и обрабатывает многоязычную речь.
custom_vocabulary Массив строк До 1000 пользовательских терминов, акронимов, названий брендов или имен собственных для корректировки распознавания речи.
mode Нить Режим транскрипции: "VERBATIM" (по умолчанию) или "SMART" (умная транскрипция). При выборе режима "SMART" модель удаляет слова-паразиты, форматирует списки и исправляет невнятные речи.
automatic_activity_detection.disabled Логический Установите значение true , чтобы отключить автоматическое определение активности голоса и отправлять сигналы activityStart и activityEnd вручную.

Поля ответа сервера

Поле Описание
server_content.interim_input_transcription Гипотеза о частичной транскрипции с низкой задержкой, осуществляемой непрерывно во время активной речи пользователя.
server_content.input_transcription Окончательная, достоверная стенограмма выводится по завершении реплики.

Ограничения

  • Продолжительность сеанса: Сеансы транскрипции в режиме реального времени поддерживают непрерывную трансляцию продолжительностью до 10 минут.
  • Диалог говорящих: Диалог говорящих не поддерживается в сеансах прямой трансляции. Для диаринга говорящих используйте конечную точку транскрипции аудио , не предназначенную для потоковой передачи.
  • Временные метки на уровне слов: Временные метки на уровне слов не поддерживаются через Live API. Live API выдает временные метки на уровне высказывания ( interim_input_transcription и input_transcription ).
  • Пользовательский словарь: В custom_vocabulary можно указать до 1000 терминов, но наилучшие результаты обычно достигаются при использовании до 100 терминов.
  • Совместимость режимов: интеллектуальная транскрипция ( "mode": "SMART" ) удаляет слова-паразиты и форматирует текст с учетом намерений говорящего, но не может сочетаться с аннотациями слов.

Что дальше?