zebra-report/web
Russell Ballestrini 64094ecf31
zebra-spaces: route listener audio via AudioContext — bypass Firefox Android <audio> autoplay block
Telemetry on the Firefox Android phone listener exposed the real
mechanism: every <audio>.play() rejects with "play method is not
allowed by the user agent", the audio pool exhausts as the wedge-
recovery cycles, and every fresh element produced fails identically.
Pre-blessing the pool via SILENCE_WAV at entry click does NOT carry
over when srcObject is later swapped to a WebRTC MediaStream —
Firefox Android grants <audio>.play() engagement PER ELEMENT PER
SOURCE, and the gesture window expires before the SFU subscribe
round-trip finishes.

AudioContext has a different model: one resume() inside the user
gesture covers every MediaStreamSource subsequently connected to its
destination. No per-source re-engagement needed.

Implementation:
- attachListenerStreamViaAudioContext(uuid, stream): creates a
  MediaStreamSource + GainNode, connects through to
  audioCtx.destination
- detachListenerStream(uuid): disconnects on peer-left
- attachSfuTrack: if myRole === 'listener', try the AudioContext
  path first; on failure (older browsers) falls through to the
  existing <audio> path
- primeAudioOnGesture now CREATES audioCtx if absent (listeners
  never grab a mic so it wouldn't otherwise exist) + resumes it
  inside the gesture
- peer-left handler also calls detachListenerStream

Listener-only because speakers/cohosts/hosts have an active mic +
setSinkId speaker-picker requirements that still want <audio>
elements. Listeners don't pick speaker output devices and don't
talk — Web Audio is the simpler path that survives the mobile
autoplay regime.

Meter unaffected — startMeter creates its own MediaStreamSource for
analysis (multiple sources per stream is allowed in Web Audio).
2026-06-04 11:46:25 -04:00
..
blog phase 1: unfirehose reconstruction from session JSONL ingest 2026-05-27 13:51:14 -04:00
fonts phase 2: gap analysis — cat>> append + binary asset recovery 2026-05-27 13:54:19 -04:00
chat.html zebra-spaces: listener mute button doubles as audio-unlock gesture 2026-06-03 20:57:09 -04:00
host-your-own.html zebra-spaces: listener mute button doubles as audio-unlock gesture 2026-06-03 20:57:09 -04:00
how-it-works.html zebra-spaces: listener mute button doubles as audio-unlock gesture 2026-06-03 20:57:09 -04:00
index.html web: bump mobile body padding from 1rem to 1.25rem so the right edge has visible breathing room 2026-05-31 14:13:25 -04:00
kernel.html web: bump mobile body padding from 1rem to 1.25rem so the right edge has visible breathing room 2026-05-31 14:13:25 -04:00
stamp.js web: stamp each zebra-report page with build date + md5/sha256 2026-05-28 17:50:12 -04:00
zebra-audio.html zebra-spaces: listener mute button doubles as audio-unlock gesture 2026-06-03 20:57:09 -04:00
zebra-spaces.html zebra-spaces: route listener audio via AudioContext — bypass Firefox Android <audio> autoplay block 2026-06-04 11:46:25 -04:00