Python tool based on FFmpeg and FFprobe to handle the video preprocessing required for VMAF:
- Deinterlacing
- Upscaling / downscaling
- Frame-to-frame syncing
- Frame rate adaptation
Details about How it Works can be found here.
- Linux / macOS
- Python >= 3.8
- FFmpeg >= 5.0 built with
--enable-libvmaf(built-in models required) - Python package:
ffmpeg-progress-yield
For GPU-accelerated VMAF:
- NVIDIA GPU with CUDA support
- FFmpeg built with
--enable-nonfree --enable-ffnvcodec --enable-libvmaf - libvmaf built with
-Denable_cuda=true -Denable_float=true - NVIDIA Container Toolkit (for Docker GPU usage)
pip install easyvmafOr from source:
git clone https://github.com/gdavila/easyVmaf.git
cd easyVmaf
pip install -e .FFmpeg must be on PATH, or override via environment variables:
FFMPEG=/path/to/ffmpeg FFPROBE=/path/to/ffprobe easyvmaf ...easyvmaf -d <distorted> -r <reference> [options]
| Flag | Description |
|---|---|
-d D |
Distorted video path (supports glob patterns for batch) |
-r R |
Reference video path |
| Flag | Default | Description |
|---|---|---|
-sw SW |
0 |
Sync window size in seconds. Enables automatic sync search between the first frames of the distorted and a subsample of the reference. 0 disables sync. |
-ss SS |
0 |
Sync start time: offset into the reference where the sync window begins. |
-fps FPS |
0 |
Force frame rate conversion. Disables auto-deinterlace when set. |
-subsample N |
1 |
Frame subsampling factor to speed up computation. |
-reverse |
off | Reverse sync direction: match reference first-frames against distorted instead of the default. |
-model MODEL |
HD |
VMAF model. Options: HD, 4K. |
-threads N |
0 |
Number of threads (0 = auto). |
-output_fmt FMT |
json |
Per-frame VMAF output file format: json, xml, or csv. |
-verbose |
off | Enable verbose log level. |
-progress |
off | Show FFmpeg progress during VMAF computation. |
-endsync |
off | Stop when the shorter video ends. |
-cambi_heatmap |
off | Compute and save CAMBI banding heatmap. |
-sync_only |
off | Measure sync offset only — skip VMAF computation. |
-json |
off | Print final results as JSON to stdout. Compatible with -sync_only and full VMAF runs. In batch mode, one JSON object per line (NDJSON). |
-gpu |
off | Use GPU-accelerated VMAF via libvmaf_cuda. Requires a CUDA-capable FFmpeg build (see Docker: CUDA). |
easyvmaf -d distorted.mp4 -r reference.mp4# Sync window of 2 seconds starting from the beginning of reference
easyvmaf -d distorted.mp4 -r reference.mp4 -sw 2
# Sync window starting at 6 s into reference, reverse direction
easyvmaf -d distorted.mp4 -r reference.mp4 -sw 3 -ss 6 -reverse# Human-readable output
easyvmaf -d distorted.mp4 -r reference.mp4 -sw 2 -sync_only
# Structured JSON output
easyvmaf -d distorted.mp4 -r reference.mp4 -sw 2 -sync_only -jsonThe -json flag prints a single JSON object to stdout (or one object per line in batch mode):
easyvmaf -d distorted.mp4 -r reference.mp4 -sw 2 -json{
"distorted": "distorted.mp4",
"reference": "reference.mp4",
"sync": { "offset": 0.7007, "psnr": 48.863779 },
"vmaf": {
"model": "HD",
"vmaf_hd": 89.123456,
"vmaf_hd_neg": 88.654321,
"vmaf_hd_phone": 91.234567,
"output_file": "distorted_vmaf.json"
}
}# Glob pattern — one result per file
easyvmaf -d "folder/*.mp4" -r reference.mp4 -jsoneasyvmaf -d distorted_4k.mp4 -r reference_4k.mp4 -model 4KRequires a CUDA build of FFmpeg/libvmaf (see Docker section below):
easyvmaf -d distorted.mp4 -r reference.mp4 -gpuSync computation always runs on CPU regardless of -gpu. The GPU is used only for the final VMAF scoring step.
docker build -t easyvmaf .docker build -f Dockerfile.cuda -t easyvmaf:cuda .Note: The CUDA image links FFmpeg with
--enable-nonfreecomponents (nvcc/CUDA). It cannot be legally redistributed — build and use locally only.
Both Dockerfiles accept these build-time arguments:
| ARG | Default | Description |
|---|---|---|
FFMPEG_version |
8.1 |
FFmpeg release tag |
VMAF_version |
3.0.0 |
libvmaf release tag |
EASYVMAF_VERSION |
2.1.0 |
easyVmaf version label |
DAV1D_version |
1.4.3 |
dav1d release (CUDA image only — built from source) |
# Custom versions
docker build --build-arg FFMPEG_version=8.1 --build-arg VMAF_version=3.0.0 -t easyvmaf .# CPU
docker run --rm -v /path/to/videos:/videos \
easyvmaf -d /videos/distorted.mp4 -r /videos/reference.mp4
# With sync
docker run --rm -v /path/to/videos:/videos \
easyvmaf -d /videos/distorted.mp4 -r /videos/reference.mp4 -sw 2
# JSON output
docker run --rm -v /path/to/videos:/videos \
easyvmaf -d /videos/distorted.mp4 -r /videos/reference.mp4 -json
# GPU (requires NVIDIA Container Toolkit)
docker run --rm --gpus all -v /path/to/videos:/videos \
easyvmaf:cuda -d /videos/distorted.mp4 -r /videos/reference.mp4 -gpuA docker-compose.yml is included with pre-configured easyvmaf (CPU) and easyvmaf-cuda (GPU) services:
# CPU service
VIDEO_DIR=/path/to/videos docker compose run easyvmaf \
-d /videos/distorted.mp4 -r /videos/reference.mp4
# GPU service
VIDEO_DIR=/path/to/videos docker compose run easyvmaf-cuda \
-d /videos/distorted.mp4 -r /videos/reference.mp4 -gpuVIDEO_DIR defaults to ./video_samples if not set.
reference.ts starts 0.7 seconds after distorted-A.ts. Use -sw to search for the offset automatically:
easyvmaf -d distorted-A.ts -r reference.ts -sw 2The sync window sw=2 means easyVmaf searches the first 2 seconds of reference.ts for the best PSNR match against the first frames of distorted-A.ts.
distorted-B.ts starts 8.3 seconds after reference.ts. Use -reverse to flip the sync direction:
easyvmaf -d distorted-B.ts -r reference.ts -sw 3 -ss 6 -reverse-ss 6 begins the sync search 6 seconds into reference.ts; -reverse matches reference first-frames against the distorted stream.