# Your first FFmpeg encode

Canonical URL: https://encode.wiki/guides/first-ffmpeg-encode/
Content version: ca42e61ede0a24f789d7287a0001244ad22f4abf
Status: current
License: CC BY-SA 4.0
Checksum (SHA-256): 88a0f8d6bd58a4ec9450af71905728402f903e3f5368e826657d250ef11791b3

If your FFmpeg build includes libx264 and libopus (most distribution packages and the common
Windows and macOS builds do), this is a good general-purpose encode:

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

It produces H.264 video, which plays on practically everything, with Opus audio in Matroska. If
FFmpeg stops with `Invalid channel layout 5.1(side)`, see
[copy or re-encode the audio](#copy-or-re-encode-the-audio); using `-c:a copy` instead is the quick
fix. The rest of this page covers what the two numbers mean, how to test settings on a short clip, how to
choose streams when the source has several, and when to copy audio instead of re-encoding it.

## Look at the input

```sh
ffprobe -hide_banner input.mkv
```

`-hide_banner` skips FFmpeg's build-configuration header. The stream list looks like this
(trimmed):

```text
  Stream #0:0: Video: h264 (High), yuv420p(tv, bt709, progressive), 1920x1080, 23.98 fps
  Stream #0:1(eng): Audio: ac3, 48000 Hz, 5.1(side), fltp, 640 kb/s (default)
  Stream #0:2(jpn): Audio: flac, 48000 Hz, stereo, s16
  Stream #0:3(eng): Subtitle: subrip (srt)
```

Note the audio and subtitle languages and the video pixel format. This recipe is for ordinary 8-bit
SDR video. If you see `yuv420p10le` together with `bt2020` and `smpte2084` or `arib-std-b67`, the
source is HDR: use HEVC or AV1 and follow [preserve color and HDR](/guides/preserve-color-and-hdr/)
instead.

## CRF and preset

**`-crf`** sets the quality target. The encoder spends whatever bitrate each scene needs to reach
it, so file size depends on the content. Lower is better quality and bigger. For x264 the default is
23, and about ±6 halves or doubles the bitrate. Values around 17–18 usually look the same as the
source; most encodes land between 18 and 24. Pick the highest value that still looks good to you.
CRF scales differ between encoders: x265, SVT-AV1 and others use different numbers for similar
quality (see [quality controls](/guides/quality-controls/)).

**`-preset`** trades encoding time for compression. The x264 presets run from `ultrafast` to
`placebo`; the default is `medium`. Slower presets find better ways to code the same picture, so at
the same CRF you get a smaller file or more retained detail. `slow` is a common choice; `veryslow` is
worth it for encodes you keep. `placebo` costs a lot of time for almost nothing.

**`-tune`** is optional. `film`, `animation` and `grain` adjust x264's deblocking, psychovisual and
adaptive-quantization settings for that kind of content; use `grain` for grainy film sources you
want to keep grainy.

## Test on a short clip first

Encode a minute from a demanding part of the source before committing to a full run:

```sh
ffmpeg -ss 10:00 -i input.mkv -t 60 -c:v libx264 -preset slow -crf 20 -c:a libopus -b:a 128k test-crf20.mkv
```

`-ss` before `-i` seeks quickly in the input, and `-t 60` stops after 60 seconds. Because the video
is re-encoded, the cut is frame-accurate. Make two or three versions at different CRF values, then
watch them at normal speed and pause on dark scenes, faces, grain and fast motion. Your eyes are the
final judge; [compare encoding quality](/guides/compare-encoding-quality/) covers metrics when you
want numbers as well.

## Choose the streams you want

Without `-map`, FFmpeg keeps one video stream (the highest resolution), one audio stream (the one
with the most channels) and the first subtitle stream the output format's default subtitle encoder
can handle. Within a file, a stream flagged default wins over a bigger one, so a default stereo
track beats a non-default 5.1 track. Everything else is dropped without a warning. When writing
Matroska, text subtitles are converted to ASS; MP4 output gets no subtitles at all.

As soon as you use `-map`, only the streams you list are written:

```sh
ffmpeg -i input.mkv -map 0:v:0 -map 0:a:1 -map '0:s?' \
  -c:v libx264 -preset slow -crf 20 -c:a libopus -b:a 128k -c:s copy output.mkv
```

`0:a:1` is the second audio stream of the first input (counting from zero within each type), so with
the input above this keeps the Japanese track. `0:s?` takes every subtitle stream; the `?` means "if
there are any", and the quotes stop shells such as zsh from treating `?` as a wildcard. `-c:s copy`
keeps the subtitles in their original format. To keep every stream, use `-map 0`. The
[audio and subtitles guide](/guides/audio-and-subtitles/) covers languages, default/forced flags and
fonts.

## Copy or re-encode the audio

Use `-c:a copy` when the source audio already plays where you need it. It costs no quality and no
time. Re-encoding pays off for lossless or very large tracks (FLAC, PCM, TrueHD, DTS-HD MA), where
Opus saves most of the space. Re-encoding a lossy track such as AC-3 or AAC adds another generation
of loss, so do it only for size or compatibility.

Opus at 128 kbit/s is close to transparent for stereo music; use roughly 256 kbit/s for 5.1. If the
source layout is `5.1(side)`, libopus refuses it with `Invalid channel layout 5.1(side)`. Convert it
to plain 5.1:

```sh
ffmpeg -i input.mkv -map 0:v:0 -map 0:a:0 -c:v libx264 -preset slow -crf 20 \
  -c:a libopus -b:a 256k -af aformat=channel_layouts=5.1 -mapping_family 1 output.mkv
```

`aformat` moves the side channels to the back positions; nothing is downmixed. `-mapping_family 1`
switches libopus to its surround encoder, which uses masking between channels to spend the bits
better. `-af` applies to every audio stream you encode, so with several audio tracks use
`-filter:a:N` instead (see the [audio and subtitles guide](/guides/audio-and-subtitles/)).

For MP4 output aimed at older devices, use AAC (`-c:a aac -b:a 192k`) instead of Opus.

## Compatibility settings

libx264 keeps the input's bit depth and chroma format. A 10-bit or 4:2:2 source therefore becomes
High 10 or High 4:2:2 H.264, which most hardware decoders and browsers cannot play. Add
`-pix_fmt yuv420p` when you need 8-bit 4:2:0 output that plays everywhere.

For MP4 files that will be streamed over the web, add `-movflags +faststart`. It moves the index to
the start of the file so playback can begin before the whole file has downloaded.

## Common errors

| Message                                                                             | Cause and fix                                                                                                    |
| ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `Unknown encoder 'libx264'`                                                         | Your FFmpeg build lacks that library. Install a build that includes it.                                          |
| `Stream map '...' matches no streams`                                               | That stream does not exist. Check the ffprobe list, or add `?` if the stream is optional.                        |
| `Invalid channel layout 5.1(side) for specified mapping family`                     | libopus does not accept that layout. Add `-af aformat=channel_layouts=5.1`.                                      |
| `Automatic encoder selection failed` or `Could not find tag for codec subrip` (MP4) | MP4 cannot hold that subtitle format. Use `-c:s mov_text` for text subtitles, or leave them out.                 |
| Colors look washed out or too dark                                                  | Usually an HDR source or a range/matrix mismatch. See [preserve color and HDR](/guides/preserve-color-and-hdr/). |
