# FFmpeg

Canonical URL: https://encode.wiki/tools/utilities/ffmpeg/
Content version: ca42e61ede0a24f789d7287a0001244ad22f4abf
Status: current
License: CC BY-SA 4.0
Checksum (SHA-256): 82902c05a012dc79b13cdc4c310fff2ecbb053f47394b2cf5879a72fc82b7b75

> **Repository:** [FFmpeg/FFmpeg](https://code.ffmpeg.org/FFmpeg/FFmpeg). Latest tag: [n9.0.2](https://code.ffmpeg.org/FFmpeg/FFmpeg/src/tag/n9.0.2), Sep 18, 2026. Last commit: Oct 8, 2026.

[FFmpeg](https://ffmpeg.org/) is the multimedia framework almost every other tool on this wiki leans on. It ships three command-line programs: `ffmpeg` (decode, filter, encode, mux), `ffprobe` (inspect files) and `ffplay` (a minimal player), plus the `libav*` libraries that players, browsers and encoders such as [Av1an](/tools/utilities/av1an/) use internally.

FFmpeg wraps external encoders rather than replacing them: `libx264`, `libx265`, `libsvtav1`, `libaom-av1`, `libopus` and so on are the same libraries as the standalone encoders, exposed through FFmpeg options. Which of them you have depends entirely on how your binary was built.

For a guided first encode, see [Make your first FFmpeg encode](/guides/first-ffmpeg-encode/).

## Get a good build

| Platform | Recommended source                                                                                                                                                                                                           |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Windows  | [gyan.dev](https://www.gyan.dev/ffmpeg/builds/) or [BtbN](https://github.com/BtbN/FFmpeg-Builds/releases). Both offer release and git-master builds. Pick gyan.dev's "full" build for encoding work; it includes libraries such as SVT-AV1 and dav1d that the "essentials" build leaves out. `winget install ffmpeg` installs it. |
| macOS    | [Homebrew](https://formulae.brew.sh/formula/ffmpeg) (`brew install ffmpeg`) or the static builds linked from the [download page](https://ffmpeg.org/download.html#build-mac).                                                     |
| Linux    | Your distribution's package if it is recent. Debian/Ubuntu LTS packages are often several major versions behind; [BtbN](https://github.com/BtbN/FFmpeg-Builds/releases) publishes static Linux builds as well.                 |
| Any      | Build from source following the [compilation guide](https://trac.ffmpeg.org/wiki/CompilationGuide) when you need a specific encoder version or a library no packaged build includes.                                         |

The FFmpeg project itself only publishes source code; every binary above is a third-party build. Encoders improve quickly, so an old distribution FFmpeg can be stuck on an SVT-AV1 or libaom release that is years out of date. `ffmpeg -encoders` shows what your build actually contains.

Licensing follows the build: FFmpeg is LGPL by default, becomes GPL when GPL libraries such as x264 or x265 are enabled, and builds with "nonfree" components such as `libfdk_aac` cannot be redistributed. See [FFmpeg legal](https://ffmpeg.org/legal.html).

## How a command is put together

```sh
ffmpeg [global options] [input options] -i input [output options] output
```

Options apply to the next input or output file named after them, so position matters:

```sh
ffmpeg -r 24 -i input.mkv output.mkv   # input option: treat the input as 24 fps
ffmpeg -i input.mkv -r 24 output.mkv   # output option: convert to 24 fps, dropping or duplicating frames
```

A normal encode:

```sh
ffmpeg -i input.mkv -c:v libx264 -crf 20 -preset slow -c:a libopus -b:a 128k output.mkv
```

The `:v` and `:a` suffixes are stream specifiers. `-c:v` sets the video codec, `-b:a` the audio bitrate, `-c:a:1` the codec of the second audio stream only. Encoder-specific options (`-crf`, `-preset`, `-svtav1-params`, `-x265-params`) are documented on each encoder's page and in [FFmpeg codecs](https://ffmpeg.org/ffmpeg-codecs.html); `ffmpeg -h encoder=libsvtav1` prints the options your build's wrapper accepts.

The output container is chosen from the file extension. Use `-f` only when there is no extension to go by, for example `-f null -` to decode without writing a file or `-f yuv4mpegpipe -` to pipe to another program.

Common general options:

| Option                  | Use                                                                                         |
| ----------------------- | ------------------------------------------------------------------------------------------- |
| `-y`                    | Overwrite the output without asking.                                                        |
| `-ss`, `-t`, `-to`      | Start time, duration and end time. Before `-i` they apply to the input, after it to the output. |
| `-frames:v N`           | Stop after N video frames.                                                                  |
| `-hide_banner`          | Hide the build configuration that FFmpeg prints at startup.                                 |
| `-loglevel error`       | Print only errors (useful in scripts).                                                      |

## Choose streams with `-map`

Without `-map`, FFmpeg picks **one** video stream (highest resolution), **one** audio stream (most channels) and one subtitle stream if the output container can hold it. Extra audio tracks, subtitles, attachments and data streams are silently dropped. That is the most common surprise for newcomers.

Once you use `-map`, only the mapped streams go to the output:

```sh
ffmpeg -i input.mkv -map 0 -c:v libx264 -crf 20 -c:a copy -c:s copy output.mkv
```

| Map                          | Selects                                                                  |
| ---------------------------- | ------------------------------------------------------------------------ |
| `-map 0`                     | Every stream of the first input                                          |
| `-map 0:v:0`                 | The first video stream                                                   |
| `-map 0:a`                   | All audio streams                                                        |
| `-map 0:a:m:language:jpn`    | Audio streams tagged Japanese                                            |
| `-map -0:a:1`                | Removes the second audio stream from what is already mapped              |
| `-map '0:s?'`                | All subtitle streams, without failing if there are none                  |
| `-map 1:a`                   | Audio from the second input file (inputs are numbered from 0)            |

Quote maps that contain `?` so your shell does not treat it as a wildcard. `ffprobe input.mkv` lists the streams with their indexes and languages.

## Copy streams instead of re-encoding

`-c copy` copies the compressed stream into the new container untouched. It is fast and lossless, so use it for every stream you are not re-encoding:

```sh
ffmpeg -i input.mkv -map 0 -c copy output.mp4
```

The target container must support every copied codec. MP4, for example, cannot hold ASS or PGS subtitles, so the command above fails if the input has them; drop them with `-map -0:s` or keep Matroska. You can mix copy and encoding per stream:

```sh
ffmpeg -i input.mkv -map 0 -c copy -c:a:1 libopus -b:a:1 96k output.mkv
```

Cutting with `-c copy` can only start on a keyframe. With `-ss` before `-i`, FFmpeg keeps the frames from the previous keyframe so the cut starts earlier than you asked; re-encode the video if the cut has to be frame-accurate. For lossless cutting and joining of Matroska files, [mkvmerge](/tools/utilities/mkvtoolnix/) is usually easier.

## Filters

Filters only run on streams you re-encode; you cannot filter and `-c copy` the same stream. A single-input chain uses `-vf` (video) or `-af` (audio), with filters separated by commas:

```sh
ffmpeg -i input.mkv -vf "crop=1920:800,scale=-2:720" -c:v libsvtav1 -crf 35 -preset 6 -c:a copy output.mkv
```

`scale=-2:720` keeps the aspect ratio and rounds the width to an even number, which 4:2:0 encoders require. Filters with several inputs or outputs use `-filter_complex` with labelled pads. This one scales an encode back to the source resolution and stacks the two side by side for a visual comparison:

```sh
ffmpeg -i source.mkv -i encode.mkv -filter_complex "[1:v]scale=1920:1080:flags=bicubic[enc];[0:v][enc]hstack" -frames:v 1 compare.png
```

Commonly used filters include `scale` and `zscale` (resizing and colour conversion), `crop`, `format` (pixel format), `fps`, `yadif`/`bwdif` (deinterlacing) and the metric filters `libvmaf`, `xpsnr`, `ssim` and `psnr`. Anything more involved, such as denoising, debanding or inverse telecine, is usually done in [VapourSynth](/tools/filtering/vapoursynth/).

## Pipe into standalone encoders

Standalone encoders often get new features before FFmpeg's wrappers expose them. Pipe decoded frames to them as Y4M:

```sh
ffmpeg -i input.mkv -pix_fmt yuv420p10le -strict -1 -f yuv4mpegpipe - | SvtAv1EncApp -i - --crf 30 --preset 4 -b output.ivf
```

`-strict -1` is needed because 10-bit pixel formats are not part of the original Y4M specification and FFmpeg refuses to write them otherwise. The encoder writes video only; mux it with the audio afterwards using FFmpeg or mkvmerge.

## Inspect files with ffprobe

```sh
ffprobe input.mkv
ffprobe -v error -show_streams -show_format -of json input.mkv
```

The first prints a readable summary of every stream. The second gives the full stream properties (codec, profile, pixel format, colour metadata, frame rate, language and disposition) as JSON for scripts. `-select_streams v:0` limits the output to one stream, and `-show_entries stream=codec_name,pix_fmt,color_transfer` to specific fields.

To check that a file decodes cleanly from start to finish:

```sh
ffmpeg -v error -i output.mkv -f null -
```

Any decode error is printed; no output means the streams decoded without errors.

## Documentation

- [ffmpeg](https://ffmpeg.org/ffmpeg.html), [filters](https://ffmpeg.org/ffmpeg-filters.html), [codecs](https://ffmpeg.org/ffmpeg-codecs.html), [formats](https://ffmpeg.org/ffmpeg-formats.html) and [ffprobe](https://ffmpeg.org/ffprobe.html) manuals; `ffmpeg -h full` prints every option offline.
- The [FFmpeg wiki](https://trac.ffmpeg.org/wiki) has encoding guides for [H.264](https://trac.ffmpeg.org/wiki/Encode/H.264), [H.265](https://trac.ffmpeg.org/wiki/Encode/H.265) and [AV1](https://trac.ffmpeg.org/wiki/Encode/AV1), some of them dated.
- On this wiki: [first FFmpeg encode](/guides/first-ffmpeg-encode/), [audio and subtitles](/guides/audio-and-subtitles/), [preserving colour and HDR](/guides/preserve-color-and-hdr/), and the encoder pages such as [SVT-AV1](/tools/software-encoders/svt-av1/) and [x264](/tools/software-encoders/x264/).
