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"
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
-g 150
(orkf_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.- It used to be the case that a 1920 pixel wide video could only use 4 tile-columns and thus 4 threads, but I believe now you can use any number of threads you like.
-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
andlag-in-frames
>= 12 will turn on VP9's alt-ref frames, a VP9 feature that enhances quality. More info here. -row-mt 1
enables 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.
References
- 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