Basic Command: Overlaying BGM on a Video

To keep a video’s own sound and add background music (BGM) under it, use the amix filter. The mixed audio has to be re-encoded, so you cannot use -c:a copy here.

ffmpeg -i input.mp4 -i bgm.mp3 \
  -filter_complex "[0:a][1:a]amix=inputs=2:duration=shortest:dropout_transition=0[aout]" \
  -map 0:v:0 -map "[aout]" -c:v copy -c:a aac -b:a 192k output.mp4

-filter_complex mixes the two audio streams. -map 0:v:0 keeps the video, and -map "[aout]" picks the mixed audio. The video is copied as it is (-c:v copy), so the command finishes in seconds even on long files.

Key amix options

Option Default Description
inputs 2 Number of inputs to mix
duration longest longest, shortest, or first decides output length
dropout_transition 2 Fade duration (seconds) when an input ends
weights 1 1 Per-input weight; combines with the volume filter
normalize 1 Auto-normalises the output to prevent clipping

amix vs amerge

The two filters are easy to confuse, but they do different jobs.

Filter Purpose Output channels
amix Sums signals that share the same channel layout Same as inputs
amerge Combines the channels of the inputs (e.g., 2 mono → 1 stereo) Sum of input channels

For video plus BGM you want the signals summed, so use amix. amerge keeps each input on its own channels: two stereo inputs give a 4-channel file, and two mono inputs give a stereo file with the original audio on the left and the BGM on the right. That is almost never what you want.

Replacing Original Audio with BGM

To drop the original audio and keep only the BGM, use -map to pick the video stream and the BGM stream. The original audio is left out. (Adding -an to the output would drop the BGM too.)

ffmpeg -i input.mp4 -i bgm.mp3 \
  -map 0:v:0 -map 1:a:0 -c:v copy -c:a aac -b:a 192k -shortest output.mp4

-shortest stops the output when the shorter input ends, so a long BGM is cut automatically. Re-encode the audio to AAC (-c:a aac) instead of copying the MP3 into the MP4. FFmpeg accepts MP3 in MP4, but some players may not play it.

Adjusting Volume Balance

If the BGM drowns out the voice, put a volume filter before amix to turn down only the BGM.

ffmpeg -i input.mp4 -i bgm.mp3 \
  -filter_complex "[1:a]volume=0.3[bgm];[0:a][bgm]amix=inputs=2:duration=shortest:dropout_transition=0[aout]" \
  -map 0:v:0 -map "[aout]" -c:v copy -c:a aac -b:a 192k output.mp4

volume=0.3 is about -10 dB. Some starting points:

Use case Original audio BGM
Tutorial / explainer 1.0 0.15–0.25
Vlog (keep ambience) 0.7 0.30–0.40
Silent footage with BGM (muted) 1.0
Music-led content 0.20 1.0

You can also give the level in dB: volume=-12dB. amix uses normalize=1 by default. It turns every input down by the same amount (about 6 dB with two inputs), so the ratio you set stays the same, but the whole mix gets quieter. When one input ends, the others get louder again. Add normalize=0 to keep the levels you set.

Verify with a single input

To try the same chain with only one audio file, split it with asplit and mix the copies.

ffmpeg -i input.mp3 -filter_complex "[0:a]asplit=2[a1][a2];[a1]volume=0.3[bgm];[a2]volume=1.0[voice];[bgm][voice]amix=inputs=2:duration=longest:dropout_transition=0[out]" -map "[out]" -c:a libmp3lame output.mp3

asplit=2 makes two copies of the input. One copy is turned down, then both are mixed back together. For real work, replace the split with two -i inputs.

When BGM Is Shorter or Longer Than the Video

When the lengths differ (for example, a 60-second video and a 30-second BGM), you have four options:

Situation Filter Effect
BGM short — pad with silence apad Appends silence to the end
BGM short — loop instead aloop Repeats the BGM
BGM long — trim to video amix=duration=shortest or -shortest Stops at the shorter input
BGM long — clean cut atrim + afade Cuts at a chosen second with a fade

Loop the BGM until the video ends

ffmpeg -i input.mp4 -i bgm.mp3 \
  -filter_complex "[1:a]aloop=loop=-1:size=2e+09[loop];[0:a][loop]amix=inputs=2:duration=first:dropout_transition=0[aout]" \
  -map 0:v:0 -map "[aout]" -c:v copy -c:a aac -b:a 192k output.mp4

aloop=loop=-1 repeats the BGM without end. size=2e+09 is the maximum number of samples to loop, large enough to hold the whole BGM. duration=first ends the mix when the first input, the video’s own audio, ends.

Pad the BGM tail with silence

ffmpeg -i input.mp4 -i bgm.mp3 \
  -filter_complex "[1:a]apad[pad];[0:a][pad]amix=inputs=2:duration=first:dropout_transition=0[aout]" \
  -map 0:v:0 -map "[aout]" -c:v copy -c:a aac -b:a 192k output.mp4

With no options, apad adds endless silence after the BGM, and duration=first makes amix stop when the video’s own audio ends. The BGM plays once, then silence fills the rest.

Test apad alone (single input)

ffmpeg -i input.mp3 -af "apad=pad_dur=5,atrim=0:25" output.mp3

On a 20-second clip, this adds 5 seconds of silence and trims the result to exactly 25 seconds. It is a quick way to check the length adjustment before you use it in the full command.

BGM Fade-In / Fade-Out

BGM that starts at full volume sounds abrupt. Use afade to add a 2-second fade-in and a 3-second fade-out.

ffmpeg -i input.mp4 -i bgm.mp3 \
  -filter_complex "[1:a]volume=0.3,afade=t=in:st=0:d=2,afade=t=out:st=57:d=3[bgm];[0:a][bgm]amix=inputs=2:duration=first:dropout_transition=0[aout]" \
  -map 0:v:0 -map "[aout]" -c:v copy -c:a aac -b:a 192k output.mp4

afade=t=out:st=57:d=3 means “start fading at second 57 and reach silence 3 seconds later”. On a 60-second video, the fade ends exactly at the end. Always set st a little before the point where the output is cut; a fade that starts after the cut does nothing.

Verify the fade chain on a single file

ffmpeg -i input.mp3 -af "volume=0.3,afade=t=in:st=0:d=2,afade=t=out:st=15:d=5" output.mp3

On a 20-second clip, this lowers the volume, fades in over 2 seconds, and fades out over 5 seconds from second 15. For more, see Audio Fade-In / Fade-Out.

Chaining Multiple BGM Tracks (Intro / Main / Outro)

To play an intro, a main track and an outro back to back as one BGM, use the concat filter for audio.

ffmpeg -i intro.mp3 -i main.mp3 -i outro.mp3 \
  -filter_complex "[0:a][1:a][2:a]concat=n=3:v=0:a=1[bgm]" \
  -map "[bgm]" -c:a libmp3lame combined_bgm.mp3

n=3 is the number of inputs, and v=0:a=1 means “0 video streams and 1 audio stream per input”. You can then use combined_bgm.mp3 as bgm.mp3 in any of the mix commands above.

Try concat with one input

ffmpeg -i input.mp3 -filter_complex "[0:a]asplit=3[a1][a2][a3];[a1]atrim=0:5,asetpts=PTS-STARTPTS[s1];[a2]atrim=0:10,asetpts=PTS-STARTPTS[s2];[a3]atrim=0:5,asetpts=PTS-STARTPTS[s3];[s1][s2][s3]concat=n=3:v=0:a=1[out]" -map "[out]" -c:a libmp3lame output.mp3

This cuts one source into 5-, 10- and 5-second pieces and joins them. asetpts=PTS-STARTPTS resets each piece’s timestamps to 0. Here every piece already starts at 0, but a piece cut from later in the file, such as atrim=10:15, needs it. Without it, that piece keeps its original times and concat leaves a gap before it.

Auto-Duck BGM Under the Original Audio

To keep the narration clear, use a sidechain compressor: a compressor on the BGM that the voice controls. It lowers the BGM automatically whenever someone speaks.

ffmpeg -i input.mp4 -i bgm.mp3 \
  -filter_complex "[0:a]aformat=fltp:44100:stereo,asplit=2[voice1][voice2];[1:a]aformat=fltp:44100:stereo,volume=0.5[bgm];[bgm][voice1]sidechaincompress=threshold=0.02:ratio=6:attack=200:release=1000[ducked];[voice2][ducked]amix=inputs=2:duration=first:dropout_transition=0[aout]" \
  -map 0:v:0 -map "[aout]" -c:v copy -c:a aac -b:a 192k output.mp4

When the voice starts, the compressor turns the BGM down. When the voice stops, the BGM comes back up. The voice goes to two places, the sidechain and the final amix. A filter output can feed only one filter, so the voice is copied with asplit. For what each setting does and natural attack and release values, see Auto-Duck BGM Under Narration with sidechaincompress.

Stream-Mapping Pitfalls

-filter_complex does not turn off automatic stream selection on its own. Filter outputs without a label can be added to the first output file. Map a labeled output such as [aout] exactly once with -map "[aout]", and map the video you want to keep with -map 0:v. See the official stream-selection rules.

Pattern Result
-map 0:v:0 -map "[aout]" Correct — video plus mixed audio
-map "[aout]" only Wrong — audio-only file (no video)
-map 0 only Wrong — [aout] is not used, so FFmpeg stops with an error
No -map at all Wrong — FFmpeg stops with the same error
# Wrong
ffmpeg -i input.mp4 -i bgm.mp3 \
  -filter_complex "[0:a][1:a]amix=inputs=2:duration=shortest[aout]" \
  -c:v copy -c:a aac output.mp4

This command has no -map, so [aout] is not used anywhere, and FFmpeg stops with an error such as Filter 'amix:default' has output 0 (aout) unconnected. Whenever you use -filter_complex, add -map as well.

Batch: Apply Same BGM to Many Videos

This Bash loop adds the same BGM to every .mp4 in the current folder:

mkdir -p out
for f in *.mp4; do
  ffmpeg -i "$f" -i bgm.mp3 \
    -filter_complex "[1:a]volume=0.3,afade=t=in:st=0:d=2[bgm];[0:a][bgm]amix=inputs=2:duration=first:dropout_transition=0[aout]" \
    -map 0:v:0 -map "[aout]" -c:v copy -c:a aac -b:a 192k "out/${f%.mp4}_bgm.mp4"
done

In Windows PowerShell, use Get-ChildItem *.mp4 | ForEach-Object { ffmpeg ... }. -c:v copy skips video re-encoding, but the video length, the audio processing and the disk still affect how long it takes. Run one file first and check the output and the time.

Troubleshooting

The command stops with an error

If -map "[aout]" is missing, FFmpeg stops with an error such as Filter 'amix:default' has output 0 (aout) unconnected. Add it after -filter_complex. -c:a copy does not work here either: the mixed audio has to be encoded, so FFmpeg stops with Streamcopy requested for output stream fed from a complex filtergraph. Filtering and streamcopy cannot be used together. Use -c:a aac instead.

BGM clips (distorts)

The mix went over full scale. With the default normalize=1, the mix never peaks higher than its loudest input, so the sum itself cannot clip, but the mix gets quieter. With normalize=0, the sum can clip. This version keeps the level and limits the peaks:

ffmpeg -i input.mp4 -i bgm.mp3 \
  -filter_complex "[0:a]volume=0.8[v];[1:a]volume=0.3[bgm];[v][bgm]amix=inputs=2:duration=first:dropout_transition=0:normalize=0,alimiter=limit=0.95:level=0[lim]" \
  -map 0:v:0 -map "[lim]" -c:v copy -c:a aac -b:a 192k output.mp4

normalize=0 turns off the automatic rescaling, and alimiter caps the peak at 0.95 (about -0.45 dBFS). Without level=0, alimiter raises the level back to full scale after limiting. To bring the whole mix to a broadcast loudness standard, see Loudness Normalization (loudnorm/LUFS).

Audio drifts out of sync

Different sample rates do not necessarily cause drift, because FFmpeg can negotiate and convert formats. Compare the sync at the beginning, middle and end. aformat makes the mixing format explicit, but it does not fix a timing offset that is already there:

ffmpeg -i input.mp4 -i bgm.mp3 \
  -filter_complex "[0:a]aformat=fltp:44100:stereo[v];[1:a]aformat=fltp:44100:stereo,volume=0.3[bgm];[v][bgm]amix=inputs=2:duration=first:dropout_transition=0[aout]" \
  -map 0:v:0 -map "[aout]" -c:v copy -c:a aac -b:a 192k output.mp4

FAQ

BGM is too loud

Apply volume=0.2–0.3 to the BGM before amix. If the BGM still covers the voice, use auto-ducking with sidechaincompress.

BGM doesn’t match the video length

If the BGM is short, loop it with aloop. If it is long, cut it with amix=duration=first or -shortest. You can combine the two.

How do I auto-duck?

Use the sidechain compressor command above. The settings are explained in Auto-Duck BGM Under Narration.

Keep original audio vs replace it?

To keep it, use amix. To replace it, map only 1:a:0 for the audio and leave out 0:a. For vlogs, keeping the ambient sound helps; music videos usually replace it entirely.

BGM only plays in one channel

This happens when amerge is used by mistake. Use amix instead; it puts a mono BGM on both channels of a stereo mix.

Where do I find royalty-free BGM?

Good places to start are the YouTube Audio Library (free, in YouTube Studio), Pixabay Music, Free Music Archive and Incompetech. Before you publish, check the licence and whether you must credit the artist.


Primary source: ffmpeg.org/ffmpeg-filters.html#amix