~/ffmpeg.party
[ GUIDE · G/04 ]

VP9 encoder guide

FFmpeg parameters and quality settings for VP9 video encoding with libvpx-vp9

Overview

This guide provides opinionated recommendations for VP9 video encoding using the libvpx-vp9 encoder in FFmpeg. VP9 is a royalty-free codec with near-universal browser and hardware decode support, making it the safe choice for WebM output. For new work where compression matters most, AV1 is smaller and faster to encode; VP9 remains the compatibility pick.

These settings target local files and high-quality encodes. They use constant quality mode throughout and never set a bitrate.

Note: Like any encoding guide, these are opinionated recommendations. Your specific content and use case may benefit from different settings.

Recommended Parameters

The following two-pass command encodes with libvpx-vp9 in constant quality mode. The keyframe interval is set to 10 seconds of 30fps video:

ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 28 -b:v 0 -g 300 -an -pass 1 -f null /dev/null && \
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 28 -b:v 0 -g 300 -c:a libopus -b:a 128k -pass 2 output.webm

-b:v 0 is required. With -crf alone, libvpx runs in constrained quality mode and caps output at its default 256 kbit/s target. Setting -b:v 0 removes the cap and switches to pure constant quality, which is the mode this guide is about.

Why Constant Quality

CRF describes the thing you actually care about — visual quality — and lets the encoder spend whatever each scene needs. A bitrate is a guess that is too high for easy scenes and too low for hard ones, and it is only correct for one particular resolution, frame rate and content type. Constant quality gives the smallest file at your chosen quality with one setting that carries across all content.

Bitrate control makes sense when there is an external constraint: bandwidth-limited streaming, adaptive bitrate ladders, a fixed-size medium, or a decoder buffer limit. For local files none of those apply. Note that the widely copied Google/YouTube VP9 tables are streaming ladders, not quality recommendations.

Quality Settings (CRF Values)

CRF Scale

  • Range: 0 to 63, where lower values mean higher quality (larger files) and higher values mean lower quality (smaller files)
  • Default: 28 is a good starting point for 1080p high-quality encodes
  • Compared to other codecs: the scale is not x264's 0–51. VP9 CRF 28 ≈ x264 CRF 20 in practice
  • A change of ±6 in CRF roughly halves or doubles the bitrate

Recommended CRF by Purpose and Resolution

These values assume two-pass encoding with the parameters in this guide.

Purpose/Use Case 1080p 1440p 4K Notes
Near-Transparent 20–24 18–22 15–20 Archival. Indistinguishable from source on close inspection
High Quality 26–30 24–28 20–24 Recommended default. Personal libraries, delivery masters
Space-Saving 31–34 28–32 25–28 Visibly good, noticeably smaller. Fine for casual viewing

Resolution-Specific Guidelines

  • Standard Definition (480p/576p): CRF 30–34
  • 720p HD: CRF 28–32
  • 1080p Full HD: CRF 26–30, most tested range
  • 4K UHD (2160p): CRF 20–24; tolerance for artifacts drops as pixel density rises

Recommended baseline: CRF 28 for 1080p. Move lower for archival, higher for 720p and below. Always test a short clip before encoding your full video.

Essential libvpx-vp9 Parameters

These are the parameters worth setting. Everything else is left at its default.

  • Constant quality (-crf 28 -b:v 0) - Quality target plus the bitrate override that turns on pure constant quality mode
  • Two-pass (-pass 1 / -pass 2) - Unlike x264, libvpx uses the first pass to place alternate reference frames and choose frame types, so two-pass improves quality at the same CRF. Discard the first pass with -an -f null /dev/null (NUL on Windows)
  • Keyframe interval (-g 300) - Maximum frames between keyframes. FFmpeg's generic default is very short (12), so set this explicitly: 10 seconds of video is a good target (240 for 24fps, 300 for 30fps, 600 for 60fps)
  • Adaptive quantization (-aq-mode 2) - Optional. Complexity-based AQ shifts bits toward detailed regions of a frame at a modest cost in encode time. Off by default
  • Tune content (-tune-content screen) - For screencasts, presentations and sharp text. Leave unset (default) for live-action and animation

Content-Specific Recommendations

Live-Action (Default)

Use the parameters shown at the top. Add -aq-mode 2 for detailed or high-motion sources.

Screen Content

For screencasts, terminal recordings or slides:

-c:v libvpx-vp9 -crf 28 -b:v 0 -g 300 -tune-content screen

Complete Example Command

Two-pass encode of 30fps live-action content to WebM with Opus audio:

ffmpeg -i input.mp4 \
  -c:v libvpx-vp9 -crf 28 -b:v 0 -g 300 -aq-mode 2 \
  -an -pass 1 -f null /dev/null && \
ffmpeg -i input.mp4 \
  -c:v libvpx-vp9 -crf 28 -b:v 0 -g 300 -aq-mode 2 \
  -c:a libopus -b:a 128k \
  -pass 2 output.webm

Audio recommendations: Use Opus (libopus) in WebM and MKV containers. WebM only permits Opus or Vorbis audio.

Notes

  • Constant quality requires -b:v 0; omitting it silently falls back to constrained quality at 256 kbit/s
  • Two-pass is worth the time even in CRF mode; alternate reference frames are only used with two-pass
  • Use WebM or MKV as the container. VP9 in MP4 is valid but player support is poor
  • The bitstream profile is chosen automatically from the pixel format: yuv420p gives profile 0 (8-bit, the universally supported one), yuv420p10le gives profile 2 (10-bit). Add -pix_fmt yuv420p when the source is RGB or 4:4:4
  • VP9 encodes slowly. If speed matters more than the last few percent of quality, add -row-mt 1 and -cpu-used 2 to the second pass
  • Keyframe interval affects seeking: smaller values seek faster at a small cost in file size

References

  1. FFmpeg VP9 Encoding Guide
  2. FFmpeg Codecs Documentation — libvpx
  3. Google VP9 VOD Encoding Settings
  4. libvpx on GitHub