Denoise HD Video with FFmpeg nlmeans on Multi-Core
This article explains how to use the nlmeans (Non-Local
Means) filter in FFmpeg to remove noise and grain from high-definition
(HD) video. Because nlmeans is a highly effective but
computationally expensive spatial denoising filter, we will focus on
optimization techniques and command configurations that maximize
multi-core processor performance to speed up render times.
Understanding the nlmeans Filter
The nlmeans filter works by finding and averaging
similar pixel patches across a search window. While this process
preserves edges and fine details much better than simple blur filters,
processing 1080p or 4K video using default settings can be incredibly
slow.
To run this efficiently on a multi-core CPU, you must balance the algorithm’s search parameters and leverage FFmpeg’s multi-threading capabilities.
The Basic nlmeans Command
The basic syntax for applying the nlmeans filter is:
ffmpeg -i input.mp4 -vf "nlmeans=s=1.0:p=7:r=15" -c:v libx264 -crf 18 output.mp4s(Denoising Strength): Controls how aggressively the noise is filtered (default is 1.0).p(Patch Size): The size of the template patch (default is 7, representing a 7x7 grid).r(Research Size): The size of the search window (default is 15).
Optimizing Parameters for Speed on HD Video
For HD video, the default patch and research sizes are often too demanding. You can significantly reduce processing time with minimal loss in visual quality by adjusting these parameters:
ffmpeg -i input.mp4 -vf "nlmeans=s=1.5:p=5:r=11" -c:v libx264 output.mp4- Reducing
pto 5 andrto 11 dramatically reduces the number of mathematical calculations per pixel, allowing your multi-core processor to cycle through frames much faster.
Maximizing Multi-Core Processor Usage
FFmpeg automatically attempts to multi-thread video decoding, filtering, and encoding, but you can explicitly force optimized threading behavior to ensure all CPU cores are saturated.
1. Enable Global Threading
Use the -threads option to tell FFmpeg to use all
available CPU threads for both the filtering pipeline and the
encoder:
ffmpeg -i input.mp4 -vf "nlmeans=s=1.0:p=5:r=11" -threads 0 -c:v libx264 -preset slow output.mp4Setting -threads 0 forces FFmpeg to automatically spawn
the optimal number of threads based on your processor’s logical core
count.
2. Specify Filter Threads
You can specifically allocate CPU threads to the filter graph itself
by using the -filter_threads flag. This is highly
beneficial when running heavy filters like nlmeans:
ffmpeg -i input.mp4 -filter_threads 8 -vf "nlmeans=s=1.0:p=5:r=11" -c:v libx264 output.mp4Replace 8 with the number of physical cores or logical
threads you wish to dedicate solely to the denoising process.
3. Segmented parallel processing (Advanced)
If your CPU has a high core count (e.g., 16+ cores), a single FFmpeg
process using nlmeans might still underutilize your system
due to internal filtering bottlenecks. To fully saturate a high-end
processor, you can split your video into segments, process them
simultaneously in parallel, and concatenate them:
# Process segment 1 on threads 0-7
ffmpeg -ss 00:00:00 -t 00:05:00 -i input.mp4 -vf "nlmeans" -threads 8 part1.mp4
# Process segment 2 on threads 8-15
ffmpeg -ss 00:05:00 -t 00:10:00 -i input.mp4 -vf "nlmeans" -threads 8 part2.mp4Using these optimization strategies ensures you achieve high-quality, detail-preserving denoising on HD video without stalling your post-production workflow.