FFmpeg nlmeans Denoiser for Low-Light Video
This article provides a practical guide on how to use the
nlmeans (Non-Local Means) filter in FFmpeg to remove heavy
noise from low-light video footage. You will learn the core mechanics of
the non-local means algorithm, understand its key parameters, and get
step-by-step command examples to achieve highly accurate denoising
results while balancing processing time and visual quality.
Understanding the nlmeans Filter
The Non-Local Means (nlmeans) algorithm is one of the
most effective denoising methods available in FFmpeg. Unlike local
denoising filters that only average neighboring pixels,
nlmeans searches a larger area of the frame for similar
pixel patches. By averaging these similar, non-local patches, it removes
noise while preserving sharp edges, textures, and fine details. This
makes it highly effective for low-light videos, which often suffer from
both sensor grain and color (chroma) noise.
Because of its complexity, nlmeans is computationally
expensive and runs slower than simpler filters like hqdn3d
or owdenoise.
Key Parameters of the nlmeans Filter
To get the best results, you need to configure the filter’s primary parameters:
s(strength): Controls the denoising strength for the luma (brightness) channel. The default is1.0. Higher values reduce more noise but can make the image look unnaturally smooth or blurry.p(patch size): The size of the template patch used for comparison. The default is7(representing a 7x7 pixel patch). Larger patches preserve larger structures but increase processing time. Must be an odd integer.r(research size): The size of the search window around the patch. The default is15. A larger window improves accuracy by finding more matching patches but significantly slows down rendering. Must be an odd integer.sc(chroma strength): Controls the denoising strength for the chroma (color) channels. If not set, it defaults to the value ofs.pc(chroma patch size): Patch size for chroma channels (defaults top).rc(chroma research size): Research window size for chroma channels (defaults tor).
Practical FFmpeg Command Examples
1. Basic Denoising
For mild noise, the default settings are often sufficient. Use the
following command to apply standard nlmeans denoising:
ffmpeg -i input.mp4 -vf "nlmeans" -c:v libx264 -crf 18 -c:a copy output.mp42. High-Accuracy Denoising for Low-Light Video
Low-light video typically suffers from heavy luma grain and colorful
chroma noise. To tackle this, you can increase the denoising strength
(s) and separately tune the chroma strength
(sc):
ffmpeg -i input.mp4 -vf "nlmeans=s=2.5:p=7:r=15:sc=3.5" -c:v libx264 -crf 18 -c:a copy output.mp4In this example: * s=2.5 aggressively targets
luma noise to smooth out dark, grainy areas. * sc=3.5
applies even stronger filtering to color noise, which is highly visible
in shadow regions.
3. High-Quality (But Slower) Configuration
If processing time is not an issue and you want the highest possible
fidelity, increase the research size (r) to allow the
filter to scan a wider area for matching patches:
ffmpeg -i input.mp4 -vf "nlmeans=s=2.0:p=9:r=21" -c:v libx264 -crf 18 -c:a copy output.mp4Performance Tips
Since nlmeans is CPU-intensive, consider these tips to
speed up your workflow: * Test on a short segment
first: Use -ss and -t to test your
settings on a 5-second clip before processing the entire video (e.g.,
ffmpeg -ss 00:01:00 -i input.mp4 -t 5 -vf "nlmeans=s=2.0" output_test.mp4).
* Hardware Acceleration: If your system supports
OpenCL, you can use the hardware-accelerated version of the filter,
nlmeans_opencl, to offload the processing to your GPU.