Repeating images in a ffmpeg -i %04d.png pattern

Viewed 721

I'm making a video of 20 seconds at FPS=25, with 500 frames which are 0000.png, 0001.png, ..., 0499.png. This works:

ffmpeg -framerate 25 -i images/%04d.png out.mp4

but in fact there are only a few changes in the video, in my case at frames 0000, 0122, 0288, 0312, 0450. In the meantime the PNG are identical.

Problem: it's always slow to generate 500 PNG files when only 5 different files would be enough! I would like to generate only those 5 PNG files, and generate the video from them.

When I try the command above with images/ containing only 0000.png, 0122.png, 0288.png, 0312.png, 0450.png and not the 495 others, obviously it fails with:

[image2 @ 00000000006d4040] Could not open file : images/0001.png

Question: is there a way to tell ffmpeg to ignore missing frames and use the latest available frame instead of failing, when using -i images/%04d.png?

If not, what alternative is there to generate the video with only these 5 PNG that should arrive at a precise timeframe?

2 Answers

Method 1: concat filter

Declare duration with -t input options and then concatenate with the concat filter.

ffmpeg -loop 1 -framerate 25 -t 4.88 -i 0000.png -loop 1 -framerate 25 -t 6.64 -i 0122.png -loop 1 -framerate 25 -t 0.96 -i 0288.png -loop 1 -framerate 25 -t 00:00:05.52 -i 0312.png -filter_complex "[0][1][2][3]concat=n=4:v=1:a=0,format=yuv420p" output.mp4

Method 2: concat demuxer

Declare duration with duration directive in the concat demuxer input file list, and then concatenate with the concat demuxer.

This may be the fastest method.

  1. Make input.txt containing the following:

    file 0000.png
    duration 4.88
    file 0122.png
    duration 6.64
    file 0288.png
    duration 0.96
    file 0312.png
    duration 5.52
    
  2. Concatenate:

    ffmpeg -f concat -i input.txt -vf format=yuv420p output.mp4
    

Method 3: trim filter

This method lets you declare the duration either in frames (and/or by using a time value if you prefer).

Example using frames for duration with the trim filter and concatenate with the concat filter:

ffmpeg -loop 1 -framerate 25 -i 0000.png -loop 1 -framerate 25 -i 0122.png -loop 1 -framerate 25 -i 0288.png -loop 1 -framerate 25 -i 0312.png -filter_complex "[0]trim=start_frame=0:end_frame=121,setpts=PTS-STARTPTS[v0];[1]trim=start_frame=122:end_frame=287,setpts=PTS-STARTPTS[v1];[2]trim=start_frame=288:end_frame=311,setpts=PTS-STARTPTS[v2];[3]trim=start_frame=312:end_frame=449,setpts=PTS-STARTPTS[v3];[v0][v1][v2][v3]concat=n=4:v=1:a=0,format=yuv420p" output.mp4

Hello I tried the loops method yesterday and I found that it may takes even longer time for encoding the video then the image sequence if you have a dated cpu. (also I broke my laptop for good). I think it's because even with 5 images ffmpeg has always to read 500 frames to encode the video. Since the concern is the encoding efficency, read this encoding guide https://trac.ffmpeg.org/wiki/Encode/H.264 and get back to your code. The -framerate is 25 by default and you don't need to declare it

ffmpeg -y -f image2 -pattern_type sequence -i images/%04d.png -c:v h264 -crf 51 -preset 'ultrafast' out.mp4

the declaring of " -f image2 -pattern_type sequence" theoretically should spare the time of probing the file.

-crf and presets are the encoding bread and butter and that code should give you the fastest encoding times at the cost of low quality, try that and gradually decrease values untill you reach an acceptable quality.

Last but not least the thing that is slowing down the encoding is the format you are using: the PNG use a huge colorspace of 256x256x256 colors, they can be uncompressed (1file=30mb). if you don't need the alpha channel, try with jpegs and things will go much faster.

Related