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.
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
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
(with different scale and meaning). A good range should be 21-25.
$ 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
||1-63||file size vs. visual quality||good range should be 10-23|
||0-13||file size vs. en-/decoding speed||4-6 for 'home enthusiasts'|
||file size vs. skippability and error resilience||240 for 24 Hz input|
||8-bit vs. 10-bit encoding||go with 10-bit|
||0-1||psycho-visual quality (0) vs. PSNR (1)||go with 0|
||0-50||file size vs. sharpness and encoding speed||use 8 for grainy material|
- 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.
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 -
- VMAF rating requires frame accuracy between both files which may not be
fulfilled when using
-ssoption 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
ffmpeg wrapper for encoding (providing a progress bar and ETA).