This is meant as a personal note to myself as I constantly keep forgetting about encoding parameters. Use with caution, your mileage may vary.
Note: All recommendations below target 1080p content as I don't own any UHD BluRays.
H.265
CPU based (x265)
$ ffmpeg -i input.mkv \
-c:a copy \
-c:s copy \
-c:v libx265 \
-preset slow \
-crf 20 \
-x265-params log-level=error \
output.mkv
As with other encoders -preset
performs codec feature selection (i.e.
trade-off between file size and en-/decoding speed) and -crf
sets the visual
quality target (again in constrast to file size).
I like to keep slow
for the former and pick a value between 18
and 25
for
the latter.
GPU based (VA-API)
The following works fine on my RX 6800XT. I'm not sure about differing options for other cards.
$ ffmpeg -vaapi_device /dev/dri/renderD128 \
-i input.mkv \
-vf 'format=nv12,hwupload' \
-c:a copy \
-c:s copy \
-c:v hevc_vaapi \
-profile:v main \
-rc_mode CQP \
-qp 23 \
output.mkv
In CQP (Constant Quantization Parameter) mode -qp
is the equivalent of -crf
(with different scale and meaning). A good range should be 21-25.
AV1
$ ffmpeg -i input.mkv \
-c:a copy \
-c:s copy \
-c:v libsvtav1 \
-crf 18 \
-preset 6 \
-g 240 \
-pix_fmt yuv420p10le \
-svtav1-params tune=0:film-grain=8 \
output.mkv
Tuning knobs
option | range | trade-off | recommendation |
---|---|---|---|
-crf |
1-63 | file size vs. visual quality | good range should be 10-23 |
-preset |
0-13 | file size vs. en-/decoding speed | 4-6 for 'home enthusiasts' |
-g |
file size vs. skippability and error resilience | 240 for 24 Hz input | |
-pix_fmt |
yuv420p or yuv420p10le |
8-bit vs. 10-bit encoding | go with 10-bit |
tune |
0-1 | psycho-visual quality (0) vs. PSNR (1) | go with 0 |
film-grain |
0-50 | file size vs. sharpness and encoding speed | use 8 for grainy material |
General recommendations
- Regarding CRF one can go as low as output file size allows.
- Movies with dark scenes benefit greatly from 10-bit encoding (reduced colour artifacts).
- AV1 is very sensitive to film grain, resulting in larger output files. For
movies shot with analogue grain, using
film-grain=8
(or higher) can compensate for that, potentially allowing a higher CRF.
VMAF Rating
In addition to visual inspection there is an objective quality metric developed by Netflix: VMAF.
$ ffmpeg -i encoded.mp4 -i original.mp4 \
-filter_complex libvmaf="n_threads=$(nproc)" -f null -
Notes
- VMAF rating requires frame accuracy between both files which may not be
fulfilled when using
ffmpeg
s-ss
option for taking samples.
Automatic CRF Determination for a Given VMAF Score
Using the incredibly handy tool ab-av1 one can easily find the minimal CRF value that reaches a certain VMAF score.
I like to use the following for AV1 encoding:
$ ab-av1 crf-search \
--min-vmaf 96 \
--preset 6 \
--svt tune=0 \
--keyint 240 \
--input input.mkv
There are plenty other options for other purposes and it can even be used as a
nice ffmpeg
wrapper for encoding (providing a progress bar and ETA).