Most 8-bit video that survives lossy compression lands somewhere between 30 and 50 dB on the PSNR scale. That single number is the oldest and most widely reported quality score in video. It’s still the default readout in FFmpeg, x264, x265, and nearly every codec research paper published in the last thirty years.
PSNR compares a compressed frame against the original, pixel by pixel, and reports how much error the video encoding process introduced. Higher means closer to the source. Lower means more visible damage.
It’s also the metric most likely to lie to you.
Both things are true at once. Knowing which PSNR you’re looking at is the whole skill.
What Is PSNR?
PSNR is a full-reference video and image quality metric that measures the ratio between the maximum possible pixel value of a signal and the power of the compression error affecting it, expressed in decibels. PSNR stands for peak signal-to-noise ratio.
Two properties define it:
- Full-reference: you need the pristine original alongside the degraded copy, aligned frame for frame and pixel for pixel
- Logarithmic: reported in dB rather than a linear percentage, so a 3 dB gain represents roughly halving the mean squared error rather than a 3% improvement
PSNR exists because engineers needed a reproducible number to answer a subjective question. Before it, comparing two encoder settings meant putting people in a room and asking which looked better.
That works. It’s also slow, expensive, and impossible to run inside a build pipeline. PSNR turned “does this look worse?” into arithmetic any machine can compute in seconds.
The catch is baked into the definition. PSNR measures signal error, not perceived quality. Those two things overlap, but they’re not the same thing, and the gap between them is where most PSNR misreadings happen.
| Property | PSNR |
|---|---|
| Metric type | Full-reference, objective |
| Unit | Decibels (dB) |
| Scale | Logarithmic, typically 20–50 dB for lossy video |
| Direction | Higher is better |
| Computed on | Per frame, then averaged across the sequence |
| Derived from | Mean squared error (MSE) |
| Needs original? | Yes, pixel-aligned and same resolution |
The PSNR Formula: How PSNR Is Calculated
PSNR is built on mean squared error, so the calculation runs in two steps.
Step one: compute MSE. For a frame of size m × n, subtract each pixel in the distorted frame K from the matching pixel in the reference frame I, square the difference, and average across every pixel:
MSE = (1 / (m·n)) · Σ Σ [ I(i,j) − K(i,j) ]²
Step two: convert MSE to decibels. Divide the squared maximum pixel value by the MSE, take the base-10 logarithm, and scale by 10:
PSNR = 10 · log₁₀ ( MAX² / MSE )
= 20 · log₁₀ ( MAX / √MSE )
MAX is the largest value a single sample can hold, so it depends entirely on bit depth. For 8-bit video MAX is 255. For B-bit samples the general form is 2^B − 1, which gives 1023 for 10-bit and 4095 for 12-bit.
That bit-depth dependency has a consequence people often miss: PSNR scores aren’t comparable across bit depths. A 10-bit encode and an 8-bit encode of the same clip sit on different ceilings.
Luma and chroma are measured separately
Video codecs work in YUV color space, not RGB, so FFmpeg reports four PSNR figures rather than one:
- psnr_y: the luma (brightness) plane
- psnr_u and psnr_v: the two chroma (color) planes
- psnr_avg: a weighted average across all three
Most encoding teams quote psnr_y alone. Human vision resolves brightness detail far better than color detail, and chroma is subsampled to half resolution in 4:2:0 content anyway, so the luma score carries most of the information you care about.
Identical frames produce an infinite score
If the distorted frame is identical to the reference, MSE hits zero, the division blows up, and PSNR is mathematically infinite. FFmpeg prints inf for those frames. You’ll see this on lossless compression or on static frames a video codec reproduced perfectly.
In practice, tools clamp the result. According to the peak signal-to-noise ratio reference definition, the maximum finite value works out to 48.131 dB for 8-bit data, 60.198 dB for 10-bit, and 72.245 dB for 12-bit. Anything reported above those ceilings is an artifact of how the tool handles zero error, not a real measurement.
What Is a Good PSNR Value?
There’s no universal pass mark, but there are well-established bands. For 8-bit video and images under lossy compression, scores generally fall between 30 and 50 dB, and higher is better within that window.
| Bit depth / context | Typical good range | Notes |
|---|---|---|
| 8-bit lossy video | 30–50 dB | The standard working range for streaming |
| 12-bit imagery | 60 dB and above | Higher ceiling, higher expectations |
| 16-bit data | 60–80 dB | Scientific and medical imaging |
| Wireless transmission | 20–25 dB | Degradation is expected; the bar drops |
For 1080p streaming specifically, encoding teams work with a rougher rule of thumb:
- Above 45 dB: differences from the source generally aren’t visible
- 35 to 45 dB: acceptable, with artifacts appearing only under close inspection
- Below 35 dB: visible artifacts on typical viewing setups
Here’s the catch. Those thresholds only hold at 1080p. A 180p rung in an ABR ladder can look completely fine at 32 dB, because it’s being scaled up and the viewer’s expectations are calibrated to a small window. A 360p file scoring 38 dB tells you almost nothing about how a human will perceive it.
This is why PSNR targets have to be set per resolution, not globally, and why cross-resolution PSNR comparison is close to meaningless without careful scaling. If you’re picking transcoding presets, set a separate floor for each rung rather than one number for the whole ladder.
PSNR vs SSIM vs VMAF
These three metrics dominate video quality measurement, and they answer different questions. PSNR asks how much pixel error exists. SSIM asks whether image structure survived. VMAF asks what a human would probably score it.
| PSNR | SSIM | VMAF | |
|---|---|---|---|
| Full name | Peak signal-to-noise ratio | Structural similarity index | Video multi-method assessment fusion |
| Introduced | Long-standing engineering metric | 2004 | 2016, by Netflix |
| Scale | 0–~50 dB, logarithmic | 0–1, logarithmic behavior | 0–100, linear |
| Measures | Pixel-wise error | Luminance, contrast, structure over local windows | Fusion of multiple elementary features via machine learning |
| Correlation with human scores | Weak | Moderate | Strongest of the three |
| Compute cost | Very low | Low | High |
| Best at | Comparing one codec against itself | Blur and blockiness | Predicting subjective opinion |
| Weak at | Perceptual relevance | Spatial shifts, color and hue changes | Cost in live pipelines; needs the right model |
Why PSNR and SSIM disagree
SSIM computes luminance, contrast, and structural similarity across local neighborhoods rather than treating every pixel independently. That makes it much better at catching blur and blocking, the two artifacts viewers actually complain about. On the SSIM scale, 0.97 to 1.0 indicates minimal degradation and 0.95 to 0.97 indicates low degradation.
SSIM still evaluates one frame at a time, though, so temporal artifacts like flicker and judder slip past it the same way they slip past PSNR.
Why VMAF changed the conversation
Netflix released VMAF as open source in 2016 after concluding that no single existing metric tracked viewer opinion well enough to drive encoding decisions at their scale. Rather than designing a better standalone formula, VMAF fuses dozens of elementary features and trains the fusion model against large-scale subjective ratings.
The output is a 0 to 100 score that maps roughly onto how a viewer would rate the clip. That linear range is easier to reason about than logarithmic decibels: a VMAF of 93 versus 95 tells you something immediately, while 41 dB versus 43 dB doesn’t.
VMAF isn’t free, though. It’s the most expensive of the three to compute, which matters when you’re scoring thousands of assets or trying to measure quality on a live stream in real time.
How PSNR Is Used in Video Encoding
PSNR survives despite its flaws because it’s woven into how codecs are built, tuned, and compared.
Rate-distortion optimization. Encoders make thousands of per-block decisions about mode, partition size, and quantization. Each decision trades bits for error. PSNR-derived distortion is the standard cost function driving those choices, which is why encoder output is implicitly optimized toward it.
Codec benchmarking. When a paper claims a new codec beats the old one, the evidence is almost always a rate-distortion curve with bitrate on one axis and PSNR on the other. Comparisons like AV1 against H.264 and HEVC and H.264 were established this way long before perceptual metrics were mature.
BD-rate and BD-PSNR. The Bjøntegaard Delta measurements condense a whole rate-distortion curve into one number. BD-PSNR reports the average PSNR gain at equal bitrate; BD-rate reports the average bitrate saving at equal PSNR. When you read that AV1 delivers roughly 30% BD-rate savings over VP9, that figure came from PSNR curves.
Encoder tuning modes. Several encoders default to tuning for PSNR. SVT-AV1 and libaom both optimize for it unless you explicitly pass a perceptual tune flag, which means the score you measure is partly a reflection of what the encoder was already aiming at.
Regression testing. If a preset change drops PSNR by 2 dB on your test clips, something broke. As a tripwire against your own baseline, PSNR is fast, deterministic, and hard to argue with.
Where PSNR gets shakier is picking video bitrate ladders. Selecting rungs for adaptive bitrate streaming means comparing encodes at different resolutions, and that’s exactly the comparison PSNR handles worst. Most teams use it as one input alongside VMAF and known-good bitrate targets.
Advantages of PSNR
It’s cheap to compute
PSNR is a subtraction, a square, an average, and a logarithm. It runs orders of magnitude faster than VMAF and adds almost nothing to an encoding job. You can score every asset in a library without a dedicated compute budget.
It’s deterministic and reproducible
The same two files produce the same number on any machine, in any tool, forever. No trained model, no version drift, no model-selection debate. That reproducibility is why PSNR remains the lingua franca of codec research.
It’s universally supported
FFmpeg, x264, x265, SVT-AV1, libaom, MATLAB, OpenCV, and every commercial analysis tool report it. There’s nothing to install and no license to negotiate.
It’s sensitive to real signal degradation
PSNR reliably detects added noise, banding, and quantization error. If your encode picked up genuine corruption, PSNR will catch it even when a perceptual metric shrugs.
It’s an excellent regression detector
PSNR is unambiguously good at exactly one comparison: today’s build against yesterday’s, on identical source content. Same codec, same content, same resolution. A drop means a real quality drop.
It’s a scale everyone already understands
Thirty years of literature means engineers, vendors, and reviewers share a rough sense of what 38 dB versus 44 dB implies. That shared vocabulary saves a lot of explaining when you’re comparing notes across teams.
Limitations of PSNR
PSNR has six well-documented blind spots. None of them get better by staring harder at the number.
It doesn’t model human vision
Pixel-wise error and perceived quality diverge constantly. Two frames can score identically while looking completely different, because the human visual system weights errors by where they land.
Damage in a flat sky is glaring. The same magnitude of error hidden in dense foliage is invisible. PSNR treats both the same.
Mitigation: pair it with VMAF or SSIM before making any quality claim to a non-engineer.
It treats every pixel as equally important
PSNR assumes uniform signal importance. Real viewers focus on faces, motion, and screen center, and barely register the edges of the frame.
An encoder that protects a face at the cost of background detail may score worse on PSNR while looking better to everyone watching. Mitigation: use perceptually weighted variants like PSNR-HVS-M or XPSNR.
It only holds within a single codec and content pair
The strongest documented caveat is that PSNR is only conclusively valid when comparing results from the same codec type and the same source content. Comparing an AV1 encode’s PSNR against an H.264 encode’s PSNR across different clips isn’t a meaningful ranking. Mitigation: fix codec and content, vary one setting at a time.
It breaks across resolutions
An ABR ladder forces you to compare 360p against 1080p, and PSNR gives no honest way to do it. You have to pick a comparison resolution and scale, and the scaling filter you choose changes the result. Mitigation: score each rung against its own resolution-appropriate target and lean on VMAF for cross-rung decisions.
It’s blind to temporal artifacts
PSNR scores frames independently, then averages. Flicker, judder, and pumping between keyframe interval boundaries can wreck the viewing experience without moving the average at all. Mitigation: inspect per-frame PSNR logs for variance rather than trusting the mean, and treat quality of experience as a separate measurement problem from codec fidelity.
It over-punishes film grain and noise
PSNR is sensitive to noise that barely registers visually. Film grain, dither, and sensor noise all drag the score down even when a viewer would call the result faithful, so grain-preserving encodes get punished unfairly. Mitigation: compare grain-heavy content only against other encodes of the same source.
That’s half the work. The other half is producing the number reliably and wiring it into a pipeline that acts on it.
How to Calculate PSNR With FFmpeg
FFmpeg ships a PSNR filter out of the box, so measuring quality takes one command and no additional tooling.
Step 1: Confirm your inputs match
Both files need the same resolution, the same pixel format, and the same frame count. The filter compares frames one by one in order, so a single dropped frame shifts everything after it and produces garbage. Check first:
ffprobe -v error -select_streams v:0 \
-show_entries stream=width,height,pix_fmt,nb_frames \
-of default=noprint_wrappers=1 reference.mp4
Step 2: Run the basic PSNR comparison
Pass the distorted file first and the reference second:
ffmpeg -i distorted.mp4 -i reference.mp4 \
-lavfi psnr -f null -
FFmpeg prints a summary line at the end with psnr_avg, psnr_y, psnr_u, psnr_v, and the matching mse_* values.
Step 3: Write per-frame results to a log
The average hides the interesting parts. Dump every frame so you can find the worst ones:
ffmpeg -i distorted.mp4 -i reference.mp4 \
-lavfi psnr=stats_file=psnr.log -f null -
The FFmpeg psnr filter writes one line per frame with the frame number and every plane’s score. Sort that log by psnr_y and look at the bottom 1% of frames, because that’s where visible artifacts live. A clip averaging 42 dB with a hundred frames at 28 dB is a worse product than a clip that sits flat at 39 dB.
Step 4: Handle different resolutions
If the files differ in size, scale both to a common resolution inside a filter graph. Be explicit about the scaler, since the choice affects the score:
ffmpeg -i distorted_720p.mp4 -i reference_1080p.mp4 \
-filter_complex "[0:v]scale=1920x1080:flags=bicubic[dist]; \
[1:v]scale=1920x1080:flags=bicubic,format=pix_fmts=yuv420p[ref]; \
[dist][ref]psnr=stats_file=psnr.log" \
-f null -
Step 5: Get PSNR and VMAF in one pass
The libvmaf filter can emit PSNR alongside VMAF, which saves a full decode:
ffmpeg -i distorted.mp4 -i reference.mp4 \
-lavfi libvmaf=psnr=1:log_path=metrics.json:log_fmt=json \
-f null -
Step 6: Automate it, then decide what to do with the number
Measuring is the easy part. The hard part is running it on every asset, tracking scores over time, alerting when a preset regresses, and keeping hardware encoders and software encoders producing consistent output across your fleet. That’s a real service to build and maintain.
If your goal is shipping video features rather than operating an encoding lab, this is where a managed encoding API earns its keep. LiveAPI handles transcoding, adaptive bitrate rendition generation, and HLS packaging for you, with instant encoding that makes videos playable within seconds of upload regardless of length. You get consistent quality across renditions up to 4K without owning the tuning, the QC pipeline, or the servers underneath it.
PSNR Variants and Alternatives
Researchers have spent years patching PSNR’s perceptual gap rather than abandoning it, and several of those patches are production-ready.
PSNR-HVS applies contrast sensitivity properties of the human visual system before computing error, so damage in regions the eye scrutinizes counts for more than damage in regions it skims.
PSNR-HVS-M adds visual masking on top, modeling how texture and detail conceal nearby errors. It has been shown to approximate human quality judgements better than both PSNR and SSIM by a wide margin, while keeping the familiar dB scale.
XPSNR (extended perceptually weighted PSNR) applies block-wise psycho-visual weighting based on local spatiotemporal activity. It correlates better with subjective scores than plain PSNR for VVC content, and the VVenC encoder uses the same model for its quantization parameter adaptation. It’s the most practical drop-in upgrade if you already report PSNR.
ITU-T J.340 standardizes a PSNR variant that compensates for spatial shifts, temporal delays, and luminance offsets, which matters when your reference and distorted files aren’t perfectly aligned.
MS-SSIM extends SSIM across multiple scales, catching degradation that shows up at some viewing distances but not others.
VMAF remains the strongest predictor of subjective opinion and the right default when you can afford the compute.
LPIPS compares deep-network feature representations rather than pixels. It’s common in image restoration and generative model research, less so in streaming, though you’ll see PSNR, SSIM, and LPIPS reported side by side in plenty of papers.
The practical stance for most teams: keep PSNR as your fast regression check, add VMAF as the score you report, and consider XPSNR if you want perceptual weighting without leaving the decibel scale you already understand. If you’re evaluating AV1 encoding settings, running two metrics catches disagreements that a single number would hide.
Building Quality Measurement Into Your Streaming Pipeline
A PSNR score is only useful if something changes because of it. That means measurement has to sit inside the encoding workflow, not beside it in a spreadsheet.
Score at the rendition level, not the asset level
Every rung in your ladder is a separate encode with its own quality profile. Measure each one against a resolution-appropriate target. One aggregate number per asset hides the rung that’s actually failing.
Set thresholds per resolution and per content class
Animation, sports, and talking-head video compress differently. A 40 dB floor that’s generous for a lecture recording may be unreachable for a high-motion sports clip at the same bitrate. Build separate baselines and compare each new encode against its own class.
Store per-frame data, alert on the tail
Averages smooth over exactly the frames viewers notice. Persist the frame-level logs, and alert on the fraction of frames below your floor rather than on the mean.
Treat delivery quality as a separate problem
A 45 dB encode still buffers if HLS segments arrive late. Encode fidelity and delivery performance are independent failure modes, and PSNR only speaks to the first one. Track startup time, rebuffer ratio, and rendition switching alongside your quality scores.
Decide whether to build or buy the encoding layer
Build it yourself and you’re running transcode farms, tuning presets per codec, maintaining a metrics service, and keeping all of it healthy as codecs change. That’s a team, not a sprint.
A video transcoding API collapses most of that work into an API call. LiveAPI generates adaptive bitrate renditions and HLS output automatically, supports RTMP and SRT ingest for live sources, delivers through Akamai, Cloudflare, and Fastly, and prices on video minutes rather than reserved capacity. For teams whose product is the application rather than the encoder, that’s usually the faster path to consistent quality.
Should You Use PSNR?
PSNR is worth keeping in your toolkit, but only for the jobs it’s good at.
PSNR is a good fit if you:
- Compare encodes of the same content with the same codec at the same resolution
- Need a fast regression check inside CI where compute budget is tight
- Report codec research where PSNR-based rate-distortion curves are the expected format
- Want a deterministic number that any reviewer can reproduce
- Are detecting genuine signal corruption like noise, banding, or quantization error
- Already report BD-rate and need the underlying curves
PSNR is a poor fit if you:
- Need to predict how viewers will rate the video
- Are comparing different codecs against each other
- Are choosing rungs across resolutions for an ABR ladder
- Care about temporal artifacts such as flicker or judder
- Work with grain-heavy or stylized content where noise is intentional
If most of your answers land in the second list, VMAF should be your primary metric and PSNR a secondary sanity check. And if the underlying question is really “how do I ship reliably good video without running an encoding lab,” cloud encoding handles the tuning so your team can spend its time on the product instead.
PSNR FAQ
What does PSNR stand for?
PSNR stands for peak signal-to-noise ratio. It’s the ratio between the maximum possible power of a signal and the power of the error corrupting it, reported on a decibel scale.
What is a good PSNR value?
For 8-bit lossy video, 30 to 50 dB is the normal range. At 1080p, above 45 dB is generally imperceptible, 35 to 45 dB is acceptable, and below 35 dB shows visible artifacts. Lower resolutions can look fine at lower scores, so set targets per rung.
Is a higher PSNR always better?
Higher PSNR means less pixel error, but not always better perceived quality. An encoder that smooths away film grain can score higher while looking worse to a viewer. Confirm with a perceptual metric before treating a higher score as a win.
Can PSNR be infinite?
Yes. If the compared frames are pixel-identical, MSE is zero and PSNR is mathematically infinite, and FFmpeg reports inf for those frames. Tools cap the finite maximum at 48.131 dB for 8-bit, 60.198 dB for 10-bit, and 72.245 dB for 12-bit data.
What’s the difference between PSNR and SSIM?
PSNR measures pixel-wise error on a decibel scale. SSIM measures luminance, contrast, and structural similarity across local windows on a 0 to 1 scale. SSIM tracks human perception better, particularly for blur and blockiness, while PSNR is faster and more reproducible.
How do I calculate PSNR in FFmpeg?
Run ffmpeg -i distorted.mp4 -i reference.mp4 -lavfi psnr -f null -. Add psnr=stats_file=psnr.log to write per-frame results. Both inputs must share resolution, pixel format, and frame count.
What is PSNR in image processing?
The same formula applies to still images: compute MSE between the reference and processed image, then convert to decibels. Image processing work uses it for denoising, super-resolution, and compression benchmarks, often reported alongside SSIM and LPIPS.
Why do encoders tune for PSNR by default?
Rate-distortion optimization needs a cheap distortion function to evaluate thousands of block-level decisions per frame, and PSNR-derived error is fast enough to run inside that loop. SVT-AV1 and libaom both tune for PSNR unless you pass a perceptual tuning flag.
Does PSNR work for live streaming?
Only partially. It needs a pixel-aligned reference, which you have at the encoder but not at the player. Live pipelines typically measure PSNR on the encode side against the ingest feed and rely on playback telemetry for everything downstream.
The Bottom Line on PSNR
PSNR is the fastest, most reproducible, most widely supported quality metric in video, and it’s still the foundation under codec research and rate-distortion optimization. It’s also a poor predictor of what viewers actually see, and it falls apart the moment you compare across codecs or resolutions.
Use it for what it’s genuinely good at: catching regressions against your own baseline, on the same codec, with the same content. For anything you’re going to report as “quality,” measure VMAF too.
Ready to ship video without building an encoding lab? LiveAPI gives you instant encoding, adaptive bitrate renditions up to 4K, HLS output, RTMP and SRT ingest, and delivery across Akamai, Cloudflare, and Fastly, with pay-as-you-grow pricing. Get started with LiveAPI.