ffmpeg autocrop bash script function

This ffmpeg auto crop function is derived from this mplayer based script from the mplayer mailing lists in 2005 http://lists.mplayerhq.hu/pipermail/mplayer-users/2005-November/056636.html

My one differs a little.  It runs cropdetect with a 2x rounding because I only encode with  x264 which doesn’t require the ‘divisible by 16’ dimensions of older encoders (in theory there is an efficiency penalty with x264 like with the old divx/xvid encoders, but in practice the penalty is so tiny as to be effectively non-existent) and it always crops an extra 2 pixels from each side because it’s so usual for DVDs/vobs/rips to have a picture which has line of slightly different luminosity at one or more borders that the human eye sees easily but isn’t detected at all by cropdetect algorithms (and yes I’m the kind of person who runs mplayer with -noborder for manual crop detection so my eye is not tricked by edge effects).


It works as a stand alone script or you can just drop it as a function in to your own script and use the crop value it produces (usual mplayer/mencoder/ffmpeg  w:h:x:y syntax).




11 Responses to “ffmpeg autocrop bash script function”

  1. Jeff Says:

    That’s great, just what I was trying to do myself for auto cropping TV captures and not having much luck.
    I have been playing around with it and testing it out on my Mythtv captured files. Many files do not return any cropdetect information.
    and the script just returns -4:-4:2:2

    These I will have to trap as errors, or get my script process them without cropping unless I can figure out how to fix the files to somehow return cropdetect information.

    Some return information intermittently only on some loops and the script still returns -4:-4:2:2

    adding a test for blank crop results seems to fix these though:-

    while [ “$D” -lt “$TOTAL_LOOPS” ] ; do
    D=”$(( $D + 1 ))”
    if [ -n “${CROP[$D]}” ] ; then
    if [ “${COUNT_CROP[$D]}” -gt “$HIGHEST_COUNT” ] ; then

    No deities were invoked in amending this script 😉

  2. takla Says:

    Thanks Jeff. I found that most failures are due to interval between cropdetect in secs x passes exceeding video duration, so another approach is to change the number of seconds skipped according to the video duration. For example instead of
    SKIP_SECS=”$(( 120 * $A ))”
    SKIP_SECS=”$(( $SECS * $A ))”

    and determine the variable $SECS with ffmpeg/ffprobe and grep. I use a 15 second interval for videos less than 30 mins and 180 secs for everything else. It works OK but I think there will always be movies with lengthy dark scenes that defeat any autocrop.

    To illustrate here’s an extract from a bigger script that uses my cropdetect as a function:


  3. Jeff Says:

    Thanks, that might be useful.
    I’m not sure that that is the problem though. Most of my TV captures are at least 30 min shows and I was testing it out on captured movies mostly to autocrop SD letterboxed movies to 2.39:1. Some of my TV captures just don’t seem to seek properly. I am now trying to use a select filter rather than -ss to seek to the required selections as that seems to work on the problematic videos.

    -t 111… -vf select=’gte(t\,110)*lte(t\,111)’,cropdetect=30:2

    gets results where

    -ss 110 … -vframes 10… -vf cropdetect=30:2

    gets no results on the same problematic videos

    but using something like
    SKIP_SECS=”$(( 300 + ($A * 60 )))”
    SKIP_SEC_TO=”$((SKIP_SECS + 1))”

    vf select=’gte(t\,${SKIP_SECS})*lte(t\,${SKIP_SECS_TO}))’,cropdetect=30:2

    just does not work.

    I’m working on it though even:-
    ffmpeg -t ${SKIP_SEC_TO} -i “$@” -an -sn -vf select${SELECT1}${SKIP_SECS}${SELECT2}${SKIP_SEC_TO}${SELECT3},cropdetect${CROPDETECT}…
    does not seem to work either.

    Maybe I’m just going about it in the wrong way.
    I never was much of a coder, though “good coders write good code but great coders steal great code” was always my mantra, so thanks for the great code 🙂

  4. takla Says:

    If the problem is with seeking then I’d mux the video into a different container and try again. Matroska .mkv seems to be the most compatible and least demanding for playback. If there is still a problem seeking the video in mkv then probably the original encoding settings need to be examined.

  5. Jan Says:

    I encountered the same problem as Jeff: most of my mythtv recording would return -4:-4:2:2. After experimenting a bit I found the cause to be -vframes being to short for ffmpeg to even do the crop detection in most cases. Raising it to 20 fixed the problem for me on all material that was problemtaic before. Also I added an “INITIAL_SKIP” Parameter, because usually my recordings start 3 minutes early, so there might be aspect ratio changes etc. Here is the diff for what works for me now:

    — /var/lib/mythtv/crop_detect.sh.orig 2012-12-18 11:34:29.000000000 +0100
    +++ /var/lib/mythtv/crop_detect.sh 2012-12-18 11:33:39.000000000 +0100
    @@ -3,14 +3,15 @@
    – TOTAL_LOOPS=”10″
    + TOTAL_LOOPS=”20″
    + INITIAL_SKIP=300 # Skip the first 300 seconds

    while [ “$A” -lt “$TOTAL_LOOPS” ] ; do
    A=”$(( $A + 1 ))”
    – SKIP_SECS=”$(( 120 * $A ))”
    + SKIP_SECS=”$(( $INITIAL_SKIP + 20 * $A ))”

    – ffmpeg -ss $SKIP_SECS -i “$@” -vframes 10 -an -sn -vf \
    + ffmpeg -ss $SKIP_SECS -i “$@” -vframes 20 -an -sn -vf \
    cropdetect=30:2 -y /tmp/crop.mp4 2>$FFOUT
    CROP[$A]=$(grep -m 1 crop= $FFOUT |awk -F “=” ‘{print $2}’)

    @@ -46,7 +47,7 @@
    CROP=$(echo $CROP|awk -F “:” ‘{print $1-4″:”$2-4″:”$3+2″:”$4+2}’)
    echo $CROP
    – rm $FFOUT
    +# rm $FFOUT
    cropdetect “$@”
    exit 0

  6. takla Says:

    Thanks for the input Jan.

    Adding a 300 secs delay is not something I think is generally useful as it is specific to particular circumstances and usage, and it can even introduce a problem running cropdetect on short video clips. It also introduces unexpected behaviour which could prove confusing. Example:

    Some films have different letter/pillar boxing at different places. Sometimes this is a creative effect (such as the film of the Woostock concert) and other times it is because the film is composed of multiple sources of different proportions; this is quite common in documentary films. In these cases one often wants to run cropdtect on specific portion(s) and having to remember a 5 minute shift is not ideal; if one forgets there is a 5 minute shift it could be incredibly confusing.

    I can’t reproduce a bad result using 10 vframes vs. 20 vframes. I get the same intermediate and final crop values but running it with set -x I do see some unexpected behaviour (awk sometimes apparently running before grep instead of afterwards). The original mplayer crop script this one is based on did use 20 vframes and I can no longer remember why I changed it to 10….. I think it’s a good idea to revert to 20 and wait and see if it bites me so I remember the reason for the change (if there was one). I’ve made the vframes change on pastebin.

    Thanks again for your input.

  7. Eric Kirchner Says:

    Thank you for the script, was a great addition to my manipulation tools.

  8. Eric Kirchner Says:

    I realize this post is a bit old, and I am going to make it worse, because I am too lazy to update this to github right now, that’s a task on it’s own for me right now.


    (I am not sure how long Fedora will keep the above link active.)

    I made several changes to the script to help speed things up, and in my mind, increase effectiveness.

    1. Removed the need to write the temporary FFmpeg file
    2. Calculate the sample interval based on file length and number of samples Variable
    3. Added a Variable for number of Frames to check
    4. Reduced the For Loops on Analysis
    5. Colorized the Outputs (more color options included than used)
    6. Added Revision Display Function (my own use in functions)
    7. Added option to select crop detect (potentially obsolete with above improvements)
    8. Added ffmpeg encode function
    9. Added dependency check for required bash commands (ffmpeg, bc, etc) (no all required, cut and paste from my other bash scripts)
    10. Added “No Crop Detected” texts for something I can’t explain yet
    11. Renamed Variable to work for me (sorry)
    12. Multiple other changes, but I have since forgotten what the original script did and did not do


    1. Identify what #10 above is an issue
    2. Confirm Batch ability works, thought likely not required or this application

    Thank you for the Starting Point. I have github library, but I am still struggling to use it correctly.

    I have a script that works pretty well, to identify Commercials in videos, then after manually removing the auto created clips you don’t want, you can recompile the video with a basic ffmpeg concatenate command (again another script I have), if anyone is interested.

    I am not posting the other scripts here, as I need to get them all on my GitHub site. At the time of this post, this is only beta, and very outdated.


    The scripts I have, and willing to share, by name only are:


    • takla Says:

      Thanks Eric, it looks great. I’ll try it out soon. If you’re worried it might disappear from fedora’s page maybe put it up on pastebin for now until you get around to your github stuff.

      Anyway I have a raw copy, will try it out and will be happy to put it up on my pastebin. I will update this thread and post a link on doing so.

      Thanks again.

    • takla Says:

      Hi Eric.

      In the end I didn’t incorporate your changes. Some of them go beyond what this bash function is really for and some run into the same problems already discussed above with Jeff.

      First point first: this is really intended to be a function that people can incorporate into their own transcoding/encoding scripts. People encode/transcode with all kinds of different use cases in mind i.e. specific hardware, specific file sizes, specific codecs, different expectations of quality etc. So my splendid and useful video encoding script is almost certainly going to be very different to your splendid and useful video encoding script and different again to someone else’s. In the case of this function I just aimed to share a good solution to getting and applying a sane crop value automatically (usually). The “usually” leads to the second point:

      Manual intervention is occasionally inevitable. There are movies/clips out there which comprise video in different sizes and aspect ratios within the same file. There are videos with vast areas of unchanging dark or black space. There are numerous transfers from videotape where the w:h:x:y co-ordinates drift even while the movie plays 🙂 There have been, are, and will be movies that contain video in differing formats within the same disc/file. There is no magic bullet to deal with this. Experience shows that today’s neat tweak fails on tomorrow’s unexpected encounter. For example, I tried your changes on my Blu-Ray of “The Assassin”, a BAFTA nominated 2015 movie http://www.imdb.com/title/tt3508840/?ref_=fn_al_tt_1 Result? Enigmatic Confucian movie confounds modern western barbarian crop script! Sorry for the bad joke.

      Anyway, I’ll continue to welcome changes and plan to make some of my own, but I think the important part – the crop detection – is essentially done until someone introduces AI.

  9. Eric Kirchner Says:


    I have since made more enhancements, and it works well for me, thanks for the starting point. Just wanted to try to add some input and give back, to the Internet, where I have taken so much, LOL

    One script I do have now that is working really well, about 90/95% accuracy, is identifying ads in movies recorded off OTA TV. I still have to confirm the clips to keep or remove, but it goes really fast, leaving a really clean movie considering the original source. But that’s another topic.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: