Using FFmpeg fftfilt for 2D Frequency Filtering

The fftfilt filter in FFmpeg allows you to perform two-dimensional Fast Fourier Transform (2D FFT) filtering on video frames directly in the frequency domain. This article explains how the filter functions, details the mathematical coordinates and variables used by its expressions, and provides ready-to-run examples for low-pass, high-pass, and periodic noise-reduction filters.


How fftfilt Works

The fftfilt filter applies a 2D Real Discrete Fourier Transform to each plane (luminance and chrominance) of a frame, converts spatial pixel values into spatial frequency coefficients, applies user-defined weight expressions to these coefficients, and transforms the result back to the spatial domain using an Inverse FFT.

Filtering in the frequency domain makes it straightforward to attenuate or isolate specific patterns, such as horizontal scan lines, moiré patterns, or general high/low frequencies, which can be computationally difficult with standard spatial convolution kernels.

Filter Parameters and Syntax

The filter accepts distinct parameters for luminance (Y) and chrominance (U, V) planes:

  • weight_Y, weight_U, weight_V: Mathematical expressions evaluated for every frequency point (X, Y). The resulting value multiplies the frequency coefficient at that position (a weight of 1 preserves the frequency; 0 eliminates it).
  • dc_Y, dc_U, dc_V: Explicit values to override the DC component (average brightness) of the plane. If left unset, the DC component is processed using the weight expression.

Expression Variables

When defining weight_Y, weight_U, or weight_V, the following variables are available:

  • X: Horizontal frequency index (0 to W - 1).
  • Y: Vertical frequency index (0 to H - 1).
  • W: Width of the frequency matrix.
  • H: Height of the frequency matrix.

In an unshifted 2D FFT, the lowest frequencies (including the DC component at (0, 0)) reside in the four corners of the frequency plane: (0, 0), (W, 0), (0, H), and (W, H). High frequencies reside toward the center (W/2, H/2).

To calculate the radial distance d from the nearest low-frequency corner, use the Euclidean distance formula folded around the boundaries:

d = hypot(min(X, W-X), min(Y, H-Y))

Practical Examples

1. Ideal Low-Pass Filter (Smoothing / Blurring)

To attenuate fine details and noise while retaining low-frequency base shapes, keep frequencies within a radius of \(R\) pixels from the DC origin.

ffmpeg -i input.mp4 -vf "fftfilt=weight_Y='lte(hypot(min(X,W-X),min(Y,H-Y)),30)':weight_U=1:weight_V=1" -c:a copy output.mp4
  • This command keeps all luminance frequencies where the radial distance is \(\le 30\) and zeroes out everything higher.
  • weight_U=1 and weight_V=1 preserve the original color planes.

2. High-Pass Filter (Edge Isolation)

A high-pass filter eliminates low frequencies and keeps edges, fine lines, and sharp transitions.

ffmpeg -i input.mp4 -vf "fftfilt=weight_Y='gte(hypot(min(X,W-X),min(Y,H-Y)),20)':weight_U=0:weight_V=0" -c:a copy output.mp4
  • The expression retains luminance frequencies where distance is \(\ge 20\).
  • Setting weight_U=0 and weight_V=0 removes color variations, generating a grayscale edge map.

3. Gaussian Low-Pass Filter (Smooth Roll-off)

A hard cutoff can introduce ringing artifacts (Gibbs phenomenon). A Gaussian function smooths the transition between retained and attenuated frequencies.

ffmpeg -i input.mp4 -vf "fftfilt=weight_Y='exp(-0.5*(pow(min(X,W-X),2)+pow(min(Y,H-Y),2))/pow(25,2))'" -c:a copy output.mp4
  • Adjust 25 to change the cutoff spread; higher values preserve more detail.

4. Notch Filter (Removing Periodic Horizontal Lines)

Periodic horizontal interference manifests as concentrated energy along the vertical frequency axis (where horizontal frequency min(X, W-X) is close to zero, but vertical frequency min(Y, H-Y) is non-zero).

ffmpeg -i input.mp4 -vf "fftfilt=weight_Y='not(lte(min(X,W-X),2)*gte(min(Y,H-Y),15))'" -c:a copy output.mp4
  • This checks whether a coordinate lies within a strip close to the vertical axis (X <= 2) at high vertical frequencies (Y >= 15), setting its weight to 0 while leaving the rest of the spectrum at 1.

Performance Considerations

Because computing forward and inverse 2D Fast Fourier Transforms on every frame requires significant processing power, fftfilt is slower than spatial convolution alternatives like boxblur or unsharp. Limit its use to tasks where frequency-selective precision (such as narrow-band notch filtering or exact harmonic attenuation) is strictly required.