Generating random thumbnails using PHP + FFMPEG

I am trying to create thumbnails from random points in a movie using the FFMPEG and FFMPEG-PHP extensions.

My script is working fine .. however it takes 20 minutes to generate 5-10 thumbnails!

The script works by generating random numbers, which are later used as frame numbers. All generated numbers are within the number of frames in films.

Can you decide why this script takes 20 minutes to complete? If not, the best solution?

<?php //Dont' timeout set_time_limit(0); //Load the file (This can be any file - still takes ages) $mov = new ffmpeg_movie('1486460.mp4'); //Get the total frames within the movie $total_frames = $mov->getFrameCount(); //Loop 5-10 times to generate random frames 5-10 times for ($i = 1; $i <= 5; ) { // Generate a number within 200 and the total number of frames. $frame = mt_rand(200,$total_frames); $getframe = $mov->getFrame($frame); // Check if the frame exists within the movie // If it does, place the frame number inside an array and break the current loop if($getframe){ $frames[$frame] = $getframe ; $i++; } } //For each frame found generate a thumbnail foreach ($frames as $key => $getframe) { $gd_image = $getframe->toGDImage(); imagejpeg($gd_image, "images/shot_".$key.'.jpeg'); imagedestroy($gd_image); echo $key.'<br/>'; } ?> 

script SHOULD generate frame numbers that are valid? Anything within START-END should be the actual number of frames? But the cycle takes a lot of time!

+6
php ffmpeg
source share
4 answers

You can call ffmpeg from the command line, using the -ss switch to search for a suitable starting point (in time, not in the number of frames) and -vframes 1 to tell it to extract exactly one frame, for example:

 ffmpeg -i 1486460.mp4 -ss 10 -vframes 1 images/shot_10.jpg 

Extract a frame from 10 seconds and call it images/shot_10.jpg

+4
source share

The problem here is the word random . I successfully got the duration of the video, and then try to get one frame with such a random duration. Easy to modify for more frames:

  $cmd = "ffmpeg -i {$src} 2>&1 |grep Duration"; $output = array (); exec($cmd, $output); if(count($output)) { $duration = explode(':', trim(str_replace('Duration:', NULL, current(explode(',', current($output)))))); list($hour, $min, $sec) = $duration; $sec = sprintf("%02d:%02d:%02d", rand(0, $hour), rand(0, $min), rand(0, $sec)); } else { $sec = "00:00:12"; //12sec it ok :) } $cmd = "ffmpeg -ss {$sec} -i {$src} -s {$w}x{$h} -f image2 -vframes 1 {$destination}"; $output = array (); exec($cmd, $output); 
+1
source share

I don’t know much about movie formats, but since the compression probably depends on the delta compression of one pass with the reference frames, if the position of the reference frames is not defined, this means that the system must play the full film to get to a specific offset. It would be easy to verify this, always loading, say, a frame search between offset 20 and the number of frames divided by some value.

Assuming this is the case, you have another problem in how you developed your algorithm, you need to fast-forward and search forward for each of the 5 frames - if you created your offsets in advance, then a sorted list, ffmpeg can get frames in one run.

NTN

FROM.

0
source share

You wrote an error in your loop.

 if($getframe) { $frames[$frame] = $getframe; $i++; } 

Suppose a for loop runs endlessly until it breaks. If the if statement is false for the first time, so $i++ cannot be reached, and the loop is then infinite.

You need to put $i++ at the end of the for loop, then the execution will be 2 seconds instead of 20 minutes.

-5
source share

All Articles