In the world of video compression, the ultimate question isn't just "How small is the file?" but "How does it actually look to a human?" For years, we relied on PSNR (Peak Signal-to-Noise Ratio) or SSIM (Structural Similarity Index), but these metrics often fail to capture the nuances of human perception.
Enter VMAF (Video Multi-method Assessment Fusion). Developed by Netflix, VMAF has become the industry gold standard for bridge-building between raw data and human vision.
How VMAF Works: The "Brain" Behind the Metric
VMAF isn't just a single calculation; it’s a fusion of multiple metrics powered by a machine learning model (Support Vector Machine). It looks at video quality through three primary lenses:
- Visual Information Fidelity (VIF): Measures the loss of information during the encoding process across four different spatial scales.
- Detail Loss Measure (DLM): Specifically looks at the loss of details and the presence of impairments that distract the viewer.
- Temporal Motion: Since video is moving, VMAF accounts for the differences between adjacent frames to ensure motion looks natural.
By combining these, VMAF predicts how a human audience would rate the video on a scale from 0 to 100.
Understanding the Scores: What’s "Good"?
Unlike older metrics where the scale was often logarithmic or obscure, VMAF is designed to be intuitive. While "perfect" is 100, here is how the industry generally views the ratings:
Pro Tip: A "Just Noticeable Difference" (JND) is typically considered a 6-point shift in VMAF. If your encode settings change the score by only 1 or 2 points, a human likely won't see the difference.
How Quality is Measured
To get a VMAF score, you need two things:
- The Reference: Your original, uncompressed (or high-quality) source video.
- The Distorted: Your encoded/compressed video that you want to test.
The two videos must be perfectly aligned in terms of synchronization and resolution. If your distorted video is 720p but your source is 1080p, you must upscale the distorted video to match the source before the VMAF filter can run its comparison.
Quick Code Breakdown: Getting a Score with FFmpeg
FFmpeg makes it remarkably easy to calculate VMAF using the libvmaf filter. Here is the basic syntax to compare a compressed file against its source:
What’s happening in this command?
- -i compressed_video.mp4 -i original_source.mkv: We load both files. In FFmpeg, the first is index [0:v] and the second is [1:v].
- filter_complex: This tells FFmpeg to take both video streams and run them through the libvmaf filter.
- model: You must point to the VMAF model file (usually a .json or .pkl file) which contains the "intelligence" for the scoring.
- log_path: This saves a frame-by-frame breakdown into an XML or JSON file for deep analysis.
- -f null -: Since we are just calculating a score and not creating a new video file, we output to a "null" sink.
To truly master VMAF with FFmpeg, you need to account for real-world scenarios—like when your encoded video is a different resolution than your source. VMAF requires both inputs to match, so we often use a filter chain to upscale the "distorted" file on the fly.
Here is a breakdown of a production-ready command and what every single character is doing.
The Full Production Command
This command takes a 1080p source and compares it against a 720p encode, upscaling the encode to match the source before calculating the score.
Step-by-Step Code Breakdown
To understand how FFmpeg handles this "double-input" logic, look at the flow of the filter graph:
- -i encoded_720p.mp4 -i source_1080p.mkv: We load two inputs. FFmpeg assigns them indices: [0:v] is the first file, [1:v] is the second.
- [0:v]scale=1920:1080:flags=bicubic[dist]:
- [dist][1:v]libvmaf=...:
- model='path/to/vmaf_v0.6.1.json': This points to the pre-trained VMAF model. You must download this from the repository.
- log_path=results.json:log_fmt=json: This saves a frame-by-frame score to a file. This is crucial for identifying "quality drops" in specific scenes (like high-motion action) rather than just seeing a single average number.
- n_threads=4: VMAF is computationally heavy. Telling FFmpeg to use multiple threads will significantly speed up the calculation.
- -f null -: Since we aren't creating a new video file, this tells FFmpeg to discard the video frames after the calculation is done and just output the text data to the console.
Analyzing the Output
Once the command finishes, you will see a summary in your terminal that looks like this:
VMAF score: 94.123456
This single number represents the harmonic mean of the scores for every frame. While the average is great for a quick "Pass/Fail" check, always look at your .json log file to see if any specific frames dipped below a score of 70, which would indicate a visual glitch or a macroblocking spike.
Common Pitfalls to Avoid
- Frame Rate Mismatch: Ensure your source and encode have the exact same frame rate. If one is 24fps and the other is 23.976fps, the VMAF score will be completely inaccurate because the frames won't align.
- Model Version: Always use the model version that matches your libvmaf version. Most modern setups use the .json models (v0.6.1).
VMAF has revolutionized how we optimize bitrates. Instead of guessing, we can now mathematically ensure that our viewers are getting the best possible experience. Whether you're optimizing for Netflix-level streaming or just trying to save storage space on your server, VMAF is the tool you need in your belt.
Cheat Sheet:




0 Comments