zebra-report: deploy — fresh MediaStream per remote video track
This commit is contained in:
parent
8a055ea9fe
commit
aeb61c5ce0
1 changed files with 19 additions and 10 deletions
|
|
@ -2441,20 +2441,29 @@ async function sfuSubscribe(){
|
||||||
logLine('', 'sfu ontrack: kind=' + kind + ' pub=' + pubHex +
|
logLine('', 'sfu ontrack: kind=' + kind + ' pub=' + pubHex +
|
||||||
' track=' + ev.track.kind + ' mute=' + ev.track.muted + ' state=' + ev.track.readyState);
|
' track=' + ev.track.kind + ' mute=' + ev.track.muted + ' state=' + ev.track.readyState);
|
||||||
}
|
}
|
||||||
/* Stream-identity guard on removeFn: when a publisher supplants
|
/* MSID-supplant safety: the SFU re-uses the same streamID
|
||||||
* themselves (typical: hard refresh — new SFU peer_id same pubkey +
|
* (`shortPub-kind`) when a publisher supplants themselves. WebRTC
|
||||||
* kind), the OLD track's mute → ended → removeFn would tear down the
|
* merges the new track into the EXISTING MediaStream — ev.streams[0]
|
||||||
* tile that the NEW track just installed. Only remove if the stream
|
* is literally the same instance as before, containing both the
|
||||||
* we registered against is still the one in the store for this pub. */
|
* dead old track AND the new live one. Setting srcObject to that
|
||||||
|
* stream doesn't switch the playing track; the video element keeps
|
||||||
|
* showing the (now-ended) old track's last frame and reports muted.
|
||||||
|
* Construct a fresh MediaStream containing only the new track so
|
||||||
|
* the video element binds to the new RTP flow cleanly.
|
||||||
|
*
|
||||||
|
* Stream-identity guard on removeFn: when the OLD track's mute →
|
||||||
|
* ended → removeFn would tear down the tile that the NEW track
|
||||||
|
* just installed. Only remove if the stream we registered against
|
||||||
|
* is still the one in the store for this pub. */
|
||||||
if (kind === 'screen'){
|
if (kind === 'screen'){
|
||||||
const s = ev.streams[0];
|
const s = new MediaStream([ev.track]);
|
||||||
screenStreams.set(pubHex, s);
|
screenStreams.set(pubHex, s);
|
||||||
renderScreenTile(pubHex, s);
|
renderScreenTile(pubHex, s);
|
||||||
watchVideoTrackForRemoval(ev.track, () => { if (screenStreams.get(pubHex) === s) removeScreenTile(pubHex); }, VIDEO_REMOVE_MUTE_WINDOW_SCREEN_MS);
|
watchVideoTrackForRemoval(ev.track, () => { if (screenStreams.get(pubHex) === s) removeScreenTile(pubHex); }, VIDEO_REMOVE_MUTE_WINDOW_SCREEN_MS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (kind === 'camera'){
|
if (kind === 'camera'){
|
||||||
const s = ev.streams[0];
|
const s = new MediaStream([ev.track]);
|
||||||
cameraStreams.set(pubHex, s);
|
cameraStreams.set(pubHex, s);
|
||||||
renderCameraTile(pubHex, s);
|
renderCameraTile(pubHex, s);
|
||||||
watchVideoTrackForRemoval(ev.track, () => { if (cameraStreams.get(pubHex) === s) removeCameraTile(pubHex); }, VIDEO_REMOVE_MUTE_WINDOW_MS);
|
watchVideoTrackForRemoval(ev.track, () => { if (cameraStreams.get(pubHex) === s) removeCameraTile(pubHex); }, VIDEO_REMOVE_MUTE_WINDOW_MS);
|
||||||
|
|
@ -2464,7 +2473,7 @@ async function sfuSubscribe(){
|
||||||
/* a publisher is sharing their gameplay (Region-Capture cropped
|
/* a publisher is sharing their gameplay (Region-Capture cropped
|
||||||
* iframe). Route to its own TILE_KIND so it coexists with a
|
* iframe). Route to its own TILE_KIND so it coexists with a
|
||||||
* normal screen-share from the same person. */
|
* normal screen-share from the same person. */
|
||||||
const s = ev.streams[0];
|
const s = new MediaStream([ev.track]);
|
||||||
gameStreams.set(pubHex, s);
|
gameStreams.set(pubHex, s);
|
||||||
renderVideoTile('gameshare', pubHex, s);
|
renderVideoTile('gameshare', pubHex, s);
|
||||||
watchVideoTrackForRemoval(ev.track, () => { if (gameStreams.get(pubHex) === s) removeVideoTile('gameshare', pubHex); }, VIDEO_REMOVE_MUTE_WINDOW_SCREEN_MS);
|
watchVideoTrackForRemoval(ev.track, () => { if (gameStreams.get(pubHex) === s) removeVideoTile('gameshare', pubHex); }, VIDEO_REMOVE_MUTE_WINDOW_SCREEN_MS);
|
||||||
|
|
@ -3861,8 +3870,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">
|
<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> · built <span class="stamp-date">2026-06-03</span><br>
|
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> · built <span class="stamp-date">2026-06-03</span><br>
|
||||||
md5 <span class="stamp-md5">5bba3e681d0b4c34ede5d0f0bb4da138</span><br>
|
md5 <span class="stamp-md5">c84ac1d4ba2674e2927e3b741b593dfb</span><br>
|
||||||
sha256 <span class="stamp-sha">9445032ab40c1b6bbd69eda3b8a6b33c4b3ff849e1a5c23955e4f0d9619d4540</span><br>
|
sha256 <span class="stamp-sha">95f894002cb10ec9fdf575fbc04d6f5c55a99027fb2cb5d93c72ac3b54cb614f</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">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>
|
<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>
|
</footer>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue