19

Let's say I have an mp3 file of 1 minute length. And I have 20 png images. I want to combine these images and an audio into a video file, but I do not want each image to last 3 seconds on screen, I want some images to last 5 seconds, others 1 second etc.

The only way I can think of is just copy the images that should last more time, e.g. to have image1, image2, image3 to be exactly the same, this gives me 3x more time in video.

However this is very time and space consuming. Is there any switch / parameter in ffmpeg that allows me to do that?

  • As you found out ffmpeg should display each image for the same length. If you want to vary the length you will have to duplicate the images beforehand or create separate videos of each desired duration and then concatenate them. Maybe some other users have better ideas, but this type of task might be easier with an editor such as Kdenlive, etc. – llogan Jul 9 '13 at 17:22
  • I am doing it from php script, so editor is not what I am looking for. – Flot2011 Jul 10 '13 at 0:53
25

Using ffmpeg 2.0 there are a couple of ways to do this:

  1. One method is to use file modification times. First set the modification time of the image files so that each image file has a modification time greater than the one before it; the time difference is the duration of the previous image (with 1 second resolution). Then use the image2 demuxer option -ts_from_file 1. For example:

    touch -t 01010000.00 image01.png
    touch -t 01010000.03 image02.png
    touch -t 01010000.08 image03.png
    ...
    ffmpeg -ts_from_file 1 -i image%2d.png -i audio.mp3 -c:a copy -vf fps=25 out.avi
    
  2. Another method is to use the concat demuxer, which takes a list of files to concatenate, with optional durations. First create a file listing your images and durations that looks like this:

    ffconcat version 1.0
    file image01.png
    duration 3
    file image02.png
    duration 5
    file image03.png
    

    Then provide this file as input to ffmpeg. For example:

    ffmpeg -i in.ffconcat -i audio.mp3 -c:a copy -vf fps=25 out.avi
    

You may need to duplicate the last file after the final duration. -c:a copy copies the mp3 audio as-is; if you want to convert it to another audio codec then you can specify that instead of copy. You may also want to specify a different video codec with -c:v or a different pixel format with -pix_fmt, such as -c:v libx264 -pix_fmt yuv420p. -vf fps=25 will make the output frame rate 25 fps. If your audio is longer and you want it cut off after the images, use the -shortest option.

| improve this answer | |
  • Any idea why this just does not seem to work (I mean, I followed the second (and tried to first) option to the letter but it just outputs either a black video with not images or the images just flash for one frame, not several seconds as specified in the ffconcat file. – sup Jul 25 '15 at 11:31
  • @sup: This still works for me. If the video is black then your player may not support the video format you are using; try -c:v libx264 -profile:v baseline -pix_fmt yuv420p out.mp4 instead of out.avi, or try a different player such as mpv or ffplay. Also be sure you are using a current version of FFmpeg, and duplicate the last image file name after the final duration. – mark4o Jul 27 '15 at 22:01
  • Hm, weird, U use mpv and the ffmpeg static build downloaded from ffmpeg.org, and it just ignores the durations. Anyway, I found another way how to do this, so it is not that important: ffmpeg.org/pipermail/ffmpeg-user/2015-July/027702.html – sup Jul 28 '15 at 7:51
1

Assuming ffmpeg -i in.ffconcat -vf fps=25 out.avi

(2018: in.ffconcat file contents) - this works:

ffconcat version 1.0
file text.png
duration 30.0
file text.png

while this doesn't

ffconcat version 1.0
file text.png
duration 30.0

ie in second case

ffprobe out.avi -show_entries format=duration -v 0

[FORMAT]
duration=0.040000
[/FORMAT]
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.