Programster's Blog

Tutorials focusing on Linux, programming, and open source

VP9 Encoding

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.

Related Posts

Conversion Script

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"

ffmpeg \
-i $INPUT_FILE \
-c:v libvpx-vp9 \
-pass 1 \
-b:v $BITRATE \
-g 150 \
-threads 4 \
-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 4 \
-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
  • -g 150 (or 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.
  • -cpu-used or -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, -speed is an alias for -cpu-used.
  • Setting auto-alt-ref and lag-in-frames >= 12 will turn on VP9's alt-ref frames, a VP9 feature that enhances quality. More info here.

References