FFmpeg and Blender's short movie 'Sintel'...

I have been perhaps spending far too much time transcoding with FFmpeg for far too many years and I confess, Gentle Reader, that I am in fact far from even being a media professional in any sense of the word! Nevertheless it is a fascinating hobby and to formalise things a little I have put some of my explorations of FFmpeg onto this page where I will outline what has worked well for me in transcoding lossless material to a variety of older and newer codecs. And perhaps if this page has demonstrated a clearer path for your own experimentation with video transcoding the work on this page has been well worthwhile...

All the codecs...

So, Gentle Reader, which codecs will feature on this page? Well there is a pretty straightforward criteria: those that have interested me the most! I will kick off with the current codec of interest: AV1 and then delve back in time to perhaps to look at some failed efforts like Theora and even those codecs that never really took off like X265. Perhaps also some of the codecs that I have still not really explored thoroughly like VP9 and a few others. And in case some would like to duplicate my efforts for encoding I have used various lossless files associated with Blender's wonderful short movie 'Sintel'; these files are are a free download and can be found either here or here...

AV1 encoding...

I first encountered encoding to AV1 when I started building libaom for FFmpeg and that was first encounter with the glacial slowness of encoding with FFmpeg and libaom. FWIW I still maintain the libaom SlackBuild on SBo but like anybody with common sense I have moved to encoding AV1 with FFmpeg and rav1e, a much more pleasant experience. Below is a pretty effective command line to get a great result with FFmpeg and librav1e, note that I use the Sintel trailer for this effort

ffmpeg -i sintel_trailer_2k_720p24.y4m -i sintel_trailer-audio.flac \
       -c:v librav1e -qp 80 -speed 4 \
       -tile-columns 2 -tile-rows 2 \
       -c:a libfdk_aac -b:a 128k \
       sintel_trailer_av1.mp4

The quantizer has a range from 0-255 with better quality being low numbers, the speed preset is from 0-10 with lower numbers being better quality but slower. I am still experimenting with the tile based encoding but the values I have given above seem to keep my threadripper's cores moving along well enough.

I have a personal slackbuild for rav1e but creating an 'official' script for SBo has pretty much defeated me as Rust likes to download a heap of extra packages, fine on my own system but others would doubtless be unhappy. However I do maintain a popular question and answer on AskUbuntu which is hopefully helping Ubuntu users experiment with the early days of rav1e. And I am still having a huge amount of fun experimenting with this rapidly developing codec!

H.264 hardware encoding...

When I built my current Threadripper system one of my aims was to not only build a system capable of highly efficient video transcoding but also a system that would allow me to experiment with hardware GPU encoding. So I purchased a comparitively modest card, an MSI GeForce GTX 1660Ti which gives me access to the NVIDIA Turing architecture. This has worked well for me wih the NVidia binary blob, the current git FFmpeg and the use of the nv-codecs-headers maintained by the FFmpeg developers. I maintain the nv-codec-headers for SBo btw...

This time I have used the full lossless Sintel movie as in my experience hardware GPU encoding is blindingly fast! Quality perhaps not as good as CPU based encoding but no arguments with the spped for sure. Note in the example below I am using a constrained, quality encode which works well with the source material and plays back on my system equally as well:

ffmpeg -hwaccel nvdec -i sintel-4k.y4m -i sintel-master-st.wav \
       -c:v h264_nvenc -preset medium -rc:v vbr_hq -qmin 0 -cq 19 \
       -b:v 4M -minrate:v 2M -maxrate:v 6M -bufsize:v 8M \
       -profile:v high -bf 3 -rc-lookahead:v 32 \
       -c:a libfdk_aac -b:a 128k \
       4k_h264_sintel.mp4  

My aim was to stress my GPU as much as possible and it looks like the GPU could take a little more still. Utilising absolutely zero processing power from the CPU this 7 minute encode ran at 50-55fps and pushed the GPU frequency to a steady 1995Mhz. GPU temp went up to just above 60° Celcius which was enough to kick the GPUs cooling fans into action at 32% possible speed and 1070rpm; this is with default fan curves and the GPU's 'Frozr' technology. And now to sit back and enjoy the movie!

Encoding with Theora...

I was a little horrified to realise that there has been no development with Theora for almost 10 years! But for me this codec was the beginning of an idea that video and audio codecs, together with their containers, could and should be totally free. I have been involved with the codec only briefly on askubuntu where I posted a menu for WinFF and the Theora codec as well as some simple FFmpeg instructions. So below is a version of those simple FFmpeg instructions, this time using the Sintel trailer only:

ffmpeg -i sintel_trailer_2k_720p24.y4m -i sintel_trailer-audio.flac \
       -c:v libtheora -qscale:v 8 \
       -c:a libvorbis -qscale:a 5 \
       sintel_trailer_theora.ogv

Options to manipulate with this VBR encoding is the qscale for the video which takes integers from 0 - 10 with 0 being lowest quality and 10 the highest quality and qscale for the audio which follows this pattern exactly. The results are usable but not breathtaking but the dream of totally free video and audio encoding can still be seen here!

Encoding with VP9...

You may be pleased to know, Gentle Reader, that there I have no particular association with VP9 encoding and in fact the first time such encoding came across my radar was when I was researching the best way to add video clips to my website. The easy answer was to use HTML5 with a couple of simple tags and one of the easiest codecs to use was VP9 using libvpx-vp9 under FFmpeg.

For my first effort I borrowed extensively from a beautifully explicit set of pages on the Google developer site, best link here.... These pages surpass those found on the FFmpeg trac pages for libvpx-vp9 encoding and I would most definitely recommend them for anybody keen to try out VP9 encoding. For my first successful effort I have used the full lossless Sintel movie and lossless soundtrack but a resized version at 1280 pixels by 545 pixels. Aim was for good playback on my own computer:

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    

A 70 minute encode on my system but pretty good video and audio display. The technique I have used here is called Constrained Quality (CQ) with a target bitrate as well as a quality setting. Of course both of these can be manipulated for better playback results. It is a 110MiB result though and not really suitable for placing on my website, so back to the command line and this time using Constrained Bitrate; although a smaller CQ effort would have been fine:

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

As you can see I have used the Sintel trailer for this effort and you will be pleased to know, Gentle Reader, that I have placed the resulting 6.5MiB file on this website 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). But for me: time to have a look at hevc encoding!