0

If I have a .mp4 video file with black boarders on the top, bottom, and/or sides, How can I trim these boarders off with python?

I do not want to replace the boarders with anything, I just want to trim the video.

For example, if I run magically_trim_black_boarders_from_vid(in_vid) on a video that looks like the frame below, the video's height would not change, but its width would be reduced.

enter image description here

Thanks!

perry_the_python
  • 385
  • 5
  • 14

1 Answers1

0

We my use cropdetect filter as described in the following post.

Within Python we may execute FFmpeg as subprocess twice - first time with cropdetect filter for finding the black borders, and second time for cropping the borders.

The output of cropdetect filter is as a lines of text, that should be parsed:

#[Parsed_cropdetect_0 @ 00000232c2705e00] x1:69 x2:551 y1:0 y2:309 w:480 h:304 x:72 y:4 pts:512 t:0.040000 crop=480:304:72:4
#[Parsed_cropdetect_0 @ 00000232c2705e00] x1:69 x2:551 y1:0 y2:309 w:480 h:304 x:72 y:4 pts:1024 t:0.080000 crop=480:304:72:4
...

Suggested stages:

  • Execute FFmpeg as subprocess with cropdetect filter, and storing the (stderr) output in cropdetect_output string:

     cropdetect_output = sp.run(['ffmpeg', '-hide_banner', '-i', in_video_file, '-vf', 'cropdetect=skip=0', '-t', '1', '-f', 'null', 'pipe:'], stderr=sp.PIPE, universal_newlines=True).stderr
    
  • Find the substring, that starts with "crop=" and ends by new line using re.search regular expression searching:

     crop_str = re.search('crop=.*', cropdetect_output).group(0)  # crop=480:304:72:4
    
  • Execute FFmpeg using crop filter with the crop= arguments found above.

     sp.run(['ffmpeg', '-hide_banner', '-i', in_video_file, '-vf', crop_str+',setsar=1', out_video_file])
    

Code sample:

import subprocess as sp
import re

in_video_file = 'wnkaa.mp4'
out_video_file = 'cropped_wnkaa.mp4'

# ffmpeg -hide_banner -i wnkaa.mp4 -vf cropdetect=skip=0 -t 1 -f null
cropdetect_output = sp.run(['ffmpeg', '-hide_banner', '-i', in_video_file, '-vf', 'cropdetect=skip=0', '-t', '1', '-f', 'null', 'pipe:'], stderr=sp.PIPE, universal_newlines=True).stderr

# Return: crop=480:304:72:4
crop_str = re.search('crop=.*', cropdetect_output).group(0)  # Find the first match of "crop=", and return all characters from "crop=" up to new line.

# ffmpeg -hide_banner -i wnkaa.mp4 -vf crop=480:304:72:4,setsar=1 cropped_wnkaa.mp4
sp.run(['ffmpeg', '-hide_banner', '-i', in_video_file, '-vf', crop_str+',setsar=1', out_video_file])

Note:
The above command uses default codec arguments (it's just an example).
We may add encoding arguments like '-vcodec', 'libx264', '-crf', '20', '-pix_fmt', 'yuv420p'...


Sample output frame:
enter image description here

Rotem
  • 30,366
  • 4
  • 32
  • 65