Skip to content

FFmpeg Helper

FFmpeg Helper solves a common pain point in audio/video processing pipelines: reliably getting FFmpeg to run across different operating systems and architectures without manual installation. It ships pre-built static FFmpeg binaries for six platform targets and wraps them in a tiny TypeScript API — one import and you’re encoding, transcoding, or converting media files.

Whether you’re building a CI pipeline for audio asset generation, a desktop app that needs to transcode user uploads, or a server-side media processing service, this package removes the “install FFmpeg on the target machine” step entirely.

  • Six platform targets — Ships static FFmpeg binaries for macOS (x64 + Apple Silicon arm64), Linux (x64, arm64, ia32), and Windows (x64, ia32) — all resolved automatically at runtime
  • Zero-config API — Auto-detects os.platform() and os.arch() to select the correct binary; no configuration needed
  • Programmatic execution — Promise-based run() function wraps child_process.exec with the correct binary path pre-applied
  • CLI mode — Use npx ffmpeg-helper -i input.wav output.mp4 to run FFmpeg directly from the command line without installing it globally
  • macOS codesigning & Gatekeeper checks — Includes shell scripts to verify code signatures, Gatekeeper assessment, and notarization stapling — critical for macOS Ventura+ where unsigned binaries are silently blocked
  • Self-testing on install — The postinstall script sets file permissions and runs the test suite automatically, catching binary issues before they surface at runtime
  • Timeout utility — Bundles a reusable timeout.sh script for wrapping long-running FFmpeg commands with configurable time limits

The core module in index.ts is remarkably concise — under 50 lines. It maps platform/architecture pairs to the correct binary path:

import { exec } from 'child_process';
import { arch, platform } from 'os';
import { resolve } from 'path';
import { promisify } from 'util';
export const binaries = {
darwin: {
x64: 'ffmpeg-darwin-x64.app/Contents/MacOS/ffmpeg-darwin-x64',
arm64: 'ffmpeg-darwin-arm64.app/Contents/MacOS/ffmpeg-darwin-arm64',
},
linux: {
x64: 'linux-x64',
arm64: 'linux-arm64',
},
win32: {
x64: 'win32-x64.exe',
arm64: 'win32-ia32.exe',
},
} as const;

On macOS, the binaries are packaged as .app bundles — this is intentional, as it allows proper codesigning and Gatekeeper compliance. The run function simply prepends the resolved binary path to your FFmpeg arguments:

export const run = (cmd: string) => {
return promisify(exec)(`${path} ${cmd}`);
}

A notable part of this project is the suite of shell scripts for dealing with macOS security. The test.sh script runs on every install to verify the binary works, but there are also dedicated scripts for deeper checks:

  • check-codesign.sh — Verifies code signatures with codesign -v --verify --deep --strict
  • check-gatekeeper.sh — Runs spctl --assess to confirm the binary passes Gatekeeper, and checks notarization stapling
  • check-allowed.sh — Verifies the binary label is in the allowed list via spctl --list
  • check-permissions.sh — Loops through all platform binaries to confirm execute permissions are set

This level of attention to macOS binary distribution reflects real-world experience with CI/CD pipelines where FFmpeg would mysteriously fail on macOS Ventura because of unsigned binary restrictions.

The project uses shell-based tests that run automatically during postinstall. The test.sh script validates the correct binary is selected for the current platform, verifies code signatures on macOS, and runs a trial encode. The test_timeout.sh script covers the timeout utility with three scenarios: command finishes before timeout, command exceeds timeout (expecting exit code 124), and command that fails with an error.

LanguageTypeScript, Bash
RuntimeNode.js
PlatformsmacOS (x64, arm64), Linux (x64, arm64, ia32), Windows (x64, ia32)
FFmpeg sourceffmpeg-static
LicenseGPL-3.0-or-later

The source code is available on the project’s GitHub repository.