fstephany
fstephany

Reputation: 2354

Merge video and audio with ffmpeg. Loop the video while audio is not over

I'm trying to merge an audio file with a video file.

I have two options:

I'm using the latter with the -t <duration in second> option of ffmpeg. It means I have to get the duration of the audio file to feed it into ffmpeg. Is it possible to avoid this step?

Any pointer for the first solution?

Upvotes: 35

Views: 26906

Answers (4)

hcf1425
hcf1425

Reputation: 719

If you want to merge new Audio with video repeat video until the audio finishes, you can try this:

ffmpeg  -stream_loop -1 -i input.mp4 -i input.mp3 -shortest -map 0:v:0 -map 1:a:0 -y out.mp4

Using -stream_loop -1 means infinite loop input.mp4, -shortest means finish encoding when the shortest input stream ends. Here the shortest input stream will be the input.mp3.

And if you want to merge new Audio with video repeat audio until the video finishes, you can try this:

ffmpeg  -i input.mp4 -stream_loop -1 -i input.mp3 -shortest -map 0:v:0 -map 1:a:0 -y out.mp4

use -y option will overwrite output files without asking.

Upvotes: 49

Chamath
Chamath

Reputation: 2044

For the first bullet point I don't see a direct command. What I'm suggesting is to use ffprobe to calculate the duration of both files and calculate the number of video loops that need to play for the duration of audio.

Following will result the duration of the inputs.

ffprobe -i input_media -show_entries format=duration -v quiet -of csv="p=0"

Then you can loop the video manually until you satisfy the calculated value of video instances.

ffmpeg -i input_audio -f concat -i <(for i in {1..n}; do printf "file '%s'\n" input_video; done) -c:v copy -c:a copy -shortest output_video

1..n stands for the number of times the video need to be looped. Instead of -shortest you can use -t as you have already calculated the duration of the audio.

Following is the associated shell script.

#!/bin/bash
audio_duration=$(ffprobe -i ${1} -show_entries format=duration -v quiet -of csv="p=0")
video_duration=$(ffprobe -i ${2} -show_entries format=duration -v quiet -of csv="p=0")
n_loops=$(echo "(${audio_duration} / ${video_duration}) + 1"|bc)
ffmpeg -i ${1} -f concat -i <(for i in {1..${n_loops}}; do printf "file '%s'\n" ${2}; done) -c:v copy -c:a copy -shortest ${3}

For windows you can convert this shell script to a batch script.

More information:

Hope this helps!

Upvotes: 1

inha leex hale
inha leex hale

Reputation: 13

for the first one, try ffmpeg -i yourmovie.mp4 -loop 10 to loop the input 10 times

Upvotes: -2

fstephany
fstephany

Reputation: 2354

The second bullet point was easily solved by using the -shortest option of ffmpeg. See: http://www.ffmpeg.org/ffmpeg-doc.html#SEC12 for more details.

Upvotes: 1

Related Questions