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 сочетает автоматическое определение начала речи на стороне сервера с определением конца речи на стороне клиента для завершения реплики без задержки:
- Автоматическая обработка VAD на стороне сервера остается включенной для точного определения начала речи с помощью аудиодополнения в префиксе, предотвращая усечение слов в начале речи.
- Обнаружение тишины клиентским устройством VAD : Когда локальное устройство VAD обнаруживает, что говорящий перестал говорить, клиент немедленно отправляет сигнал
audio_stream_end. - Быстрая окончательная обработка : Сервер обрабатывает
audio_stream_endкак немедленный запрос на завершение трансляции, минуя стандартное время ожидания на стороне сервера и возвращая окончательную расшифровку с минимальной задержкой. - Резервный вариант : Если клиентский 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") удаляет слова-паразиты и форматирует текст с учетом намерений говорящего, но не может сочетаться с аннотациями слов.
Что дальше?
- Ознакомьтесь с документацией Gemini Transcribe для работы с аудиофайлами, не являющимися потоковой передачей.
- Ознакомьтесь с обзором API для работы с голосовыми агентами в режиме реального времени .
- Ознакомьтесь с руководством по переводу в режиме реального времени для получения информации о переводе речи в речь.
- Цены на потоковую передачу данных через API в реальном времени можно посмотреть на странице «Цены» .
- Ознакомьтесь с руководством по возможностям Live API .