Repository navigation
Conversation
Port of livekit/rust-sdks#1467 and #1505 (CLT-3380). The camera x-google-start-bitrate cap is 1 Mbps for connections that set up within 1.5 s and ramps linearly down to 300 kbps at 3.5 s or slower. Screen share stays uncapped. RTCEngine times each join attempt and hands the setup time to the publisher when the primary transport first connects. A video published during connect is seeded from the time elapsed so far rather than delaying its offer.
changt
requested review from
1egoman,
lukasIO and
xianshijing-lk
as code owners
October 9, 2026 22:11
🦋 Changeset detectedLatest commit: a78655d The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
There was a problem hiding this comment.
🔍 Devin Review: 1 flag
Not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)
Contributor
size-limit report 📦
|
This branch has not been deployed
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.
Linear: CLT-3380
Rust counterparts: livekit/rust-sdks#1467, livekit/rust-sdks#1505
Android counterparts: livekit/client-sdk-android#1031, livekit/client-sdk-android#1036
Flutter counterpart: livekit/client-sdk-flutter#1228
Builds on #2102, which made the
x-google-start-bitratehint a connection-level value written once per peer connection.Problem
For camera tracks, the hint is a fixed min(90% of target, 1 Mbps), chosen with no information about the network. On a constrained uplink, 1 Mbps overshoots. The estimator then has to recover, which shows up as a freeze and a retransmit storm over the first 5–15 s. On a good network 1 Mbps is the right value. libwebrtc cannot probe the path before a video sender exists, so connection setup time is the only network signal available before the first video offer.
Change
Same formula as Rust and Android:
RTCEnginetimes eachjoin()attempt, so a join retry or a full restart is timed from scratch. It hands the setup time to the publisherPCTransportthe first time the primary transport reports connected. Resumes and ICE restarts never restart the timer and keep the estimator they have. The write-once latch from Write the video start bitrate hint as one connection-level value, once #2102 is unchanged.Publishing during connect
Unlike Rust, JS lets an app publish before the peer connection is up.
publishTrackonly waits for the signal connection, and the demo does exactly this to shorten time-to-publish. In that case the first video offer is built before the setup time is known. Holding the offer until the connection is up would add latency, so the offer uses the time elapsed since the join started instead. Real setup time can only be longer, so this never seeds higher than the previous fixed 1 Mbps cap. It is a partial ramp, though: a connection that takes 3.6 s to set up but builds its offer 2.5 s in gets about 650 kbps rather than the floor. With no timing at all, the cap stays at 1 Mbps.The existing
applied x-google-start-bitratelog line reportsconnectionSetupTimeMs, which is the measured setup time or the elapsed estimate, whichever was used. A separateconnection setup took N msline is logged when the transport connects.Testing
PCTransport.test.ts: the ramp at the measured setup times and anchors (same cases as Rust), the 1 Mbps fallback without a setup time, 90% of target under the ramp, screen share uncapped at every setup time, the connection-level value, and the elapsed-time estimate before the setup time is measured.npx vitest run src: 870 passed.examples/demoagainst a LiveKit Cloud development token server with a fake camera in Chrome, on an unshaped network: setup about 400 ms, offer carriedx-google-start-bitrate=1000, and the estimate opened at about 1.8 Mbps.