Skip to content

Keep screen share uncapped by the start bitrate ramp - #1036

Merged
changt merged 2 commits into
mainfrom
senchang/clt-3380-exempt-screen-share-from-start-bitrate-ramp
Oct 7, 2026
Merged

changt merged 2 commits into
mainfrom
senchang/clt-3380-exempt-screen-share-from-start-bitrate-ramp

Conversation

@changt

@changt changt commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Linear: CLT-3380
Flutter counterpart: livekit/client-sdk-flutter#1228

Follow-up to #1031.

Change

#1031 left screen share uncapped only while the setup-time cap was at the 1 Mbps ceiling; on a slow setup, screen share was ramped down with camera. We've decided screen share should be exempt from the ramp entirely: its content needs the bitrate right away to stay legible, so its hint is now always 90% of its target, however long setup took. Camera tracks are ramped as before.

The core change is one condition in computeTrackStartBitrate: isScreenShare && capKbps >= maxStartBitrateKbps becomes isScreenShare.

Since the hint is the max across the connection's video m-sections, a connection that publishes both camera and screen share takes the screen share's uncapped value.

The changeset from #1031 hasn't been released yet, so this updates its wording rather than adding a new one.

Tests

SdpMungingTest: the screen-share test now checks that screen share stays at 2700 kbps (3 Mbps target) at 1.3 s, 2.5 s and 4.1 s setup, and that a slow setup with camera + screen share yields the screen share's 2700 while camera alone is still ramped to 650. spotlessCheck and detektRelease clean.

Screen share content needs its bitrate immediately to stay legible, so
it is now exempt from the connection-setup-time ramp as well as the
1 Mbps ceiling. A slow setup lowers only the camera's hint. Matches
client-sdk-flutter.
@changeset-bot

changeset-bot Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 7bacc31

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes changesets to release 1 package
Name Type
client-sdk-android Patch

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Diffuse output:

OLD: diffuse-source-file
NEW: livekit-android-sdk-release.aar

 AAR      │ old      │ new      │ diff 
──────────┼──────────┼──────────┼──────
      jar │    3 MiB │    3 MiB │ -1 B 
 manifest │  1.5 KiB │  1.5 KiB │  0 B 
 lint-jar │ 12.7 KiB │ 12.7 KiB │  0 B 
    other │  2.4 KiB │  2.4 KiB │  0 B 
──────────┼──────────┼──────────┼──────
    total │    3 MiB │    3 MiB │ -1 B 

 JAR     │ old   │ new   │ diff      
─────────┼───────┼───────┼───────────
 classes │  1706 │  1706 │ 0 (+0 -0) 
 methods │ 21983 │ 21983 │ 0 (+0 -0) 
  fields │  5703 │  5703 │ 0 (+0 -0)
AAR
 size  │ diff │ path          
───────┼──────┼───────────────
 3 MiB │ -1 B │ ∆ classes.jar 
───────┼──────┼───────────────
 3 MiB │ -1 B │ (total)

changt added a commit to livekit/rust-sdks that referenced this pull request Oct 7, 2026
Linear:
[CLT-3380](https://linear.app/livekit/issue/CLT-3380/scale-the-video-start-bitrate-300-1000-kbps-by-connection-setup-time)
Android counterpart: livekit/client-sdk-android#1036
Flutter counterpart: livekit/client-sdk-flutter#1228

Follow-up to #1467.

## Change

#1467 left screen share uncapped only while the setup-time cap was at
the 1 Mbps ceiling; on a slow setup, screen share was ramped down with
camera. We've decided screen share should be exempt from the ramp
entirely: its content needs the bitrate right away to stay legible, so
its hint is now always 90% of its target, however long setup took.
Camera tracks are ramped as before.

The core change is one condition in
`PeerTransport::compute_start_bitrate_kbps`: `is_screen_share &&
cap_kbps >= Self::MAX_START_BITRATE_KBPS` becomes `is_screen_share`.

The changeset from #1467 hasn't been released yet, so this updates its
wording rather than adding a new one.

## Tests

`slow_connection_setup_caps_screen_share_too` is renamed to
`slow_connection_setup_leaves_screen_share_uncapped` and now checks that
screen share stays at 2700 kbps (3 Mbps target) at 1.3 s, 2.5 s and 4.1
s setup. `cargo test -p livekit --lib` start-bitrate tests pass; `cargo
fmt` clean.
@changt
changt merged commit 6c06fbc into main Oct 7, 2026
5 checks passed
@changt
changt deleted the senchang/clt-3380-exempt-screen-share-from-start-bitrate-ramp branch October 7, 2026 00:17
pblazej pushed a commit to livekit/client-sdk-swift that referenced this pull request Oct 20, 2026
Follow-up to #1121. Ports the setup-time ramp from
livekit/client-sdk-js#2146, livekit/rust-sdks#1467 and
livekit/client-sdk-android#1031.

## Problem

#1121 caps the camera `x-google-start-bitrate` hint at a fixed 1 Mbps.
On slow or lossy links, that seed overshoots what the link can carry.

## Change

Connection setup time (signaling join plus ICE/DTLS) is the only network
signal available before the first video offer, since libwebrtc cannot
probe the path until a video sender exists. Setup time grows with
round-trip time and loss, so the camera cap now scales with it:

- **Ramp:** 1 Mbps at a setup of 1.5 s or less, falling linearly to 300
kbps at 3.5 s or more. The anchors come from shaped-link measurements
(CLT-3380).
- **Screen share:** uncapped, however slow the setup, as in all three
SDKs (livekit/rust-sdks#1505, livekit/client-sdk-android#1036,
livekit/client-sdk-js#2146).
- **What is timed:** from the top of `fullConnectSequence` until the
primary transport connects. Every attempt is timed from scratch: initial
connect, full reconnect and region failover. A quick reconnect keeps its
peer connection and estimator, so it doesn't measure again.
- **Publishing during connect:** a video published before the primary
transport connects uses the time elapsed so far. That is a lower bound,
so it can only err toward the 1 Mbps ceiling.
- **Where the cap is applied:** in
`Transport.startBitrateKbps(…connectionSetupTime:)`, the formula both
`LocalParticipant` video publish paths already call. `addTransceiver`
and the offer munge are unchanged.

## Differences from the other SDKs

- **What is timed:** Swift matches Kotlin and JS (until the primary
transport connects). Rust waits for both peer connections in dual-PC
mode.
- **Offer created mid-connect:** Swift matches Kotlin and JS (time
elapsed so far). Rust uses no setup time, which leaves the cap at the 1
Mbps ceiling.
- **Not ported:** the JS cap based on the browser's
`navigator.connection.effectiveType`. It is browser-only and has no
Apple-platform equivalent.

## Testing

- **Ramp:** rust-sdks' cases at setup times measured on shaped links.
- **Formula with a setup time:** camera capped, 90% of a low target
kept, screen share uncapped.
- **`Transport.connectionSetupTime`:** recorded, time elapsed so far,
and unset.
- The macOS build passes, the four start-bitrate and SDP suites pass (50
tests), and swiftlint and swiftformat are clean.
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.

2 participants