Your first FFmpeg encode
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:
ffmpeg -i input.mkv -c:v libx264 -preset slow -crf 20 -c:a libopus -b:a 128k output.mkvIt 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; 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
Section titled “Look at the input”ffprobe -hide_banner input.mkv-hide_banner skips FFmpeg’s build-configuration header. The stream list looks like this
(trimmed):
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
instead.
CRF and preset
Section titled “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).
-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
Section titled “Test on a short clip first”Encode a minute from a demanding part of the source before committing to a full run:
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 covers metrics when you
want numbers as well.
Choose the streams you want
Section titled “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:
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.mkv0: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 covers languages, default/forced flags and
fonts.
Copy or re-encode the audio
Section titled “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:
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.mkvaformat 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).
For MP4 output aimed at older devices, use AAC (-c:a aac -b:a 192k) instead of Opus.
Compatibility settings
Section titled “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
Section titled “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. |