From 639b551664be1642ffa1b7ac4a4d0d4dcbf142cf Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Mon, 21 Sep 2026 09:17:38 -0700 Subject: [PATCH 1/3] docs(quest): scope capture system-dependency removal Co-Authored-By: Muse Spark --- quest/m2/README.md | 2 ++ quest/m2/capture-alsa-link.md | 23 +++++++++++++++++++++++ quest/m2/capture-v4l-bindings.md | 24 ++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 quest/m2/capture-alsa-link.md create mode 100644 quest/m2/capture-v4l-bindings.md diff --git a/quest/m2/README.md b/quest/m2/README.md index 544e5fd23d..bd14502768 100644 --- a/quest/m2/README.md +++ b/quest/m2/README.md @@ -205,6 +205,8 @@ before format-specific metadata. Unrelated areas can proceed in parallel. - [Runtime QA hosts](/quest/m2/runtime-qa-hosts.md) - run exact source snapshots on accessible Linux and device hosts with retrievable debug evidence - [Media QA on other engines](/quest/m2/browser-media-qa-engines.md) - the media harness measures a Firefox or WebKit player over the fallback and names what each engine lacks - [#1310](/quest/m2/1310-why-use-the-worklet-plugin.md) - why use the worklet plugin? +- [Capture without V4L2 bindgen](/quest/m2/capture-v4l-bindings.md) - moq-video capture builds on Linux without libclang or kernel headers +- [Audio capture without ALSA link](/quest/m2/capture-alsa-link.md) - moq-audio capture and playback build on Linux without linking libasound - [Ship capture and playback](/quest/m2/cli-packaging.md) - a released moq binary can capture and play, which no distribution currently enables - [Windows capture parity](/quest/m2/capture-windows.md) - system audio and screen cursor capture with a settled app-capture policy - [Linux capture parity](/quest/m2/capture-linux.md) - Wayland window/system-audio capture with explicit display-selection and app-capture limits diff --git a/quest/m2/capture-alsa-link.md b/quest/m2/capture-alsa-link.md new file mode 100644 index 0000000000..749f0efcc4 --- /dev/null +++ b/quest/m2/capture-alsa-link.md @@ -0,0 +1,23 @@ +# [S] Audio capture without link-time ALSA + +## Goal + +moq-audio `capture` and `playback` build on Linux without linking libasound, +so the microphone path stops blocking capture-by-default. + +## Plan + +Narrow the cpal backend set so a Linux capture build does not link libasound +unless the ALSA backend is asked for. Keep the `pipewire` and `pulseaudio` +host flags independent and never activating cpal alone, aligning with +[Optional native compilation](/quest/m0/media-features.md), and document the +capability combination. + +Verify by building the capture and playback features on a host without the +ALSA development libraries and by inspecting the dependency graph to prove +libasound is absent when unasked. The PR 3850 capture gate keeps the coverage. + +## Related + +- [Ship capture and playback](/quest/m2/cli-packaging.md) - shippable capture needs this first +- [Optional native compilation and opt-in rendering](/quest/m0/media-features.md) - the host-flag rule this aligns with diff --git a/quest/m2/capture-v4l-bindings.md b/quest/m2/capture-v4l-bindings.md new file mode 100644 index 0000000000..887fc92a9b --- /dev/null +++ b/quest/m2/capture-v4l-bindings.md @@ -0,0 +1,24 @@ +# [S] Capture without the V4L2 bindgen build dependency + +## Goal + +moq-video `capture` builds on Linux without libclang or kernel headers, so the +camera path stops blocking capture-by-default. + +## Plan + +Vendor or pin the `v4l` crate with checked-in bindings and drop its bindgen +build script, the way `moq-nvenc` does and +[VAAPI](/quest/m2/video-vaapi.md) plans. Keep the `v4l` API so +`capture/v4l2.rs` and the `v4l2` codec backend need no logic changes. Fixing +`v4l` fixes both features since both drive the same device node through it. + +Verify by building `just rs capture` on a host without libclang and by +inspecting the dependency graph to prove bindgen is gone. The PR 3850 capture +gate keeps the coverage. + +## Related + +- [Ship capture and playback](/quest/m2/cli-packaging.md) - shippable capture needs this first +- [VAAPI encode and decode](/quest/m2/video-vaapi.md) - same pre-generated bindings pattern for libva +- [Linux capture parity](/quest/m2/capture-linux.md) - the capture surface this unblocks From 4bb0eb852f690f0c27c3536cacb9a6f9c6b37764 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Mon, 21 Sep 2026 10:36:13 -0700 Subject: [PATCH 2/3] docs(quest): address review round on capture system deps Co-Authored-By: Muse Spark --- quest/m2/capture-alsa-link.md | 20 +++++++++++++++----- quest/m2/capture-v4l-bindings.md | 2 +- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/quest/m2/capture-alsa-link.md b/quest/m2/capture-alsa-link.md index 749f0efcc4..32b49ca788 100644 --- a/quest/m2/capture-alsa-link.md +++ b/quest/m2/capture-alsa-link.md @@ -8,10 +8,20 @@ so the microphone path stops blocking capture-by-default. ## Plan Narrow the cpal backend set so a Linux capture build does not link libasound -unless the ALSA backend is asked for. Keep the `pipewire` and `pulseaudio` -host flags independent and never activating cpal alone, aligning with -[Optional native compilation](/quest/m0/media-features.md), and document the -capability combination. +unless the ALSA backend is asked for. The current matrix is the contract to +change: `capture` and `playback` pull cpal, whose `alsa` dependency is +non-optional on Linux in cpal 0.18, so libasound links whenever either is on; +`pipewire = ["cpal/pipewire"]` and `pulseaudio = ["cpal/pulseaudio"]` activate +cpal without either. The target matrix keeps those host flags but makes them +require `capture` or `playback` so they never activate cpal alone, and puts +the ALSA backend behind an opt-in capability instead of the always-linked +default. Whether that capability comes from a cpal release gating `alsa` or +from in-tree handling is the implementation decision; document the supported +combinations in the moq-audio feature table with the same change. + +Verify by building the capture and playback features on a host without the +ALSA development libraries and by inspecting the dependency graph to prove +libasound is absent when unasked. The PR 3850 capture gate keeps the coverage. Verify by building the capture and playback features on a host without the ALSA development libraries and by inspecting the dependency graph to prove @@ -19,5 +29,5 @@ libasound is absent when unasked. The PR 3850 capture gate keeps the coverage. ## Related -- [Ship capture and playback](/quest/m2/cli-packaging.md) - shippable capture needs this first +- [Ship capture and playback](/quest/m2/cli-packaging.md) - the shippable capture milestone this work supports - [Optional native compilation and opt-in rendering](/quest/m0/media-features.md) - the host-flag rule this aligns with diff --git a/quest/m2/capture-v4l-bindings.md b/quest/m2/capture-v4l-bindings.md index 887fc92a9b..a8f46fc7ce 100644 --- a/quest/m2/capture-v4l-bindings.md +++ b/quest/m2/capture-v4l-bindings.md @@ -19,6 +19,6 @@ gate keeps the coverage. ## Related -- [Ship capture and playback](/quest/m2/cli-packaging.md) - shippable capture needs this first +- [Ship capture and playback](/quest/m2/cli-packaging.md) - the shippable capture milestone this work supports - [VAAPI encode and decode](/quest/m2/video-vaapi.md) - same pre-generated bindings pattern for libva - [Linux capture parity](/quest/m2/capture-linux.md) - the capture surface this unblocks From 1d2198fe863a034ff68bdf95ad680d987410cb2d Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Mon, 21 Sep 2026 11:04:02 -0700 Subject: [PATCH 3/3] docs(quest): reframe around Nix dev-time plus zero runtime requirements Co-Authored-By: Muse Spark --- quest/m2/capture-alsa-link.md | 46 +++++++++++++++++--------------- quest/m2/capture-v4l-bindings.md | 26 ++++++++++-------- quest/m2/cli-packaging.md | 5 ++++ 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/quest/m2/capture-alsa-link.md b/quest/m2/capture-alsa-link.md index 32b49ca788..13721d6b41 100644 --- a/quest/m2/capture-alsa-link.md +++ b/quest/m2/capture-alsa-link.md @@ -1,31 +1,35 @@ -# [S] Audio capture without link-time ALSA +# [S] Audio capture without runtime system libraries ## Goal -moq-audio `capture` and `playback` build on Linux without linking libasound, -so the microphone path stops blocking capture-by-default. +A released moq-audio capture/playback build carries no runtime system +requirement on Linux: Nix provides everything needed at dev time to compile, +and the shipped binary starts and degrades cleanly on hosts without those +libraries. ## Plan -Narrow the cpal backend set so a Linux capture build does not link libasound -unless the ALSA backend is asked for. The current matrix is the contract to -change: `capture` and `playback` pull cpal, whose `alsa` dependency is -non-optional on Linux in cpal 0.18, so libasound links whenever either is on; +Nix already covers the dev-time side (alsa-lib, alsa-plugins, and pipewire +are in the dev shell). What remains is the runtime linkage: cpal 0.18's +`alsa` dependency is non-optional on Linux, so libasound becomes a load-time +requirement and the binary refuses to start where it is absent. Follow the +vaapi/nvidia pattern and load the system library at runtime instead, falling +through to the next host when it is missing, so a build with the feature on +still links and starts driverless. + +The current feature matrix is the contract to change: `capture` and +`playback` pull cpal with ALSA always linked, while `pipewire = ["cpal/pipewire"]` and `pulseaudio = ["cpal/pulseaudio"]` activate -cpal without either. The target matrix keeps those host flags but makes them -require `capture` or `playback` so they never activate cpal alone, and puts -the ALSA backend behind an opt-in capability instead of the always-linked -default. Whether that capability comes from a cpal release gating `alsa` or -from in-tree handling is the implementation decision; document the supported -combinations in the moq-audio feature table with the same change. - -Verify by building the capture and playback features on a host without the -ALSA development libraries and by inspecting the dependency graph to prove -libasound is absent when unasked. The PR 3850 capture gate keeps the coverage. - -Verify by building the capture and playback features on a host without the -ALSA development libraries and by inspecting the dependency graph to prove -libasound is absent when unasked. The PR 3850 capture gate keeps the coverage. +cpal without either. Make the host flags require `capture` or `playback` so +they never activate cpal alone, and document the supported combinations in +the moq-audio feature table with the same change. If cpal cannot load ALSA at +runtime in-tree, split that half into its own upstream quest holding the cpal +release as a plain-text `Required` condition, and this quest requires it. + +Verify by building in the Nix shell, then running the shipped binary on a +host without libasound: it starts, lists devices, and captures where a +backend exists. Inspect the binary to prove no load-time requirement on +libasound. The PR 3850 capture gate keeps the coverage. ## Related diff --git a/quest/m2/capture-v4l-bindings.md b/quest/m2/capture-v4l-bindings.md index a8f46fc7ce..a68ea29819 100644 --- a/quest/m2/capture-v4l-bindings.md +++ b/quest/m2/capture-v4l-bindings.md @@ -2,23 +2,27 @@ ## Goal -moq-video `capture` builds on Linux without libclang or kernel headers, so the -camera path stops blocking capture-by-default. +moq-video `capture` builds for every builder without libclang or kernel +headers at build time, and carries no runtime system requirement. ## Plan -Vendor or pin the `v4l` crate with checked-in bindings and drop its bindgen -build script, the way `moq-nvenc` does and -[VAAPI](/quest/m2/video-vaapi.md) plans. Keep the `v4l` API so -`capture/v4l2.rs` and the `v4l2` codec backend need no logic changes. Fixing -`v4l` fixes both features since both drive the same device node through it. +The runtime side is already clean: the camera path drives the kernel through +ioctls, so no system library ships in the binary. What remains is build time. +Nix already covers in-tree builds (bindgenHook provides libclang), so vendor +or pin the `v4l` crate with checked-in bindings and drop its bindgen build +script, the way `moq-nvenc` does and +[VAAPI](/quest/m2/video-vaapi.md) plans. That covers every other builder too +(`cargo install`, Docker). Keep the `v4l` API so `capture/v4l2.rs` and the +`v4l2` codec backend need no logic changes; fixing `v4l` fixes both features +since both drive the same device node through it. -Verify by building `just rs capture` on a host without libclang and by -inspecting the dependency graph to prove bindgen is gone. The PR 3850 capture -gate keeps the coverage. +Verify by building `just rs capture` with no libclang on PATH and by +inspecting the binary to prove no new runtime library requirement. The PR +3850 capture gate keeps the coverage. ## Related - [Ship capture and playback](/quest/m2/cli-packaging.md) - the shippable capture milestone this work supports - [VAAPI encode and decode](/quest/m2/video-vaapi.md) - same pre-generated bindings pattern for libva -- [Linux capture parity](/quest/m2/capture-linux.md) - the capture surface this unblocks +- [Linux capture parity](/quest/m2/capture-linux.md) - the Linux capture milestone this work supports diff --git a/quest/m2/cli-packaging.md b/quest/m2/cli-packaging.md index be8a91fe7f..677d521666 100644 --- a/quest/m2/cli-packaging.md +++ b/quest/m2/cli-packaging.md @@ -28,3 +28,8 @@ dependencies present, and a Docker image without them fails at build rather than at run. Then verify the shipped artifact runs `moq devices` and `moq play` on each platform, since a feature that compiles into the binary and then fails to open a device is the same gap one layer down. + +## Required + +- [Capture without V4L2 bindgen](/quest/m2/capture-v4l-bindings.md) - the camera path must build without libclang before every distribution can ship it +- [Audio capture without runtime system libraries](/quest/m2/capture-alsa-link.md) - the microphone path must start without system audio libraries before every distribution can ship it