av / dives /Realtime Voice: Textbook
source about me

Bonus dive

Chapter 12: The Two Hundred Millisecond Problem

This is the textbook chapter for the Realtime Voice deep dive, a bonus dive that picks up exactly where Multimodal stops. The README is the lab manual; this is the lecture. It covers why conversational voice is a different engineering discipline from everything else in this series, what human conversation actually demands of a machine, and the one architectural fork every voice product must choose a side of.


12.1 What linguists know that engineers forget

In the 2000s, a team of researchers timed thousands of turn transitions in recorded conversations across ten languages, from Danish to Yélî Dnye, a language of Papua New Guinea. The finding: across wildly different cultures, the typical gap between one person finishing and the other starting is around two hundred milliseconds. A fifth of a second. Some transitions are actually negative; the reply begins before the question ends.

Now consider what that number implies. Producing a spoken sentence takes the brain something like six hundred milliseconds of planning before sound comes out. If people waited to hear the end of your sentence before planning their reply, gaps would run close to a second. They do not, which means humans are doing something remarkable in every conversation: predicting how your turn will end while you are still speaking, planning their response in parallel, and launching it the instant they judge you done. Conversation is not a walkie-talkie exchange; it is two prediction engines running full-duplex, and every human being is an expert operator of the protocol without knowing it has rules.

This is why voice interfaces feel broken at delays that would be excellent anywhere else in computing. A web page that responds in a second is fine. A conversational partner that responds in a second has, by the standards your brain enforces without consulting you, gone strange; something between "distracted" and "offended." Users cannot articulate why the agent feels off, but they feel it, reliably, at gaps well under a second. The lab's working budget of roughly 300 to 500 milliseconds before an agent feels sluggish is not a spec-sheet preference; it is a constraint inherited from human neurology, and it is the hardest latency target in this series by an order of magnitude.

Hence the one big idea:

Realtime voice is a low-latency, full-duplex loop: audio streams in and out at once, the agent can be interrupted mid-sentence, and every hundred milliseconds is felt. The engineering is a turn-taking state machine over that stream, plus one architectural choice: a pipeline of three models, or a single speech-to-speech model.

12.2 Why this dive is a simulator, and why that is honest

Before the content, the method, because this dive breaks the series' pattern and the reason is instructive.

A genuine realtime session needs a microphone, a speaker, and a low-latency streaming transport (WebSocket or WebRTC), plus platform-specific audio libraries, echo cancellation, and reconnection handling. None of that can be shown honestly in a small, readable, offline repository; it would be a plumbing project wearing a teaching repo's clothes, and the plumbing would obscure exactly the concepts that matter. So this dive simulates: audio is modeled as timestamped frames, each processing stage carries a latency budget in milliseconds, and the whole apparatus is deterministic, offline, and free.

What is simulated is the transport. What is real is everything this chapter is actually about: the state machine, the interruption logic, the latency arithmetic, and the architectural decision. This is the same pedagogical bet the Production and Harness dives made with their mock providers (study the machinery on a system that behaves on cue), applied to the one domain where the real thing is loudest and least inspectable. The README's production-mapping table is the bridge back to reality, and it is short precisely because the concepts transfer whole.

12.3 There is no recording

The first mental shift is small and total. Every audio system you have built or used in batch mode (the Multimodal dive's transcription included) operates on a complete file: upload, wait, result. Realtime audio never gives you the file. Sound arrives as a stream of tiny frames, ten to twenty milliseconds each, and at any moment all you possess is the stream so far. The user has not finished speaking. They may never finish in a way a file would make crisp. Every decision must be made on a prefix of the data.

The first decision built on that stream is deceptively hard: when has the user stopped talking? This is turn detection (voice-activity detection plus what the trade calls end-pointing), and the naive rule (some run of silence means done) contains a genuine dilemma rather than a tuning detail. Trigger too eagerly and you cut people off mid-thought; every pause for word-finding becomes an interruption. Wait too patiently and you add dead air to every single exchange, which section 12.1 just told you is the one thing you cannot afford. There is no correct threshold, because human pauses are ambiguous; production systems use trained end-pointing models that read prosody and content, not just silence, and they still get it wrong at the margins. When a voice product feels either pushy or slow, this dial is usually why.

12.4 The state machine, and the feature that makes it real

Strip any voice agent to its skeleton and you find a small state machine cycling over the stream: LISTENING (accumulate frames, watch for the turn's end), THINKING (the user stopped; produce a response), SPEAKING (play it), and back to LISTENING. The lab runs a clean three-turn dialogue so you can watch the machine cycle, and if that were the whole story, voice would be a walkie-talkie with good manners.

The feature that separates a conversation from a walkie-talkie is barge-in: the user interrupts while the agent is mid-sentence, and the agent stops, instantly, discards the rest of what it planned to say, and listens. People do this constantly and unapologetically ("no, wait, actually..."), because interruption is a first-class move in the human protocol. An agent that keeps talking over you does not read as slightly deficient; it reads as broken, and talking-over is the most common single failure that ruins voice demos.

Barge-in has two technical prerequisites worth seeing clearly, because both cut against habits from the rest of this series. First, full-duplex operation: the agent must still be listening while it speaks, which sounds obvious and is not; it requires echo cancellation good enough that the agent does not hear its own voice and interrupt itself, a problem telephony spent decades solving. Second, fast cancellation: the instant the user's voice is detected, kill the TTS stream, flush the playback buffer, and cancel the in-flight model response. Note what that last item means: you will routinely throw away work you paid for, mid-generation, because the alternative (finishing the sentence) costs more in conversational trust than the tokens cost in dollars. Batch-mode instincts say never waste a response; voice says waste them cheerfully and often.

The lab's capstone exercise makes a subtle point about this that is worth spelling out: run the same barge-in scenario on a faster and a slower architecture and the interruption lands in different states. The fast agent is already speaking and gets cut off; the slow one is still thinking and the interruption becomes a queued correction. Latency does not just change how the agent feels; it changes which code paths run.

12.5 The latency budget: where a second of dead air comes from

The obvious way to build a voice agent is three models in series, the batch pipeline from the Multimodal dive with ambitions: speech-to-text hears the user, the LLM composes a reply, text-to-speech says it. Every stage works. The problem is arithmetic: the number the user feels is time-to-first-audio, the gap between their last word and the first sound of the reply, and in a naive pipeline the three stages stack. A few hundred milliseconds of transcription, several hundred to a thousand of model time, a few hundred more before synthesis yields its first samples: the sum lands over a second, which section 12.1 priced as conversationally fatal.

The general-purpose fix is the one this series has met twice already (Chapter 1's token streaming, Chapter 6's streaming tool loops), applied ruthlessly: overlap the stages. Stream the transcription as the user speaks rather than transcribing after; stream the LLM's tokens as they generate; begin synthesizing and playing the first sentence while the rest is still being written. None of the stages got faster; the pipeline got concurrent, and time-to-first-audio collapses toward the latency of the slowest first hop rather than the sum of all three. A useful trick of the trade rides on top: the agent can speak a fast acknowledgment ("let me check that...") generated almost instantly, buying the slow reasoning time behind a natural-sounding turn. Perceived latency is a design surface, not just a measurement.

The lab makes the budget visible per stage, in milliseconds, which builds the habit that matters in production: engineer against the number users feel, tracked as percentiles, not against any single stage's spec sheet.

12.6 The fork: pipeline or speech-to-speech

The second way to build a voice agent dissolves the pipeline entirely: a single speech-to-speech model that hears audio and speaks audio, no text in the middle. This is the architecture behind the most fluid consumer voice modes (OpenAI's Realtime API being the prominent example), and where it wins, it wins for two reasons. Latency: one hop instead of three, no stacked handoffs. And naturalness: because the model hears sound rather than a transcript, it perceives tone, hesitation, sarcasm, and pacing, and it can produce them; a transcript flattens "fine." into the same four letters whether it was said warmly or through teeth.

What speech-to-speech gives up is exactly what the pipeline's awkward middle step provided: a transcript, and the control that hangs off it. With text in the middle you can log the conversation, run moderation and the guardrails of Chapter 7, redact what should not be stored, feed RAG and tools with clean queries, evaluate answers with Chapter 5's machinery, and swap vendors per stage. With no text in the middle, every one of those becomes harder, approximate, or impossible; you cannot easily audit what you never had.

So the fork is the series' oldest lesson wearing headphones: it is a control-versus-fluidity tradeoff, and the right side depends on your real constraints. Consumer companions and assistants, where feel dominates and the content is low-stakes: speech-to-speech earns its keep. Regulated domains, transactional flows, anything needing audit trails, tool use, or retrieval mid-call: the pipeline's transcript is not overhead, it is the product's spine. And production systems increasingly refuse to choose cleanly, running speech-to-speech for the conversational turn while a parallel transcription stream feeds safety and logging: the hybrid that buys back observability at the cost of running both.

If this decision structure feels familiar, it should; it is the hosted-versus-client-executed tools fork from Chapter 6 and the compaction-versus-cache tradeoff from Chapter 10, the same judgment (what are you willing to stop seeing, and what does seeing cost?) in a third costume. By this point in the series you are not learning new decisions so much as recognizing one decision in new clothes.

12.7 Where the real world intrudes

A short tour of what production adds, so the simulator's boundaries are marked. The transport becomes WebRTC or WebSocket carrying real PCM frames both directions, with jitter buffers and reconnection. Turn detection becomes a trained model that also ignores backchannels, the "mm-hm" and "right" listeners emit that are participation, not interruption, and that a naive barge-in implementation treats as a reason to stop talking (a genuinely funny failure mode the first time you see it: an agent that halts whenever the user agrees with it). Telephony adds SIP, echo cancellation, and the acoustic chaos of speakerphones in cars. And the biggest deployed use case for all of it is the least futuristic: phone-based customer service, where call volumes are enormous, the conversations are structured, and a voice agent that handles the routine half of calls, and hands off the rest gracefully, is an economic argument that closes itself. Evaluation, per Chapter 5's habits, becomes latency percentiles, interruption-handling rates, and transcription accuracy tracked as numbers rather than demo impressions.

12.8 Where this chapter leaves you

You leave this dive with a discipline map rather than a wiring diagram, and that is the intended trade. The concepts (frames, end-pointing, the state machine, barge-in, time-to-first-audio, the pipeline-versus-speech-to-speech fork) are the durable layer; the transports and vendor APIs churn annually, and the README's mapping table converts one to the other when you need it.

The deeper thing to take is respect for the constraint. Everything else in this series operates on machine time, where a second is slow but survivable. Voice operates on conversational time, a protocol negotiated by human brains over hundreds of thousands of years, with tolerances a fifth of a second wide and violations that users feel before they can name. Engineering inside that budget forces choices (throw away paid-for work, overlap everything, sometimes give up the transcript itself) that look extreme from the batch world and are simply the price of admission here. It is the clearest case in the whole series of a truth that generalizes: the hard constraints in AI engineering are rarely the model's; they are the humans'.


Lab manual: README.md · Exercises: EXERCISES.md · Builds on: Multimodal