Updated November 2026: new section on PSNR in image processing with the default peak value in scikit-image, OpenCV, MATLAB and TorchMetrics, a NumPy PSNR calculation, and the xpsnr filter status in FFmpeg 9.0 "Lei".
What is PSNR? The short answer
PSNR stands for Peak Signal-to-Noise Ratio: a full-reference metric that measures how much a compressed image or video frame differs from its original, expressed in decibels (dB). It is computed as PSNR = 10 · log₁₀(MAX² / MSE), where MAX is the largest pixel value (255 for 8-bit) and MSE is the mean squared error between the two frames. Higher PSNR is better: for 8-bit lossy video, 30–50 dB is the normal range, below 30 dB errors are usually visible, above 40 dB the copy is close to the original, and identical frames score infinity. PSNR is fast and universal, but it only measures pixel error, so it is trustworthy for comparing encodes of the same source and weak at predicting how good video looks to a viewer.
| Question | PSNR at a glance |
|---|---|
| Full form | Peak Signal-to-Noise Ratio |
| Formula | 10 · log₁₀(MAX² / MSE), MAX = 2B − 1 for B-bit video |
| Unit | decibels (dB), logarithmic |
| Higher or lower is better? | Higher. +3 dB ≈ half the pixel error |
| Typical 8-bit video range | 30–50 dB; identical frames = ∞ |
| What it measures | average pixel error against the original (full reference) |
| Valid for | same content, same codec: encoder tuning, RDO, regression gates, BD-rate |
| Not valid for | ranking quality across different clips, codecs or resolutions |
Why this matters
If you measure video quality, PSNR is the first number you will see and the first one you will be tempted to over-trust. It appears in encoder logs, in FFmpeg output, in vendor benchmark charts, and in academic tables — usually with no explanation of what it can and cannot tell you. This article gives you that explanation, so you can read a PSNR figure the way a skeptic would: knowing what it measures, which comparisons it is valid for, and the exact content where it will mislead you. It is the foundation for the perceptual metrics that come next — SSIM and VMAF — both of which exist precisely because PSNR was not good enough.
What PSNR actually measures
Start with the thing PSNR is built on, because the name hides it. Underneath the decibels, PSNR (see the PSNR glossary entry) is a measurement of pixel error: how different is each pixel in the compressed video from the same pixel in the original, on average, squared.
Think of it as a spell-checker that counts wrong letters. Give it the original document and a copy, and it will tell you how many characters differ. What it will not tell you is whether the sentence still reads well — a typo in the headline and a typo in the footer count exactly the same. PSNR has the same blind spot. It counts how many pixel values changed and by how much, never asking whether those changes landed somewhere the eye is looking.
To measure that pixel error you need the pristine original, frame for frame. That makes PSNR a full-reference metric — a metric that compares the impaired video against the complete uncompressed master. If you do not have the original on disk, you cannot compute PSNR at all; on a live stream or a user-uploaded clip there is no master to reference, and the number simply does not exist. (The three reference setups — full, reduced, and no-reference — are covered in full-reference, reduced-reference, no-reference metrics; PSNR sits firmly in the first.)
From pixel error to decibels: the math, shown once
PSNR is computed in two steps. First you measure the raw error with the Mean Squared Error, almost always written MSE. Then you turn that error into decibels. Both steps are short, and seeing them once removes all the mystery.
The Mean Squared Error is exactly what its name says, read right to left: take the error at every pixel (original value minus compressed value), square it, then take the mean of all those squares across the whole frame. Squaring does two things: it makes every error positive so they do not cancel out, and it punishes big errors far more than small ones. For an image of width m and height n:
MSE = (1 / (m·n)) · Σ Σ [ I(i,j) − K(i,j) ]²
Here I is the original frame, K is the compressed frame, and the double sum runs over every pixel. An MSE of zero means the two frames are identical. A larger MSE means more error.
MSE on its own is awkward to read — its scale depends on the bit depth, and the numbers are unintuitive. So PSNR rescales it against the brightest possible pixel and takes the logarithm, which compresses a huge range of error into a friendly two-digit decibel number:
PSNR = 10 · log₁₀ ( MAX² / MSE ) [dB]
MAX is the largest value a pixel can take. For ordinary 8-bit video that is 255; for B bits per sample it is 2^B − 1 (1023 for 10-bit, 4095 for 12-bit). Because the formula divides MAX² by MSE, smaller error gives a larger PSNR — the scale runs the intuitive way, higher is better.
A worked example
Suppose you measure an 8-bit clip and find its MSE is 25. That means the average pixel is off by 5 levels (because 5² = 25) on a 0–255 scale — a small error. Plug it in:
PSNR = 10 · log₁₀ ( 255² / 25 )
= 10 · log₁₀ ( 65025 / 25 )
= 10 · log₁₀ ( 2601 )
= 10 · 3.415
= 34.15 dB
So a 5-level average error lands at about 34 dB. Now push the error up: an MSE of 100 (average error of 10 levels) gives 10 · log₁₀(65025 / 100) = 28.1 dB. Push it down to an average error of one level, an MSE of 1, and you get 10 · log₁₀(65025) = 48.13 dB. That figure is often quoted as the 8-bit "ceiling", but it is not one: MSE is an average, so it can fall below 1. If only one pixel in a 1920×1080 frame is off by one level, MSE is 1 / 2,073,600 and PSNR is about 111 dB. A perfect match has MSE = 0, the division blows up, and PSNR is infinite — which is why tools either print inf or clamp the value (see the table below).
Figure 1. PSNR in four steps: difference, square, average (MSE), then convert to decibels. The metric never looks at where the errors are — only how big they are on average.
The one rule of thumb worth memorizing
Because PSNR is logarithmic, there is a clean shortcut: every halving of the error adds about 3 dB (since 10 · log₁₀ 2 ≈ 3.01), and every doubling subtracts about 3 dB. So if encoder A scores 36 dB and encoder B scores 39 dB on the same clip, B has roughly half the pixel error of A. That 3-dB-per-doubling intuition is the single most useful thing to carry out of the math.
Reading a PSNR number: the decibel scale
A PSNR figure means nothing until you know what range to expect. For 8-bit lossy video and image compression, real-world PSNR almost always lands between 30 and 50 dB, and the bands inside that range have rough, well-worn meanings.
Below about 30 dB, errors are usually visible — the picture looks degraded to an attentive viewer. From 30 to about 40 dB you are in the normal operating range of streaming-grade compression, where quality is acceptable to good and most viewers are content. Above 40 dB the compressed frame is close to the original, and by the high 40s (an average error of about one level) the difference is near-imperceptible for 8-bit content. Higher bit depths shift the whole scale up: high-quality 12-bit imagery is judged at 60 dB or above, and 16-bit data runs from roughly 60 to 80 dB, because more bits mean a higher MAX and a higher ceiling.
Figure 2. The 8-bit PSNR scale with the worked examples placed on it. The bands are rules of thumb, not guarantees — content and codec move them.
The caveat attached to that scale is the most important sentence in this article. A PSNR value is only conclusively valid when you compare results from the same codec and the same content (Huynh-Thu and Ghanbari, Electronics Letters, 2008). A 38 dB score on an animation clip and a 38 dB score on a film grain clip do not mean the two look equally good — they mean nothing relative to each other. Use PSNR to compare two encodes of the same source, and the comparison is sound. Use it to rank quality across different sources, resolutions, or codecs, and you are reading tea leaves.
What is a good PSNR value? By bit depth and by tool
For 8-bit video, a good PSNR is roughly 35 dB and above: below 30 dB errors are usually visible, 30–40 dB is the normal range for streaming-grade compression, and above 40 dB the copy is close to the original. The same error reads as a higher number at higher bit depths, because MAX grows with the bits. The column "PSNR at MSE = 1" is the value for an average error of one code value, a useful reference point but not a hard limit.
| Bit depth | MAX | PSNR at MSE = 1 | Typical lossy range | libvmaf PSNR cap |
|---|---|---|---|---|
| 8-bit | 255 | 48.13 dB | 30–50 dB | 60 dB |
| 10-bit | 1023 | 60.20 dB | shifted up by ~12 dB vs 8-bit for the same relative error | 72 dB |
| 12-bit | 4095 | 72.25 dB | 60 dB and above is high quality | 84 dB |
| 16-bit | 65535 | 96.33 dB | 60–80 dB | 108 dB |
Tools treat the top of the scale differently, so check which one produced a number before comparing near-lossless results. Netflix's libvmaf clamps PSNR at 60 dB for 8-bit, 72 dB for 10-bit, 84 dB for 12-bit and 108 dB for 16-bit input (libvmaf source, checked November 2026). FFmpeg's own psnr filter applies no such clamp: it reports values above 90 dB for near-identical frames and inf for identical ones. A "60 dB" from libvmaf and a "74 dB" from FFmpeg on the same pair can describe the same encode.
Luma, chroma, and the "average" you actually quote
There is one more wrinkle between the formula and the number in your log. Video is not one channel; it is split into brightness (luma, the Y component) and color (chroma, the U and V components). PSNR is computed separately for each, so a tool reports psnr_y, psnr_u, psnr_v, and a combined psnr_avg.
The eye is far more sensitive to brightness than to color, which is why encoders spend most of their bits on luma. For the same reason, the luma PSNR (psnr_y) is the figure most engineers quote — it tracks the part of the picture viewers notice. The combined average is weighted by how many pixels each plane has, and because chroma is usually subsampled, luma dominates it anyway. When you read or report a PSNR number, say which one it is; "PSNR 38 dB" with no component named is a small but real ambiguity.
How to compute PSNR with FFmpeg
You will rarely write the formula yourself. The everyday tool is FFmpeg, whose psnr filter takes two video inputs — the distorted clip first, the reference second — and prints the per-component and average PSNR.
# PSNR between a distorted encode and its reference master.
# Output prints psnr_y, psnr_u, psnr_v and psnr_avg to the console.
ffmpeg -i distorted.mp4 -i reference.mp4 \
-lavfi psnr -f null -
To capture a value per frame — useful for finding the worst moments, not just the average — write a stats file:
# Per-frame PSNR written to psnr.log (n, mse_avg, psnr_avg, per-plane values).
ffmpeg -i distorted.mp4 -i reference.mp4 \
-lavfi "psnr=stats_file=psnr.log" -f null -
The shape of the command encodes the full-reference contract: it will not run without both files. If you want PSNR, SSIM, and VMAF in a single pass, the libvmaf filter can emit all three — that workflow, with model selection and output parsing, is covered in depth in measuring quality with FFmpeg and libvmaf, and the encoder-side quick reference lives in Video Encoding's FFmpeg cheat sheet.
To make the math concrete at your desk, we built a small, dependency-light script that computes PSNR between two image or frame files from first principles — MSE, then decibels — and prints every intermediate value so you can see exactly where the number comes from. Download the from-scratch PSNR calculator (Python) and run it against your own frames.
The alignment trap
PSNR assumes the two videos line up exactly: the same frame, at the same resolution, with the same brightness. Compare frame 100 of the encode against frame 98 of the master — a two-frame temporal slip — and PSNR reports a quality collapse the eye would never see. A one-pixel spatial shift or a small brightness offset does the same. This sensitivity is why the ITU standardized a dedicated alignment-compensated PSNR, ITU-T J.340 (2010), which corrects for constant spatial shift, temporal shift, and luminance gain before scoring. The practical rule: if a PSNR score looks shockingly bad, suspect misalignment before you suspect the encoder. Calibrate first, score second.
PSNR in image processing
In image processing, PSNR is computed exactly as it is for video: the mean squared error between a reference image and a processed copy, converted to decibels with 10 · log₁₀(MAX² / MSE). It is the usual score for JPEG, WebP and AVIF compression tests, denoising, deblurring and super-resolution, because it is cheap and every library ships it. For a color image you either average the squared error over all three RGB channels or score only the luma (Y) channel; both are common, and the two give different numbers for the same image, so state which one you used.
The trap in image work is the peak value. The formula needs MAX, and each library guesses it differently when you do not pass it:
| Library | Call | Peak value if you do not set it |
|---|---|---|
| scikit-image 0.26 | skimage.metrics.peak_signal_noise_ratio(image_true, image_test, data_range=...) | estimated from the image data type; pass data_range explicitly |
| OpenCV | cv2.PSNR(src1, src2, R) | R = 255 |
| MATLAB (Image Processing Toolbox) | psnr(A, ref, peakval) | 255 for uint8, 1 for double/single |
| TorchMetrics 1.9 | PeakSignalNoiseRatio(data_range=...) | set data_range yourself (a number, or a min/max tuple) |
If your images are floats scaled to 0–1 and the tool assumes 255, the result is off by about 48 dB. A 10-bit or 16-bit image scored with a peak of 255 is wrong in the other direction. Set the peak to 2B − 1 for B-bit integer data, or to 1.0 for normalized floats, and write it down next to the number.
PSNR calculation in Python
The whole calculation fits in a few lines of NumPy. Convert to float first: subtracting two uint8 arrays wraps around below zero and silently corrupts the MSE.
import numpy as np
def psnr(ref, test, max_val=255.0):
ref = ref.astype(np.float64)
test = test.astype(np.float64)
mse = np.mean((ref - test) ** 2)
if mse == 0:
return float("inf") # identical images
return 10 * np.log10(max_val ** 2 / mse)
# Every pixel off by 5 levels: MSE = 25, PSNR = 34.15 dB
ref = np.full((4, 4), 100, dtype=np.uint8)
print(psnr(ref, ref + 5))
The same pair through skimage.metrics.peak_signal_noise_ratio(ref, ref + 5, data_range=255) or cv2.PSNR(ref, ref + 5) returns the same 34.15 dB, which is a quick way to check that your peak value is set the way you think.
Why PSNR is a poor predictor of perceived quality
Here is the heart of the matter, and the reason every metric after PSNR exists. PSNR measures pixel error with perfect arithmetic and almost no understanding of vision. It has three blind spots that matter every day.
First, it treats every pixel as equally important. A pixel error in the sharp edge of a face and an identical error in a patch of flat sky contribute the same amount to the MSE, even though the eye forgives the sky and notices the face instantly. The metric has no idea where you are looking.
Second, it ignores structure and masking. Human vision hides errors in busy, textured, or high-contrast regions and exposes them in smooth ones — a property called visual masking. PSNR has no model of this, so it over-penalizes harmless noise in textured areas and under-penalizes banding in smooth gradients, exactly backwards from perception.
Third, it cannot tell two very different distortions apart if they have the same total error. A faint, even haze of noise spread across the whole frame and a chunk of ugly blocking concentrated in one corner can produce the same MSE — and therefore the same PSNR — while looking nothing alike to a viewer.
Figure 3. Same PSNR, different quality. PSNR sums pixel error and cannot see that one distortion lands where the eye is looking and the other does not.
This is not a fringe complaint. The defining academic study on the question, Huynh-Thu and Ghanbari's "Scope of validity of PSNR in image/video quality assessment" (2008), showed that PSNR's agreement with human opinion holds only within the same content and codec and breaks down across them. A 2025 study from TU Ilmenau and RWTH Aachen puts numbers on both halves of that finding: 216 4K sequences encoded with AV1, VVC and two neural codecs (DCVC-FM, DCVC-RT), rated by 30 viewers. Within one source clip, PSNR had the highest rank correlation of all tested metrics with viewer scores (SRCC 0.953). Across different clips, its Pearson correlation fell to 0.750, against 0.886 for VMAF (Herb et al., arXiv, November 2025). Same content: PSNR ranks encodes as well as anything. Different content: it is the weakest proxy in the table. The honest framing is the one to carry: every objective metric, PSNR included, is a proxy for human opinion that gets graded against subjective tests, and PSNR is among the weakest proxies we have.
Where PSNR is still the right tool
If PSNR predicts perception poorly, why is it everywhere — and why do we still use it? Because for several specific jobs its weaknesses do not bite and its strengths are decisive.
It is fast and free. PSNR is a handful of arithmetic operations per pixel, with no model to load, no training data, and no license. It runs in real time on anything, which is why every video encoder uses MSE or PSNR inside its rate-distortion optimization — the inner loop that decides, thousands of times per frame, whether spending another bit is worth the error it removes. A perceptual metric is too slow to call in that loop; PSNR is perfect for it.
It is a clean signal for same-codec, same-content comparison. When you change one encoder setting and re-encode the same master, PSNR will faithfully tell you whether pixel error went up or down. That makes it a fine sanity check and a cheap regression gate: if a code change drops PSNR on your fixed test clips, something broke, and you want to know before perceptual scoring even runs.
It is the universal baseline. Because PSNR has been computed the same way for decades, it is the one number every paper, every codec, and every tool can produce, which makes it the common currency for BD-rate and other rate-distortion comparisons. And it is exact for verifying losslessness: an infinite PSNR proves two files are bit-identical, which is the right tool for confirming a transcode changed nothing.
The rule is simple. Reach for PSNR when you are comparing encodes of the same source, when you need speed, or when you need a baseline everyone recognizes. Reach for a perceptual metric when you are predicting how good the video will look to a viewer.
The perceptual cousins: PSNR-HVS, PSNR-HVS-M, and XPSNR
PSNR's weaknesses were obvious enough that researchers built perceptually weighted versions that keep its speed. PSNR-HVS weights the pixel errors by a model of human contrast sensitivity, so errors the eye barely sees count less. PSNR-HVS-M goes further and adds visual masking — the way busy regions hide errors — and in its 2007 evaluation it tracked human judgement far better than both PSNR and SSIM.
The newest and most practical of these is XPSNR, the Extended Perceptually Weighted PSNR from Fraunhofer HHI. Its xpsnr filter shipped in FFmpeg 7.1 (September 2024) and is still documented in the current FFmpeg 9.0 "Lei" branch (9.0.2, September 2026). It is a low-complexity, psychovisually weighted PSNR whose values sit in the same decibel range as ordinary PSNR but follow perceived quality more closely; Fraunhofer HHI's evaluations on VVC-coded UHD video report XPSNR tracking subjective scores more closely than plain PSNR (Helmrich et al., 2020; Menon et al., 2024), which is why it is used for VVC encoder tuning and convex-hull ladder estimation. If you like PSNR's simplicity but want a number closer to the eye, xpsnr in a current FFmpeg build is worth knowing about:
# Extended perceptually weighted PSNR (Fraunhofer HHI, FFmpeg 2024+).
ffmpeg -i distorted.mp4 -i reference.mp4 -lavfi xpsnr -f null -
These variants matter because they show the real lesson of PSNR: the problem was never the decibel scale, it was treating all pixel errors as equal. Weight the errors by how the eye actually works, and a PSNR-style metric becomes useful again.
PSNR vs SSIM vs VMAF: when to reach for which
PSNR is one of three metrics you will meet constantly, and the fastest way to hold them in your head is side by side. The columns that matter are not just the scores but what each metric actually measures and where each one lies.
| Metric | Scale | What it measures | Where it lies (blind spot) | Best for |
|---|---|---|---|---|
| PSNR | dB (≈20–50, ∞ if identical) | Average pixel error vs the original | Ignores where errors are; same score for very different-looking distortions | Same-codec comparison, RDO, regression gates, lossless checks |
| SSIM | 0–1 (higher better) | Structural similarity — luminance, contrast, structure | Misses some color and temporal errors; still a spatial model | A better-than-PSNR perceptual proxy, per-frame structure |
| VMAF | 0–100 (higher better) | Fused, perception-trained quality (model-dependent) | Meaningless without the model named; gameable by sharpening | Predicting viewer-perceived streaming quality at scale |
Table 1. The three full-reference metrics at a glance. All need the original; they differ in how close they get to the eye and what they miss. Pick the row by the job, and always name the conditions.
The progression is the story of the field: PSNR measures error, SSIM measures structure, VMAF is trained directly on human scores. Each is a better perceptual proxy than the last, and each costs more to compute. None replaces a subjective test as ground truth. The full catalogue of where each objective metric misleads is in where objective metrics lie.
Common mistakes with PSNR
Mistake: comparing PSNR across different content, resolutions, or codecs. A 40 dB encode of a cartoon and a 34 dB encode of a grainy film do not tell you the cartoon "looks better" — PSNR is only valid comparing encodes of the same source. Cross-content PSNR rankings are the single most common abuse of the metric.
Mistake: quoting one PSNR number with no context. "PSNR 38" hides whether it is luma or average, mean-pooled or worst-case, and on what content. A single mean PSNR can hide a few terrible seconds inside an otherwise clean clip — which is why pooling matters. Report the component, the pooling, and the content.
Mistake: optimizing for PSNR instead of the viewer. Tuning an encoder to maximize PSNR can push it toward choices that score well on pixel error but look worse — over-smoothing detail, for instance. The metric is a proxy; optimizing the proxy past the point where it tracks perception is how teams ship video that scores high and looks flat.
PSNR FAQ
What does PSNR stand for?
PSNR stands for Peak Signal-to-Noise Ratio. "Peak signal" is the largest possible pixel value, "noise" is the error between the original and the processed frame, and the ratio between them is expressed in decibels.
What is the PSNR formula?
PSNR = 10 · log₁₀(MAX² / MSE), where MAX is the maximum pixel value (255 for 8-bit, 1023 for 10-bit) and MSE is the mean of the squared per-pixel differences between the original and the compressed frame. The equivalent form is 20 · log₁₀(MAX) − 10 · log₁₀(MSE).
Is a higher or lower PSNR better?
Higher PSNR is better: it means less pixel error. Every +3 dB roughly halves the mean squared error, and identical frames have infinite PSNR.
What is a good PSNR value?
For 8-bit video, roughly 35 dB and above is good: 30–40 dB is the normal streaming range, above 40 dB is close to the original, and below 30 dB errors are usually visible. Compare values only between encodes of the same source with the same codec.
What is the range of PSNR in dB?
PSNR runs from 0 dB upwards with no fixed maximum: identical frames give infinity. In practice 8-bit lossy video lands between 30 and 50 dB, and tools such as libvmaf clamp the top end at 60 dB for 8-bit content.
What does PSNR measure in video?
PSNR measures the average pixel error between a decoded video and its original master, usually on the luma (Y) channel and averaged over frames. It does not measure where the errors are or how visible they are to a viewer.
What is PSNR in image processing?
In image processing, PSNR scores how close a compressed, denoised or upscaled image is to its original, in decibels. It uses the same formula as video, 10 · log₁₀(MAX² / MSE), with MAX set to the image's peak value: 255 for 8-bit images, 1.0 for images normalized to 0–1.
Is PSNR measured in dB?
Yes. PSNR is a logarithmic ratio expressed in decibels (dB). Each +10 dB means the mean squared error is ten times smaller, and each +3 dB means it is roughly halved.
What is XPSNR?
XPSNR (Extended Perceptually Weighted PSNR) is a Fraunhofer HHI variant that weights pixel errors by how visible they are, keeping PSNR's speed and dB scale. It is available as the xpsnr filter in FFmpeg 7.1 and later, including FFmpeg 9.0.
PSNR vs SSIM: which should I use?
Use PSNR for fast same-source comparisons, encoder tuning and lossless checks; use SSIM or VMAF when you need to predict how the video looks to people, especially across different content.
Free download: From-scratch PSNR calculatorA dependency-light Python script that computes PSNR between two image or frame files from first principles - Mean Squared Error, then the decibel conversion - printing every intermediate value, per-channel MSE, MAX, MSE and PSNR in dB, so you can see exactly where the number comes from.Where Fora Soft fits in
Fora Soft has built video software since 2005 — streaming, WebRTC conferencing, OTT, e-learning, telemedicine, and surveillance — and PSNR is the first metric we compute on almost every encoding task, then the first one we refuse to trust on its own. We use it where it is strong: as a fast regression check that an encoder change did not increase pixel error, and as the baseline currency for rate-distortion comparison. We stop trusting it the moment the question becomes "how good does this look to the viewer," where we move to VMAF with its model named and pooling stated, anchored on real subjective testing. Our benchmark methodology documents which metric produced every number, and why PSNR was or was not the right one for that comparison. When an encoder change has to be signed off, our video processing and encoding developers build the PSNR and VMAF regression gates into the pipeline, and our streaming software team ties those numbers to the bitrate ladder viewers actually receive.


The handbook
Fora Soft Video Engineering Handbook
We wrote a seven-volume handbook that takes the whole video stack apart across 9,000+ pages - encoding, delivery, audio and AI - so that an engineer who works through it can design and build the systems these decibels grade. Volume 1 runs from the quantizer that creates the pixel error to the metrics that score it, PSNR first and then the perceptual ones built because pixel error was not enough; volume 3 is where a quality target stops being a number and becomes an ABR ladder, a player and a CDN bill; volume 5 does the same job for sound, whose quality metrics have their own decibel history. Written by Nikolay Sapunov, CEO at Fora Soft.
Is the PSNR number in your pipeline answering the question you are actually asking?
Send us your test clips and the numbers your CI produces, and we will tell you which comparisons are sound, which ones are cross-content tea leaves, and which metric belongs in each gate. 250+ video products shipped since 2005.
See our case studies
Case study
Speed.Space
Remote production recording at 1080p and 8 Mbps for Netflix, Electronic Arts and HBO shoots - the master sits on disk, which is exactly the case where a same-source PSNR check is the right regression gate.
Case study
Worldcast Live
Concert streaming at 1.5 Gb/s with 0.4-0.5 s latency for 10,000 simultaneous viewers, quality dropped per viewer on weak connections - the moment the question turns from pixel error into what the viewer sees.
Case study
Mindbox
An AI video management system on RTSP, FFmpeg and HLS across 50+ deployments - live camera feeds with no master to compare against, so PSNR cannot be computed at all and no-reference scoring takes over.
What to read next
Metrics
VMAF Explained: Netflix's Perceptual Video Quality Metric
The metric built because pixel error was not enough: what VMAF fuses, and what it still misses.
Metrics
Where Objective Video Quality Metrics Lie (and Why)
The full catalogue of content and motion cases where the number and the eye part ways.
Tooling
FFmpeg VMAF: Measure Video Quality with libvmaf
One FFmpeg pass that emits PSNR, SSIM and VMAF together, with the model named and the output parsed.
Benchmarks
BD-Rate Explained: Bitrate Saving at Equal Quality
What PSNR is really for: the rate-distortion comparison that turns two curves into one percentage.
References
- Recommendation ITU-T J.340 (06/2010), Reference algorithm for computing peak signal to noise ratio of a processed video sequence with compensation for constant spatial shifts, constant temporal shift, and constant luminance gain and offset. International Telecommunication Union. Tier 1. The standardized alignment-compensated PSNR computation for video. https://www.itu.int/rec/T-REC-J.340
- Recommendation ITU-T P.1401 (01/2020), Methods, metrics and procedures for statistical evaluation, qualification and comparison of objective quality prediction models. International Telecommunication Union. Tier 1. Defines PCC, SROCC, and RMSE — how any objective metric, PSNR included, is graded against subjective scores. https://www.itu.int/rec/T-REC-P.1401
- Recommendation ITU-R BT.500-15 (2023), Methodologies for the subjective assessment of the quality of television images. International Telecommunication Union. Tier 1. The subjective ground truth against which objective metrics like PSNR are validated. https://www.itu.int/rec/R-REC-BT.500
- Q. Huynh-Thu and M. Ghanbari, "Scope of validity of PSNR in image/video quality assessment," Electronics Letters, vol. 44, no. 13, pp. 800–801, 2008. Tier 5 (peer-reviewed). The defining study showing PSNR is valid only within the same content and codec. doi:10.1049/el:20080522 (https://doi.org/10.1049/el:20080522)
- Q. Huynh-Thu and M. Ghanbari, "The accuracy of PSNR in predicting video quality for different video scenes and frame rates," Telecommunication Systems, vol. 49, no. 1, pp. 35–48, 2012. Tier 5 (peer-reviewed). Quantifies how PSNR's predictive accuracy varies with content and frame rate. https://doi.org/10.1007/s11235-010-9351-x
- K. Egiazarian, J. Astola, N. Ponomarenko, V. Lukin, F. Battisti, M. Carli, "New full-reference quality metrics based on HVS," Proc. 2nd Int. Workshop on Video Processing and Quality Metrics (VPQM), 2006. Tier 5. Introduces PSNR-HVS, weighting pixel error by human contrast sensitivity. http://www.ponomarenko.info/psnrhvsm.htm
- N. Ponomarenko, F. Silvestri, K. Egiazarian, M. Carli, J. Astola, V. Lukin, "On between-coefficient contrast masking of DCT basis functions," Proc. 3rd Int. Workshop on Video Processing and Quality Metrics (VPQM), 2007. Tier 5. Defines PSNR-HVS-M, adding visual masking; outperformed PSNR and SSIM in evaluation. http://www.ponomarenko.info/vpqm07_p.pdf
- C. R. Helmrich, M. Siekmann, S. Becker, S. Bosse, D. Marpe, T. Wiegand, "XPSNR: A Low-Complexity Extension of the Perceptually Weighted Peak Signal-to-Noise Ratio for High-Resolution Video Quality Assessment," Proc. IEEE ICASSP, 2020; and the Fraunhofer HHI XPSNR FFmpeg plug-in. Tier 5 / Tier 3. The perceptually weighted PSNR now integrated into FFmpeg (2024). https://github.com/fraunhoferhhi/xpsnr
- FFmpeg, psnr and xpsnr filter documentation, accessed 2026-11-10. Tier 3 (first-party tooling). The
psnrfilter (two inputs, per-plane and average output,stats_file) and thexpsnrfilter added in FFmpeg 7.1 (2024) and present in 9.0 (2026). https://ffmpeg.org/ffmpeg-filters.html#psnr - Netflix, VMAF documentation and repository, accessed 2026-10-10. Tier 3 (first-party / metric-author). Netflix's rationale for building a perception-trained metric rather than relying on PSNR. https://github.com/Netflix/vmaf
- Z. Wang, A. C. Bovik, H. R. Sheikh, E. P. Simoncelli, "Image Quality Assessment: From Error Visibility to Structural Similarity," IEEE Transactions on Image Processing, vol. 13, no. 4, pp. 600–612, 2004. Tier 1 (metric-author). The SSIM paper, whose opening argument is precisely PSNR's failure to model perception. https://ece.uwaterloo.ca/~z70wang/publications/ssim.html
- B. Herb, R. R. Ramachandra Rao, S. Göring, A. Raake, "Evaluating Video Quality Metrics for Neural and Traditional Codecs using 4K/UHD-1 Videos," arXiv:2511.00969, November 2025. Tier 5 (preprint, TU Ilmenau / RWTH Aachen). 216 sequences, 30 viewers; PSNR within-sequence SRCC 0.953, overall PCC 0.750; VMAF overall PCC 0.886. https://arxiv.org/abs/2511.00969
- V. V. Menon, C. R. Helmrich, A. Wieckowski, B. Bross, D. Marpe, "Convex-hull Estimation using XPSNR for Versatile Video Coding," arXiv:2406.13712, June 2024. Tier 5 (Fraunhofer HHI). XPSNR's correlation with subjective scores on VVC-coded UHD content. https://arxiv.org/abs/2406.13712
- Netflix libvmaf, float_psnr.c (PSNR feature extractor), accessed 2026-11-10. Tier 3 (first-party tooling). PSNR clamp values per bit depth: 60 / 72 / 84 / 108 dB. https://github.com/Netflix/vmaf/blob/master/libvmaf/src/feature/float_psnr.c
- FFmpeg download page, "FFmpeg 9.0.2 'Lei'," released 2026-09-18 (9.0 branch since August 2026), accessed 2026-11-10. Tier 3 (first-party). Current stable FFmpeg release; the psnr and xpsnr filters are in the current filter documentation. https://ffmpeg.org/download.html
- scikit-image 0.26.0, skimage.metrics.peak_signal_noise_ratio API reference, accessed 2026-11-10. Tier 3 (first-party tooling). Signature and data_range default. https://scikit-image.org/docs/stable/api/skimage.metrics.html
- OpenCV source, core.hpp, declaration of
cv::PSNR(4.x branch), accessed 2026-11-10. Tier 3 (first-party tooling). R, the maximum pixel value, defaults to 255. https://github.com/opencv/opencv/blob/4.x/modules/core/include/opencv2/core.hpp - MathWorks, psnr (Image Processing Toolbox) reference page, accessed 2026-11-10. Tier 3 (first-party tooling). Default peakval: 255 for uint8, 1 for double and single. mathworks.com/help/images/ref/psnr.html
- TorchMetrics 1.9.0, Peak Signal-to-Noise Ratio (PSNR), accessed 2026-11-10. Tier 3 (first-party tooling). PeakSignalNoiseRatio and data_range semantics. https://lightning.ai/docs/torchmetrics/stable/image/peak_signal_noise_ratio
- "Peak signal-to-noise ratio," Wikipedia, accessed 2026-10-10. Tier 6 (educational, orientation only). Source for the typical dB ranges by bit depth (its "maximum PSNR" figures are the MSE = 1 values, not true limits); primary claims are cited to the standards and papers above. https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio
