15

Its possible to run cropdetect and crop in one line and get thumbs from video?

something like this

ffmpeg -ss 1 -i 0.flv -vf cropdetect=24:16:0,crop=w:h:x:y -vcodec mjpeg -vframes 1 -an -f rawvideo -s 240x180 0.jpg

Or maybe need to run in 2 line, first run cropdetect and than run crop and generate thumbs from video, but in this way i need to get value from cropdetect?

1 Answer 1

26

cropdetect outputs to the console, so you can parse the output and then use it as a variable:

ffmpeg -i input -t 1 -vf cropdetect -f null - 2>&1 | awk '/crop/ { print $NF }' | tail -1

This will result in something like:

crop=640:480:0:50

Then run your actual crop command:

ffmpeg -i input -vf $cropvalue,scale=240:-1 -vframes 1 -qscale:v 2 output.jpg
  • -vcodec mjpeg, -an, and -f rawvideo are superfluous

  • Use -qscale:v to control jpg output quality. A sane range is 2-5 (a lower value is a higher quality).

  • Use the scale filter instead of -s; especially if you're already using filters. Also the scale filter will allow you to set a specific width or height and with -1 it will automatically provide the correct value to preserve aspect. Otherwise if you try to force a specific size you can risk a squished or stretched output.

Obviously I'm not a PHP coder, but this should give you an idea at least.

11
  • Hmm cant get crop value in $cropvalue ... im run in php this code, but when im run in comand line im get value Commented Jun 28, 2013 at 14:42
  • Im just create function like this function crop($id){ $d = shell_exec("ffmpeg -i $id -t 1 -vframes 1 -ss 50 -vf cropdetect -f null - 2>&1 | awk '/crop/ { return $NF }' | tail -1"); $array = explode('crop=',$d); $cropvalue = $array[1]; $cropvalue = 'crop='.$cropvalue; return $cropvalue; } and than im call in new line 'crop("111.mp4")' Commented Jun 29, 2013 at 23:50
  • 6
    I would be more rigorous in your cropdetect, this seeks 10 minutes into a movie, and analyzes the film for 2 minutes.. sorts the resulting values then uses uniq, so the most 'popular' value is used. ffmpeg -ss 600 -i $filename -f matroska -t 120 -an -vf cropdetect=24:16:0 -y -crf 51 -preset ultrafast /dev/null 2>&1 | grep -o crop=.* | sort -bh | uniq -c | sort -bh | tail -n1 | grep -o crop=.*
    – Kevin
    Commented Jul 7, 2014 at 13:45
  • 1
    I know it's a bit late, but you were using $array = explore('crop=', $d); $cropvalue = $array[1]; on your output. When you explode the output at this value, you would have to use $cropvalue = $array[0]; since arrays start at 0 in PHP. The output of your shell_exec command would be something like crop=1440:1072:240:4 or similar. So, you don't need your explode part and concatenate string. Just use the output of shell_exec, so return shell_exec('...');. Commented Apr 5, 2015 at 22:02
  • 1
    @HashimAziz -vframes 1 limits the output to 1 frame, and in the case of outputting a single image avoids the error: Could not get frame filename number 2 from pattern 'output.jpg' (either set updatefirst or use a pattern like %03d within the filename pattern). It is used because in the original question wanted to output a single JPEG image. If you want to output a video then remove -vframes 1.
    – llogan
    Commented Apr 5, 2021 at 18:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.