Skip to main content

AV1 encoding: SVT-AV1 & VMAF

I’ve been experimenting with av1 video encoding for a while now. Av1 is a royalty free video codec set to replace existing codecs with better quality and/or lower bitrates. Support for it is somewhat decent now. Back when I first tried it I found the encoding speed (using the reference encoder libaom) to be just too slow.

However, I later read about the svt-av1 encoder over at phoronix which offers much faster encoding. More recently svt-av1 v0.9 has released and is even faster. So I think we’re at the point where av1 encoding is now fast enough for mortals like me to actually use.

Re-encoding h264 & friends

A fair test of a codec is to take a high quality original compare an encoding using av1 and one using h264 (or whatever). However, in reality I have a bunch of already h264-ed videos with no high-quality originals. Av1 in many cases can do a much harder feat in re-encoding h264 to a significantly smaller size without perceptible quality loss.

Lets re-encode a ~35 minute 854x480 h264 video as an example. First you’ll need svt-av1 & ffmpeg installed.

sudo pacman -Syu svt-av1 ffmpeg

Then we can use them to re-encode vid.mp4.

ffmpeg -loglevel error -i vid.mp4 -pix_fmt yuv420p10le -strict -1 -f yuv4mpegpipe - \
  | SvtAv1EncApp -i stdin --crf 32 --preset 8 --input-depth 10 -b stdout \
  | ffmpeg -i - -i vid.mp4 -map 0:v -map 1:a:0 -c:a copy -c:v copy vid.av1.mp4

Here we’re doing 3 commands each piping into the next:

  • Use ffmpeg to convert vid.mp4 into a format that svt-av1 can encode (using 10-bit over 8-bit as it’s generally recommended).
  • Use svt-av1 to encode the stream using a crf (quality) and preset (encoder speed) setting we just made up.
  • Finally use ffmpeg again to take the av1 data stream and combine with the original audio into a new vid.av1.mp4 file.

On my 5800x this takes ~7 minutes, so pretty fast, and encodes down to 66% original size. When I look at both side by side they seem the same quality. That’s great! …But I wonder if we can do better.

The most important settings above are the crf & preset.

  • preset (0-13) is how fast the encoder works, higher values mean faster encodes but with lower quality.
  • crf is “constant rate factor” (1-63), higher values mean lower quality & lower size.

preset values seem to work pretty consistently across all videos. You can pick a preset based on how impatient you are. My rough guide would be pick 6 if 4 is too slow for you, 8 if 6 is.

crf is trickier. The “right” setting will be different for how high quality you want, obviously, but it’s also different video to video, particularly across video resolutions.

If we have time we can try more crf (and preset) values and check if the quality is good enough. But it’s slow, boring and inconsistent to compare videos manually with my actual eyes. It would be nice if we had a way to check the quality of the result eyelessly.

VMAF

VMAF is a video quality metric we can use to do that. You give it two videos and it’ll give you a score (0-100) of how close the distorted was to the original, 100 being perfect.

sudo pacman -Syu vmaf

We can use this (via ffmpeg) to test our vid.av1.mp4.

ffmpeg -i vid.av1.mp4 -i vid.mp4 -lavfi libvmaf -f null -

This produces a VMAF score of 96.044922. So supports what my eyes thought vid.av1.mp4 is very similar to the h264 vid.mp4. It also suggests we could get the av1 version even smaller and achieve, say, VMAF 95.

Now we have the tools to test different crf values to find the highest that gives us a given VMAF score. We can try different preset values too.

The catch is VMAF itself isn’t super fast. The run above took ~6 minutes using all my cores. So testing another crf will take another 13 minutes or so. If we try lower presets it’ll take longer to encode. And of course this is with a shortish low resolution video, longer 1080p or 4k videos will take ages.

In the next post I’ll talk about a way to get much faster VMAF scores for any given svt-av1 crf & preset.