zebra-spaces: video playoutDelayHint matches audio — fix lip sync

Audio receivers sit on a 4s jitter buffer (RECV_PLAYOUT_DELAY_SEC) while
video receivers had no playoutDelayHint set, so the picture played out
as fast as RTP arrived — mouse clicks, mouth movement and keystrokes
led the voice by ~4s. Set the same hint on every screen / camera /
game receiver inside attachSfuTrack. Mesh path is audio-only so no
mesh-video branch to touch.

Audio is more vital than video for QoS — video adapts to audio's delay,
never the other way around.
This commit is contained in:
Russell Ballestrini 2026-06-04 09:51:36 -04:00
parent 24b42a35bb
commit 358a8648f9
No known key found for this signature in database

View file

@ -2632,6 +2632,13 @@ function handleRemoteSfuTrack(ev){
if (kind === 'screen' || kind === 'camera' || kind === 'game'){
logLine('', 'sfu ontrack: kind=' + kind + ' pub=' + pubHex +
' track=' + ev.track.kind + ' mute=' + ev.track.muted + ' state=' + ev.track.readyState);
/* Video receivers (screen / camera / game) match the audio receiver's
* playoutDelayHint so the picture stays in sync with the voice. The
* mic jitter buffer is 4s; without a matching hint on video, mouse
* clicks / mouth movement / keystrokes lead the voice by ~4s. Audio
* is more vital than video — video adapts to audio's delay, never
* the other way around. */
try { if (ev.receiver) ev.receiver.playoutDelayHint = RECV_PLAYOUT_DELAY_SEC; } catch(_){}
}
/* MSID-supplant safety: the SFU re-uses the same streamID
* (`shortPub-kind`) when a publisher supplants themselves. WebRTC
@ -4941,8 +4948,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');
<footer style="margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> &nbsp;·&nbsp; built <span class="stamp-date">2026-06-04</span><br>
md5 <span class="stamp-md5">ba7ee3bfe287f743d4e7c3aad2803123</span><br>
sha256 <span class="stamp-sha">3f7ad07e1e1fca3679839edd49c5aed1dce0f9d162f43169d22a505e441098b5</span><br>
md5 <span class="stamp-md5">884a96ec7223a1a6998a58c20135b48c</span><br>
sha256 <span class="stamp-sha">5e7cb79da69ca902af2a9f365fc851e89b370f3e8316633e28144cd1e53a5311</span><br>
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify against these hashes; point at your own servers with ?signal= and ?turncred=, or <a href="host-your-own.html" style="color:#999">host your own community</a></span>
</footer>