Remove Audio DC Offset with FFmpeg dcshift

A DC offset occurs when an audio signal's waveform rests above or below the zero-amplitude baseline, eating up valuable headroom and causing audible clicks, pops, or distortion. This guide explains how to identify DC offset in a damaged audio file and use FFmpeg’s dedicated dcshift audio filter to re-center the waveform, restore dynamic headroom, and clean up your recording.

Understanding the dcshift Filter

The dcshift filter directly modifies the vertical baseline of an audio waveform by adding or subtracting a constant value from every sample. Its primary parameters are:

  • shift: A floating-point number between -1.0 and 1.0. A negative value shifts the waveform down, while a positive value shifts it up.
  • limitergain: An optional float between 0.0 and 1.0. If adjusting the DC offset causes the signal to exceed digital maximum (\(0\text{ dBFS}\) or \(1.0\)), limitergain attenuates the audio proportionally to prevent digital clipping.

Step 1: Measuring the DC Offset

Before shifting the audio, you must calculate the exact amount of baseline deviation. You can determine the DC offset using FFmpeg's astats filter.

Run the following command in your terminal:

ffmpeg -i input.wav -af "astats=metadata=1:reset=1" -f null -

Inspect the console output for the DC offset field for each audio channel. If the command reports an offset of 0.045000, the waveform is resting \(0.045\) units too high relative to zero.

Step 2: Applying the Correction with dcshift

To cancel out the offset, apply the dcshift filter using the inverted value of the measured offset. For an offset of +0.045, shift by -0.045.

Execute the correction with:

ffmpeg -i input.wav -af "dcshift=shift=-0.045" output.wav

If your audio is close to peak amplitude, shifting the baseline might cause the signal to clip. You can enable the limiter by adding a limitergain value roughly equal to the shift amount:

ffmpeg -i input.wav -af "dcshift=shift=-0.045:limitergain=0.045" output.wav

Handling Multi-Channel Audio

If you have a stereo recording where only one channel has a DC offset or both channels have different offsets, you must split and process the channels independently using pan or channelmap combined with dcshift, or run an automated high-pass filter:

ffmpeg -i input.wav -af "highpass=f=10" output.wav

While a low-frequency high-pass filter (cut off at \(10\text{ Hz}\) to \(20\text{ Hz}\)) automatically strips DC components across all channels, manually using dcshift provides a surgically pure phase response by applying a linear mathematical offset without affecting any audible low-end frequencies.