zebra-report/web
Russell Ballestrini 4d48df96e4
zebra-spaces: role-aware playout delay everywhere — speaker 0.5s, listener 4s
Conversation latency for speakers / cohosts / hosts; lean-back cushion
for listeners. Every receiver type updated together so audio + video
stay in sync (the existing memory rule: video must match audio's
playout delay).

Changes:
1. SPEAKER_PLAYOUT_DELAY_SEC = 0.5; playoutDelayForRole(role) — listener
   gets 4s, all others get 0.5s.

2. attachListenerStreamViaAudioContext → attachAudioStreamViaWorklet
   (generalized). Listener wrapper just calls into it with 4s + the
   Media Session hook. Every role now routes SFU mic audio through the
   AudioWorklet + per-role buffer — so a speaker hearing high-bitrate
   stereo Opus music STILL gets a 0.5s cushion that Firefox's native
   jitter buffer would have ignored.

3. attachSfuTrack: speakers / cohosts / hosts route through the worklet
   path with 0.5s buffer; <audio>-element fallback only on
   AudioContext failure.

4. SFU sub PC video + mic native receiver: jitterBufferTarget +
   playoutDelayHint = playoutDelayForRole(myRole). Listener=4s, others=0.5s.

5. Mesh peer receivers: SPEAKER_PLAYOUT_DELAY_SEC always (mesh is
   always peer-to-peer conversation, no role-mixed case).

6. AudioWorklet handles a {cmd:'retarget', targetSeconds} message —
   recomputes targetSamples / maxSamples and shrinks the queue if the
   new cap is smaller. No reconstruction needed across role changes.

7. retargetAllReceivers(role) called from onRoleChanged before mic
   acquisition starts. Walks listenerAudioNodes (worklet) and
   sfuSubPC.getReceivers() (native audio + video) and applies the new
   target. Mesh peers stay at 0.5s unconditionally.

Speakers were previously running the same 4s setting as listeners. The
native buffer was honoring it for voice (ramping to ~3s) which meant
back-and-forth conversation was effectively impossible — they were
hearing each other 3 seconds late and didn't notice because they were
mostly publishing. This brings conversational latency back to ~500ms
while keeping the listener cushion intact.

No new SDP / signaling — all changes are receiver-side at attach. Role
transition refreshes targets on the existing PC without a renegotiation.
2026-06-04 15:58:59 -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: role-aware playout delay everywhere — speaker 0.5s, listener 4s 2026-06-04 15:58:59 -04:00