How to Encode VP9 Video with FFmpeg: libvpx-vp9 CRF, Bitrate, and Quality Guide

VP9 is Google's open, royalty-free video codec. It powers most of YouTube's streaming library, and every modern browser supports it through the WebM container. If you need high-quality web video without licensing headaches, VP9 with FFmpeg's libvpx-vp9 encoder is the standard choice.
This guide covers the practical settings: CRF mode, 2-pass encoding, speed tuning, and multithreading. Everything here applies to FFmpeg's libvpx-vp9 encoder directly.
TL;DR: The Default VP9 Command
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 31 -b:v 0 -c:a libopus -b:a 128k output.webm
CRF 31 with -b:v 0 gives you true constant-quality mode. Opus audio at 128k is the natural pairing for WebM.
What CRF Does in VP9
CRF stands for Constant Rate Factor. It tells the encoder to target a consistent visual quality across the whole file, letting the bitrate float up or down as needed. Flat talking-head footage gets a low bitrate. Complex action scenes get more.
VP9's CRF scale runs from 0 to 63. Lower means better quality and bigger files. This is different from H.264's libx264, which uses a 0-51 range.
You must set -b:v 0 for true CRF mode. If you leave out -b:v 0, FFmpeg treats the CRF value as a "constrained quality" floor and caps the bitrate at a default target. That usually produces worse results than either pure CRF or proper 2-pass encoding. This is the single most common VP9 encoding mistake.
Basic VP9 Encoding Command
ffmpeg -i input.mp4 \
-c:v libvpx-vp9 \
-crf 31 \
-b:v 0 \
-deadline good \
-cpu-used 2 \
-row-mt 1 \
-c:a libopus -b:a 128k \
output.webm
This hits a solid balance between quality, file size, and encoding speed for most web video.
VP9 CRF Values by Use Case
| CRF | Use Case | Notes |
|---|---|---|
| 15-20 | Archival / master copies | Near-lossless. Large files. |
| 24-28 | High-quality streaming | Visually transparent for most content |
| 30-33 | General web video | Good quality at reasonable file sizes |
| 36-42 | Low-bandwidth delivery | Noticeable softness, but watchable |
| 45+ | Previews / thumbnails | Significant quality loss |
CRF 31 is a reasonable default. It sits in the same perceptual territory as CRF 23 in libx264 or CRF 28 in libx265, roughly speaking.
Speed Settings: -cpu-used and -deadline
VP9 doesn't use named presets like x264's "slow" or "fast." Instead, speed is controlled by two flags.
-deadline sets the encoding mode:
bestis painfully slow and mostly useful for benchmarks.goodis what you want for production encodes.realtimeis for live streaming only. Quality suffers.
-cpu-used is a number from 0 to 8. Zero is the slowest and highest quality. Eight is the fastest with the worst quality.
For most encodes, -deadline good -cpu-used 2 is the sweet spot. Bumping to -cpu-used 4 roughly halves encode time with a small quality drop. Values above 5 start showing visible artifacts on complex footage.
| -cpu-used | Relative Speed | Quality Impact |
|---|---|---|
| 0 | 1x (baseline) | Best possible |
| 1 | ~1.5x | Negligible loss |
| 2 | ~2.5x | Minimal loss, good default |
| 4 | ~5x | Slight softness |
| 6 | ~10x | Noticeable on complex scenes |
| 8 | ~20x | Fast but rough |
2-Pass Encoding for VP9
VP9 benefits more from 2-pass encoding than most codecs. The first pass analyzes the entire video so the second pass can distribute bits more intelligently. For anything targeting a specific bitrate, 2-pass is strongly recommended.
# Pass 1: analysis only (no audio, output discarded)
ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 2M \
-deadline good -cpu-used 2 -row-mt 1 \
-pass 1 -an -f null /dev/null
# Pass 2: actual encode
ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 2M \
-deadline good -cpu-used 2 -row-mt 1 \
-pass 2 -c:a libopus -b:a 128k output.webm
The first pass creates a log file that the second pass reads. Both passes need matching settings for -b:v, -cpu-used, and -deadline.
You can also combine 2-pass with CRF by replacing -b:v 2M with -crf 31 -b:v 0 in both passes. This gives CRF-quality encoding with better bit distribution across scenes.
Row-Based Multithreading
By default, libvpx-vp9 doesn't parallelize well. Two flags fix this.
-row-mt 1 -tile-columns 2 -threads 8
-row-mt 1 enables row-based multithreading, which lets the encoder process multiple rows of macroblocks simultaneously. This alone can cut encode time by 50% or more on multi-core machines.
-tile-columns splits each frame into independent tile columns for parallel encoding. Set it based on resolution: 1 for 720p, 2 for 1080p, 3 for 4K. The value is a log2 count, so -tile-columns 2 means 4 tile columns.
Always enable -row-mt 1. There's no quality penalty and the speed improvement is substantial.
Running VP9 Encodes via the FFmpeg Micro API
If you don't want to install FFmpeg or manage encoding infrastructure, you can run the same VP9 encode through the FFmpeg Micro API.
{
"inputs": [{ "url": "https://storage.example.com/video.mp4" }],
"outputFormat": "webm",
"options": [
{ "option": "-c:v", "argument": "libvpx-vp9" },
{ "option": "-crf", "argument": "31" },
{ "option": "-b:v", "argument": "0" },
{ "option": "-deadline", "argument": "good" },
{ "option": "-cpu-used", "argument": "2" },
{ "option": "-row-mt", "argument": "1" },
{ "option": "-c:a", "argument": "libopus" },
{ "option": "-b:a", "argument": "128k" }
]
}
Send that as a POST to https://api.ffmpeg-micro.com/v1/transcodes with your Bearer token. FFmpeg Micro runs the same FFmpeg binary in the cloud. You send an API call, it runs your VP9 encode, no server to manage. Grab a free API key at ffmpeg-micro.com.
Common Pitfalls
Forgetting -b:v 0 in CRF mode. Without it, libvpx-vp9 operates in constrained quality mode and caps bitrate at a low default. Your CRF value becomes a quality floor, not a target. Always pair -crf with -b:v 0.
Using -cpu-used 0 and wondering why it takes forever. CPU-used 0 is extremely slow. For a 10-minute 1080p video, it can take hours. Start with -cpu-used 2 and only go lower if you have time to burn and need every last bit of quality.
Skipping -row-mt 1. Without row-based multithreading, libvpx-vp9 barely uses multiple cores. This is free performance. There's no reason to leave it off.
Using .mp4 as the output container. VP9 belongs in WebM (or MKV). While some players handle VP9 in MP4, browser support and spec compliance are best with .webm.
FAQ
Is VP9 better than H.264 for web video?
VP9 typically achieves 30-50% better compression than H.264 at the same visual quality. The tradeoff is slower encoding. For web delivery where bandwidth costs matter, VP9 produces smaller files that look just as good.
Should I use VP9 or AV1?
AV1 is the newer codec and compresses roughly 20-30% better than VP9. But AV1 encoding is significantly slower, and hardware decoder support is still catching up. VP9 is the practical choice today when you need broad browser compatibility and reasonable encode times.
What's the difference between CRF mode and 2-pass in VP9?
CRF mode targets consistent quality and lets file size vary. 2-pass targets a specific bitrate and distributes bits optimally across the video. Use CRF when quality matters most. Use 2-pass when you need predictable file sizes, like hitting a CDN storage budget.
Why is my VP9 encode so slow?
Check your -cpu-used value. Zero is the slowest setting. Also make sure -row-mt 1 is enabled for multithreading. Encoding speed scales roughly linearly with -cpu-used from 0 to 4. A jump from -cpu-used 0 to -cpu-used 2 can cut encode time by 60% with minimal quality impact.
Can I use VP9 with MP4 containers?
Technically yes, but don't. The WebM container is the correct home for VP9 video. Browser <video> tags expect VP9 in .webm, and some players won't recognize VP9 inside .mp4. Stick with WebM for maximum compatibility.
*Last verified against FFmpeg 7.1 (libvpx-vp9) on June 23, 2026.*
About Javid Jamae
Founder & CEO at FFmpeg Micro
Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.
You might also like

How to Encode Video with H.264 (libx264) Using FFmpeg
Learn the right CRF and preset values for FFmpeg libx264 encoding. Includes a decision table, common pitfalls, and how to run H.264 encodes via API.

Cut Video File Size 50% with FFmpeg H.265 (CRF Guide)
Compress H.265 videos 2x smaller without quality loss. Complete CRF and preset settings for FFmpeg libx265, with commands for 480p to 4K.

Pick the Right FFmpeg CRF: libx264 + libx265 Reference
Find the right FFmpeg CRF and preset for libx264, libx265, VP9, and AV1. Recommended settings per use case, real quality comparisons, and copy-paste commands.
Ready to process videos at scale?
Start using FFmpeg Micro's simple API today. No infrastructure required.
Get Started Free