Skip to main content
All audio is base64-encoded and mono. Input and output are configured independently and can differ. Browsers and Twilio handle capture, playback, and echo for you. This page is for clients that move the bytes themselves.

Encodings

Both default to audio/pcm at 24 kHz. Change it for telephony, where 8 kHz G.711 matches the phone network and avoids resampling. Set it on the agent when you create or update it:
Or inline, in a session.update:
Inline, output.format is immutable after session.ready, so set it on your first update. Volume is separate, see Output volume.

Sending audio

Send input.audio events continuously, each a base64 chunk in the configured encoding. Chunk size doesn’t matter; ~50 ms works well.
Three rules:
  • Wait for session.ready before the first chunk.
  • Send at real time, not faster. Frames beyond about one second of audio per second of wall clock are dropped, not buffered, and transcription comes back incomplete. Pace pre-recorded test clips with asyncio.sleep.
  • Send raw mic audio. The server denoises already, and a second layer (RNNoise, Krisp, BVC) adds artifacts that cost more accuracy than the noise did. To tune it, use input.voice_focus, see Isolate the caller’s voice.
Without echo cancellation the agent hears itself and interrupts itself, cutting every reply short with status: "interrupted". Native audio APIs (PortAudio, sounddevice) have none, so use headphones. Browsers and carriers handle it for you.

Playing output audio

Write each reply.audio chunk straight into an output buffer and let the OS drain it. The buffer absorbs network jitter, so late messages don’t create gaps:
Don’t schedule playback with sleep. Sleep durations aren’t exact, so the playback clock drifts from the hardware clock and you get pops and gaps.

Handling interruptions

On barge-in the server stops generating and emits reply.done with status: "interrupted", plus transcript.agent with interrupted: true and the text trimmed to what was actually spoken. Flush your queued audio so the user doesn’t hear stale speech, then restart the stream:
Barge-in is semantic: “uh-huh” won’t interrupt, “wait, stop” will. See Turn detection and interruptions.