1

I've got lots of images stored on a server, and a reference in a MySQL database so that i can easily query it for image from specific dates/time.

Images is taken with an interval of 7 images/hour.

Lets say i want to create a timelapse from the last 4 days, and make a 5 sec movie. How can i calculate how to evenly drop frames to get to that desired length of 5 seconds?

This is what i got so far.

Total images: 4 Days * 24 hours * 7 images/hour = 672 images Required images at 24 fps: 24 * 5 = 120 images

Divide the total images with the required images to find out which/every frame i need to keep

672 / 120 = 5.6

Then i loop trough all 672 images, and every 5th or 6th time i store a reference to the image in an array.

Here is my problem. If i round up i get a video thats longer than i want, and if i round down i get a video thats shorter.

If i keep every 5th image when looping: 134 images / 24 fps = 5.6 sec video If i keep every 6th image when looping: 112 images / 24 fps = 4.6 sec video

Is it possible to get it better, and still skip images evenly?

Solved this using xxfelixxx's answer in PHP Heres the code in PHP:

$start  = 1;
$stop   = 672; // Total Images

$dur    = 5;   // Video Duration
$n      = 24 * $dur; // Required frames - 24 FPS * Duration
$next   = $start;
$step = ( $stop - $start ) / $n;

$frames = array();

for ($i = 1; $i <= $n; $i++) {
    $frames[] = round($next);
    $next += $step;
};

var_dump($frames);
Espen Birk
  • 436
  • 1
  • 5
  • 16

2 Answers2

2

You shouldn't need to perform any calculations.

Basic command template should be

ffmpeg -framerate 672/5 -i img%d.png -r 24 output.mp4

FFmpeg will take care of frame selection and timing. I've skipped encoding parameters like bitrate..etc

Gyan
  • 85,394
  • 9
  • 169
  • 201
  • Thanks, I did not know about that feature in ffmpeg. Right now its not helping me, as I need to know which frames to use before rendering the video. The frames are not stored on the same server as the running script, so before rendering the timelapse i download the required images from another server. Will be moving all images over to the same server that's running the scripts in the future, then this will be just what i need. – Espen Birk Jun 12 '16 at 14:45
1

You could try linear-interpolation to get exactly 120 frames. Interpolation will get you fractional frame numbers, so you just need to round to the nearest integer.

For 120 frames in the range of 1 - 672, here are the indexes:

perl -e '
    my $start = 1;
    my $stop  = 672;
    my $n     = 120;

    my $step = ( $stop - $start ) / $n;
    my $next = $start;
    my @frames;
    for ( 1 .. $n ) {
        push @frames, int($next+0.5); # int truncates, so add 1/2 to round correctly
        $next += $step;
    };
    print join(",", @frames) . "\n"
' 

1,7,12,18,23,29,35,40,46,51,57,63,68,74,79,85,90,96,102,107,113,118,124,130,135,141,146,152,158,163,169,174,180,186,191,197,202,208,213,219,225,230,236,241,247,253,258,264,269,275,281,286,292,297,303,309,314,320,325,331,336,342,348,353,359,364,370,376,381,387,392,398,404,409,415,420,426,432,437,443,448,454,460,465,471,476,482,487,493,499,504,510,515,521,527,532,538,543,549,555,560,566,571,577,583,588,594,599,605,610,616,622,627,633,638,644,650,655,661,666
xxfelixxx
  • 6,512
  • 3
  • 31
  • 38