Skip to content

fix(web): emit a new MediaStream ref per track so Firefox renders screen share#28

Merged
ralyodio merged 1 commit into
masterfrom
fix/web-viewer-black-screen
Jun 23, 2026
Merged

fix(web): emit a new MediaStream ref per track so Firefox renders screen share#28
ralyodio merged 1 commit into
masterfrom
fix/web-viewer-black-screen

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Bug

Joining a session on the web showed camera + black instead of the host's screen share — on Firefox. The host was publishing SCREEN_SHARE video (the egress composited it fine), and the viewer subscribed; it just never rendered.

Root cause

useWebRTCSFU kept one MediaStream and mutated it on each TrackSubscribed, calling setRemoteStream(stream) with the same object reference. React bails on setState with an unchanged reference, so VideoViewer's srcObject effect (dep [stream]) never re-ran. Firefox does not render a track added to a MediaStream that's already attached to a <video> element — and audio is usually subscribed before the screen-share video — so the video never appeared. Chrome tolerates the live mutation, which is why the egress (Chrome) was fine.

Fix

Emit a fresh MediaStream reference on every track add/remove, so remoteStream changes identity → React re-renders → srcObject re-binds → Firefox renders the screen share.

Test

The existing test had actually asserted the buggy same-reference behavior (toBe(firstStream)); updated it to assert a new reference each time, with the correct track contents after add and unsubscribe. Passes; lint clean.

Web (apps/web) — deploys to Railway on merge.

🤖 Generated with Claude Code

…een share

Web SFU viewers showed camera/black instead of the host's screen share on
Firefox. useWebRTCSFU mutated one MediaStream and called setRemoteStream with
the same object reference on each TrackSubscribed, so React bailed on the
re-render and VideoViewer's srcObject effect (dep [stream]) never re-ran.
Firefox does NOT render a track added to a MediaStream already attached to a
<video> element — and audio is usually subscribed before the screen-share
video — so the video never appeared (Chrome tolerated it, hence egress was
fine). Now emit a fresh MediaStream reference on every track add/remove so
srcObject re-binds. Updated the test, which had asserted the buggy same-ref.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ralyodio ralyodio merged commit 48a1eeb into master Jun 23, 2026
@ralyodio ralyodio deleted the fix/web-viewer-black-screen branch June 23, 2026 10:13
@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant