26

I'm adding audio to a video file using ffmpeg like so

ffmpeg -i videofile.mp4 -i audiofile.wav output.mp4

However this extends the output video file to be the length of the audio file if it is longer than the video. Using -shortest cuts the video file short if the audio file is shorter than the video. So is there a flag to tell ffmpeg to cut the keep the length of the output video to the length of the input video?

1
  • 1
    Please select a correct answer. The only real correct one is the one by @Zurechtweiser. May 31, 2019 at 2:46

4 Answers 4

21
  • If video length is shorter than audio length, -shortest is what you want.
  • If video length is longer than audio length, no flag at all will be what you want.

There is no flag to automate this decision.

EDIT

Inspired by @deadcode's answer, I need to make clear, that "no flag to automate" is of course not true, if you are willing to reencode: In this case go with apad as suggested by @deadcode.

If however you want to avoid reencoding (i.e. -c:v copy) the answer stands.

There is a workaround using the ffconcat demuxer, but it needs a bit of work:

  • create a file containing silence in exactly the same format as your audiofile ("silence.wav")
  • create a concat file "audio.ffconcat" (with as many silence lines as you need to make sure your audio is long enough):

.

file 'audiofile.wav'
file 'silence.wav'
file 'silence.wav'
...
file 'silence.wav'
  • run ffmpeg -i videofile.mp4 -f concat -i audio.ffconcat -c:v copy output.mp4

This will synthesize the apad filter without a filter graph, thus allowing a mux without reencoding.

2
  • @RoelVandePaar As I said: If video length is shorter than audio length use -shortest, else use this workaround if you want to add silence without reencoding. May 31, 2019 at 8:31
  • Correct, missed that on review. Removed input. Feel free to do the same. May 31, 2019 at 8:39
14

I believe you can achieve your desired aim by using the -filter_complex option and the apad filter option to pad out your audio with silence at the end if the video is longer. Your command would be:

ffmpeg -i videofile.mp4 -i audiofile.wav -filter_complex " [1:0] apad " -shortest output.mp4

This assumes the audio you want is in the first stream of audiofile.wav, the [A:B] syntax says to take the B'th stream from the A'th input (both starting with 0, so [1:0] is the 1st stream from the 2nd input, or audiofile.wav above).

Details at: https://www.ffmpeg.org/ffmpeg-filters.html#Examples-68

5
  • You should mention, that the -filter_complex option forces reencoding - it is e.g. possible to run ffmpeg -i videofile.mp4 -i audiofile.wav -c:v copy output.mp4 but not ffmpeg -i videofile.mp4 -i audiofile.wav -filter_complex " [1:0] apad " -c:v copy -shortest output.mp4 Jun 20, 2018 at 11:31
  • This is the opposite answer of what is requested. OP asks to end video when audio ends, the answer given is to add audio silence if the audio is shorter then the video. This answer is incorrect. May 31, 2019 at 2:43
  • 1
    It's not "the opposite" of what the OP requested. The OPs wants the output video to be the length of the input video, regardless of the length of the audio track. My answer addresses the circumstance where the input video is longer than audio file. The OP already has a solution for when the input video is shorter than the audio file, which is to use -shortest.
    – deadcode
    May 31, 2019 at 6:10
  • I am attempting to use apad with -map 0:v:0 -map 1:a:0, which is intended to replace the audio of a video with a second audio input. However, using apad, causes the stream order to be reversed: index 0 is audio and index 1 is video. Do you have any clue why? This is a problem because it causes lossless concatenation to fail.
    – bryc
    Jul 29, 2023 at 2:42
  • Figured it out. I had to change -map 0:0 -filter_complex "[1:0] apad" -map 1:0 -shortest -> -map 0:0 -filter_complex "[1:0] apad [a]" -map "[a]" -shortest. You have to sorta redirect apad's output and then map that output after the video. Otherwise the audio track always goes before the video track.
    – bryc
    Jul 29, 2023 at 3:09
10

If you know the length of your video-file, you can accomplish that by using

ffmpeg -i videofile.mp4 -i audiofile.wav -t 43 output.mp4

Where 43 is the length of your video-file in seconds.

3
  • the author question wants to loop the audio file while the video hasn't finished. Does this work for that? Apr 19, 2017 at 18:34
  • @RafaelSanches No, he doesn't. Apr 29, 2017 at 22:42
  • The author doesn't want to loop the audio. This answer is also the only correct one which does what the OP was asking; end the video when the input video ends. May 31, 2019 at 2:46
1

FYI, now, the default behavior of current/latest ffmpeg via CMD:

c:\sbin\ffmpeg.exe -i "D:\video.m4s" -i "\audio.m4s" -c:v copy -c:a copy "D:\combined.mp4" 

is padding the shorter one.

  • If (audio.length < video.length), then it pads the audio with silence, so that audio.length === video.length
  • If (audio.length > video.length), then it pads the video with the last frame of this video, so that audio.length === video.length

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .