From 7983701b03da1cbbc9c337534460113c08cfcd56 Mon Sep 17 00:00:00 2001 From: Mollusk Date: Mon, 18 May 2026 04:25:17 -0400 Subject: [PATCH] Fix latency drift: cap framerate + tune mpv buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Symptom: cross-machine streams drifted ~6-9 seconds per minute. mpv showed continuous "Audio device underrun detected" with video packets piling up in its demuxer queue while audio queue stayed at 0. Root causes: - pipewiresrc captured at the host monitor's refresh rate (180Hz), not at the configured framerate. The encoder + mux produced 6x more frames per wallclock second than mpv could consume at realtime, burying audio packet density in mpv's demuxer queue. - `--profile=low-latency` sets `audio-buffer=0`, which is too aggressive — any sub-millisecond network jitter immediately starves the audio device. Underruns slowed mpv's audio clock, and with `video-sync=audio` (also from low-latency profile) video followed. Fixes: - `videorate ! video/x-raw,framerate=/1` after pipewiresrc to cap input to the requested rate deterministically. - mpv command grows `--audio-buffer=0.2 --demuxer-max-bytes=2M --demuxer-readahead-secs=0.5`: small audio buffer to absorb network jitter, demuxer cap to prevent runaway buildup. A leaky-queues attempt landed and was reverted in the same commit — it removed backpressure without addressing the root cause and made things worse. Verified cross-machine 6m51s: drift held at ~1s floor, zero audio underruns, perfect A-V sync. Co-Authored-By: Claude Opus 4.7 --- src/host/wayland.rs | 8 +++++++- src/viewer/mod.rs | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/host/wayland.rs b/src/host/wayland.rs index 7d17677..92a9986 100644 --- a/src/host/wayland.rs +++ b/src/host/wayland.rs @@ -132,12 +132,18 @@ pub async fn start(opts: &HostOpts) -> Result { "!", "fdsink", "fd=1", - // video branch + // video branch — videorate caps to 30fps so we don't ship at the + // monitor's refresh rate (e.g. 180Hz) and pile up frames in mpv's + // demuxer queue faster than realtime. "pipewiresrc", &format!("fd={raw_fd}"), &format!("path={node_id}"), "do-timestamp=true", "!", + "videorate", + "!", + &format!("video/x-raw,framerate={}/1", opts.framerate), + "!", "queue", "!", "videoconvert", diff --git a/src/viewer/mod.rs b/src/viewer/mod.rs index bfb931f..2452c88 100644 --- a/src/viewer/mod.rs +++ b/src/viewer/mod.rs @@ -46,7 +46,9 @@ fn print_viewer_banner(port: u16) { eprintln!("┌─ PixelPass · viewer ───────────────────────────────────────"); eprintln!("│ Connected to host. Open the stream in your player:"); eprintln!("│"); - eprintln!("│ mpv --profile=low-latency --untimed {url}"); + eprintln!( + "│ mpv --profile=low-latency --untimed --audio-buffer=0.2 --demuxer-max-bytes=2M --demuxer-readahead-secs=0.5 {url}" + ); eprintln!("│ vlc --network-caching=200 --live-caching=200 {url}"); eprintln!("│"); eprintln!("│ Press Ctrl+C to disconnect.");