Encoding webm Videos with ffmpeg: vp9 / av1

Videos are a very powerful media type of entertainment and visualisation, let's see hwo we can self host high compression videos that save bandwidth for your viewers/users and how to find out which codec to pick from.

A word of caution, lots of people, like me, do not prefer video over written text for many contexts, but to explain complex user interfaces or complex data types they're incredibly good.

This post does not apply if you are not responsible for the content distribution, if you are uploading your videos to YouTube or Vimeo that have their own transcoding machinery, you should just render what ever is convenient and high quality to you, because you have no control over the finished result that they transcode for you. This post is about producing end results that are similar to theirs.

There are lots of cases where you want to self-host video, for example if it's going to be part of a layout element or if you need more control over how your video is displayed or without third party branding and recommended videos at the end.

The video examples in this post are from our Norway Travel VLOG, that you can see in full below with a few epic drone shots and some dog and moose content:

Installing ffmpeg 5

If you're on an Ubuntu-like distro like Linux Mint or similar, you might want to ensure you have ffmpeg 5 installed for the stable version of the av1 encoder through the PPA if necessary.

You can check your locally installed version of ffmpeg by running:

ffmpeg -version
ffmpeg version 5.1.2-0ubuntu1~20.04.sav1 Copyright (c) 2000-2022 the FFmpeg developers
built with gcc 9 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
configuration: --prefix=/usr --extra-version='0ubuntu1~20.04.sav1' --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-gnutls --enable-ladspa --enable-lcms2 --enable-libaom
# [...]

and you want to look for 5.x and in the list of features for --enable-libaom to confirm that you have the av1 encoder built into your ffmpeg binary.

If they don't show up or if you want to upgrade to the stable av1 encoder you can check out the ffmpeg 5 ppa and follow the installation instructions below:

sudo add-apt-repository ppa:savoury1/ffmpeg4
sudo add-apt-repository ppa:savoury1/ffmpeg5
sudo apt-get update
sudo apt-get upgrade && sudo apt-get dist-upgrade
sudo apt-get install ffmpeg

What Codec is Best? VP9 vs AV1

Great about both codecs is that they are rather unproblematic in terms of patent restrictions, which historically have been an issue in mp3, mp4, m4a and other formats.

If you don't care about Edge or Safari and iOS users, you can use av1 as your only video codec today, otherwise I would strongly recommend vp9. This is true for the time of writing, I would recommend checking caniuse: vp9/av1 for the up to date support of browsers and platforms.

Let's compare the size and quality of the different encoders below, we'll use an h/264 mp4 rendered by Adobe Premiere of a vertical video trailer for instagram promoting our NORWAY travel VLOG 😉.

Note: The video examples are cut to the beat of the music, they do not stutter randomly, please play with audio!

Encode to vp9:

ffmpeg -i mobile-trailer.mp4 -c:v libvpx-vp9 -b:v 3M -cpu-used 8 mobile-trailer_vp9.webm
  • -i mobile-trailer.mp4 specifies the input file
  • -c:v libvpx-vp9 use the vp9 encoder for video
  • -b:v 3M keep the target bitrate per second under/at this

Encode to av1:

ffmpeg -i mobile-trailer.mp4 -c:v libaom-av1 -b:v 3M -cpu-used 8 mobile-trailer_av1.webm
  • -c:v liaom-av1 use the av1 encoder for video
  • -cpu-used 8 use 8 threads

The -cpu-used option was only necessary for av1 because otherwise it was excruciatingly slow to encode. I'm not sure if it just has a different default for now, but adding it helped it run at about the same speed of vp9, on my AMD Ryzen 7 2700+ at about .4 the play time of the video, so about twice the time spent playing the video.

Now that we have produced two video files, we can compare them locally:

9.1M mobile-trailer_av1.webm
 42M mobile-trailer.mp4
7.9M mobile-trailer_vp9.webm

As we can see they are both significantly smaller than the source file. The av1 version is slightly larger, so we would have to tweak the averate bitrate setting to get a smaller result, we could decrease -b:v 3M to something like -b:v 2500k.

We can go with the result as is, which looks slightly sharper, especially in areas of the frame where a lot of motion happens (like the waterfall on dark rock).

Remove Audio Track from Video

If you want to use a video as a replacement for a GIF that auto plays on a loop for comedic effect or to visualise something, you can remove the audio track instead of just muting it on the video element itself, which is a requirement for some browsers to play it at all:

ffmpeg -i mobile-trailer.mp4 -an -c:v libvpx-vp9 -b:v 3M -cpu-used 8 mobile-trailer_vp9_no_audio.webm
  • The -an option will not encode any audio tracks

This will also reduce the file size slightly:

7.7M mobile-trailer_vp9_no_audio.webm
7.9M mobile-trailer_vp9.webm

Lastly, we can implement it as an auto-playing element with this HTML snippet:

<video muted autoplay loop playsinline>
  <source src="/assets/mobile-trailer_vp9.webm" type="video/webm" />

If your video is not auto-playing in Safari, you likely forgot the muted and playsinline attributes.

Converting GIFs to WEBM

If you have a hand full of GIFs and you're trying to replace them, you can use the ffmpeg line below:

ffmpeg -y -i jeannie.gif -c:v libvpx-vp9  -cpu-used 8 -b:v 500K -pix_fmt yuv420p jeannie.webm

which saves you some bandwidth as well, which will have more extreme effects on larger GIFs with higher framerates, even though a GIF is limited to much fewer colours.

656K jeannie.gif
176K jeannie.webm

Let me know what sort of video you're producing and if the post was slightly useful \o/


Music by Alexander Nakarada (www.serpentsoundstudios.com) Licensed under Creative Commons BY Attribution 4.0 License https://creativecommons.org/licenses/by/4.0/

Thank you for reading! If you have any comments, additions or questions, please tweet or toot them at me!