Skip to content

fix(linux): ship the shared ffmpeg CLI so transcription works over MCP and the CLI - #1222

Merged
EtienneLescot merged 1 commit into
mainfrom
fix/linux-ship-ffmpeg-cli
Oct 14, 2026
Merged

EtienneLescot merged 1 commit into
mainfrom
fix/linux-ship-ffmpeg-cli

Conversation

@EtienneLescot

@EtienneLescot EtienneLescot commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Summary

Linux packages now ship an ffmpeg executable, so native transcription works in the editor, over MCP (both transports) and through the CLI.

Root cause. build:linux runs fetch:ffmpeg:sdk, which vendors the shared SDK but skips the CLI. The package carried the libav shared objects and no ffmpeg, so resolveFfmpeg() returned null and extractMono16kPcm threw FfmpegUnavailableError (stt:native-extraction-unavailable).

Fix. build-linux-pipewire-helper.mjs stages the SDK's shared ffmpeg CLI at linux-<arch>/ffmpeg, the path ffmpegCandidates() already resolves.

Why this option.

  • Same shape as Windows and macOS. Windows ships ffmpeg-shared.exe, macOS stages the SDK's CLI beside its dylibs. Every entry point already goes through resolveFfmpeg(), so no runtime code changes.
  • No second implementation. Extracting through the addon's libav would duplicate extractAudio.ts in Rust. Fixing the renderer fallback's path approval would only make the slow path work, and the editor would stay on it.
  • System ffmpeg fallback rejected. A machine without one would stay broken, and an arbitrary system build can be GPL or a different version.
  • Size. About 0.5 MB plus libavdevice (5 MB), not the 110 MB static build. Same LGPL archive already verified by fetch-ffmpeg.mjs.

Packaging consistency.

  • AppImage, deb, rpm, pacman: all four take linux-*/** from the same directory, so all four get it. libavdevice needs only libc, so no depends change.
  • Nix: already covered and untouched. The wrapper sets OPENSCREEN_FFMPEG_PATH to an LGPL ffmpeg-headless, the first candidate.
  • Flatpak: still a spike (--disable-programs, no crates/thirdparty). The script warns and skips there, as stageFfmpeg already does.

Out of scope. The renderer fallback still cannot read an unapproved path in the CLI and MCP runners. That path is no longer hit on a packaged build. It is worth a separate issue if a no-ffmpeg dev setup matters.

Related issue

Fixes #1221

Type of change

  • Bug fix
  • Feature
  • Enhancement
  • Documentation
  • Refactor / maintenance
  • Performance
  • Security

Release impact

  • Patch
  • Minor
  • Major / breaking change
  • No release note needed

Desktop impact

  • Windows
  • macOS
  • Linux
  • Installer / packaging
  • Not platform-specific

Screenshots / video

Not applicable.

Testing

  • Staging, in WSL Ubuntu 24.04 against the pinned BtbN tree: copied the CLI and the 7 libraries into the target layout, ran patchelf --set-rpath '$ORIGIN/helper-ffmpeg'. Result: RUNPATH [$ORIGIN/helper-ffmpeg], -version starts from / without LD_LIBRARY_PATH, -L reports LGPL, and the STT extraction args (-vn -af aresample=first_pts=0 -ac 1 -ar 16000 -f s16le) decode a 2 s AAC clip to 64,644 bytes. GLIBC ceiling of the CLI and libavdevice is 2.28.
  • Unit tests: before-pack.test.mjs (Linux payload without ffmpeg is refused), audioPeaks.test.ts (platform pinned to linux: the candidate list contains linux-x64/ffmpeg, and the linux-*/** filter ships it).
  • npx tsc --noEmit, npx tsc -p tsconfig.test.json --noEmit, npm run lint: clean.
  • npx vitest --run electron/stt electron/mcp electron/cli src/cli electron/media scripts/before-pack.test.mjs: 407 passed.
  • Real Linux build: artifact-only dispatch of build.yml on this branch, run 38597935774. The Linux job logs Staged …/linux-x64/ffmpeg: ffmpeg version n8.1.2-34-g9b6c8969e0, then passes before-pack, the symbol floor and the clean-container check for deb, rpm and pacman.
  • Not run: a packaged transcription. A Linux e2e re-run of transcribe on that artifact is the remaining check.

🤖 Generated with Claude Code

Linux packages carried the libav shared objects but no ffmpeg executable, so native STT extraction threw FfmpegUnavailableError over MCP and the CLI. build-linux-pipewire-helper.mjs now stages the SDK's shared CLI at linux-<arch>/ffmpeg with its RUNPATH on helper-ffmpeg/ (plus libavdevice), probes it, and before-pack refuses a Linux payload without it.
@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 29c930f9-e836-4481-9943-acebb08f95e3
📥 Commits

Reviewing files that changed from the base of the PR and between 2d98601 and 65daf25.

📒 Files selected for processing: 6
  • electron-builder.json5
  • electron/media/audioPeaks.test.ts
  • scripts/before-pack.cjs
  • scripts/before-pack.test.mjs
  • scripts/build-linux-pipewire-helper.mjs
  • scripts/fetch-ffmpeg.mjs

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 5 remain after this review.

📝 Walkthrough

The Linux build now stages the shared FFmpeg CLI with its required library and RUNPATH. Packaging checks require the executable, and a test verifies its Linux candidate path and resource filter.

Changes: Linux FFmpeg CLI packaging

Layer / File(s) Summary
Stage the shared FFmpeg CLI
scripts/build-linux-pipewire-helper.mjs, scripts/fetch-ffmpeg.mjs, electron-builder.json5
The build script stages the shared FFmpeg executable, sets its RUNPATH, and includes libavdevice. Comments describe how the staged CLI supports waveform peaks and native STT audio extraction.
Validate CLI packaging and resolution
scripts/before-pack.cjs, scripts/before-pack.test.mjs, electron/media/audioPeaks.test.ts
Linux payload validation now requires the ffmpeg executable. Tests check payload acceptance and rejection, the Linux FFmpeg candidate path, and the Linux resource filter.

Priority: ⬆️ High

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: christian-wr

Merge Risk: ⚪ Minimal · up to 65daf

No actionable merge-blocking issue remains after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 5 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Linked Issues check Passed The PR addresses active issue #1221. build-linux-pipewire-helper.mjs stages the shared CLI at linux-<arch>/ffmpeg, stages libavdevice with the unrenamed libraries, sets the CLI RUNPATH to `$ORIG…
Out of Scope Changes check Passed The changes stay within issue #1221. Packaging comments, before-pack validation, build staging, and tests directly support shipping and resolving the Linux FFmpeg CLI. The changes do not alter unrel…
Title check Passed The title clearly identifies the primary change: shipping the shared Linux ffmpeg CLI so transcription works over MCP and the CLI.
Description check Passed The description completes the required sections, identifies issue #1221, classifies the change, documents Linux and packaging impact, explains the fix, and lists detailed testing and remaining validat…
Full details: Docstring Coverage

Explanation

Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 5 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@EtienneLescot
EtienneLescot merged commit 7e914af into main Oct 14, 2026
27 checks passed
@EtienneLescot
EtienneLescot deleted the fix/linux-ship-ffmpeg-cli branch October 14, 2026 16:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Linux package: transcription fails over MCP and the CLI (no ffmpeg executable shipped)

1 participant