This skill wires ffmpeg-static — a self-contained FFmpeg binary distributed as an npm package — into every assistant interaction. When a native system FFmpeg is also installed, the skill prefers the system binary (usually newer and GPU-capable); otherwise it falls back to the bundled one. All FFmpeg capabilities are available in both paths.
No PATH manipulation needed.
require('ffmpeg-static')returns the absolute path to the binary; scripts pass it directly tochild_process.spawn.
ffmpeg-static downloads pre-built binaries from GitHub Releases during npm install. Verify the package on npmjs.com/package/ffmpeg-static.bash
npm install ffmpeg-static
bash
npm install ffmpeg-static ffprobe-static
bash
node -e "console.log(require('ffmpeg-static'))"
# e.g. /path/to/node_modules/ffmpeg-static/ffmpeg
bash
node scripts/resolve_ffmpeg.js
The skill resolves the FFmpeg binary in this priority order:
FFMPEG_PATH env var — explicit override, always winsPATH directories with fs.accessSync; preferred when present (newer codecs, hardware acceleration)require('ffmpeg-static') absolute path; guaranteed to exist after npm installjs
// Canonical resolution — use this pattern in all scripts
const { resolveFfmpeg } = require('./scripts/resolve_ffmpeg');
const ffmpegPath = resolveFfmpeg(); // throws if none found
bash
$(node -e "process.stdout.write(require('ffmpeg-static'))") \
-i input.mkv -c:v libx264 -crf 23 -preset fast \
-c:a aac -b:a 128k output.mp4
bash
ffmpeg -ss 00:01:30 -i input.mp4 -frames:v 1 -q:v 2 thumb.jpg
bash
ffmpeg -i input.flac -q:a 2 output.mp3
bash
ffmpeg -i input.mp4 -vn -c:a copy audio.aac
bash
ffmpeg -ss 00:00:10 -to 00:01:00 -i input.mp4 -c copy trimmed.mp4
bash
ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4
filelist.txt format:
text
file '/abs/path/clip1.mp4'
file '/abs/path/clip2.mp4'
bash
ffmpeg -i input.mp4 -vf "scale=1280:-2" -c:a copy scaled.mp4
bash
ffmpeg -i input.mp4 -vf "fps=10,scale=480:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" output.gif
bash
ffmpeg -i input.mp4 -codec: copy -start_number 0 \
-hls_time 10 -hls_list_size 0 -f hls output.m3u8
Copy-paste patterns are in templates/node_patterns.txt. Key steps:
scripts/resolve_ffmpeg.js (pure fs, no shell calls)child_process.spawnfluent-ffmpeg — pass the resolved path via ffmpeg.setFfmpegPath()js
// In YOUR project (not inside the skill)
const { resolveFfmpeg } = require('ffmpeg-static-skill/scripts/resolve_ffmpeg');
const ffmpegBin = resolveFfmpeg(); // absolute path, ready to pass to spawn or fluent-ffmpeg
See templates/node_patterns.txt for ready-to-copy spawn, progress, ffprobe, and fluent-ffmpeg snippets.
VariableEffectFFMPEG_PATHOverride binary path; takes precedence over system and bundledFFPROBE_PATHOverride ffprobe binary pathFFMPEG_STATIC_SKIP_BINARY_DOWNLOADSet to 1 to skip download during npm install (use with system FFmpeg)
Call resolveFfmpeg() once and cache the result — don't call require('ffmpeg-static') inline in hot paths.
-c copy when no re-encoding is needed#Stream copy ( -c copy) is instantaneous and lossless. Only decode/encode when you actually need to change the codec or apply filters.
-ss before -i for fast seeking#-ss 00:01:00 -i input.mp4 (before -i) uses keyframe seeking (fast). -i input.mp4 -ss 00:01:00 (after -i) decodes from the start (accurate but slow for large files).
-y in non-interactive scripts#-y overwrites output without prompting. Without it, FFmpeg hangs waiting for stdin in CI or background processes.
Never interpolate user-supplied strings directly into FFmpeg args. Always validate paths exist and are the expected media type using ffprobe first.
Check ffmpeg -hwaccels at startup and gate hardware-accelerated paths on the system binary being active.
-loglevel error in production#Reduces stderr noise. Re-enable verbose logging ( -loglevel verbose) when debugging a failed transcode.
The bundled ffmpeg-static binary is compiled with a broad but fixed set of codecs. Key inclusions:
Video: H.264 (libx264), H.265 (libx265), VP8/VP9 (libvpx), AV1 (libaom-av1), MPEG-2/4, ProRes, DNxHD, Theora
Audio: AAC (native + libfdk-aac where licensed), MP3 (libmp3lame), Opus (libopus), Vorbis, FLAC, PCM
Containers: MP4, MKV, MOV, WebM, AVI, TS, HLS (m3u8), DASH, FLV, GIF, APNG
Images: MJPEG, PNG, WebP (via lavf)
Hardware encoders (nvenc, qsv, vaapi, videotoolbox) are not in the bundled binary. Use the system FFmpeg for GPU acceleration.
SymptomFixCannot find module 'ffmpeg-static'Run npm install ffmpeg-static in the project rootBinary not executable on Linux/macOSRun chmod +x $(node -e "process.stdout.write(require('ffmpeg-static'))")``Encoder libx264 not foundBundled binary may lack the codec; install system FFmpeg ( apt install ffmpeg / brew install ffmpeg)No such file or directory on outputEnsure the output directory exists before running FFmpegTranscode hangs in CIAdd -y flag to overwrite without promptingProgress not reportedUse -progress pipe:1 to write progress data to stdoutSlow GIF generationUse the two-pass palettegen approach (see example above)FFMPEG_STATIC_SKIP_BINARY_DOWNLOAD ignoredSet the env var before running npm install, not after