fix: clash agents silent — use Chromium new headless so browser audio renders#76
Conversation
… renders
Clash agents broadcast pure 0.000000 silence: the runner launched Chromium
with `headless: true`, which is Playwright's OLD headless ("headless shell")
that has no audio stack. The agents' TTS/WebRTC voice plays inside the page
but is never rendered to the PulseAudio sink, so agora-broadcaster captures
and publishes silence. (The agents' MICs still work — those are fed by
PipeWire pacat/loopback, not the browser — which is why the moderator was
audible but neither agent was.)
Fix: launch with new headless mode (`--headless=new`), which runs the full
Chromium including the audio pipeline, no X server required. Empirically
verified in the live runner container: old headless → Sink_A_Out RMS
0.000000; new headless → RMS 0.199. Mirrors voice-agent-tester, which already
uses new headless for the same reason.
Runner image must be rebuilt (CI on merge) and redeployed (vox-upgrade.sh)
for this to take effect.
🤖 Built with SMT <smt@agora.build>
🤖 Claude Code ReviewThis is a focused, low-risk change. The only functional modification is in Assessment: Looks good. The A few notes, none blocking:
The change is well-scoped, correctly reasoned, and the comments preserve the rationale for future maintainers. Ship it. |
🤖 Codex Code ReviewNo findings. I reviewed the two changed files in PR #76 and don’t see any real security, logic, performance, or maintainability issues from the change. The Checked:
Residual risk: I didn’t run the clash tests or container audio validation locally in this read-only environment, so this review is based on code inspection only. |
Problem
A live clash match produced audible moderator but completely silent agents. Inspecting the broadcasters' captured audio in the running runner container showed both agents' output was perfect digital silence:
agent_a_in/agent_b_in(mic feeds)agent_a_out/agent_b_out(→ uid 100/200)Root cause
browser-agent.tslaunched Chromium withheadless: true— Playwright's old headless mode (the "headless shell"), which has no audio stack. The agents' TTS/WebRTC voice plays inside the page but is never rendered to the PulseAudio sink, soagora-broadcastercaptures and publishes silence. The agents' microphones still work because those are fed by PipeWirepacat/loopback (not the browser) — which is exactly why the moderator was audible while the agents were mute.Fix
Launch with new headless mode (
--headless=new), which runs the full Chromium including the audio pipeline, with no X server required. Mirrorsvoice-agent-tester, which already uses new headless for the same reason.Validation
Empirically verified in the live runner container with a WebAudio tone probe capturing
Sink_A_Out:headless: true):RMS 0.000000--headless=new):RMS 0.199595Typecheck clean; all 64 clash unit tests pass (
clash-audio,clash-runner).Deploy note
Runner-side change — the
vox-clash-runnerimage must be rebuilt (CI on merge, sincevox_clash_runner/**changed) and redeployed viavox-upgrade.shfor this to take effect. No server/schema changes.Generated with SMT smt@agora.io