Bundle the ffmpeg sidecar (#117) #118

Merged
crowmaki merged 2 commits from issue-117-ffmpeg-sidecar into main 2026-10-09 08:56:01 +00:00
Owner

Closes #117.

Ships ffmpeg as a Tauri sidecar, so posters, joined Voice clips, master stamping and proxies no longer depend on the ffmpeg on PATH.

The build

The comment on #117 named gyan.dev 9.0.2. However, gyan.dev builds are all GPLv3, and neither the essentials nor the full build has libopenh264. That conflicts with the issue's "unmodified LGPL build" and with the OpenH264 proxy fallback. After discussion, this uses an LGPL build of the same version:

  • BtbN FFmpeg-Builds ffmpeg-n9.0.2-17-g2a571b6068-win64-lgpl-9.0.zip, from release autobuild-2026-09-30-13-08. BtbN keeps month-end autobuilds and prunes the daily ones.
  • Configured with --enable-version3 (LGPLv3), without --enable-gpl or --enable-nonfree.
  • Has libopenh264 and h264_nvenc (checked by a new test).

Changes

  • scripts/fetch-ffmpeg.mjs downloads the pinned zip and checks the zip's SHA-256 and ffmpeg.exe's SHA-256. It then writes src-tauri/binaries/ffmpeg-x86_64-pc-windows-msvc.exe, which is gitignored. If the sidecar already matches, the script exits in about 0.15 s. It has a small zip reader, so it needs no system unzip/tar (Bun tests in fetch-ffmpeg.test.mjs).
  • src-tauri/build.rs runs the script before tauri_build::build(). So tauri dev, tauri build and cargo test --workspace fetch it on a fresh checkout. It runs again when the script (and so the pin) changes or the sidecar is missing. The first build needs node and network access.
  • tauri.conf.json: bundle.externalBin: ["binaries/ffmpeg"], and bundle.resources for licenses/ffmpeg/.
  • Ffmpeg::locate: in debug builds, if nothing is found beside the exe, it tries the fetched sidecar in the checkout before PATH. The order is now AI_STUDIO_FFMPEG, beside the exe, the fetched sidecar (debug only), PATH.
  • Integration tests now use Ffmpeg::locate() instead of reading AI_STUDIO_FFMPEG or falling back to "ffmpeg", so they run the same binary.
  • src-tauri/licenses/ffmpeg/: the LGPLv3 and GPLv3 texts and NOTICE.md. The notice names the build, both hashes, the FFmpeg source commit and the BtbN build-recipe commit. It also says the binary is used unmodified and can be replaced.
  • run-ai-studio skill: how the sidecar is fetched for development.

Verification

  • Without ffmpeg on PATH: cargo test --workspace --all-features passes, including the two proxy tests from the issue. This machine's own PATH ffmpeg lacks libopenh264 and used to fail them.
  • Installer contents: bun run tauri build produced the MSI and NSIS installers. An administrative extract of the MSI puts ffmpeg.exe next to ai-studio.exe, with the licence files under licenses/ffmpeg/.
  • Re-fetch: deleting src-tauri/binaries/ and rebuilding fetches the sidecar again.
  • Other checks: bun test src scripts and bun run check pass. Clippy shows only warnings that were already on main.
  • Encoder choice: detect_proxy_encoder is unchanged. the_encoder_the_startup_check_finds_makes_a_proxy passes on an RTX 5090.

Open points

  • Notices for statically linked libraries. The build statically links other libraries under BSD/MIT-style licences, such as OpenH264 and dav1d. NOTICE.md points to the build recipe, which lists them, but does not reproduce their licence texts. If you want full attribution in the bundle, that is a follow-up.
  • Source availability. The source references point to upstream hosts (FFmpeg git and BtbN on GitHub). Under LGPLv3 the distributor stays responsible for keeping that source available. Mirroring the source is an option if that matters for releases.
  • ADR-0003. The doc comment in ffmpeg.rs and the issue both cite ADR-0003 for the sidecar, but ADR-0003 ("A Rust core owns the domain") doesn't mention ffmpeg. This decision may deserve its own ADR.
  • cargo test -p studio-core alone doesn't build src-tauri, so on a fresh checkout run node scripts/fetch-ffmpeg.mjs first. The skill says so.
Closes #117. Ships ffmpeg as a Tauri sidecar, so posters, joined Voice clips, master stamping and proxies no longer depend on the ffmpeg on `PATH`. ## The build The comment on #117 named gyan.dev 9.0.2. However, gyan.dev builds are all GPLv3, and neither the essentials nor the full build has `libopenh264`. That conflicts with the issue's "unmodified LGPL build" and with the OpenH264 proxy fallback. After discussion, this uses an LGPL build of the same version: - **BtbN FFmpeg-Builds** `ffmpeg-n9.0.2-17-g2a571b6068-win64-lgpl-9.0.zip`, from release `autobuild-2026-09-30-13-08`. BtbN keeps month-end autobuilds and prunes the daily ones. - Configured with `--enable-version3` (LGPLv3), without `--enable-gpl` or `--enable-nonfree`. - Has `libopenh264` and `h264_nvenc` (checked by a new test). ## Changes - **`scripts/fetch-ffmpeg.mjs`** downloads the pinned zip and checks the zip's SHA-256 and `ffmpeg.exe`'s SHA-256. It then writes `src-tauri/binaries/ffmpeg-x86_64-pc-windows-msvc.exe`, which is gitignored. If the sidecar already matches, the script exits in about 0.15 s. It has a small zip reader, so it needs no system `unzip`/`tar` (Bun tests in `fetch-ffmpeg.test.mjs`). - **`src-tauri/build.rs`** runs the script before `tauri_build::build()`. So `tauri dev`, `tauri build` and `cargo test --workspace` fetch it on a fresh checkout. It runs again when the script (and so the pin) changes or the sidecar is missing. The first build needs `node` and network access. - **`tauri.conf.json`**: `bundle.externalBin: ["binaries/ffmpeg"]`, and `bundle.resources` for `licenses/ffmpeg/`. - **`Ffmpeg::locate`**: in debug builds, if nothing is found beside the exe, it tries the fetched sidecar in the checkout before `PATH`. The order is now `AI_STUDIO_FFMPEG`, beside the exe, the fetched sidecar (debug only), `PATH`. - **Integration tests** now use `Ffmpeg::locate()` instead of reading `AI_STUDIO_FFMPEG` or falling back to `"ffmpeg"`, so they run the same binary. - **`src-tauri/licenses/ffmpeg/`**: the LGPLv3 and GPLv3 texts and `NOTICE.md`. The notice names the build, both hashes, the FFmpeg source commit and the BtbN build-recipe commit. It also says the binary is used unmodified and can be replaced. - **`run-ai-studio` skill**: how the sidecar is fetched for development. ## Verification - **Without ffmpeg on `PATH`:** `cargo test --workspace --all-features` passes, including the two proxy tests from the issue. This machine's own `PATH` ffmpeg lacks `libopenh264` and used to fail them. - **Installer contents:** `bun run tauri build` produced the MSI and NSIS installers. An administrative extract of the MSI puts `ffmpeg.exe` next to `ai-studio.exe`, with the licence files under `licenses/ffmpeg/`. - **Re-fetch:** deleting `src-tauri/binaries/` and rebuilding fetches the sidecar again. - **Other checks:** `bun test src scripts` and `bun run check` pass. Clippy shows only warnings that were already on `main`. - **Encoder choice:** `detect_proxy_encoder` is unchanged. `the_encoder_the_startup_check_finds_makes_a_proxy` passes on an RTX 5090. ## Open points - **Notices for statically linked libraries.** The build statically links other libraries under BSD/MIT-style licences, such as OpenH264 and dav1d. `NOTICE.md` points to the build recipe, which lists them, but does not reproduce their licence texts. If you want full attribution in the bundle, that is a follow-up. - **Source availability.** The source references point to upstream hosts (FFmpeg git and BtbN on GitHub). Under LGPLv3 the distributor stays responsible for keeping that source available. Mirroring the source is an option if that matters for releases. - **ADR-0003.** The doc comment in `ffmpeg.rs` and the issue both cite ADR-0003 for the sidecar, but ADR-0003 ("A Rust core owns the domain") doesn't mention ffmpeg. This decision may deserve its own ADR. - **`cargo test -p studio-core` alone** doesn't build `src-tauri`, so on a fresh checkout run `node scripts/fetch-ffmpeg.mjs` first. The skill says so.
Ship BtbN's unmodified LGPLv3 win64 build of FFmpeg 9.0.2 as a Tauri
sidecar. scripts/fetch-ffmpeg.mjs downloads it at a pinned month-end
autobuild, checks the zip's and ffmpeg.exe's SHA-256, and places it at
src-tauri/binaries/ffmpeg-x86_64-pc-windows-msvc.exe (gitignored).
src-tauri/build.rs runs it before tauri-build, so tauri dev, tauri build
and cargo test --workspace all get it.

Ffmpeg::locate falls back, in debug builds, to the fetched sidecar in
the checkout, so tests run the shipped binary and not the PATH ffmpeg.
Integration tests now use Ffmpeg::locate instead of reading
AI_STUDIO_FFMPEG themselves.

The bundle carries the LGPL and GPL texts and a notice naming the build,
its hashes, the FFmpeg commit and the build-recipe commit.
Rerun build.rs when the sidecar is missing, not only when the fetch
script changes, and say so. Drop the ADR-0003 citation from the fetch
script, since that ADR does not record the sidecar. The dev-sidecar
tests reuse FETCHED_SIDECAR and its cfg, so they skip in release test
builds. Clearer names in the fetch script and Ffmpeg::search.
crowmaki deleted branch issue-117-ffmpeg-sidecar 2026-10-09 08:56:01 +00:00
Sign in to join this conversation.
No description provided.