How to Encode VP9 with FFmpeg in 4 Steps
- Check your FFmpeg build: run
ffmpeg -encodersand look forlibvpx-vp9in the list. Most builds include it. - Pick a quality:
-crf 30 -b:v 0is a good start for 1080p web video. A lower CRF means higher quality and bigger files. - Pick a speed:
-cpu-used 3or 4 with-row-mt 1keeps encode times reasonable. - Add Opus audio with
-c:a libopus -b:a 128kand save the output as.webm.
VP9 Encoding Modes
Constant Quality (CRF + b:v 0)
Our recommended approach for file conversion. Set a quality target with CRF and let the encoder decide the bitrate per frame. The -b:v 0 flag is required to enable pure CRF mode (otherwise FFmpeg applies a default bitrate cap).
Command: ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 output.webm
Constrained Quality (CRF + bitrate cap)
Combines CRF quality targeting with a maximum bitrate. Useful for streaming where you need to stay within bandwidth limits while maintaining quality.
Command: ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 2M output.webm
Variable Bitrate (VBR)
Target a specific average bitrate. Used for broadcast and streaming where bandwidth must be predictable.
Command: ffmpeg -i input.mp4 -c:v libvpx-vp9 -b:v 2M output.webm
CRF Values for VP9
VP9’s CRF scale ranges from 0 (best) to 63 (worst quality). Higher numbers mean more compression and lower quality. True lossless needs -lossless 1.
| CRF Range | Quality | Use Case |
|---|---|---|
| 0 | Highest lossy quality | Archival (use -lossless 1 for true lossless) |
| 15–20 | High quality | Master copies, high-quality delivery |
| 30–35 | Good balance (default) | Web delivery, general use |
| 40–50 | Lower quality | Previews, thumbnails |
| 50–63 | Poor quality | Rarely useful |
Our default is CRF 30, which produces roughly equivalent visual quality to H.264 CRF 23 at 30–50% smaller file sizes.
Speed Settings (cpu-used)
The cpu-used parameter controls encoding speed vs compression efficiency. Values 0–5 are used for normal (good-quality) encoding; higher values belong to realtime mode.
| cpu-used | Relative Speed | Compression Penalty | Use Case |
|---|---|---|---|
| 0 | Slowest | None (best) | Offline batch processing |
| 1 | Slow | Very small | High-quality encoding |
| 3 | Medium | Small | Online converters (our setting) |
| 5 | Fast | Noticeable | Quick previews |
| 8 | Fastest (realtime mode) | Largest | Real-time / lowest latency |
Multithreading (row-mt)
The -row-mt 1 flag enables row-based multithreading, which can speed up encoding several times on multi-core systems with little or no quality impact. This is a pure speed gain and should always be enabled.
Audio: Opus Settings
WebM pairs VP9 video with Opus audio, which is efficient at every common bitrate:
- 64 kbps: good for speech and podcasts
- 128 kbps: transparent for most content (our default)
- 192 kbps: high quality for music
Two-Pass vs Single-Pass
Single-pass CRF (our approach) produces the optimal quality-to-size ratio for file conversion. The encoder adjusts bitrate per frame based on complexity, resulting in the best possible quality at the target CRF.
Two-pass encoding is needed only when you must hit a specific target bitrate (streaming, broadcast). First pass analyzes content, second pass encodes with optimal bit allocation.
Our Converter's VP9 Pipeline
The core FFmpeg command our converter uses (it also applies the last two flags in the list below):
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -cpu-used 3 -row-mt 1 -c:a libopus -b:a 128k output.webm
Flag by flag:
-c:v libvpx-vp9— use VP9 video codec-crf 30— quality target (equivalent to H.264 CRF 23)-b:v 0— pure CRF mode, no bitrate cap-cpu-used 3— balanced speed for online conversion-row-mt 1— row-based multithreading for faster encoding-c:a libopus— Opus audio codec-b:a 128k— transparent audio quality for most content-pix_fmt yuv420p— 8-bit 4:2:0 color, which every VP9 decoder plays-vf scale=trunc(iw/2)*2:trunc(ih/2)*2— rounds width and height down to even numbers
Suggested Settings by Resolution
| Resolution | Suggested CRF | Target Bitrate (VBR) |
|---|---|---|
| 360p | 36–40 | 200–400 kbps |
| 480p | 33–36 | 500–900 kbps |
| 720p | 30–33 | 1–2 Mbps |
| 1080p | 28–32 | 2–4 Mbps |
| 2160p (4K) | 25–30 | 8–16 Mbps |
VP9 Encoding in HandBrake
- Open the source video.
- On the Summary tab, set Format to WebM.
- On the Video tab, choose the VP9 encoder and set Constant Quality. As with CRF, a higher RF number means a smaller file.
- On the Audio tab, choose Opus, then click Start Encode.
HandBrake uses the same libvpx encoder as FFmpeg, so the CRF and speed advice on this page applies.
10-Bit and HDR VP9
For 10-bit video, add -pix_fmt yuv420p10le -profile:v 2. HDR also needs the color metadata, for example -color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc. The converter on this page outputs 8-bit 4:2:0 (yuv420p), which every VP9 decoder plays.