How to remove black bars from videos


In the world of web development, sometimes we have to deal with other issues that are not directly related to programming or web design itself. In this case we are going to talk about cropping in FFmpeg and how to use it to remove black bars from videos. Thanks to this we will be able to generate thumbnails of our videos for use in our web projects (such as a Youtube clone).

As an example, let's see the following capture made from a video:

Capture of a video frame showing the black bars

Let's imagine that this capture has been done automatically by a server-side application (FFmpeg can do this too). Next we are going to use FFmpeg to auto-detect and remove the black bars.

Getting the cut-off values automatically

The first step is to use the cropdetect video filter to get the values automatically. The FFmpeg parameter is: -vf "cropdetect=24:16:0".

The cropdetect parameters follow the format cropdetect=limit:round:reset.

This parameter can contain up to three extra options. For our example we are not going to use any of them, but still, a brief explanation:

  • limit: Sets the black color intensity threshold, which can be specified from nothing (0) to all (255). By default it's 24. This will help when removing dark parts that are not black bars. Or vice versa, when it is not detecting the bars because they are not so black.
  • round: Ensures that the output resolution is divisible by the specified value. Default is 16, the best value for most video codecs.
  • reset: Determines after how many frames cropdetect will reset the previously detected largest video area and start counting again to detect the optimal crop area. This is useful when there are logos or animations at the beginning of a video. Default is 0, no reset.

We run the following command and since we are using 2>&1 the result will be printed on the screen.

ffmpeg -i video.mp4 -vf cropdetect -f null - 2>&1
[Parsed_cropdetect_0 @ 000000000268d400] x1:0 x2:719 y1:74 y2:501 w:720 h:416 x:0 y:80 pts:1814400 t:20.160000 crop=720:416:0:80

[Parsed_cropdetect_0 @ 000000000268d400] x1:0 x2:719 y1:74 y2:501 w:720 h:416 x:0 y:80 pts:1814400 t:20.160000 crop=720:416:0:80

As we can see at the end of the result, we already have our crop values.

Using the cutoff values

The next step is to use those values in the following way:

ffmpeg -i video.mp4 -vf "crop=720:416:0:80"

The crop parameters follow the format crop=w:h:x:y. Where W and H refer to the size (width and height), and X and Y refer to the coordinates where the result will start. An X and Y of 20 indicates that 20px to the left and 20px to the top will be ignored.

In this example, horizontally nothing is removed since there are no horizontal black bars. Vertically, the result will remove 80px at the top using the Y parameter. The bottom part is calculated in a different way. Our video is 576px high so after skipping 80px at the top by Y, FFmpeg will give us a H of 416 (576 - 80 - 80). Or in other words, 80px will be removed from both top and bottom.

This result can be used in our server application. For example, if our application is written in PHP we can use something like this:

  • PHP
$cropDetect = shell_exec('ffmpeg -ss 150 -i video.mp4 -vframes 1 -vf cropdetect -f null - 2>&1');
preg_match('/.*crop=([0-9:]+).*/', $cropDetect, $matches);

This would be useful in case we want to do something with the cropdetect data before cutting the black bars, such as cutting further to maintain an aspect ratio.

$parts = explode(':', $matches[1]);

$output = array();
$output['width'] = (int) $parts[0];
$output['height'] = (int) $parts[1];
$output['x'] = (int) $parts[2];
$output['y'] = (int) $parts[3];

exec('ffmpeg -ss 150 -i video.mp4 -vframes 1 -vf "crop='.$matches[1].'" thumbnail.jpg 2>&1');

In order not to receive an immense amount of cropping results, we have used the -vframes 1 parameter, which limits our command to a single frame. Also, since the first frame is very likely to be all black, we will skip the first 150 seconds using the -ss 150 parameter. This values will depend on the type of videos we are going to crop, a 40-second ad is not the same as a 120-minute movie.

The result is as follows:

Capture of a video frame after removing the black bars

If we want consistency in our thumbnails, rather than each having a different aspect, this is the step to take.

Remember that this generates images at the same size as the original video. If we want smaller thumbnails we have to add the resize process to make the images smaller.

You can support me so that I can dedicate even more time to writing articles and have resources to create new projects. Thank you!