fix(webrtc): Fix Firefox simulcast race condition and respect HPB bandwidth limits#17775
Closed
tareko wants to merge 1 commit intonextcloud:mainfrom
Closed
fix(webrtc): Fix Firefox simulcast race condition and respect HPB bandwidth limits#17775tareko wants to merge 1 commit intonextcloud:mainfrom
tareko wants to merge 1 commit intonextcloud:mainfrom
Conversation
…dwidth limits - Chain sender.setParameters() before createOffer() in Firefox to avoid a race where the offer SDP is generated before simulcast encodings are applied. Previously the promise was ignored, causing simulcast to fail silently on low-bandwidth links and fall back to a single high-bitrate stream that congested the connection. - Add _getMaxBitrates() helper that derives simulcast tiers from the signaling server's maxstreambitrate instead of hardcoded values. The server already sent this limit in the room join response but the client never used it, so publishers always tried to push 1.3 Mbps even when the uplink or server policy was much lower. - Parse data.room.bandwidth.maxstreambitrate in joinResponseReceived and expose it on the signaling connection so Peer objects can read it. - Guard s.track before accessing s.track.kind in getSenders() find, matching the existing upstream fix for disabled tracks in Firefox. Fixes nextcloud#17774 Signed-off-by: Tarek Loubani <tarek@tarek.org>
Author
|
Closing to reopen from nextcloud/spreed branch instead of fork. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Title
Firefox simulcast:
setParameters()race condition causes failed simulcast initialization on low-bandwidth connectionsDescription
When using Firefox with the High Performance Backend (HPB / MCU) and simulcast enabled, the publisher side initializes simulcast encodings via
sender.setParameters(). However, the returnedPromiseis not awaited beforecreateOffer()is called. This creates a race condition where the offer SDP may be generated before the simulcast parameters are actually applied to the sender.On low-bandwidth connections, this is catastrophic: if simulcast fails to initialize, Firefox falls back to a single high-bitrate stream. Combined with hardcoded
maxBitrates(high: 900000,medium: 300000,low: 100000) that ignore the signaling server's configuredmaxstreambitrate, the publisher saturates its uplink. This causes severe packet loss, ICE connection failures, and a constant disconnect/reconnect loop for subscribers.Steps to Reproduce
Expected Behavior
rid: h/m/l) should be fully applied before the offer is created.maxstreambitratelimit instead of using hardcoded values.Actual Behavior
checking→connected→disconnected→failed.requestOfferloop inwebrtc.js).about:webrtcshows packet loss spiking before each disconnect.Root Cause Analysis
1.
setParameters()race condition inpeer.jsIn
src/utils/webrtc/simplewebrtc/peer.js, theoffer()method:sender.setParameters()returns aPromise. Because it is not chained or awaited,createOffer()runs immediately in the next tick, potentially before the simulcast encodings are committed by Firefox.2. Hardcoded
maxBitratesignoring server bandwidth limitIn
src/utils/webrtc/simplewebrtc/simplewebrtc.js:The Standalone Signaling Server already sends
room.bandwidth.maxstreambitratein the room join response (seeserver/hub.goandapi/signaling.go), but the frontend ignores it. When the server is configured with a limit lower than ~1.3 Mbps (the sum of the hardcoded layers), the publisher still tries to push the full hardcoded bitrate, congesting the link.Proposed Fix
Fix 1: Await
setParameters()before creating the offerIn
src/utils/webrtc/simplewebrtc/peer.js, restructure theoffer()method so thatcreateOffer()is only called aftersender.setParameters()resolves:Fix 2: Calculate
maxBitratesdynamically from the signaling server's limitIn
src/utils/webrtc/simplewebrtc/simplewebrtc.js, replace the hardcodedmaxBitrateswith a function that derives values fromopts.connection.maxStreamBits:And in
src/utils/signaling.js, store the value from the room join response:Environment
mainbranch (post-31)nextcloud-spreed-signalingwith Janus MCU, simulcast enabledRelated Code
spreed/src/utils/webrtc/simplewebrtc/peer.js—Peer.prototype.offer()spreed/src/utils/webrtc/simplewebrtc/simplewebrtc.js—maxBitratesconfigurationspreed/src/utils/signaling.js—joinResponseReceived()nextcloud-spreed-signaling/server/hub.go—processRoom()(sendsBandwidthin room response)nextcloud-spreed-signaling/api/signaling.go—RoomBandwidth.MaxStreamBitrateSeverity
High — causes completely unusable video calls in Firefox for users on constrained networks.