Files
skills/docs/media/audio/audio-codec-ffmpeg-native/src/binary/binary.md
2026-05-29 08:20:56 +01:00

3.2 KiB

binary

(no submodules)

Purpose

This module owns ffmpeg-binary discovery for @suaveplan/audio-codec-ffmpeg-native. It implements a fixed four-step precedence chain — caller-supplied provider, explicit absolute path, dynamically imported @ffmpeg-installer/ffmpeg optional dependency, then PATH-based discovery — and memoises successful resolutions by options-object identity so that high-traffic decode/encode pipelines pay the resolution cost exactly once per shared options bundle.

The resolver throws AudioCodecFfmpegNativeError("AUDIO_CODEC_FFMPEG_NATIVE.BINARY_MISSING") when every step fails, which lets the codec surface an actionable error to the caller instead of waiting for a downstream ENOENT from child_process.spawn.

Features

  • Strict precedence: provider → explicit path → installer → PATH lookup.
  • Promise-returning provider supported (sync providers also accepted).
  • Dynamic import("@ffmpeg-installer/ffmpeg") so the optional dependency is never a hard requirement at module load.
  • Test-injectable installerLoader and pathLookup hooks decouple resolution from real filesystem state.
  • BINARY_MISSING error code on full-chain failure with no leaked stack from the underlying optional-dep failure.
  • WeakMap-keyed memoisation that automatically GCs entries when the caller drops their options reference.

Usage: Basic

import { resolveBinary } from "@suaveplan/audio-codec-ffmpeg-native/binary/binary";

const { path, source } = await resolveBinary();
console.log(`Using ffmpeg at ${path} via ${source}`);

Usage: Advanced

import { resolveBinary } from "@suaveplan/audio-codec-ffmpeg-native/binary/binary";

const opts = {
    binaryProvider: async () => process.env.FFMPEG_PATH ?? "",
    binaryPath: "/usr/local/bin/ffmpeg",
    installerLoader: async () => ({ path: "/opt/ffmpeg" }),
    pathLookup: () => "/usr/bin/ffmpeg",
} as const;

const first = await resolveBinary(opts);
const second = await resolveBinary(opts); // memoised — no re-resolution.

API Reference

  • resolveBinary(opts?): Promise<ResolvedBinary> — returns { path, source }.
  • BinaryResolverOptions — binaryProvider, binaryPath, installerLoader, pathLookup (all optional; first match wins per the precedence chain).
  • ResolvedBinary.source — "provider" | "explicit" | "installer" | "path".

Implementation Notes

The four-step chain is hard-coded — there is no plugin slot — because deviation in precedence would silently change which binary actually runs on production servers. Empty strings are treated as "miss" so callers can write () => "" in a provider to opt into the next strategy without throwing.

The installer is imported via dynamic import() because static imports would make @ffmpeg-installer/ffmpeg a hard dependency rather than the optional one the spec requires. Any failure inside the installer load (missing module, platform mismatch, exec-bit stripped) is swallowed and the chain advances — the only surfaced error is BINARY_MISSING after the entire chain misses.

Memoisation uses a WeakMap keyed by the options object reference; callers who want forced re-resolution pass a fresh options bundle.