Speed Up FFmpeg VMAF with Multi-Threading
Computing Video Multi-Method Assessment Fusion (VMAF) scores can be
computationally intensive, often creating bottlenecks in automated video
processing pipelines. By default, the libvmaf filter in
FFmpeg may not utilize all available CPU resources efficiently. This
guide explains how to enable multi-threading for the VMAF calculation
itself, optimize decoder thread allocation, and structure your FFmpeg
commands to maximize processing throughput.
Enabling the
n_threads Option in libvmaf
The primary method to enable multi-threading during VMAF calculation
is passing the n_threads parameter directly to the
libvmaf filter inside the -filter_complex
argument.
Here is a standard multi-threaded command:
ffmpeg -i distorted.mp4 -i reference.mp4 -filter_complex \
"[0:v][1:v]libvmaf=n_threads=8:log_fmt=json:log_path=vmaf.json" \
-f null -n_threads: Sets the number of execution threads allocated strictly to the VMAF algorithm.log_fmtandlog_path: Specify the output format and file destination for the resulting metric data.-f null -: Instructs FFmpeg to discard the video output rather than encoding it to disk, saving I/O overhead.
Optimizing Input Decoder Threads
Calculating VMAF requires decoding two video streams simultaneously:
the reference video and the distorted video. If the decoders cannot
supply frames fast enough, the VMAF filter will stall regardless of how
many threads are assigned to n_threads.
Explicitly allocate decoding threads prior to each input to prevent decoder starvation:
ffmpeg -threads 4 -i distorted.mp4 -threads 4 -i reference.mp4 -filter_complex \
"[0:v][1:v]libvmaf=n_threads=8:model=version=vmaf_v0.6.1:log_fmt=json:log_path=vmaf.json" \
-f null -In this setup, each input utilizes 4 decoding threads, while
libvmaf utilizes 8 threads to process the comparative
scoring.
Optimal Thread Allocation Strategy
To find the most efficient thread allocation:
- Avoid Oversubscription: The total number of threads
(Input 1 Decoder + Input 2 Decoder +
n_threads) should not exceed your machine's total logical CPU cores. For an 8-core/16-thread CPU, a balanced configuration is-threads 4(Input 1),-threads 4(Input 2), andn_threads=8. - Diminishing Returns:
libvmafscaling generally plateaus between 8 and 16 threads depending on the video resolution. Settingn_threadshigher than 16 rarely provides proportional performance gains.
Performance Optimization Checklist
- Pre-align Formats and Resolutions: If the reference
and distorted files have different pixel formats or resolutions, FFmpeg
automatically inserts scaling and conversion filters that might run on a
single thread. Ensure both inputs are normalized to matching pixel
formats (such as
yuv420p) and identical resolutions beforehand. - Use Fast Frame Seeking for Sampling: If you only
need an estimate across a video, use the
-ssand-tflags to sample representative segments rather than analyzing the entire file. - Hardware Decoding: If CPU decoding forms a
bottleneck, utilize hardware-accelerated decoders (e.g.,
-hwaccel cudaor-hwaccel qsv) to offload decoding to the GPU, reserving 100% of the host CPU cores exclusively for then_threadscalculation.