Voice Agent Runtime
A voice agent that runs entirely on a 4 GB laptop GPU.
Speech in, speech out, with no cloud inference. The median reply starts 2.07 s after you stop talking, measured at the client over 179 turns.
Measured
Where the 2.07 seconds go
- Silence window0.80 s
- Speech to text, CPU0.67 s
- Waiting for the first LLM sentence0.42 s
- Speech synthesis0.11 s
- Everything else0.08 s
Each part is its own median, so they add to about 2.07 s and not exactly. About 40% of the delay is waiting to be sure you have stopped speaking, and about a third is transcription on the CPU. The models are not the bottleneck.
179 of 180 turns across three fresh-start runs, 12 pre-recorded utterances, RTX 3050 Laptop 4 GB, Ryzen 5 6600H. The speech is synthetic and single-voice, and the client is a gRPC client, not a browser, so browser capture and WebRTC playout are not included. One call at a time. Faster-Whisper base on the CPU, Qwen2.5 3B through Ollama on the GPU, Piper on the CPU. How each number is measured.
How it is built
A browser connects to AetherRTC, a WebRTC gateway written in Go, integrated with this runtime. It passes audio to a Go orchestrator over gRPC, and the orchestrator streams it to a Python inference engine over a second bidirectional gRPC stream. Audio keeps arriving while a slow model is busy, and replies are spoken sentence by sentence as the model writes them.
The GPU has 4 GB, so only the language model uses it. Speech recognition, speech synthesis and voice activity detection run on the CPU.
- 1BrowserMicrophone and speakerclient
- 2AetherRTCGo, WebRTC, G.711 audioCPU
- 3OrchestratorGo, session state, gRPCCPU
- 4InferenceSilero VAD, Faster-Whisper, PiperCPU
- 5Language modelQwen2.5 3B through OllamaGPU
Demo recording
A recording of a local run.
What it does not do yet
- No barge-in
- You cannot interrupt a reply. The microphone is muted while the agent speaks.
- Short words can be missed
- In a 50-trial replay, the one-word utterance "Hello." was missed 14% of the time by the voice activity detector. The cause is narrowed to its onset confirmation rule and is not fixed.
- An unexplained stall
- In browser testing, a call has stopped answering after about two exchanges. It did not reproduce through the gRPC path, and the cause is unknown.
- Not tested
- Concurrent calls, background noise, and real accents. The benchmark audio is synthetic.