For a hobby project of mine, I wanted to be able to merge an audio clip into the existing audio track of a video file.
After struggling for an hour or two, I finally came up with the correct incantation of the command
ffmpeg to overlay an audio clip to a video file:
ffmpeg \ -i movie.mkv \ -i new-audio-clip.mp3 \ -filter_complex "[1:0] adelay=2728000|2728000 [delayed];[0:1][delayed] amix=inputs=2" \ -map 0:0 \ -c:a aac -strict -2 \ -c:v copy \ output.mp4
Line by line:
-i movie.mkv: set the video/audio file as an input
-i new-audio-clip.mp3: set the audio clip as an input
-filter_complex "...": specify the two following filters:
"[1:0] adelay=2728000|2728000 [delayed]: the adelay filter, specifically:
[1:0]: using the second input file's first stream
adelay=2728000|2728000: add a delay of 2,728,000 milliseconds to both channels of the audio (the left and right channels, because the audio is stereo)
[delayed]: assign the name "delayed" to the new stream
[0:1][delayed] amix=inputs=2: the amix filter, specifically:
[0:1][delayed]: using the first input's second stream and the "delayed" stream
amix=inputs=2: mix the two audio streams (NOTE: I'm not 100% on the meaning of
-map 0:0: add the first input's first stream to the output (which is the video)
-c:a aac -strict -2: use AAC for audio encoding
-c:v copy: don't re-encode the video (in other words, copy the original encoding)
output.mp4: specify the output file
ffmpeg() .input('movie.mkv') .input('new-audio-clip.mp3') .complexFilter([ '[1:0] adelay=2728000|2728000 [delayed]', '[0:1][delayed] amix=inputs=2', ]) .outputOption('-map 0:0') .audioCodec('aac') .videoCodec('copy') .save('output.mp4')
After writing all of this, I now realize that I actually need to silence the video's audio track for the duration of the new audio clip. Not merge them.
Back to work.