[{"data":1,"prerenderedAt":4},["ShallowReactive",2],{"article-doc:docs\u002Frealtime\u002F8.interruptions-silence":3},"---\ntitle: Handling Interruptions & Silence\ndescription: Silence, pauses, VAD end-of-speech behavior, and connection keepalive.\n---\nHow silence, pauses, and speech interruptions are handled in realtime transcription.\n\n## VAD and speech segmentation\n\nServer-side VAD automatically detects speech segments. The WebSocket events pushed to your client are:\n\n1. Speech detected → `input_audio_buffer.speech_started` (abbreviated as `speech_started`)\n2. Speech continues → audio accumulated\n3. Silence detected → `input_audio_buffer.speech_stopped` (abbreviated as `speech_stopped`)\n4. Transcription complete → `conversation.item.input_audio_transcription.completed` (abbreviated as `completed`)\n\nUse the full `type` string in your event dispatcher. See [Server Events](\u002Fdocs\u002Fapi-reference\u002Fserver-events) for the complete payload schemas.\n\nClients do not need to implement VAD — just consume events.\n\n## Silence behavior\n\n### Short pauses\n\nNormal speaking pauses (commas, sentence ends) do not trigger segment splits. VAD has a silence threshold (`vadSilenceMs`); only silence exceeding this duration triggers end-of-speech.\n\n### Long silence\n\n- Silence exceeding `idle_timeout_seconds` closes the connection with code `4408`.\n- The actual value is returned in `session.created.limits.idle_timeout_seconds`; do not hard-code it.\n- To keep the connection alive, continue sending PCM16LE audio frames, even when they contain silence (all-zero samples).\n\nFor example, a 100 ms silent binary frame at 16 kHz mono is `new Int16Array(1600).fill(0)`. See [Audio Input](\u002Fdocs\u002Frealtime\u002Faudio-input) for frame-size guidance and [Connection Lifecycle](\u002Fdocs\u002Frealtime\u002Fconnection-lifecycle) for close-code details.\n\n## Manual flush\n\nSend `input_audio_buffer.flush` (or its alias `flush`) to force-end the current speech segment:\n\n```json\n{ \"type\": \"input_audio_buffer.flush\" }\n```\n\nUse cases:\n- You know a speech segment has ended (e.g. the user released a push-to-talk button or tapped an end-of-utterance button).\n- Force the upstream to process already-sent audio instead of waiting for VAD.\n- Reduce latency by not waiting for `vadSilenceMs`.\n\n## Max speech segment duration\n\n`vadMaxSpeechMs` limits the maximum duration of a single speech segment. When exceeded:\n\n- The current segment is finalized: `input_audio_buffer.speech_stopped` → `conversation.item.input_audio_transcription.completed`.\n- A new segment starts immediately with `input_audio_buffer.speech_started`.\n- The `reason` field of `speech_stopped` explains why the segment ended (e.g. `end_of_speech` or `max_duration`). See [Server Events](\u002Fdocs\u002Fapi-reference\u002Fserver-events) for the full list of `reason` values.\n\n## Interruption handling\n\n### Speaker interrupted\n\nIn live scenarios, if a speaker is interrupted:\n- Upstream detects the speech boundary.\n- Current segment: `input_audio_buffer.speech_stopped` → `conversation.item.input_audio_transcription.completed`.\n- A new segment starts with `input_audio_buffer.speech_started`.\n\n### Client strategy\n\n1. Each `conversation.item.input_audio_transcription.completed` event is independent and final.\n2. No need to cancel or roll back already-displayed text.\n3. New segments are ordered by `utterance_index`. If two segments overlap in time, use `audio_duration_ms` \u002F `speech_duration_ms` to position them on a timeline rather than relying on arrival order.\n\n## Recommended client handling\n\n```typescript\nws.onmessage = (event) => {\n  if (typeof event.data !== \"string\") return;\n  const data = JSON.parse(event.data);\n\n  if (data.type === \"input_audio_buffer.speech_started\") {\n    showListeningIndicator(data.utterance_index);\n  } else if (data.type === \"input_audio_buffer.speech_stopped\") {\n    showProcessingIndicator(data.utterance_index);\n  } else if (data.type === \"conversation.item.input_audio_transcription.completed\") {\n    appendTranscript(data.utterance_index, data.text);\n    hideIndicators(data.utterance_index);\n  }\n};\n```\n\n## Related\n\n- [Transcript Lifecycle](\u002Fdocs\u002Frealtime\u002Ftranscript-lifecycle) — state transitions\n- [Session Configuration](\u002Fdocs\u002Frealtime\u002Fsession-configuration) — VAD parameters\n- [Connection Lifecycle](\u002Fdocs\u002Frealtime\u002Fconnection-lifecycle) — idle timeout and reconnect\n- [Client Messages](\u002Fdocs\u002Fapi-reference\u002Fclient-messages) — `input_audio_buffer.flush`\n- [Server Events](\u002Fdocs\u002Fapi-reference\u002Fserver-events) — event schemas and `reason` values\n",1790059118958]