diff --git a/README.md b/README.md index c471c97..09ea0d3 100644 --- a/README.md +++ b/README.md @@ -67,13 +67,18 @@ pixelpass - `gstreamer`, `gst-plugins-base`, `gst-plugins-good`, `gst-plugins-bad`, `gst-plugins-ugly`, `gst-libav`, `gst-plugin-va`, `gst-plugin-pipewire` - A player: `mpv` (recommended) or `vlc` -- If you use VLC: `vlc-plugin-dvb` must also be installed. Arch / CachyOS - ship VLC's MPEG-TS demuxer (`libts_plugin.so`) in that separate - package, and without it VLC misidentifies the H.264 stream and shows - a green screen. mpv is unaffected. +- If you use VLC, two split plugin packages are also needed on Arch-family + distros — the base `vlc` package does not pull them in: + - `vlc-plugin-dvb` — provides the MPEG-TS demuxer (`libts_plugin.so`). + Without it, VLC can't parse the container. + - `vlc-plugin-ffmpeg` — provides the H.264 decoder + (`libavcodec_plugin.so`). Without it, VLC parses the container, + identifies the codec as H.264, then errors with + `Codec h264 ... is not supported`. + mpv ships its own decoder stack and doesn't share either dependency. - PipeWire (for screencast portal + audio capture) -On Arch / CachyOS: +On Arch / CachyOS / EndeavourOS: ```sh sudo pacman -S gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad \ @@ -81,7 +86,7 @@ sudo pacman -S gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad \ libva-utils mpv # plus your GPU's VAAPI driver # plus, if you want to use VLC instead of mpv: -sudo pacman -S vlc vlc-plugin-dvb +sudo pacman -S vlc vlc-plugin-dvb vlc-plugin-ffmpeg ``` If the viewer is running on battery, set the CPU governor to performance @@ -151,10 +156,11 @@ relay path otherwise. Both have been verified end-to-end. ## Known limitations and gotchas -- **VLC needs `vlc-plugin-dvb`** to demux MPEG-TS on Arch / CachyOS. The - symptom of missing it is a green screen — VLC falls back to the PS - demuxer and misidentifies the H.264 stream. pixelpass warns at - player-launch time if the plugin isn't on disk. mpv doesn't need it. +- **VLC needs `vlc-plugin-dvb` and `vlc-plugin-ffmpeg`** on Arch-family + distros — the base `vlc` package doesn't pull these in, and missing + either one breaks playback (the first kills the demuxer, the second + kills the H.264 decoder). pixelpass warns at player-launch time if + either plugin isn't on disk. mpv doesn't share these dependencies. - **Audio echo** if the host plays the stream through speakers and captures system audio — expected, the mic / monitor picks up the playback. Headphones bypass it. diff --git a/src/interactive.rs b/src/interactive.rs index 1ecf53a..068d023 100644 --- a/src/interactive.rs +++ b/src/interactive.rs @@ -69,7 +69,7 @@ impl Player { ], ), Player::Vlc => { - warn_if_vlc_ts_demuxer_missing(); + warn_if_vlc_plugins_missing(); crate::common::process::spawn_detached( "vlc", &["--network-caching=200", "--live-caching=200", url], @@ -79,22 +79,39 @@ impl Player { } } -// VLC's MPEG-TS demuxer ships in a separate package on Arch / CachyOS -// (`vlc-plugin-dvb`). Without it VLC falls through to the PS demuxer -// and shows a green screen. -fn warn_if_vlc_ts_demuxer_missing() { - const TS_DEMUX_PLUGIN: &str = "/usr/lib/vlc/plugins/demux/libts_plugin.so"; - if !std::path::Path::new(TS_DEMUX_PLUGIN).exists() { - eprintln!(); - eprintln!( - "Warning: VLC's MPEG-TS demuxer plugin ({TS_DEMUX_PLUGIN}) is missing." - ); - eprintln!( - " On Arch / CachyOS, install `vlc-plugin-dvb`. Without it," - ); - eprintln!(" VLC will show a green screen. mpv is unaffected."); - eprintln!(); +// On Arch-family distros, the base `vlc` package omits two plugins +// pixelpass needs: the MPEG-TS demuxer (`vlc-plugin-dvb`) and the +// libavcodec-based H.264 decoder (`vlc-plugin-ffmpeg`). Missing either +// produces a confusing error chain — warn at launch. +fn warn_if_vlc_plugins_missing() { + const REQUIRED: &[(&str, &str)] = &[ + ( + "/usr/lib/vlc/plugins/demux/libts_plugin.so", + "vlc-plugin-dvb", + ), + ( + "/usr/lib/vlc/plugins/codec/libavcodec_plugin.so", + "vlc-plugin-ffmpeg", + ), + ]; + let missing: Vec<&(&str, &str)> = REQUIRED + .iter() + .filter(|(p, _)| !std::path::Path::new(p).exists()) + .collect(); + if missing.is_empty() { + return; } + eprintln!(); + eprintln!("Warning: VLC is missing plugins pixelpass needs:"); + for (path, pkg) in &missing { + eprintln!(" - {path} (install `{pkg}`)"); + } + eprintln!("On Arch / CachyOS / EndeavourOS: `sudo pacman -S {}`.", { + let names: Vec<&str> = missing.iter().map(|(_, p)| *p).collect(); + names.join(" ") + }); + eprintln!("mpv is unaffected."); + eprintln!(); } pub fn prompt_player() -> Result {