dailz b4b9990efe feat(stats): populate frame_age metric for WebRTC path (partial #20)
Add quantitative capture-to-send latency measurement so we can diagnose
remaining latency sources after #24/#25 PTS fixes.

Previously frame_age_p95 was always 0.0ms because the WebRTC code path
never propagated capture timestamps, even though stats.rs already
supported the metric. The infrastructure existed but was disconnected.

Changes:

- avhw.rs: Add capture_time: Instant field to CpuNv12Frame (set when
  PipeWire delivers frame) and EncodedH264Frame (propagated through
  encode thread via new last_capture_time side-channel on SwEncEncode).

- state_portal.rs: Change sent_gap channel type from Sender<f64> to
  Sender<(f64, Option<f64>)> so WebRTC thread can send pre-computed
  age_ms = capture_time.elapsed() at the exact send moment (not at
  stats drain time, which would inflate the measurement by ~1s).

- stats.rs: record_send_from_thread now accepts Option<f64> age_ms
  and pushes to frame_age_ms Vec when Some.

After this commit:
- stats: log lines show real frame_age_p95 / frame_age_max in ms
- Expected range: 5-30ms (import + scale + encode + channel send)
- If much higher: server pipeline has queueing issue
- If low but user still sees latency: confirms bottleneck is network
  or browser-side (jitter buffer, decode queue)

Scope notes:

- Only Portal/PipeWire path is instrumented. wlr-screencopy path uses
  different code path (EncState, not SwEncState) and will continue to
  report frame_age=0.0ms. Adding wlr instrumentation is separate scope.

- This is diagnostic only — does NOT change user-visible behavior.
  No encoding, sending, or stats output format changes.

Tests:
- cargo build --release: 0 new warnings (19 baseline preserved)
- cargo test: 96 lib + 3 integration, 0 failed
- SAFETY comments preserved verbatim
- 3 files changed, +39/-10 lines

Refs #20.
2026-06-20 23:20:36 +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%