Converting videos to VP9 is a fantastic solution for those that want to compress videos to save bandwidth/storage without losing perceptual quality, and be able to play those videos back in the browser (e.g. a video site like youtube). In learning to use VP9, I have had a lot of poor results along the way. With this codec, it really pays to look into the parameters and specify what you want for your use case.
Below is the BASH script I use to encode my videos to VP9 webm after having installed ffmpeg through a PPA. I find that this script is a good balance between encoding speed and quality and I explain the parameters below it. It is a 2-pass encode targeting an overall bitrate.
#!/bin/bash EXPECTED_NUM_ARGS=3; if [ "$#" -ne $EXPECTED_NUM_ARGS ]; then echo "Expecting 3 arguments: [input filename] [output filename] [bitrate in K]" exit 1 fi INPUT_FILE=$1 OUTPUT_FILE=$2 BITRATE=$3 BITRATE="`echo $BITRATE`K" EXPECTED_NUM_ARGS=3; if [ "$#" -ne $EXPECTED_NUM_ARGS ]; then echo "Illegal number of aguments" fi INPUT_FILE=$1 OUTPUT_FILE=$2 BITRATE=$3 BITRATE="`echo $BITRATE`K" NUM_CORES=$(cat /proc/cpuinfo | grep processor | wc -l) ffmpeg \ -i $INPUT_FILE \ -c:v libvpx-vp9 \ -pass 1 \ -b:v $BITRATE \ -g 150 \ -threads $NUM_CORES \ -speed 4 \ -tile-columns 4 \ -frame-parallel 0 \ -an -f webm /dev/null \ && \ ffmpeg \ -i $INPUT_FILE \ -c:v libvpx-vp9 \ -pass 2 \ -b:v $BITRATE \ -g 150 \ -threads $NUM_CORES \ -speed 1 \ -tile-columns 4 \ -frame-parallel 0 \ -auto-alt-ref 1 \ -lag-in-frames 25 \ -auto-alt-ref 1 \ -c:a libopus \ -b:a 128k \ -f webm \ $OUTPUT_FILE
kf_max_dist)- There will be a maximum of 150 frames between keyframes. If you don't set this, it will be an absurdly high number 99999 and you will probably notice that when you seek around in a video will be slow.
-threads 4- Multi-threaded encoding may be used if -threads > 1 and -tile-columns > 0.
-tile-columns 4- using tile-columns slightly reduces quality. However it improves encoding and decoding speed by allowing multiple threads to be used. Most of my content has a 1920 pixel width so the maximum I can have is 4 with 4 threads.
-frame-parallel- Looks like this was once required for multithreading but no more so best to turn it off.
-speed- sets how efficient the compression will be, trading faster encoding for a larger file size.
- Generally good to use high speed for the first pass, and slow speed for the second pass.
- For legacy reasons,
-speedis an alias for
lag-in-frames>= 12 will turn on VP9's alt-ref frames, a VP9 feature that enhances quality. More info here.
-row-mt 1enables row-based multi-threading which maximizes CPU usage. Enabling row-mt is only faster when the CPU has more threads than the number of encoded tiles.
- FFMPEG Wiki: Encode VP9
- Webm Wiki - FFmpegâ€Ž > â€ŽVP9 Encoding Guide
- Github - Kagami/webm.py - Notes on encoding settings
- Webm - VP8 Encode Parameter Guide
- Stack Overflow - VP9 encoding limited to 4 threads?
- Phoronix - VP9 Encoder Gets Better Multi-Threading Performance
- FFmpeg - AV1 Video Encoding Guide
First published: 16th August 2018