Skip to content

VP9

currentMigrated from docs/video/VP9.mdx at 37c3317fd058; modified for Encode Wiki · CC BY-SA 4.0

VP9 is a royalty-free video format developed by Google as the successor to VP8 and released in June 2013 as part of the WebM Project. It competes with HEVC: efficiency is in the same range, decoding is relatively light, and licensing is simpler. YouTube adopted it early and still serves much of its catalogue in VP9; it is also widely used in WebRTC, where its scalable (SVC) mode suits multi-party video calls.

VP9 was never put through a standards body. The bitstream has been frozen since 2013, and the WebM Project’s published specification is still labelled draft v0.7 (2017).

  • Web delivery to browsers and devices that lack AV1 decode. Nearly every browser plays VP9, including Safari (macOS since Safari 14.1, iOS since 17.4).
  • HDR on the web or YouTube via profile 2 (10-bit), where HEVC is not an option.
  • For new encodes where AV1 decode is available, AV1 is more efficient; VP9 remains a solid middle rung between AV1 and H.264.
ProfileBit depthChroma
084:2:0
184:2:2, 4:4:0, 4:4:4
210, 124:2:0
310, 124:2:2, 4:4:0, 4:4:4

RGB is coded as 4:4:4 in profile 1 or 3. Profile 0 is what every decoder supports; profile 2 at 10-bit is the usual HDR profile and is widely hardware-decoded on recent devices. Profiles 1 and 3 are mostly software-only.

Levels run from 1 to 6.2 and limit sample rate, picture size, bitrate and tile columns. They matter mostly for hardware decoders.

VP9 sits between VP8 and AV1 in design:

  • 64×64 superblocks, recursively partitioned down to 4×4.
  • 10 intra modes: DC, vertical, horizontal, six diagonal directions and TrueMotion.
  • Three active references per frame (last, golden, alt-ref), chosen from eight stored frames, with compound prediction and 1/8-pel motion vectors using regular, sharp or smooth interpolation filters.
  • Alt-ref frames: hidden frames built from future (often temporally filtered) source frames and used only as references. They do much of the job of B-frames without frame reordering; libvpx’s --auto-alt-ref and --lag-in-frames control them.
  • DCT and ADST transforms (mixed per direction) from 4×4 to 32×32, and a lossless mode using a Walsh-Hadamard transform.
  • A boolean arithmetic coder whose probabilities adapt between frames.
  • Segmentation (up to 8 segments with their own quantiser, loop-filter level, reference or skip), a deblocking loop filter, tiles for parallel encoding and decoding, and reference scaling so resolution can change without a keyframe.
VP9 implementations
RelationshipProject or formatEvidence and scopeStatus
Implements bylibvpx / vpxenc v1.17.0libvpx v1.17.0 provides VP9 encoding and decoding.Scope: Encoder Decoder · Sources: libvpx v1.17.0 source, VP9 bitstream and decoding process specificationDocumented
Implements bySVT-VP9 v0.3.1SVT-VP9 v0.3.1 provides an experimental VP9 encoder.Scope: Experimental Encoder · Sources: SVT-VP9 v0.3.1 repositoryDocumented
  • libvpx (vpxenc, or libvpx-vp9 in FFmpeg) is the reference and practically the only software encoder in use. High-bit-depth (profile 2/3) encoding needs a build with high-bit-depth support enabled; most FFmpeg builds have it.
  • SVT-VP9 and Eve-VP9 are alternatives with limited adoption.
  • Hardware encoding: on PCs only Intel GPUs encode VP9 (Quick Sync, VA-API); NVIDIA NVENC and AMD AMF do not. Some Android SoCs (Qualcomm, Samsung Exynos) expose VP9 encoders through MediaCodec, mainly used by WebRTC.

A constant-quality VP9 WebM with FFmpeg:

Terminal window
ffmpeg -i input.mkv -c:v libvpx-vp9 -crf 31 -row-mt 1 -c:a libopus output.webm

With -crf and no bitrate, FFmpeg runs libvpx in constant-quality mode (older guides add -b:v 0 for the same effect; with a non-zero -b:v, -crf becomes constrained quality with that bitrate as a cap). -row-mt 1 enables row-based multithreading, which libvpx leaves off by default and which speeds up encoding considerably on multi-core machines. Lower CRF means higher quality; see vpxenc for speed (-cpu-used), two-pass and tile settings.

Decoders: FFmpeg’s native vp9 decoder is fast and is what most players use; libvpx also decodes. Hardware decode of profile 0 is near-universal on current GPUs and phones; on NVIDIA it starts with the GTX 950/960 (8-bit only) and 10/12-bit with Pascal (GTX 10 series). See video codec support for browsers.

VP9 container mappings
RelationshipProject or formatEvidence and scopeStatus
Carried ByWebMWebM's documented codec subset includes VP9.Scope: Container Subset · Sources: WebM container guidelinesDocumented
Carried ByISO Base Media File FormatThe WebM Project publishes a VP codec binding for ISO Base Media File Format.Scope: Container Mapping · Sources: VP Codec ISO Media File Format BindingDocumented
Carried ByMatroskaThe Matroska mapping uses the V_VP9 Codec ID.Scope: Container Mapping · Sources: Matroska codec mappingsDocumented
  • WebM / Matroska (V_VP9) is the normal container.
  • MP4 via the WebM Project’s VP codec ISOBMFF binding (vp09 sample entry). Browser MSE and DASH players support it, but some players and editors expect VP9 only in WebM.
  • IVF is the simple raw format vpxenc writes for testing.

VP9’s own header carries bit depth, chroma subsampling, range and a colour-space value. It has no field for the transfer function (PQ or HLG), so HDR VP9 relies on the container’s colour metadata: WebM/Matroska Colour elements, or in MP4 the vpcC box (primaries, transfer, matrix) plus SmDm/CoLL boxes for mastering metadata. Check that your muxer writes them. HDR10+ metadata can be carried in WebM as ITU-T T.35 data.

Google released VP9 royalty-free with an additional patent grant for its own patents, and libvpx is BSD-licensed. Sisvel has offered a VP9 patent pool to device makers since 2019, claiming patents from third parties not bound by Google’s grant.

  • Slow encoding at default settings: libvpx’s best-quality modes are slow; use -row-mt 1 and a higher -cpu-used for faster turnaround.
  • Profile 1/3 output: 4:4:4 or RGB input produces profile 1 or 3 streams that many hardware decoders reject. Use -pix_fmt yuv420p (or yuv420p10le for HDR) for delivery.
  • HDR without metadata: a 10-bit profile 2 stream with no transfer and primaries in the container plays as SDR with wrong colours.