Skip to content

fix(parsers): find FFmpeg and FFprobe installed by the project's npm installer packages - #5434

Merged
miguel-heygen merged 3 commits into
mainfrom
fix/ff-installer-packages
Oct 10, 2026
Merged

miguel-heygen merged 3 commits into
mainfrom
fix/ff-installer-packages

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

What changes for the user

A project that installs FFmpeg through npm (@ffmpeg-installer/ffmpeg and @ffprobe-installer/ffprobe in its own package.json) can now render without FFmpeg on the system PATH. Before, npx hyperframes render on such a Windows project stopped with "FFmpeg not found; FFprobe not found", and the only workaround was to prepend those packages' folders to PATH by hand.

Root cause

The FFmpeg/FFprobe lookups for CLI preflight and capture, engine render and the Studio server go through one resolver, findFfBinary in parsers/src/ffBinaries.ts. It checked the env overrides, PATH, the project's .hyperframes/bin and common Unix install folders, but never the project's own npm-installed FFmpeg, so a binary sitting in the project's node_modules was invisible.

Fix

findFfBinary now also checks an installer package as its last fallback, after .hyperframes/bin and the common Unix install folders, so any system FFmpeg wins over the old builds those packages ship. With Node's module resolution from the current directory (so its node_modules, a parent folder's, or NODE_PATH) it finds @ffmpeg-installer/ffmpeg (or @ffprobe-installer/ffprobe), resolves the platform package @ffmpeg-installer/<platform>-<arch> from there (so pnpm's isolated layout works) or else from the project (hoisted layouts), and returns the ffmpeg/ffmpeg.exe file in it only if it is executable. The Unix @ffprobe-installer packages ship ffprobe without the execute bit and rely on a postinstall chmod; when install scripts did not run, that file is skipped rather than reported as a working FFprobe. It only locates the binary: no code from the user's packages is loaded. Env overrides, PATH, .hyperframes/bin and the common install folders all still win, so machines with a system FFmpeg are unchanged.

Verification

  • New ffBinaries.test.ts cases build a temporary project with an empty PATH and a failing which: the hoisted ffmpeg and ffprobe packages are found (fail on the previous code); a pnpm-style layout, where the platform package sits next to the installer package and not in the project's node_modules, is found (fails when only the project is searched); a non-executable ffprobe is skipped (fails with a plain existence check; Unix only); a system binary in a common install folder wins over the installer package (fails when the installer lookup runs first). The tests hide the host's real install folders, so they pass on machines with FFmpeg installed.
  • The resolver tests (13) pass 3 runs in a row; typecheck, oxlint, oxfmt, the comment ratchet and fallow audit are clean.

Known limits

  • Yarn Plug'n'Play installs have no node_modules folder and are not searched.

  • @ffmpeg-installer ships FFmpeg 4.1-era builds (the @ffprobe-installer packages are newer 5.x builds). They render plain compositions, but variable-frame-rate video needs FFmpeg 5.1+ and fails with VIDEO_SOURCE_UNRENDERABLE on them; a preflight warning for an FFmpeg older than 5.1 follows in its own PR.

  • On Linux and macOS, when install scripts are blocked (pnpm 10+ by default, npm --ignore-scripts), @ffprobe-installer leaves ffprobe without the execute bit, so it is skipped and FFprobe is still reported missing; approving the package's build script (pnpm approve-builds) fixes it. Windows is unaffected.

  • media-use has its own FFmpeg lookup (env override or PATH) and does not use this resolver.

  • The lookup starts from the current directory, as the .hyperframes/bin lookup does; running the CLI from outside the project does not find the project's package.

Why this PR is small

It is a one-function change to the shared resolver with its test.

@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 2061 (base branch 2061), smooth 1502 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

@jrusso1020 jrusso1020 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at 9955457b.

  • Order. The installer packages are tried last: after the env override, PATH, .hyperframes/bin, and the common install folders. So a system FFmpeg always wins over the older npm builds, as the comment says. On Windows, where there are no common folders, the installer package is the fallback after PATH.
  • Lookup. findInInstallerPackage only resolves package.json paths through createRequire and never loads the package. It tries the platform package through the installer package first, for pnpm's isolated layout, then from the project. It returns a candidate only if isExecutablePathCandidate accepts it, and uses .exe on Windows. A missing package throws inside tryResolve and reads as not found.
  • Cost. It's a few synchronous resolutions inside the system search, with no spawn, and the result is cached like the other system lookups.
  • With #5439. Both rewrite lookupOnSystem and the doc comment in ffBinaries.ts, so whichever lands second needs a rebase. They compose: the installer lookup runs inside the search, and on a miss #5439 re-runs it every 5 s.

Note, not blocking: this lookup resolves from the current directory, but the cache is per binary for the process, so a long-running server that serves several projects keeps the first project's answer. .hyperframes/bin already behaves the same way.

Required checks are green at this head, including Windows render and tests.

— Rames

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 10, 2026
Merged via the queue into main with commit 748cda9 Oct 10, 2026
179 of 219 checks passed
@miguel-heygen
miguel-heygen deleted the fix/ff-installer-packages branch October 10, 2026 23: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.

2 participants