Skip to content

Wait for the first frame of a screen share in waitForDimensions - #2217

Merged
1egoman merged 3 commits into
livekit:mainfrom
CSantosM:fix/screen-share-first-frame-dimensions
Nov 1, 2026
Merged

1egoman merged 3 commits into
livekit:mainfrom
CSantosM:fix/screen-share-first-frame-dimensions

Conversation

@CSantosM

Copy link
Copy Markdown
Contributor

Chrome reports the resolution a screen share asked for from getSettings() until the capture delivers its first frame. A 1536x664 tab captured with the 1920x1080 ideal that ScreenShareCaptureOptions.resolution sets reads as 1920x1080 right after getDisplayMedia resolves, and as 1536x664 once a frame has arrived.

publishTrack reads the dimensions through waitForDimensions, which returns as soon as getSettings() has a width and a height. Depending on whether the first frame has arrived, the layers are announced at 1920x1080 and 960x540 while the encoder sends 1536x664 and 768x332. The server picks layers by the announced heights, so any view up to about 600px tall gets the low layer, which is really 332px tall, and the shared text arrives upscaled and blurry.

Change

waitForDimensions waits for the first frame of a ScreenShare track before reading its dimensions, the same wait #2100 and #2110 added for iOS and iPadOS cameras. The comment now covers both cases.

Verified

Chrome 156 publishing a tab capture as soon as getDisplayMedia resolves, against a local LiveKit 1.13.7. The table shows the sizes the server stored, as RoomService.ListParticipants reports them:

Build Runs announcing 1920x1080 / 960x540 Publish time
main 3 of 6 100 to 135 ms
This branch 0 of 6 111 to 160 ms
  • vitest run src: 59 files, 1029 tests pass, 1 skipped. Two new tests in LocalVideoTrack.test.ts: a screen share reads its size after the first frame, and a camera does not wait. The first one fails without the change.
  • tsc --noEmit passes, and eslint and prettier report nothing on the changed files.

Not covered

When Chrome starts sharing a tab, it adds a "sharing this tab" bar that makes the tab about 56px shorter. If the first frame arrives before the bar, the layers are announced at 1536x720 and the frames shrink to 1536x664 right after. That happened in 2 of the 6 runs with this change. A resize or a surface switch later in the share leaves the announced layers stale in the same way. The client cannot re-announce layers after publishing, so both cases are for the server to cover with the sizes it parses from the media.

Chrome reports the resolution a screen share asked for from getSettings()
until the capture delivers its first frame: a 1536x664 tab captured with
the 1920x1080 ideal reads as 1920x1080. publishTrack reads the dimensions
right away, so depending on whether that frame has arrived the layers are
announced at 1920x1080 and 960x540 while the encoder sends 1536x664 and
768x332. The server then picks the low layer for any view up to about
600px tall and the shared text arrives upscaled and blurry.

Publishing a tab capture as soon as getDisplayMedia resolves, against a
local LiveKit 1.13.7 with Chrome 156, the server stored 1920x1080 in 3 of
6 runs on main and in 0 of 6 with this change. Publishing takes about
40ms longer.
@changeset-bot

changeset-bot Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e01ff3d

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

Firefox already reports the delivered size from getSettings() as soon as
getDisplayMedia resolves, so waiting there only adds publish latency.
@1egoman
1egoman force-pushed the fix/screen-share-first-frame-dimensions branch from 5cd2272 to f5c5bec Compare November 1, 2026 20:36
@1egoman

1egoman commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

@CSantosM Thanks for the contribution! I've tested this locally and I think it makes sense!

One small change I have made - per your report, this happens on chrome, and testing locally I can't reproduce the same behavior in safari or firefox. Because of this, I've gated your additional check with isChromiumBased() as waiting for the first frame can introduce a potential multi hundred millisecond penalty to the caller which should be only added if absolutely necessary.

@1egoman
1egoman merged commit 0d7acbd into livekit:main Nov 1, 2026
6 checks passed
@github-actions github-actions Bot mentioned this pull request Nov 1, 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