# ffmpeg

> A modern, typed Node.js API for processing media with FFmpeg

Latest version **1.1.3** (published 2026-08-21) · MIT license · 0 weekly downloads

## Install

```sh
npm install ffmpeg
pnpm add ffmpeg
yarn add ffmpeg
bun add ffmpeg
```

## Health

**Score 75/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; recently updated; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 1.1.3 |
| Published | 2026-08-21 |
| First published | 2012-12-04 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=24 |
| Dependencies | 0 |
| Unpacked size | 347.7 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 633 |
| Author | Damiano Ciarla |
| Maintainers | damiano.ciarla |
| Keywords | ffmpeg, ffprobe, video, audio, transcoding, typescript |

## Links

- npm: https://www.npmjs.com/package/ffmpeg
- Repository: https://github.com/damianociarla/node-ffmpeg
- Homepage: https://damianociarla.github.io/node-ffmpeg/
- Issues: https://github.com/damianociarla/node-ffmpeg/issues
- npm.io page: https://npm.io/package/ffmpeg

## Alternatives

- [@openai/codex-sdk](https://npm.io/package/@openai/codex-sdk.md) — 731.4K weekly downloads
- [babel-plugin-transform-react-jsx](https://npm.io/package/babel-plugin-transform-react-jsx.md) — 565.0K weekly downloads
- [babel-helper-remove-or-void](https://npm.io/package/babel-helper-remove-or-void.md) — 508.5K weekly downloads
- [@pnpm/store-controller-types](https://npm.io/package/@pnpm/store-controller-types.md) — 186.9K weekly downloads
- [react-native-signature-canvas](https://npm.io/package/react-native-signature-canvas.md) — 155.6K weekly downloads

## Recent versions

- 1.1.3 (latest) — 2026-08-21
- 1.1.2 — 2026-08-21
- 1.1.1 — 2026-08-21
- 1.1.0 — 2026-08-21
- 1.0.3 — 2026-08-21
- 1.0.2 — 2026-08-21
- 1.0.1 — 2026-08-21
- 1.0.0 — 2026-08-20
- 0.0.4 — 2013-01-16
- 0.0.3 — 2013-01-16
- 0.0.2 — 2012-12-05
- 0.0.1 — 2012-12-04

## README

# node-ffmpeg

[Documentation](https://damianociarla.github.io/node-ffmpeg/) · [API reference](https://damianociarla.github.io/node-ffmpeg/api/video) · [Migration guide](https://damianociarla.github.io/node-ffmpeg/guide/migration)

A small, typed Node.js wrapper around the FFmpeg and ffprobe command-line tools. It keeps the
original `ffmpeg` package API—Promise or callback construction, chainable setters, conversion,
frame extraction, audio extraction, and watermarks—while using modern Node.js primitives.

## Requirements

- Node.js 24 or newer
- `ffmpeg` and `ffprobe` on `PATH`, or explicit executable paths

The package intentionally does not download binaries. This keeps installation small and lets the
application choose the FFmpeg build and codecs it needs.

```sh
npm install ffmpeg
```

## Quick start

```ts
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');
```

CommonJS remains callable, as in `0.0.4`:

```js
const ffmpeg = require('ffmpeg');
const video = await new ffmpeg('/media/input.mp4');
await video.setVideoCodec('copy').setAudioCodec('copy').save('/media/copy.mp4');
```

The legacy callback API also remains available:

```js
new ffmpeg('/media/input.mp4', (error, video) => {
  if (error) return console.error(error);
  video.save('/media/output.mp4', (saveError, output) => {
    if (saveError) console.error(saveError);
    else console.log(output);
  });
});
```

For new TypeScript code, the named factory is the clearest form:

```ts
import { create } from 'ffmpeg';

const video = await create('/media/input.mp4', {
  timeout: 120_000,
  overwrite: true,
});
```

For services that process several files with one fixed FFmpeg installation, inspect capabilities
once with an isolated client:

```ts
import { createClient } from 'ffmpeg';

const client = await createClient({ overwrite: true, timeout: 120_000 });
const video = await client.open('/media/input.mp4');
```

Client executable paths, environment, and working directory are snapshotted at creation. Per-open
settings may adjust timeout, buffering, overwrite behavior, encoding, and cancellation without
invalidating the cached capabilities.

## Executable paths

Set paths globally for legacy applications:

```ts
ffmpeg.bin = '/opt/ffmpeg/bin/ffmpeg';
ffmpeg.ffprobeBin = '/opt/ffmpeg/bin/ffprobe';
```

Or per operation:

```ts
await ffmpeg('/media/input.mp4', {
  ffmpegPath: '/opt/ffmpeg/bin/ffmpeg',
  ffprobePath: '/opt/ffmpeg/bin/ffprobe',
});
```

When an absolute `ffmpegPath` is supplied and `ffprobePath` is omitted, a sibling `ffprobe`
executable is inferred. Hierarchical URLs such as HTTP, HTTPS, and RTSP are accepted as inputs when
supported by the installed FFmpeg build. Non-hierarchical virtual inputs, stdin (`-`), and Node.js
streams are not supported as primary inputs because initialization probes the source first.

## Settings

| Setting       | Default   | Meaning                                                  |
| ------------- | --------- | -------------------------------------------------------- |
| `encoding`    | `utf8`    | Process output encoding                                  |
| `timeout`     | `0`       | Maximum operation time in milliseconds; `0` disables it  |
| `maxBuffer`   | 16 MiB    | Conversion output tail and maximum complete probe output |
| `overwrite`   | `false`   | Use `-y`; otherwise `-n` prevents interactive hangs      |
| `ffmpegPath`  | `ffmpeg`  | FFmpeg executable                                        |
| `ffprobePath` | `ffprobe` | ffprobe executable                                       |
| `signal`      | —         | `AbortSignal` used to cancel an operation                |
| `cwd`, `env`  | inherited | Child-process working directory and environment          |

Long-running conversions retain only the most recent `maxBuffer` bytes of stdout and stderr. Probe
and configuration output must remain complete: if stdout exceeds the limit, the operation fails with
error `119` instead of parsing a truncated document.

## API

All setters are chainable:

- Video: `setDisableVideo`, `setVideoFormat`, `setVideoCodec`, `setVideoBitRate`,
  `setVideoFrameRate`, `setVideoStartTime`, `setVideoDuration`, `setVideoAspectRatio`,
  `setVideoSize`, `setVideoQuality`
- Audio: `setDisableAudio`, `setAudioCodec`, `setAudioFrequency`, `setAudioChannels`,
  `setAudioBitRate`, `setAudioQuality`
- General: `setMetadata`, `setThreads`, `setWatermark`, `addInput`, `addCommand`,
  `addOutputOption`, `addFilterComplex`, `getCommand`
- Execution: `save`, `fnExtractSoundToMP3`, `fnExtractFrameToJPG`, `fnAddWatermark`

`copy` is accepted by both codec setters. Repeated custom options such as multiple `-map` or
`-metadata` entries are supported.

Terminal methods consume the current fluent options at invocation. Their validation and process
errors always arrive through Promise rejection or the optional callback. Input/settings validation
performed by `ffmpeg()`, `new ffmpeg()`, `create()` and `client.open()` remains synchronous, as do
setters and `getCommand()`. Concurrent operations on one `Video` use isolated option snapshots. Their
shared lifecycle events may interleave, but every event includes an immutable operation context for
correlation.

### Metadata

`video.metadata` preserves the original package shape (`duration`, `video`, `audio`, and common
tags) and adds the complete ffprobe response at `video.metadata.raw`. Available formats and
encoders are exposed at `video.info_configuration`.

### Progress and lifecycle events

```ts
video.on('start', (command) => console.log(command));
video.on('progress', (progress, operation) => {
  console.log(operation.operationId, operation.destination, progress.percent);
});
video.on('stderr', (chunk) => process.stderr.write(chunk));
video.on('end', (result) => console.log(result.code));
video.on('error', (error) => console.error(error)); // optional
```

An `error` listener is optional: failed Promise operations reject normally instead of causing an
unhandled EventEmitter error.

### Frame extraction

```ts
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
are limited to files matching the extraction pattern, rather than every file in the directory.

### Custom FFmpeg options

```ts
await video
  .addCommand('-movflags', '+faststart')
  .addCommand('-map', '0:v:0')
  .addCommand('-map', '0:a:0?')
  .save('/media/output.mp4');
```

Arguments are passed directly to `spawn` with `shell: false`; do not add shell quotes.
Custom input, command, output-option, and filter methods are trusted escape hatches and must not
receive unvalidated user strings. Output destinations beginning with `-` are rejected; use an
explicit `./-name.ext` or absolute path when the filename intentionally starts with a dash.

## Migrating from 0.0.4

- Node.js 24+ and ffprobe are now required.
- Native Promises replace `when`; normal `await` and `.then()` usage is unchanged.
- Errors are `FfmpegError` instances with the historical numeric `code` and `msg` fields.
- Watermark compass positions now follow their conventional meaning (for example, `NE` is
  top-right). This fixes the old east/west inversion.
- Bitrates use modern stream-specific flags (`-b:v` and `-b:a`); numeric values are interpreted as
  kbit/s.
- Existing outputs are protected with `-n`. Set `overwrite: true` to use `-y`.
- The project publishes both ESM and CommonJS and includes its own TypeScript declarations;
  `@types/ffmpeg` is no longer needed.

See [AUDIT.md](AUDIT.md) for the code and issue audit and [CHANGELOG.md](CHANGELOG.md) for the
release summary.

## Security

FFmpeg processes untrusted and highly complex media. Keep the system FFmpeg build patched, apply
resource limits appropriate to your service, and see [SECURITY.md](SECURITY.md) before accepting
untrusted input.

## License

MIT © Damiano Ciarla

---
_Source: https://npm.io/package/ffmpeg · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
