A API Gemini Live oferece suporte à transcrição de fala em texto em tempo real e com baixa latência usando o modelo gemini-3.5-transcribe-live. Ao se conectar à API Live por WebSockets ou usar o SDK de IA generativa do Google, você pode transmitir entrada de áudio contínua e receber transcrições de texto incrementais em tempo real à medida que a fala ocorre.
Ao aproveitar a API Gemini Live, plataformas de desenvolvedores como Agora, Fishjam, LiveKit, Pipecat, Vercel e Vision Agents permitem que os desenvolvedores criem e implantem interfaces de alta performance controladas por voz com facilidade. Essas plataformas gerenciam uma infraestrutura complexa de streaming de mídia em tempo real nos bastidores, permitindo que os desenvolvedores se concentrem totalmente na criação da experiência do usuário.
Atendente x transcrição instantânea
Embora ambos usem a conexão de streaming bidirecional da API Live, a Transcrição instantânea funciona como um pipeline de reconhecimento de fala dedicado e de baixa latência, em vez de um agente de conversa.
| Recurso | Agente em tempo real | Transcrição em tempo real |
|---|---|---|
| Função principal | Assistente de conversa que ouve, raciocina e responde. | Pipeline de voz em texto em tempo real que transcreve o áudio recebido. |
| Modalidade de resposta | Áudio falado e texto (response_modalities=["AUDIO"]). |
Transcrição de texto por streaming (response_modalities=["TEXT"]). |
| Estilo de interação | Diálogo por turnos com detecção de pausas e interrupções. | Processamento contínuo de streams enquanto o falante fala. |
| Recursos compatíveis | Chamada de função, Pesquisa Google, instruções do sistema. | Preferência de fala (custom_vocabulary), detecção de idioma, VAD manual e híbrido, transcrição inteligente. |
| Fluxo de entrada | Multimodal: áudio, vídeo, imagens, texto. | Entrada de áudio (PCM bruto de 16 bits). |
Primeiros passos
Os exemplos a seguir mostram como abrir uma sessão de streaming bidirecional com gemini-3.5-transcribe-live e receber transcrições em tempo real.
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();
WebSockets
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);
}
};
Transcrição provisória e finalizada
À medida que o áudio é transmitido para a API Live, o servidor emite dois campos de transcrição complementares em server_content:
interim_input_transcription: hipóteses parciais especulativas de baixa latência atualizadas enquanto o falante está falando. Essas atualizações parciais ocorrem rapidamente com atraso mínimo. Useinterim_input_transcriptionpara renderizar legendas responsivas da interface dinâmica ou prévias de legendas.input_transcription: a transcrição finalizada emitida quando o falante faz uma pausa, o turno termina ou a fala é finalizada. Depois de emitido, esse texto representa a transcrição oficial do modelo desse segmento de fala. No modo de transcrição inteligente, isso inclui a resposta limpa e formatada.
O exemplo a seguir demonstra como mostrar resultados parciais provisórios de streaming e confirmar transcrições finais:
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);
}
};
WebSockets
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);
}
};
Enviando áudio
Transmita partes de áudio pela conexão ativa como áudio PCM bruto de 16 bits.
- Formato de áudio:PCM bruto de 16 bits a 16 kHz (mono, little endian).
- Tamanho do bloco:envie áudio em blocos de 100 ms (1.024 a 2.048 frames).
Tipo MIME:
audio/pcm;rate=16000(ou a taxa de amostragem correspondente).
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
});
WebSockets
// 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
}
}));
Recursos de transcrição
Detecção automática de idioma
Por padrão, omitir language_codes ou definir language_codes=[] ativa a identificação automática de idioma. O modelo detecta dinamicamente o idioma falado em todas as declarações, incluindo conversas multilíngues e troca de código.
Python
config = types.LiveConnectConfig(
response_modalities=["TEXT"],
input_audio_transcription=types.AudioTranscriptionConfig(
language_codes=[],
),
)
JavaScript
const config = {
responseModalities: [Modality.TEXT],
inputAudioTranscription: {
languageCodes: [],
},
};
WebSockets
const setupMessage = {
setup: {
model: 'models/gemini-3.5-transcribe-live',
generationConfig: {
responseModalities: ['TEXT'],
},
inputAudioTranscription: {
languageCodes: [],
},
},
};
websocket.send(JSON.stringify(setupMessage));
Dica de idioma específico
Forneça códigos de idioma BCP-47 explícitos (por exemplo, ["es-ES"] para espanhol ou ["fr-FR"] para francês) para direcionar o reconhecimento a idiomas específicos (consulte Idiomas compatíveis).
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'],
},
};
WebSockets
const setupMessage = {
setup: {
model: 'models/gemini-3.5-transcribe-live',
generationConfig: {
responseModalities: ['TEXT'],
},
inputAudioTranscription: {
languageCodes: ['es-ES'],
},
},
};
websocket.send(JSON.stringify(setupMessage));
Bias de vocabulário personalizado
Forneça uma lista de até 1.000 frases, substantivos próprios, nomes de marcas ou termos técnicos em custom_vocabulary para direcionar o reconhecimento de fala a uma terminologia específica. Os melhores resultados geralmente são alcançados com até 100 termos.
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'],
},
};
WebSockets
const setupMessage = {
setup: {
model: 'models/gemini-3.5-transcribe-live',
generationConfig: {
responseModalities: ['TEXT'],
},
inputAudioTranscription: {
languageCodes: [],
customVocabulary: ['Gemini', 'Kubernetes', 'BigQuery'],
},
},
};
websocket.send(JSON.stringify(setupMessage));
Transcrição inteligente
Configure a formatação da saída de transcrição usando o parâmetro mode em input_audio_transcription:
VERBATIM(padrão): produz uma transcrição literal exata de tudo o que foi falado, preservando palavras de preenchimento brutas ("um", "ã", "tipo"), repetições e falsos inícios.SMART(Transcrição inteligente): limpa e estrutura a transcrição para facilitar a leitura:- Remoção de disfluências: remove palavras desnecessárias, gagueira e falsos inícios.
- Autocorreções inline: resolvem correções faladas naturalmente.
- Formatação estruturada: formata automaticamente listas, marcadores, números, datas e quebras de parágrafo.
- Gramática e uso de maiúsculas: aplica capitalização natural e revisão de pontuação.
Python
config = types.LiveConnectConfig(
response_modalities=["TEXT"],
input_audio_transcription=types.AudioTranscriptionConfig(
mode="SMART",
),
)
JavaScript
const config = {
responseModalities: [Modality.TEXT],
inputAudioTranscription: {
mode: 'SMART',
},
};
WebSockets
const setupMessage = {
setup: {
model: 'models/gemini-3.5-transcribe-live',
generationConfig: {
responseModalities: ['TEXT'],
},
inputAudioTranscription: {
mode: 'SMART',
},
},
};
websocket.send(JSON.stringify(setupMessage));
Estratégias de detecção de atividade de voz (VAD)
VAD automático (padrão)
Por padrão, a detecção automática de atividade de voz do lado do servidor detecta quando um falante começa e para de falar.
VAD híbrido
O VAD híbrido combina a detecção automática de início de fala do lado do servidor com a detecção de fim de fala do lado do cliente para finalização de turnos com latência zero:
- A VAD automática do lado do servidor permanece ativada para detectar com precisão o início da fala com padding de áudio de prefixo, evitando o truncamento da primeira palavra.
- A VAD do lado do cliente detecta o silêncio: quando uma VAD local no dispositivo detecta que o falante parou de falar, o cliente envia um sinal
audio_stream_endimediatamente. - Finalização rápida: o servidor trata
audio_stream_endcomo um comando imediato de finalização de turno, ignorando o tempo de espera de silêncio padrão do lado do servidor e retornando a transcrição finalizada com latência mínima. - Substituição: se a VAD do cliente não for acionada, a VAD do lado do servidor vai funcionar como uma substituição automática.
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
});
WebSockets
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 manual (falar para ativar)
Para interfaces de walkie-talkie ou botões push-to-talk, desative totalmente a VAD automática e controle os limites de turno explicitamente usando activity_start e 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: {} });
WebSockets
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: {},
},
}));
Tokens temporários em aplicativos cliente
Para aplicativos cliente-servidor (como apps para dispositivos móveis ou da Web que transmitem diretamente de um microfone), use tokens efêmeros para evitar expor sua chave de API no código do cliente.
Crie um token efêmero restrito no seu servidor antes de iniciar a conexão do cliente:
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: [],
},
},
},
},
});
REST
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": []
}
}
}
}'
Idiomas compatíveis
Os seguintes idiomas e códigos de idioma BCP-47 são compatíveis com o Gemini 3.5 Transcribe Live:
| Idioma | Código BCP-47 | Idioma | Código BCP-47 |
|---|---|---|---|
| Africâner | af-ZA |
Japonês | ja-JP |
| Amárico | am-ET |
Javanês | jv-ID |
| Árabe (Egito) | ar-EG |
Kabuverdianu | kea-CV |
| Armênio | hy-AM |
Canarês | kn-IN |
| Assamês | as-IN |
Cazaque | kk-KZ |
| Azerbaijano | az-AZ |
Coreano | ko-KR |
| Bielorrusso | be-BY |
Quirguiz | ky-KG |
| Bengali (Bangladesh) | bn-BD |
Letão | lv-LV |
| Bengali (Índia) | bn-IN |
Lingala | ln-CD |
| Bósnio | bs-BA |
Lituano | lt-LT |
| Búlgaro | bg-BG |
Macedônio | mk-MK |
| Búlgaro (aromaniano) | rup-BG |
Malaio | ms-MY |
| Birmanês | my-MM |
Malaiala | ml-IN |
| Cantonês (tradicional) | yue-Hant-HK |
Maltês | mt-MT |
| Catalão | ca-ES |
Chinês mandarim (simplificado) | cmn-Hans-CN |
| Cebuano | ceb |
Marati | mr-IN |
| Khmer central | km-KH |
Mongol | mn-MN |
| Croata | hr-HR |
Nepalês | ne-NP |
| Tcheco | cs-CZ |
Norueguês | nb-NO |
| Dinamarquês | da-DK |
Oriá | or-IN |
| Holandês | nl-NL |
Polonês | pl-PL |
| Inglês (Grã-Bretanha) | en-GB |
Português (Brasil) | pt-BR |
| Inglês (Índia) | en-IN |
Português (Portugal) | pt-PT |
| Inglês (EUA) | en-US |
Punjabi | pa-IN |
| Estoniano | et-EE |
Punjabi (script gurmukhi) | pa-Guru-IN |
| Farsi | fa-IR |
Romeno | ro-RO |
| Filipino | fil-PH |
Russo | ru-RU |
| Finlandês | fi-FI |
Sérvio | sr-RS |
| Francês | fr-FR |
Sindi (escrita árabe) | sd-Arab-IN |
| Galego | gl-ES |
Eslovaco | sk-SK |
| Georgiano | ka-GE |
Esloveno | sl-SI |
| Alemão | de-DE |
Espanhol (América Latina) | es-419 |
| Grego | el-GR |
Espanhol (Estados Unidos) | es-US |
| Gujarati | gu-IN |
Suaíli (Quênia) | sw-KE |
| Hauçá | ha-NG |
Sueco | sv-SE |
| Hebraico | he-IL |
Tadjique | tg-TJ |
| Hindi | hi-IN |
Télugo | te-IN |
| Húngaro | hu-HU |
Tailandês | th-TH |
| Islandês | is-IS |
Turco | tr-TR |
| Inglês indiano | en-IN |
Ucraniano | uk-UA |
| Indonésio | id-ID |
Usbeque | uz-UZ |
| Italiano | it-IT |
Vietnamita | vi-VN |
Referência de parâmetros
Configure a transcrição instantânea usando os campos em input_audio_transcription e realtime_input_config:
| Parâmetro | Tipo | Descrição |
|---|---|---|
language_codes |
Matriz de strings | Códigos de idioma BCP-47 (por exemplo, ["en-US"]). Se omitido ou vazio ([]), o modelo detecta automaticamente o idioma e processa a fala multilíngue. |
custom_vocabulary |
Matriz de strings | Até 1.000 termos personalizados, acrônimos, nomes de marcas ou substantivos próprios para influenciar o reconhecimento de fala. |
mode |
String | Modo de transcrição: "VERBATIM" (padrão) ou "SMART" (transcrição inteligente). Quando definido como "SMART", o modelo remove palavras desnecessárias, formata listas e corrige disfluências. |
automatic_activity_detection.disabled |
Booleano | Defina como true para desativar a detecção automática de atividade de voz e enviar manualmente os sinais activityStart e activityEnd. |
Campos de resposta do servidor
| Campo | Descrição |
|---|---|
server_content.interim_input_transcription |
Hipótese de transcrição parcial provisória de baixa latência emitida continuamente enquanto o usuário fala. |
server_content.input_transcription |
Transcrição de entrada finalizada e confiável emitida quando uma rodada de fala termina. |
Limitações
- Duração da sessão:as sessões de transcrição instantânea oferecem suporte a streaming contínuo por até 10 minutos.
- Diarização de falantes:não há suporte para esse recurso em sessões de transmissão ao vivo. Para a diarização de falantes, use o endpoint Transcrição de áudio que não é de streaming.
- Carimbos de data/hora no nível da palavra:eles estão indisponíveis na API Live. A API Live emite carimbos de data/hora no nível do enunciado (
interim_input_transcriptioneinput_transcription). - Vocabulário personalizado:é possível fornecer até 1.000 termos em
custom_vocabulary, mas os melhores resultados geralmente são alcançados com até 100 termos. - Compatibilidade de modo:a transcrição inteligente (
"mode": "SMART") remove palavras de preenchimento e formata o texto com reconhecimento de intenção, mas não pode ser combinada com anotações de palavras.
A seguir
- Leia a documentação do Gemini Transcribe para arquivos de áudio não transmitidos.
- Leia a visão geral da API Live para agentes de voz conversacionais.
- Leia o guia da Tradução instantânea para tradução simultânea em tempo real.
- Confira a página de preços para saber os valores do streaming da API Live.
- Confira o guia de recursos da API Live.