FFmpeg is a free and open-source video editing tool capable of trimming, cropping, concatenating, muxing, and transcoding almost any type of media file you throw at it.
It's also a very robust solution for implementing video automation, as we use it extensively in our own video editing API. For this tutorial we'll use FFmpeg 5.1.2, but any recent version will do.
Use the crop filter to crop a video to a certain width and height:
$ ffmpeg -i input.mp4 -vf crop=w=640:h=480 output.mp4
The -vf crop=w=640:h=480 argument tells FFmpeg to crop the video to a resolution of 640 by 480. So if your input video is 1920 by 1080, you would get a crop like this:
The default behaviour is to crop from the center. You can crop from a different location by specifying x and y coordinates. Here are a few examples.
Set the crop position at x=0 and y=0 to crop from the top-left corner:
$ ffmpeg -i input.mp4 -vf crop=w=640:h=480:x=0:y=0 output.mp4
Using the in_w and in_h variables, we can set the crop position based on the width and height of the input video:
$ ffmpeg -i input.mp4 -vf crop=w=640:h=480:x=in_w-640:y=in_h-480 output.mp4
$ ffmpeg -i input.mp4 -vf crop=w=640:h=480:x=in_w-640:y=0 output.mp4
$ ffmpeg -i input.mp4 -vf crop=w=640:h=480:x=0:y=in_h-480 output.mp4
You can also use the crop filter to remove black borders from a video. The following example shows how to remove black borders at the top and bottom of a video:
$ ffmpeg -i input.mp4 -vf crop=w=1920:h=720:x=0:y=(in_h-720)/2 output.mp4
FFmpeg can also detect black borders in a video automatically. You can do this with cropdetect:
$ ffmpeg -i video.mp4 -vf cropdetect -f null -
By running the above command, FFmpeg scans every frame and returns the best cropping settings. You can then choose a setting that seems reasonable to you.
1$ ffmpeg -i video.mp4 -vf cropdetect -f null -
2
3...
4[Parsed_cropdetect_0 @ 000001da54591840] x1:320 x2:1599 y1:180 y2:899 w:1280 h:720 x:320 y:180 pts:174592 t:14.208333 crop=1280:720:320:180
5[Parsed_cropdetect_0 @ 000001da54591840] x1:320 x2:1599 y1:180 y2:899 w:1280 h:720 x:320 y:180 pts:175104 t:14.250000 crop=1280:720:320:180
6[Parsed_cropdetect_0 @ 000001da54591840] x1:320 x2:1599 y1:180 y2:899 w:1280 h:720 x:320 y:180 pts:175616 t:14.291667 crop=1280:720:320:180
7[Parsed_cropdetect_0 @ 000001da54591840] x1:320 x2:1599 y1:180 y2:899 w:1280 h:720 x:320 y:180 pts:176128 t:14.333333 crop=1280:720:320:180
8[Parsed_cropdetect_0 @ 000001da54591840] x1:320 x2:1599 y1:180 y2:899 w:1280 h:720 x:320 y:180 pts:176640 t:14.375000 crop=1280:720:320:180
9[Parsed_cropdetect_0 @ 000001da54591840] x1:320 x2:1599 y1:180 y2:899 w:1280 h:720 x:320 y:180 pts:177152 t:14.416667 crop=1280:720:320:180
10frame= 347 fps=0.0 q=-0.0 Lsize=N/A time=00:00:16.04 bitrate=N/A speed=21.9x
11video:160kB audio:2764kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
12
In this example, FFmpeg found the best crop to be crop=1280:720:320:180 (see highlighted line above). We can then run the crop command to perform the actual cropping:
$ ffmpeg -i input.mp4 -vf crop=1280:720:320:180 output.mp4