Question

I'm wondering how to use FFMpeg to grap the middle frame of a video. I've already written the C# to grab a frame at a certain time (ie pull one frame at second 3). But I've yet to figure out how to find the middle of video using the FFMpeg commands.

Was it helpful?

Solution

This could be simplified, but here's some old PHP code I had lying around that should do the trick. (Add the location to ffmpeg if it's not in your path)

$output = shell_exec("ffmpeg -i {$path}");
preg_match('/Duration: ([0-9]{2}):([0-9]{2}):([^ ,])+/', $output, $matches);
$time = str_replace("Duration: ", "", $matches[0]);
$time_breakdown = explode(":", $time);
$total_seconds = round(($time_breakdown[0]*60*60) + ($time_breakdown[1]*60) + $time_breakdown[2]);
shell_exec("ffmpeg -y  -i {$path} -f mjpeg -vframes 1 -ss " . ($total_seconds / 2) . " -s {$w}x{$h} {$output_filename}");   

OTHER TIPS

FFmpeg helps you get the framerate and the length of the video, so you can multiply one by the other and divide by 2 to get the number of the middle frame.

ie for a 30 seconds video running at 15 frames per second : 30 * 15 = 450 / 2 = 225, meaning you need to grab the 225th frame.

With simple shell scripting you can use ffprobe to get a machine readable duration output, bc to calculate the half point, and ffmpeg to make the frame:

input=input.mp4; ffmpeg -ss "$(bc -l <<< "$(ffprobe -loglevel error -of csv=p=0 -show_entries format=duration "$input")*0.5")" -i "$input" -frames:v 1 half.png

This eliminates any need for PHP, echo, awk, tr, grep, sed, etc.

This bash command works like a charm (tested):

avconv -i 'in.mpg' -vcodec mjpeg -vframes 1 -an -f rawvideo -s 420x300 -ss avconv -i in.mpg 2>&1 | grep Duration | awk '{print $2}' | tr -d , | awk -F ':' '{print ($3+$2*60+$1*3600)/2}' out.jpg
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top