Originally published at ffmpeg-micro.com
Every video encoder faces the same tradeoff: quality vs. file size. CRF (Constant Rate Factor) is how FFmpeg lets you control that tradeoff with a single number.
Most guides say "just use CRF 23." That's fine for a quick transcode, but CRF 23 means completely different things depending on your codec, your content, and where you're delivering. This guide covers what CRF actually does, how the scale works across codecs, and how to pick the right value.
What Is CRF in FFmpeg?
CRF is a rate control mode that targets consistent perceptual quality across an entire video, letting the bitrate float as needed. Simple scenes (static shots, solid colors) get fewer bits. Complex scenes (fast motion, fine detail) get more bits. The result is a file where quality looks consistent to your eyes, even though the bitrate varies frame to frame.
ffmpeg -i input.mp4 -c:v libx264 -crf 23 output.mp4
Lower CRF always means higher quality and larger files. CRF 0 is mathematically lossless (and produces enormous files). The default for libx264 is 23.
CRF Scale by Codec
CRF values are not universal. Each codec has its own scale, and the same number produces different quality levels.
| Codec | Encoder | CRF Range | Default | Visually Lossless | Good Balance | Small File |
|---|---|---|---|---|---|---|
| H.264 | libx264 | 0-51 | 23 | 17-18 | 20-23 | 28-30 |
| H.265/HEVC | libx265 | 0-51 | 28 | 20-22 | 24-28 | 32-35 |
| VP9 | libvpx-vp9 | 0-63 | 31 | 15-20 | 25-31 | 35-40 |
| AV1 | libaom-av1 | 0-63 | 32 | 20-25 | 28-32 | 38-45 |
CRF 23 in H.264 is not the same quality as CRF 23 in H.265. H.265 is a more efficient encoder, so its default is CRF 28 to produce roughly comparable quality.
A useful rule of thumb for H.264: every +6 CRF roughly halves the file size.
CRF Examples for Each Codec
H.264 (most common):
ffmpeg -i input.mp4 -c:v libx264 -crf 20 -preset medium -c:a aac -b:a 192k output.mp4
H.265/HEVC (better compression, slower):
ffmpeg -i input.mp4 -c:v libx265 -crf 24 -preset medium -c:a aac -b:a 192k output_hevc.mp4
VP9 (WebM, used by YouTube internally):
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -c:a libopus output.webm
VP9 requires -b:v 0 alongside CRF. Without it, the encoder applies a default bitrate cap that overrides your CRF setting.
AV1 (best compression, slowest encoding):
ffmpeg -i input.mp4 -c:v libaom-av1 -crf 30 -cpu-used 4 -c:a libopus output.mkv
Common CRF Pitfalls
Forgetting -b:v 0 with VP9. VP9 ignores your CRF and uses a default bitrate cap instead. Always add -b:v 0 when using CRF with libvpx-vp9.
Comparing CRF across codecs. CRF 23 in H.264 produces different quality than CRF 23 in H.265. Use the table above when switching codecs.
Using CRF 0 for "best quality." CRF 0 is lossless and creates enormous files. CRF 17-18 is visually indistinguishable from lossless for H.264, at a fraction of the size.
FAQ
What CRF should I use for H.264? CRF 23 is the default and works for most cases. For archiving or YouTube uploads, drop to CRF 18-20. For web delivery or mobile, use CRF 26-28.
Does CRF 18 in H.265 equal CRF 18 in H.264? No. H.265 is more efficient, so CRF 18 in H.265 produces higher quality than CRF 18 in H.264.
Why is VP9 ignoring my CRF setting? Add -b:v 0. VP9 in FFmpeg applies a default bitrate cap even when CRF is set.
Read the full guide with API examples and more use cases at ffmpeg-micro.com/blog/ffmpeg-crf-explained.
Top comments (0)