dailz 68a6eecfbe fix(cap_portal): phased timeouts + token-aware retry for Portal setup
Phase 2 of Portal resilience. When xdg-desktop-portal is stuck,
setup_portal now fails fast with actionable diagnostics instead of
hanging indefinitely. Auto-recovers from stale restore token case.

Phased timeouts (per Oracle review):

  Phase 1: Screencast proxy creation          5s (no user interaction)
  Phase 2: create_session                      5s (no user interaction)
  Phase 3: select_sources                      5s with token / 30s without
  Phase 4: start + response                    5s with token / 30s without
  Phase 5: open_pipe_wire_remote               5s (no user interaction)

Phase 3/4 timeout depends on whether restore token was loaded:
  - With valid token: no permission dialog expected, 5s
  - Without token: user must click Allow in dialog, allow 30s

Token-aware retry (Oracle B'):

On timeout in phase 3 or 4 IF restore token was in use:
  1. Log warning explaining auto-recovery
  2. Delete cached token (~/.cache/wl-webrtc/portal-restore-token)
  3. Retry whole setup_portal once with no_persist=true behavior
  4. On second failure: exit with diagnostic

Retry is whole-flow (new Screencast proxy, new session). Does NOT
reuse half-created objects — Oracle warned this can leak state.

Diagnostic messages:

Service-side timeout (phases 1, 2, 5, or phase 3/4 without token):
  'Portal service did not respond within timeout while <phase>.
   Try: systemctl --user restart xdg-desktop-portal xdg-desktop-portal-kde,
   then re-run wl-webrtc.'

Token-side timeout (phase 3/4 with token, after auto-retry exhausted):
  Same message + ' If this recurs, try: wl-webrtc --no-persist'

Implementation:

- PortalPhaseTimeout enum distinguishes Service vs TokenDependent failures
  (only TokenDependent triggers retry)
- _setup_portal_inner does the actual phased work with timeouts
- setup_portal wraps inner, handles retry on TokenDependent
- log_portal_phase_timeout helper for consistent diagnostics
- delete_restore_token for safe token removal (concurrent-instance safe)

Tests:
- cargo build --release: 0 new warnings (19 baseline preserved)
- cargo test: 97 lib + 3 integration, 0 failed
- All 7 existing token tests pass unchanged
- SAFETY comments preserved verbatim
- 1 file changed, +199/-22 lines

Out of scope (Oracle deferred):
- --doctor diagnostic CLI subcommand
- Runtime watchdog (Portal going bad mid-session)
- systemd auto-restart (disrupts other Portal clients)
- Phased diagnostics for the optional PipeWire first-frame wait

Combined with Phase 1 (backend_detect.rs, commit 6ccb225), Portal
service issues now fail fast with clear recovery instructions instead
of hanging indefinitely.
2026-06-21 10:44:15 +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%