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:

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.mp4

2. 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.mp4

In 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.mp4

Performance 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.