FFMPEG image sequence with various durations

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?


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.


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]