Skip to content

Additionally use browser effective connection type in determining start bitrate - #2149

Merged
lukasIO merged 2 commits into
mainfrom
sen/start-bitrate-effective-type
Oct 16, 2026
Merged

lukasIO merged 2 commits into
mainfrom
sen/start-bitrate-effective-type

Conversation

@changt

@changt changt commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Builds on #2146, which scales the camera x-google-start-bitrate cap by connection setup time.

Problem

Connection setup time grows with round-trip time and loss, so it misses links with low bandwidth but low latency. Those set up quickly and still get the 1 Mbps seed, which overshoots their uplink. In the browser, Chromium's Network Information API reports an effective connection type (navigator.connection.effectiveType) that does flag such links as 3g or slower.

Change

The camera cap is now the lower of the setup time cap and a cap from the effective connection type:

effectiveType Cap
slow-2g, 2g 300 kbps
3g 500 kbps
4g, or no API (Firefox, Safari) 1 Mbps ceiling, i.e. no extra guidance
  • One new function, connectionEffectiveTypeStartBitrateCap(), applied in one place in computeTrackStartBitrate.
  • The effective type is read when the offer is built, so it reflects the network at that moment.
  • Screen share stays uncapped.
  • The API's rtt is not used. It lags behind network changes, and setup time already reflects latency. Setup time stays the primary signal because every platform has it.

Testing

  • PCTransport.test.ts: caps for each effective type, no cap for 4g or without navigator.connection, the lower of the two caps applies, 90% of a target below the cap, and screen share uncapped. npx vitest run src: 920 passed, 1 skipped.
  • The signal was compared against connection setup time and the ICE candidate-pair RTT with a local bench in the demo app (not part of this PR), shaping with macOS Network Link Conditioner.

…rt bitrate

Chromium's navigator.connection.effectiveType catches links with low
bandwidth but low latency, which set up quickly and so slip past the
connection setup time ramp. The camera x-google-start-bitrate cap is
now the lower of the setup time cap and:

- 300 kbps for slow-2g and 2g
- 500 kbps for 3g
- the 1 Mbps ceiling for 4g, and for browsers without the API

Screen share stays uncapped. The API's rtt is not used: it lags behind
network changes, and the setup time already reflects latency.
@changeset-bot

changeset-bot Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5eb9d8a

The changes in this PR will be included in the next version bump.

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

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

@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 13, 2026 •

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size
dist/livekit-client.esm.mjs 114.02 KB (-0.02% 🔽)
dist/livekit-client.umd.js 123.2 KB (-0.02% 🔽)

@lukasIO lukasIO 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.

Changes look mostly good to me, with the globalThis access being the only thing that's blocking.

Comment thread src/room/PCTransport.ts Outdated
*/
function connectionEffectiveTypeStartBitrateCap(): number {
// `navigator.connection` is missing from the DOM typings, being Chromium only.
const connection = (globalThis.navigator as { connection?: { effectiveType?: string } })

@lukasIO lukasIO Oct 14, 2026 •

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.

fix: do not read globalThis here. The supported browsers (Chrome 64, Firefox 58, Safari 11.1) have no globalThis, and the build adds no polyfill. Use a typeof navigator guard, as the rest of the file does.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done.

Comment thread src/room/PCTransport.ts Outdated
function connectionEffectiveTypeStartBitrateCap(): number {
// `navigator.connection` is missing from the DOM typings, being Chromium only.
const connection = (globalThis.navigator as { connection?: { effectiveType?: string } })
?.connection;

@lukasIO lukasIO Oct 14, 2026 •

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.

suggestion: replace the cast with a declared NetworkInformation type, or a package that provides it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

done.

globalThis is missing from supported browsers older than Chrome 71,
Firefox 65 and Safari 12.1, and the build does not polyfill it, so
reading globalThis.navigator threw a ReferenceError while building the
first camera offer on those browsers. Check typeof navigator instead,
and type the API with a local NetworkInformation interface in place of
the inline cast.

@lukasIO lukasIO 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.

thanks!

@lukasIO
lukasIO merged commit 5ad048a into main Oct 16, 2026
6 checks passed
@lukasIO
lukasIO deleted the sen/start-bitrate-effective-type branch October 16, 2026 08:58
@github-actions github-actions Bot mentioned this pull request Oct 16, 2026
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