13

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?

Milan Milosevic
  • 413
  • 2
  • 8
  • 19

1 Answers1

24

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.

llogan
  • 121,796
  • 28
  • 232
  • 243
  • Hmm cant get crop value in $cropvalue ... im run in php this code, but when im run in comand line im get value – Milan Milosevic Jun 28 '13 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")' – Milan Milosevic Jun 29 '13 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 Jul 07 '14 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('...');`. – Michael Armbruster Apr 05 '15 at 22:02
  • @MichaelArmbruster If you mention his name like this then he will be notified of your comment (if he ever logs in again). – llogan Apr 06 '15 at 03:10
  • @LordNeckbeard Thanks, that's a great function I did not know of before :) – Michael Armbruster Apr 12 '15 at 20:19
  • What does `-vframes 1` do here? Is it used only because the input/output is a JPEG? – Hashim Aziz Apr 05 '21 at 18:51
  • 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 Apr 05 '21 at 18:58
  • Brilliant, that's what I suspected. Just to note that the included `cropdetect` filter failed for me because the first second or so of my test video was black with a small logo in the corner and that's all that was cropped. Kevin's solution printed nothing at all. I got yours to work in the end by running the filter after skipping the first few seconds: `ffmpeg -ss 5 -i "Awwal Ma Dakhalna.mp4" -t 1 -vf cropdetect -f null - 2>&1 | awk '/crop/ { print $NF }' | tail -1`. – Hashim Aziz Apr 05 '21 at 19:11
  • Save yourself a bash fork and get `awk` to only print the last matching field. `awk '/crop=/ {a=$NF} END{print a}'` – Cliff Jul 06 '23 at 22:48