silenceremove does what the name says, but its parameters don’t mean what most people assume, which leads to “it only trimmed the start” or “half my file disappeared”. For this article we built a test file with silence of known position and length, ran each setting, and measured how long the output was. The explanations below follow from those numbers.
Verified: FFmpeg 8.1 on Windows — all 11 commands in this article were executed by the verification script and passed (2026-09-06).
The test audio
gaps.wav(8.0 s): tone 1 s → silence 2 s → tone 1 s → silence 3 s → tone 1 spadded.wav(14.0 s):gaps.wavwith 2 s of silence added in front and 4 s after
“Tone” is a 440 Hz sine; “silence” is digital silence (exact zeros). Real recordings have a noise floor, so you’ll loosen the threshold to around -50dB as discussed below.
Trim leading silence only: start_periods=1
ffmpeg -i input.wav -af "silenceremove=start_periods=1:start_threshold=-50dB" output.wav
| Input | Output | What happened |
|---|---|---|
| padded.wav 14.0 s | 12.0 s | Only the 2 s of leading silence went. The 4 s at the end and the mid-file gaps are untouched |
start_periods=1 means “remove one stretch of silence before the sound starts”. It does not trim the end. Plenty of guides say it trims both ends; they are wrong (the end is handled below).
start_duration and start_silence
start_duration=0.5— “treat sound as started only after 0.5 s of continuous sound”. It guards against short clicks, but the 0.5 s used for the decision is also removed. Measured: 14.0 → 11.5 s (the audio lost half a second)start_silence=0.3— how much silence to keep. Measured: 14.0 → 12.3 s (0.3 s of silence remains at the start). Use it so the sound doesn’t begin abruptly
ffmpeg -i input.wav -af "silenceremove=start_periods=1:start_duration=0.5:start_silence=0.3:start_threshold=-50dB" output.wav
Shorten mid-file gaps: stop_periods=-1
For podcasts and lecture recordings where you want the long pauses shortened.
ffmpeg -i input.wav -af "silenceremove=stop_periods=-1:stop_duration=1:stop_threshold=-50dB" output.wav
| Input | Output | What happened |
|---|---|---|
| gaps.wav 8.0 s | 5.04 s | The 2 s and 3 s gaps each became 1 s. 1+1+1+1+1 = 5 s |
| padded.wav 14.0 s | 8.06 s | Mid gaps and the 4 s tail shrank to 1 s. The 2 s at the start is still there |
stop_periods=-1 means “act on every silence after sound stops”; stop_duration=1 means “shorten any silence longer than 1 s down to 1 s”. Again the start is not covered, so add start_periods=1 to trim that too.
ffmpeg -i input.wav -af "silenceremove=start_periods=1:start_threshold=-50dB:stop_periods=-1:stop_duration=1:stop_threshold=-50dB" output.wav
How much silence to leave after shortening
stop_silence is silence kept in addition. stop_duration=1:stop_silence=0.5 leaves 1.5 s per gap (measured: gaps.wav 8.0 → 6.04 s). Going the other way, stop_duration=0.5 squeezes each gap to 0.5 s: 8.0 → 4.04 s.
For natural-sounding conversation try stop_duration=1:stop_silence=0.3; for tight editing, stop_duration=0.3 or so.
The trap: stop_periods=1 deletes everything after the first silence
ffmpeg -i input.wav -af "silenceremove=stop_periods=1:stop_duration=1:stop_threshold=-50dB" output.wav
It’s tempting to read this as “remove one silence at the end”. The measured result: gaps.wav 8.0 s → 1.02 s. Everything after the first detected silence is discarded, because a positive stop_periods means “end the output at the Nth silence”.
To shorten mid-file gaps use stop_periods=-1 (negative); to trim only the trailing silence use the areverse trick below.
Trim trailing silence: the areverse sandwich
Since start_* only ever applies to the beginning, the standard trick is to reverse the audio, trim its start, and reverse it back.
ffmpeg -i input.wav -af "silenceremove=start_periods=1:start_threshold=-50dB,areverse,silenceremove=start_periods=1:start_threshold=-50dB,areverse" output.wav
Measured: padded.wav 14.0 s → 8.0 s (the 2 s lead and 4 s tail are gone, mid gaps kept).
areverse holds the entire audio in memory, so multi-hour recordings cost gigabytes. Anything around an hour is fine.
Preview where the silence is: silencedetect
To see what will count as silence before you cut, use silencedetect. It writes nothing and prints positions to the log.
ffmpeg -i input.wav -af "silencedetect=noise=-50dB:d=0.5" -f null -
[silencedetect @ ...] silence_start: 1
[silencedetect @ ...] silence_end: 3.000023 | silence_duration: 2.000023
[silencedetect @ ...] silence_start: 4
[silencedetect @ ...] silence_end: 7.000023 | silence_duration: 3.000023
noise is the threshold and d the minimum duration to count as silence. The ranges it reports are exactly what silenceremove will act on with the same values in stop_threshold / stop_duration. Reading the output in detail is covered in Detect silence.
Choosing the threshold
| Source | start/stop_threshold |
|---|---|
| Digitally generated audio, DAW exports | -60dB to -70dB |
| Microphone in a quiet room | -45dB to -50dB |
| Noisy environment, old cassette | -35dB to -40dB |
Set it too high (-30dB and up) and quiet speech or word endings get classified as silence and cut. Check with silencedetect and adjust in 5 dB steps.
Removing silence from a video
silenceremove is an audio filter, so applying it to a video does not remove any picture. The audio gets shorter and drifts out of sync.
ffmpeg -i input.mp4 -af "silenceremove=start_periods=1:start_threshold=-50dB" -c:v copy output.mp4
This command succeeds, but you get the original video with audio that now starts early. To cut silent sections out of the picture as well, take the timestamps from silencedetect, cut the sounding parts with trim / atrim or -ss/-to, and concat them. With many segments that needs a script, and a dedicated tool such as Auto-Editor (which drives FFmpeg underneath) is more practical.
Combining with loudness normalisation
If you normalise after removing silence, put loudnorm after silenceremove. Normalising first changes what counts as silence.
ffmpeg -i input.wav -af "silenceremove=start_periods=1:start_threshold=-50dB:stop_periods=-1:stop_duration=1:stop_threshold=-50dB,loudnorm=I=-16:TP=-1.5:LRA=11" output.wav
Output to MP3 / AAC
ffmpeg -i input.wav -af "silenceremove=start_periods=1:start_threshold=-50dB" -c:a libmp3lame -q:a 2 output.mp3
ffmpeg -i input.wav -af "silenceremove=start_periods=1:start_threshold=-50dB" -c:a aac -b:a 160k output.m4a
FAQ
Nothing is trimmed from the start
Either the threshold is too low (-90dB, say) or the “silence” in your file contains noise. Check whether silencedetect=noise=-50dB reports it as silence and raise the threshold.
Words get chopped mid-sentence
start_duration / stop_duration is too short and the tiny pauses between words are being treated as silence. Lengthen stop_duration to 0.5–1 s or keep a tail with stop_silence.
What is the window option?
The RMS window used for the threshold decision (default 0.02 s). You normally leave it alone; shorten it only to catch extremely short pulses.
Related tool
The Silence cut tool runs this article’s silenceremove in your browser; the file never leaves your device.
Related articles
- Detect silence (silencedetect) — reading the output and exporting it
- Loudness normalisation — the two-pass
loudnormprocedure - Trim a video —
-ss/-to(works the same for audio files) - Measure volume — use
volumedetectto pick a threshold