Skip to content

fix: use custom viewport dimensions in streaming frame metadata and image resolution#1033

Open
jin-2-kakaoent wants to merge 8 commits intovercel-labs:mainfrom
hyunjinee:fix/stream-frame-viewport-metadata-clean
Open

fix: use custom viewport dimensions in streaming frame metadata and image resolution#1033
jin-2-kakaoent wants to merge 8 commits intovercel-labs:mainfrom
hyunjinee:fix/stream-frame-viewport-metadata-clean

Conversation

@jin-2-kakaoent
Copy link
Copy Markdown
Contributor

@jin-2-kakaoent jin-2-kakaoent commented Mar 26, 2026

Summary

  • Use the viewport dimensions captured at screencast start for deviceWidth/deviceHeight in frame metadata, instead of CDP's Page.screencastFrame metadata which returns the physical device resolution regardless of viewport emulation
  • Resize the browser content area via Browser.setContentsSize when viewport changes, so screencast captures frames at the correct resolution
  • Restart active screencast when viewport dimensions change so maxWidth/maxHeight parameters are updated
  • Pass viewport dimensions to --window-size at Chrome launch time via LaunchOptions.viewport_size, reducing reliance on the experimental setContentsSize at runtime
  • Log setContentsSize failures via eprintln! instead of silently ignoring with let _ =
  • E2E test verifying both metadata and actual JPEG image dimensions

Context

Fixes #1031. PR #952 fixed status messages and Page.startScreencast parameters to use the configured viewport, but two issues remained:

  1. Frame metadata still used CDP's physical device dimensions (e.g., 1280x577 instead of the configured 1000x1000)
  2. Frame image resolution was incorrect because Emulation.setDeviceMetricsOverride only changes the CSS viewport — screencast captures the actual browser content area, which was still at the default --window-size=1280,720

Test plan

  • Manual reproduction with the script from the issue confirms deviceWidth/deviceHeight and image resolution now match the custom viewport
  • Runtime viewport changes are reflected in subsequent frames
  • Default viewport (no custom set) continues to work correctly
  • E2E test e2e_stream_frame_metadata_respects_custom_viewport verifies both metadata and actual JPEG image dimensions (800x600)
  • Existing E2E stream test continues to pass
  • cargo check passes cleanly

  CDP's Page.screencastFrame metadata returns physical device dimensions
  instead of the emulated viewport, causing frame messages to report
  incorrect deviceWidth/deviceHeight when a custom viewport is set.

  Use the viewport dimensions captured at screencast start instead of
  the CDP metadata values, since the screencast image is already captured
  at the configured viewport size.

  Closes vercel-labs#1031
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 26, 2026

@hyunjinee is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

  screencast dimensions

  Emulation.setDeviceMetricsOverride only changes the CSS viewport, but
  screencast captures the actual browser content area. This caused frame
  images to have incorrect dimensions (e.g., 1000x451 instead of
  1000x1000)
  when a custom viewport was set.

  - Call Browser.setContentsSize after setDeviceMetricsOverride so the
    content area matches the emulated viewport
  - Restart active screencast when viewport dimensions change so
    maxWidth/maxHeight parameters are updated
  - Skip redundant screencast restarts when dimensions are unchanged
  - Extend E2E test to verify actual JPEG image dimensions, not just
    metadata
@jin-2-kakaoent jin-2-kakaoent changed the title fix: use custom viewport dimensions in streaming frame metadata fix: use custom viewport dimensions in streaming frame metadata and image resolution Mar 26, 2026
Kept no-op viewport guard from feature branch, adopted main's
session-switch comment and notify_one() addition in set_viewport.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Copy link
Copy Markdown
Collaborator

@ctate ctate left a comment

Choose a reason for hiding this comment

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

Thanks for this fix, @hyunjinee!

One note: Browser.setContentsSize doesn't appear in the official CDP docs — worth confirming it's stable across Chrome versions, or consider Browser.setWindowBounds as an alternative. Also, the silenced let _ = on that call means failures go unnoticed; a debug! log would help with future debugging.

Looks good overall!

…ontentsSize failures

- Add viewport_size to LaunchOptions so --window-size matches the
  configured viewport from the start, reducing reliance on the
  experimental Browser.setContentsSize CDP call at runtime
- Log Browser.setContentsSize failures instead of silently ignoring
  them with let _ =
@jin-2-kakaoent
Copy link
Copy Markdown
Contributor Author

jin-2-kakaoent commented Mar 30, 2026

@ctate Thanks for the review!

Re: Browser.setContentsSize stability

Browser.setWindowBounds is also marked experimental: true in the CDP protocol, so switching wouldn't improve stability guarantees. Additionally, setWindowBounds sets the outer window size (including title bar/chrome), which requires platform-specific inset calculations to get the correct content area. setContentsSize targets the content area directly — a better fit for screencast resolution matching.

Re: let _ = silencing errors

Fixed — replaced with if let Err(e) + eprintln!. The daemon's stderr pipe is closed after startup, so a log crate subscriber wouldn't provide visibility either. eprintln! is visible during startup and in tests, matching the existing convention in the codebase.

Additional improvement

Added viewport_size to LaunchOptions so --window-size is set to the configured viewport at Chrome launch time. This reduces reliance on the experimental setContentsSize call at runtime — if it fails on an older Chrome, the initial viewport is still correct via the launch argument. Runtime viewport changes still use setContentsSize as there's no stable alternative.

The daemon's stderr pipe is closed after startup, so log crate
subscribers cannot output during normal operation. eprintln! is
visible during startup and in tests, matching the existing convention.
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.

Custom viewport is ignored in streaming frames

3 participants