dailz 727893fdc2 fix(webrtc): conservative resolution-aware startup bitrate (closes #21)
WebRTC mode now uses tier-based conservative defaults for initial encoder
bitrate instead of the aggressive formula. BWE estimate arrives within
milliseconds of client connect and overrides this; the startup value
only affects the first IDR frame.

Before (both modes used same formula):
  5 * W * H * fps / 100

  1440p@30fps = 5_529_600 bps (5.5 Mbps)
  1440p@60fps = 11_059_200 bps (11 Mbps)
  4K@30fps   = 8_294_400 bps (8.3 Mbps)

After (WebRTC uses conservative tier-based, MP4 keeps formula):

  fn webrtc_startup_bitrate_bps(width, height) -> u64:
    pixels <= 1_000_000  (720p):   1 Mbps
    pixels <= 2_500_000  (1080p):  2 Mbps
    pixels <= 4_500_000  (1440p):  4 Mbps
    else                 (4K+):    8 Mbps

Why this is safe for WebRTC:

1. BWE_INITIAL = 5 Mbps in RtcConfig (webrtc.rs)
2. Client connect triggers BWE estimate within ~10ms
3. Encoder bitrate immediately updated via BitrateCommand::UpdateBitrate
4. First IDR frame is the only output affected by startup value
5. With #23's VBV buffer_size = bitrate/4, first IDR is bounded to ~170KB
   regardless of startup bitrate

Why MP4 keeps the formula:

MP4 mode has no BWE feedback channel. The formula provides reasonable
quality for file output. Users who want specific bitrate can pass --bitrate.

Resolution tiers chosen to match common display resolutions:
  720p (1280x720 =   921_600 pixels)  → 1 Mbps
  1080p (1920x1080 = 2_073_600 pixels) → 2 Mbps
  1440p (2560x1440 = 3_686_400 pixels) → 4 Mbps
  4K (3840x2160 = 8_294_400 pixels)   → 8 Mbps (= --max-bitrate cap)

User-supplied --bitrate flag still takes precedence in both modes.

Tests:
- cargo build --release: 0 new warnings (19 baseline preserved)
- cargo test: 97 lib + 3 integration, 0 failed
- New webrtc_startup_bitrate_tiers_by_pixel_count test covers all 4 tiers
- SAFETY comments preserved verbatim
- 1 file changed
2026-06-21 10:10:19 +08:00
2026-06-13 22:46:41 +08:00

wl-webrtc

Wayland screen capture and encoding tool.

Prerequisites

  • Rust toolchain (1.70+): rustup default stable
  • FFmpeg 6.0+ dev libraries with VAAPI support:
    • Arch: pacman -S ffmpeg
    • Ubuntu/Debian: apt install libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libva-dev
    • Fedora: dnf install ffmpeg-devel libva-devel
  • Wayland dev libraries:
    • Arch: pacman -S wayland-protocols
    • Ubuntu/Debian: apt install libwayland-dev wayland-protocols
    • Fedora: dnf install wayland-devel wayland-protocols-devel
  • DRM dev libraries:
    • Arch: pacman -S libdrm
    • Ubuntu/Debian: apt install libdrm-dev
    • Fedora: dnf install libdrm-devel

Build

cargo build --release

Run

# Basic capture to file
wl-webrtc --output output.mp4

# With custom FPS and bitrate
wl-webrtc --output output.mp4 --fps 60 --bitrate 8000000

# Specify DRM device for hardware encoding
wl-webrtc --output output.mp4 --drm-device /dev/dri/renderD128

# Verbose mode
wl-webrtc --output output.mp4 -v

CLI Arguments

Argument Default Description
-o, --output (required) Output file path (e.g., output.mp4)
--output-name auto Wayland output name to capture
--fps 30 Target frames per second
--codec h264 Video codec (h264 only for MVP)
--hw-accel vaapi Hardware acceleration method
--drm-device auto DRM render device path
--bitrate auto Target bitrate in bps
--gop-size auto Group of Pictures size
-v, --verbose false Enable verbose logging
--port 0 WebTransport server port (unused in MVP)
S
Description
No description provided
Readme
2.2 MiB
Languages
Rust 98.7%
Shell 1.2%