damianociarla/node-ffmpeg
ffmpeg module for nodejs
What it is
node-ffmpeg is a JavaScript/TypeScript library that lets you control the command-line tools ffmpeg and ffprobe from your code. Instead of typing shell commands, you call methods like setVideoCodec('libx264') or save('/output.mp4'). It wraps the older, widely used ffmpeg package’s API but modernises it: native Promises, TypeScript types, and supports both ESM and CommonJS.
Requirements
- Node.js 24 or newer.
ffmpegandffprobemust be installed and available on your system’sPATH, or you must provide their exact paths.- The library intentionally does not download its own FFmpeg binaries — this keeps the package small and lets you pick the FFmpeg build and codecs you need.
Installation
npm install ffmpeg
Quick start (TypeScript)
import ffmpeg from 'ffmpeg';
const video = await ffmpeg('/media/input.mp4');
video.on('progress', ({ percent, time }) => {
console.log(percent === undefined ? `${time}s` : `${percent.toFixed(1)}% (${time}s)`);
});
await video
.setVideoCodec('libx264')
.setVideoBitRate(2_000)
.setAudioCodec('aac')
.setAudioBitRate(192)
.setVideoSize('1280x?', true, true, 'black')
.save('/media/output.mp4');
The methods are chainable — you can call one after another. The operation starts only when you call a terminal method like save(). There’s also a callback-style API from the original package, and a named factory create() that supports options like timeout and overwrite.
For services processing many files, you can create a client once with createClient() to reuse FFmpeg settings.
Executable paths
You can set the paths to ffmpeg and ffprobe globally (for legacy apps) or per operation. If you give an absolute ffmpegPath but no ffprobePath, the library guesses that ffprobe sits next to it.
Settings (table from README)
| Setting | Default | Meaning |
|---|---|---|
encoding |
utf8 |
Process output encoding |
timeout |
0 |
Max operation time in ms; 0 = no timeout |
maxBuffer |
16 MiB | How much conversion output to keep; also max probe output |
overwrite |
false |
Use -y to overwrite; otherwise -n prevents interactive prompts |
ffmpegPath |
ffmpeg |
FFmpeg executable |
ffprobePath |
ffprobe |
ffprobe executable |
signal |
— | AbortSignal to cancel an operation |
cwd, env |
inherited | Child‑process working directory and environment |
Long-running conversions only keep the last maxBuffer bytes of output. Probe output must fit completely inside maxBuffer or the operation fails with error 119.
API highlights
- Setters (all chainable): video setters like
setDisableVideo,setVideoCodec,setVideoBitRate, etc.; audio setters likesetDisableAudio,setAudioCodec,setAudioBitRate; general setters likesetMetadata,setThreads,setWatermark,addInput,addCommand,addOutputOption,addFilterComplex, andgetCommand(returns the built command). - Terminal methods:
save,fnExtractSoundToMP3,fnExtractFrameToJPG,fnAddWatermark. These start the actual process. copyis accepted as a codec value, meaning “copy the stream without re‑encoding”.- Repeated custom options (e.g. multiple
-mapor-metadataentries) are allowed.
Validation inside terminal methods gives errors through Promise rejection or the optional callback. Setter validation remains synchronous. Concurrent operations on one video object use isolated option snapshots.
Metadata and events
video.metadatakeeps the original shape (duration,video,audio, tags) and also exposes the full ffprobe response atvideo.metadata.raw.- You can listen to lifecycle events:
'start','progress'(with percent/time),'stderr','end', and'error'. - An
'error'listener is optional — failed Promises reject normally without needing it.
Frame extraction
const files = await video.fnExtractFrameToJPG('/media/frames', {
start_time: '00:00:10',
every_n_seconds: 5,
number: 10,
size: '640x?',
quality: 2,
file_name: 'preview_%s',
});
Only one of every_n_frames, every_n_seconds, or every_n_percentage may be set. Returned paths only include files matching the extraction pattern.
Custom FFmpeg options
Use addCommand to pass raw arguments. They are passed directly to spawn without shell interpretation, so do not add shell quotes. These methods are trusted escape hatches — never pass unvalidated user input. Output destinations starting with - are rejected; use ./-name.ext instead.
Migration from 0.0.4
- Node.js 24+ and
ffprobeare now required. - Native Promises replace the old
whenlibrary;awaitworks as before. - Errors are now
FfmpegErrorinstances with the historical numericcodeandmsgfields. - Watermark compass positions now follow conventional meaning (
NE= top‑right, fixing the old inversion). - Bitrates use
-b:v/-b:a; numeric values are treated as kbit/s. - Existing outputs are protected with
-n; setoverwrite: trueto use-y. - The package now ships its own TypeScript declarations, so
@types/ffmpegis unnecessary.
Security
FFmpeg processes untrusted and complex media. Keep your system FFmpeg patched, apply resource limits, and read SECURITY.md before accepting untrusted input.
License
MIT © Damiano Ciarla.
Related
- Project
- Project
- Project
- Project