Realtime transcription
GET /v1/realtime?intent=transcription — OpenAI's Realtime API in transcription mode.
On this page
Transcribe live audio over a WebSocket. The endpoint speaks OpenAI's Realtime API in transcription
mode, so OpenAI's SDKs and clients work unchanged; the public model must support
audio.transcribe.realtime (today gemini-3.5-transcribe-live, through Gemini's Live API).
Connecting
Open a WebSocket to $GATEWAY/v1/realtime?intent=transcription with your virtual key in the
Authorization: Bearer header (or, from a browser, the openai-insecure-api-key.<key> subprotocol).
The model comes from session.update; a model query parameter is refused with 400 before the
upgrade. The gateway answers with session.created. For voice conversations, connect with
?model= instead: see Realtime conversations.
Session
Send session.update with session.type: "transcription". The model goes in
audio.input.transcription.model; the provider session opens when it is set:
{
"type": "session.update",
"session": {
"type": "transcription",
"audio": {
"input": {
"format": { "type": "audio/pcm", "rate": 24000 },
"transcription": {
"model": "transcribe-live",
"languages": ["es-419", "en-US"],
"keywords": ["AI Gateway", "AC-42"],
"transcription_mode": "smart"
},
"turn_detection": null
}
}
}
}| Field | Behavior |
|---|---|
format | audio/pcm at 24 kHz (OpenAI's default) or 16 kHz, audio/pcmu, audio/pcma. The gateway converts to the provider's format. |
transcription.language / languages | Language hints (BCP-47 for Gemini). Send one or the other. |
transcription.keywords | Vocabulary hints; up to 1,000 for Gemini. |
transcription.transcription_mode | AI Gateway extension: verbatim (default) or smart, which removes fillers and formats numbers. |
transcription.prompt, delay, noise_reduction | Accepted; Gemini has no equivalent, so they are not sent. |
turn_detection | null: each input_audio_buffer.commit ends an utterance. server_vad or semantic_vad: the provider detects pauses. |
include | item.input_audio_transcription.interim adds the interim event below. |
Changing the model, languages, keywords, mode or turn detection opens a new provider session, since the provider fixes its configuration when a session starts. Changing only the audio format does not.
Audio and transcripts
Send audio with input_audio_buffer.append (base64). With turn_detection: null, end each utterance
with input_audio_buffer.commit; input_audio_buffer.clear discards the open one. The gateway
answers with OpenAI's events:
input_audio_buffer.committedandconversation.item.addedfor each utterance;input_audio_buffer.speech_startedandspeech_stoppedaround it with server VAD.conversation.item.input_audio_transcription.deltawhile the provider is still listening.conversation.item.input_audio_transcription.completedwith the finaltranscriptand, when the provider reports it,usagein tokens.
Gemini revises its running guess; OpenAI's deltas only append. So a delta carries only text that
extends what was already sent, and completed always carries the authoritative transcript. To see
every revision, include item.input_audio_transcription.interim: each
conversation.item.input_audio_transcription.interim event carries the full current transcript.
Limits
- A connection lasts at most 60 minutes. Gemini ends a provider session after 10 minutes; the gateway reconnects behind the same public session, so audio keeps flowing.
- Live sessions have no diarization or word timestamps; use
Audio transcriptions with
gemini-3.5-transcribefor those. REALTIME_WEBSOCKET_MAX_CONNECTIONSandREALTIME_WEBSOCKET_MAX_CONNECTIONS_PER_KEYcap open sessions per process and per key.
Each provider session is logged as one realtime.transcription operation with its usage and cost.
Gemini Live reports no usage for transcription sessions, so the gateway estimates it: input tokens
from the audio duration (25 tokens per second, Google's published rate) and output tokens from the
transcript length (about 4 characters per token). The operation is marked usageEstimated, and
completed events carry no usage.