OpenAI Realtime Transcription
Continuously stream audio over a Realtime WebSocket connection and receive incremental and final transcripts.
Realtime transcription receives continuous audio over a persistent WebSocket connection and returns incremental text and a final transcript for each audio item. It is suitable for live captions, meeting notes, call transcription, and voice input. To upload a complete recording in one request, use the audio transcription API.
gpt-live-transcribe is designed for low-latency incremental transcription. gpt-transcribe is designed for higher-accuracy transcription after a complete speech segment has been submitted and can return detected languages in the final event. Use the same model in the connection URL and session configuration.
wss://api.agtcloud.cn/v1/realtime?model=MODEL_IDAuthentication and connection
Server applications should use a Bearer API key in the WebSocket handshake:
| Item | Value |
|---|---|
| Connection URL | wss://api.agtcloud.cn/v1/realtime?model=MODEL_ID |
| Authorization | Bearer your-api-key |
| OpenAI-Safety-Identifier | Optional pseudonymous end-user identifier |
The WebSocket API in ordinary browsers cannot customize the Authorization header. Do not place a long-lived API key in frontend HTML, JavaScript, or client application bundles. Browser products should connect through a trusted backend or use a controlled short-lived credential mechanism.
Audio input requirements
The examples on this page use headerless, mono PCM16 little-endian audio at 24 kHz. The audio value in input_audio_buffer.append is a Base64 string containing raw PCM bytes, not a WAV file or another audio container.
Send small, consistently sized audio chunks in realtime. A single event must not exceed 15 MiB. Incorrect audio format, sample rate, or container handling can cause transcription to fail.
Session configuration
For session.update, set session.type to transcription. Transcription settings are placed under session.audio.input.transcription:
| Field | Description |
|---|---|
model | Transcription model that matches the model in the connection URL |
prompt | Business scenario, speaking environment, and contextual prompt |
keywords | Proper nouns, abbreviations, and product-name hints; they do not guarantee exact output |
languages | Expected languages, such as zh-cn and en |
delay | Latency setting for realtime models, such as low |
Use noise_reduction.type=near_field for headsets and far_field for meeting rooms or laptop microphones. Set it to null to disable noise reduction.
Manual commit and server VAD
turn_detection: null: The client callsinput_audio_buffer.commitafter sending audio. Use this when the application explicitly controls segmentation.- Server VAD: Configure the threshold, speech prefix, and silence duration so the server automatically detects speech start and end.
Do not commit an empty buffer in manual mode. With VAD enabled, use speech_started and speech_stopped to update the recording UI, but treat the completed event as the final transcript.
Connection examples
The following examples assume that audio.pcm has already been converted to raw, mono PCM16 audio at 24 kHz. A realtime application should continuously send small audio chunks rather than read an entire recording at once.
import fs from 'node:fs';
import WebSocket from 'ws';
const ws = new WebSocket('wss://api.agtcloud.cn/v1/realtime?model=MODEL_ID', {
headers: {
Authorization: 'Bearer your-api-key',
},
});
ws.on('open', async () => {
ws.send(JSON.stringify({
"type": "session.update",
"session": {
"type": "transcription",
"audio": {
"input": {
"format": { "type": "audio/pcm", "rate": 24000 },
"noise_reduction": { "type": "near_field" },
"transcription": {
"model": "MODEL_ID",
"prompt": "Chinese-language customer support call",
"keywords": ["AGTCloud", "API gateway"],
"languages": ["zh-cn", "en"]
},
"turn_detection": null
}
}
}
}));
const audio = fs.createReadStream('audio.pcm', { highWaterMark: 4800 });
for await (const chunk of audio) {
ws.send(JSON.stringify({
type: 'input_audio_buffer.append',
audio: chunk.toString('base64'),
}));
await new Promise((resolve) => setTimeout(resolve, 100));
}
ws.send(JSON.stringify({ type: 'input_audio_buffer.commit' }));
});
ws.on('message', (message) => {
const event = JSON.parse(message.toString());
if (event.type.endsWith('.delta')) process.stdout.write(event.delta);
if (event.type.endsWith('.completed')) console.log('\n', event.transcript);
});Event reference
The client uses session and audio-buffer events to control input. The server associates incremental text, final text, and errors with Item IDs. Different audio items can complete out of order, so aggregate text by item_id.
session.update
Configures the realtime transcription session, input audio, and segmentation.
| Field | Type | Required | Description | Example |
|---|---|---|---|---|
event_id | string | No | Client-generated event ID. | evt_session_001 |
type | string | Yes | Always `session.update`. | session.update |
session.type | string | Yes | Always `transcription`. | transcription |
session.audio.input.format.type | string | Yes | This page uses PCM16 little-endian audio. | audio/pcm |
session.audio.input.format.rate | integer | Yes | PCM input sample rate. | 24000 |
session.audio.input.noise_reduction.type | string | No | Near-field or far-field noise reduction. | near_field |
session.audio.input.transcription.model | string | Yes | Transcription model that matches the connection URL. | MODEL_ID |
session.audio.input.transcription.prompt | string | No | Transcription scenario and contextual prompt. | Chinese-language customer support call |
session.audio.input.transcription.keywords | string[] | No | Hints for proper nouns, abbreviations, or product names. | ["AGTCloud", "API gateway"] |
session.audio.input.transcription.languages | string[] | No | Expected languages. | ["zh-cn", "en"] |
session.audio.input.transcription.delay | string | No | Latency setting for the realtime model. | low |
session.audio.input.turn_detection | object or null | Yes | `null` uses manual commit; an object enables server VAD. | null |
{
"event_id": "evt_session_001",
"type": "session.update",
"session": {
"type": "transcription",
"audio": {
"input": {
"format": {
"type": "audio/pcm",
"rate": 24000
},
"noise_reduction": {
"type": "near_field"
},
"transcription": {
"model": "MODEL_ID",
"prompt": "Chinese-language customer support call",
"keywords": [
"AGTCloud",
"API gateway"
],
"languages": [
"zh-cn",
"en"
],
"delay": "low"
},
"turn_detection": null
}
}
}
}Error handling and recovery
| Type | Common cause | Recommended action |
|---|---|---|
| Handshake failure | Incorrect WSS URL, API key, or request header | Correct the connection settings and establish a new connection |
| Parameter error | Inconsistent session nesting, field value, or model | Read error.event_id and correct the corresponding client event |
| Audio error | Invalid format, sample rate, Base64 data, or file header | Convert the audio again and clear the buffer |
| Transcription failure | Unintelligible audio or failure to process the current audio item | Record the failed Item ID and retry only that speech segment |
| Connection interruption | Network interruption or expired session | Stop sending audio, reconnect a limited number of times, and create a new session |
Incremental text can be revised by later results. Do not write a delta value to an immutable record. Only the transcript value in completed should be treated as the final text for the current audio item.