1. Andrew's Corner »
  2. FFmpeg: Some explorations...

FFmpeg: Exploring Webm (VP9) Encoding...

This is part of a series of pages that document my own personal explorations of FFmpeg usage and as with the other pages does not aim to be in any way definitive. It represents rather one person trying to find his own way around the often contradictory and always confusing world of video encoding. And so this time I have turned my attention to encoding with VP9 using FFmpeg. While I had almost no dealings with it VP9, and its preferred container WebM, had taken the Internet by storm and become ubiquitous on YouTube as well as having garnered broad browser support except for Safari users in the Apple camp. (And I mean really Apple??). Apple-bashing now done we should get started!


Some preparation is always required when transcoding and the tools I have used on this page included the very latest git version of FFmpeg, version N-94431-g42a2edcc1d compiled on August 2nd 2009 against libvpx version 1.8.1. For source material I have used the following freely available video clips of Blender's demonstration movie Sintel. Sintel is a great choice because there is a nice range of motion inclusing fight scenes, fire scenes, snow and rain with some great colour changes throughout. It is also completely free so there will be no issues with copyright infringements!

wget https://media.xiph.org/sintel/sintel-1280.y4m && \
wget https://media.xiph.org/sintel/sintel-master-st.wav && \
wget https://media.xiph.org/video/derf/y4m/sintel_trailer_2k_720p24.y4m && \
wget https://media.xiph.org/sintel/sintel_trailer-audio.flac

Note that there are links for the full 15 minute lossless movie above, which I will use for the constrained quality (CQ) 'Desktop' encoding as well as links for the Sintel trailer which I will use for the VBR 'Streaming' encode. There is also a full 4K movie file out there but VP9 is a pretty slow codec to encode with so I left that one alone this time.

Desktop Playback...

My initial aim was to produce a file that was suitable for playback on my local computer. So no streaming, no special requirements. After some significant research I decided on a 2 pass, Constrained Quality (CQ), encode with most of the significant settings coming from a beautifully explicit set of pages on the Google developer site, best link here... The 'working version' command line is as follows:

ffmpeg -y -i sintel-1280.y4m \
       -c:v libvpx-vp9 -b:v 1024k -minrate 512k -maxrate 1485k -crf 32 \
       -row-mt 1 -tile-columns 2 -threads 8 -quality good -g 240 \
       -pass 1 -speed 4 -f webm /dev/null && \
ffmpeg -i sintel-1280.y4m -i sintel-master-st.wav \
       -c:v libvpx-vp9 -b:v 1024k -minrate 512k -maxrate 1485k -crf 32 \
       -row-mt 1 -tile-columns 2 -threads 8 -quality good -g 240 \
       -c:a libopus -b:a 96k \
       -pass 2 -speed 0 sintel_1280_test.webm

The resulting file was very, very nice with fast and smooth action scenes, great colours an excellent sound. However I have left myself some homework for my next revisit of this page when I will attempt to produce an even better result:

  1. -b:v 1024k -minrate 512k -maxrate 1485k -crf 32: The bitrate certainly seemed good and the Google pages had a nice formula of '50% less for the minrate and 145% for the maxrate'. What I would like to do next is to experiment a little with these numbers, in particular the crf setting, and see if I can produce a better result.
  2. -row-mt 1 -tile-columns 2 -threads 8: The aim of these settings was to get some advantage from multithreading and the Google pages certainly gave these settings quite explicitly for the input file size. What puzzled me a little was that there is also an FFmpeg setting for '-tile-rows' but I could not see this mentioned anywhere online.
  3. -pass 1 -speed 4 + -pass 2 -speed 0: So the speed setting of zero was pretty close to watching paint dry and if I was a little less patient I would have used '1' which produced quite a reasonable file a lot faster! I saw a pretty consistent 5-7fps on the second pass...
  4. -c:a libopus -b:a 96k: Sound was magnificent but my homework is to see if there is anything extra that can be done with the audio. Some extra options, a different bitrate etc.

So an excellent first run at encoding with VP9 in a WebM container and when I return to this page in the next month or so I am confident that with a little more research and a few more experimental runs I will be able to produce an even better output file. But now for something a little different as I attempt to produce a file suitable for some simple HTTP-based streaming.

HTTP-based Stream...

Now to use VP9 in a webm container for a simple HTTP-based stream. I have a very personal need to experiment with this as my next FFmpeg page will be dealing with screen capture with FFmpeg and I would like to place the results on this web site. So how to make a start with VP9? The excellent Google pages on VP9 encoding recommend Variable Bitrate mode (VBR) for this purpose particularly if there is fast moving content. And so the following very simple command line has done an excellent job, this time utilising the Sintel trailer rather than the full movie:

ffmpeg -i sintel_trailer_2k_720p24.y4m -i sintel_trailer-audio.flac \
       -c:v libvpx-vp9 -b:v 1024k -minrate 512k -maxrate 1485k \
       -quality good -speed 0 -c:a libopus -b:a 64k \

I spent quite some time experimenting with the bitrate and the final choice is exactly the same as the bitrate chosen for the previous Constrained Quality encode with tight control on the higher and lower bitrates. This looked more than reasonable played back on a local computer but I took the initiative of placing this sample file online on this site so there is a 'real world' example to see. As well this is my first chance to also experiment with HTML5 and the Video tag which seems to simple to be true!

A link to this page and its 6.5MiB embedded file is here... I would be very grateful to hear opinions as to the quality of this file as a 'streamed' file so please use the email link at the base of this page to let me know how it looks in your browser. Bear in mind that your browser must support HTML5 and VP9 in a Webm container (which means Apple's Safari will only get an error message). Next to try the same magic with gameplay of D2x-Rebirth!!

And in conclusion...

This page represents my own initial exploration of FFmpeg and VP9 in a Webm container. I have been very pleasantly surprised with the amazing quality of VP9 video although perhaps I should not have been after seeing so much of it on YouTube! Still a little fine tuning to do here but I feel that I have made an xcellent start...

And if I have perhaps made your own usage of FFmpeg and VP9 encoding a little easier let me know by using the email link below. Also let me know of any errors on this page or indeed if there are better ways to accomplish the various tasks I have outlined here. Your suggestions, if valid, will be incorporated in thie page along with suitable acknowledgement. And above all "Have fun!".