Video Quality Metrics: PSNR, SSIM, and VMAF Explained
Objective video quality metrics for tuning your encoding ladder — how PSNR, SSIM/MS-SSIM, and VMAF work, ffmpeg/libvmaf usage, and BD-rate basics.
You cannot tune a bitrate ladder you cannot measure. Eyeballing encodes does not scale across a catalog and does not survive an argument, so the industry leans on objective quality metrics: numbers that predict how good a compressed video looks compared to its source. This article covers the three that matter — PSNR, SSIM/MS-SSIM, and VMAF — how to compute them with ffmpeg, and how to compare codecs with BD-rate. Pair this with the ffmpeg tool to run the commands below.
What "objective" means
Every metric here is full-reference: it compares an encoded frame against the original (reference) frame and scores the difference. That makes them reproducible and automatable, but it also means they are only proxies for human perception — some better than others. The whole arc of this field is metrics getting progressively better at predicting what viewers actually perceive.
PSNR
Peak Signal-to-Noise Ratio is the oldest and simplest. It is derived from the mean squared error between reference and encoded pixels, expressed in decibels on a logarithmic scale. Higher is better; typical values run from the high 20s (poor) to the low 40s dB (excellent).
- Strengths — trivial to compute, universally understood, fine for spotting gross regressions.
- Weaknesses — it measures pixel error, not perceived quality. PSNR penalizes differences the eye does not notice (film grain, slight shifts) and misses artifacts the eye hates (blocking in smooth gradients). Two encodes with the same PSNR can look very different.
ffmpeg -i encoded.mp4 -i reference.mp4 \
-lavfi "[0:v][1:v]psnr" -f null -
SSIM and MS-SSIM
Structural Similarity improved on PSNR by modeling the fact that the human visual system cares about structure — luminance, contrast, and local patterns — rather than raw pixel error. SSIM scores from 0 to 1, where 1 is identical. MS-SSIM (Multi-Scale SSIM) evaluates structure at several resolutions, which correlates better with perception than single-scale SSIM.
- Strengths — closer to perception than PSNR, still cheap to compute.
- Weaknesses — single number does not capture temporal artifacts (flicker, judder) and does not adapt to viewing conditions.
ffmpeg -i encoded.mp4 -i reference.mp4 \
-lavfi "[0:v][1:v]ssim" -f null -
VMAF
VMAF (Video Multi-Method Assessment Fusion) is Netflix's open-source metric, released in 2016 because no single existing metric predicted their viewers' opinions well enough to drive per-title encoding decisions at scale.
How it is built
VMAF is a fusion metric. It computes several elementary features per frame — including detail-loss and contrast measures (VIF at multiple scales), an edge/blur measure (DLM), and a temporal feature capturing motion between frames — then feeds them into a machine-learning model (a support vector regressor) that was trained on human opinion scores from subjective viewing tests. The output is a single per-frame score, pooled (typically averaged) over the clip.
The 0-100 scale
VMAF scores run 0 to 100, designed so the scale roughly tracks subjective quality:
- ~90 and above — excellent; differences from source are hard to see.
- ~80 — good; the common target for high-quality VOD rungs.
- ~60-70 — acceptable on smaller screens or constrained connections.
- below ~50 — visibly degraded.
A crucial detail: VMAF is model-dependent. The default model assumes a
1080p display at a typical living-room distance; there is a separate 4k model
and a phone model that scores the same encode higher because artifacts are less
visible on a small screen. Always report which model you used.
Running VMAF with ffmpeg/libvmaf
Modern ffmpeg builds ship the libvmaf filter. Note the filter expects the
reference as the second input and they must match in resolution and frame rate
(scale the encode up to source if needed):
ffmpeg -i encoded.mp4 -i reference.mp4 \
-lavfi "[0:v]scale=1920:1080:flags=bicubic[enc];\
[1:v]scale=1920:1080:flags=bicubic[ref];\
[enc][ref]libvmaf=log_path=vmaf.json:log_fmt=json:n_threads=8" \
-f null -
To use the phone model, point the filter at it with
libvmaf=model=path=vmaf_v0.6.1neg.json (or the phone-tuned model your build
provides). The JSON log gives you per-frame and pooled scores you can chart.
Using metrics to tune the ladder
The reason VMAF matters operationally: it lets you encode to a quality target instead of a bitrate target. Rather than "give every title a 4.5 Mbps 1080p rung," you encode until each rung hits, say, VMAF 93, capping the bitrate. Simple content reaches the target at a fraction of the bitrate; complex content gets the bits it needs. This is exactly what powers the convex-hull and per-title approach in Building the Bitrate Ladder: you measure quality (usually VMAF) at several resolution/bitrate points and keep the rungs that sit on the quality-vs-bitrate upper envelope.
A practical workflow:
- Encode candidate rungs at several bitrates per resolution.
- Score each with VMAF (correct model for your audience's screens).
- Plot VMAF vs bitrate; keep the points on the convex hull.
- Trim any rung whose VMAF gain over the rung below is too small to justify its bandwidth.
BD-rate: comparing codecs and settings
When you compare two encoders (say H.264 vs AV1) or two settings, you do not get one number — you get two quality-vs-bitrate curves. Bjontegaard Delta rate (BD-rate) condenses the comparison into a single figure: the average percentage bitrate difference at equal quality across the overlapping quality range. A BD-rate of -35% means the new codec achieves the same quality (by whatever metric you fed it, often PSNR or VMAF) at 35% lower bitrate.
- BD-rate needs at least four rate-quality points per codec to fit the curves.
- It is metric-relative: BD-rate measured against PSNR and against VMAF can differ substantially, so always state the underlying metric.
- It is the standard way codec gains are reported, but treat published figures as approximate — they depend heavily on content and encoder configuration.
Caveats worth keeping in mind
- Objective metrics are proxies. For final calls on flagship content, confirm with a real subjective review.
- Pooling matters: an average VMAF can hide a few terrible scenes. Look at the per-frame minimum and the distribution, not just the mean.
- Match resolution and frame rate between encode and reference, and use the model appropriate to where your content is watched.
Measured this way, quality stops being an argument and becomes a number you can optimize. Run the commands above with the ffmpeg tool, feed the results back into your ladder design, and let the data set the bitrates.
Try it yourself
Reading about streaming is one thing — pull apart a real manifest, play a stream, and measure its QoE with the toolkit.
Browse all tools