Continues ticket 0001 fix. Fox 2026-06-07 second telemetry pass showed
blanka-chrome's audioCtx sink reverted to 'default' after a leave/rejoin
even though the user had a picked device, because applySinkToAudioCtx
only ran inside the `if (!audioCtx)` branch and a persistent ctx with a
drifted sinkId stayed default forever.
Attach now re-applies sink when audioCtx exists + speakerDeviceId is set
+ ctx.sinkId differs. Per-tick telemetry exposes ctx.sink= (and want= on
mismatch) so the next session can verify sink stays on the picked device
across leave/rejoin.
Source commit: 4cedd85 in zebra-report.git
Pulls in zebra-report b9e2541: telemetry tick now emits per-peer
mesh.recv lines with the mesh PC's inbound audio receiver stats
(pkt/lost/bytes/jitter/level/jbuf/lp + short uuid prefix). Closes
the visibility gap on ticket 0001 — we can now see whether mesh's
audio decoder is alive or also silent when SFU's receiver is
orphaned by the worklet swap. fox 2026-06-07.
Fixes ticket 0001 (fedora chrome cannot hear speakers) — fox 2026-06-07
telemetry ruled out the sink hypothesis from 0f36e02 and pinned two
coupled defects:
(A) tracks=0 race in handleRemoteSfuTrack mic branch — ev.streams[0]
can be empty at handler-time even when ev.track is live; the
silent <audio> fallback ate the listener.
(B) Mesh ontrack swapped the worklet to the mesh stream even when
the mesh track was still muted, orphaning the SFU receiver and
trapping the listener on a silent mesh source.
Mic now mirrors screen/camera/game (new MediaStream([ev.track])) and
the mesh swap waits for 'unmute' / restores SFU after a mute window.
Source commit: caa0548 in zebra-report.git
Pulls in zebra-report 1ed5263: every entry now emits a one-shot
'session: ua=... ctx={...} devs={...} picked={...}' line so the
signal-server log carries browser + audioCtx + device-count + saved-
deviceId-shortprefix context for diagnosing the open tickets
(0001 fedora chrome silence, 0002 fedora firefox cannot share camera).
Camera-open errors now include e.name + the constraints we tried
plus auto-recovery from OverconstrainedError + saved deviceId.
Pulls in zebra-report 467146a: every audioCtx now routes to the
user-picked output sink via applySinkToAudioCtx(). Fixes the
fedora chrome silent-speaker telemetry where RTP arrived, worklet
started, ctxState=running, but no audio reached the user — because
audioCtx.destination was always emitting to system default while
the speaker dropdown set <audio> sinks only. fox 2026-06-06.
Audio path now respects the picker on Chrome ≥110 and Firefox ≥116.
Older browsers continue to fall through to default.
Pulls in zebra-report 9215eaa: JitterBufferProcessor now drops the
queue down to targetSamples (not 1.5×target) on a shrinking retarget,
eliminating the residual 6%-cap speed-up phase fox heard as "janky
slow" during listener-to-speaker promotion. The processor reports
the dropped sample count back to JS so installJitterBuffer's port
handler zeros every paired video receiver's jitterBufferTarget +
playoutDelayHint — video frames drop in lockstep with the audio
skip so lip-sync survives the jump.
Fox 2026-06-06: "if we skip ahead from whatever listener is at to
speaker speed, we need to make sure the video skips ahead the same
amount or rate to keep the lips synced".
Behavior change is isolated to the role-change moment (4s→0.5s on
promote). Steady-state audio and listener-only sessions unchanged.
Pulls in two upstream zebra-report commits:
0ce1339 prefix-match in flushSfuStreams (kills the silent
fedora-chrome listener: ontrack races peer-joined, cache
keyed by 16-char streamID prefix, flush's strict-equality
matcher never resolved short→full, listener heard nothing
from anyone already in the room).
5e8cdad send 'bye' on pagehide for listeners even when
persisted=true (kills the closed-firefox-phone roster
zombies sitting through the 120s readTimeout window).
Server-side backstop (60s listenerAliveTTL) ships separately in
proxy.unturf.com main; the client fix above stands on its own for
the common bye-arrives case.
Fox 2026-06-06: "rebooting fedora chrome blanka because it never
could hear any speakers for days now".