如何用Python裁剪MP4视频的上下左右黑边?
使用Python自动裁剪视频黑边
要实现自动检测并裁剪视频黑边,核心分为两步:识别视频中所有帧的共同非黑区域,再用FFmpeg或OpenCV对视频进行裁剪。以下是具体实现:
依赖安装
首先安装所需库:
pip install opencv-python numpy ffmpeg-python
如果不想用ffmpeg-python,也可以直接安装FFmpeg工具并通过subprocess调用。
步骤1:检测黑边区域
通过采样视频中的多帧,计算所有帧的共同非黑边界,确保裁剪区域对所有帧有效:
import cv2 import numpy as np def get_crop_region(video_path, sample_frames=10, threshold=20): cap = cv2.VideoCapture(video_path) if not cap.isOpened(): raise ValueError(f"无法打开视频文件: {video_path}") total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 均匀采样若干帧,避免单帧异常影响结果 sample_indices = np.linspace(0, total_frames-1, sample_frames, dtype=int) # 初始化边界为视频最大范围,后续逐步缩小到共同非黑区域 min_x = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) max_x = 0 min_y = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) max_y = 0 for idx in sample_indices: cap.set(cv2.CAP_PROP_POS_FRAMES, idx) ret, frame = cap.read() if not ret: continue # 转灰度图简化黑边判断 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 生成非黑区域掩码(像素值大于阈值视为非黑) mask = gray > threshold coords = np.argwhere(mask) if len(coords) == 0: continue # 跳过全黑帧 # 获取当前帧的非黑边界 y_min, x_min = coords.min(axis=0) y_max, x_max = coords.max(axis=0) # 更新全局边界:取所有帧的交集 min_x = min(min_x, x_min) max_x = max(max_x, x_max) min_y = min(min_y, y_min) max_y = max(max_y, y_max) cap.release() # 计算裁剪参数:起始坐标(x,y),裁剪后宽高(w,h) x, y = min_x, min_y width = max_x - min_x + 1 height = max_y - min_y + 1 if width <= 0 or height <= 0: raise ValueError("未检测到有效非黑区域,无法执行裁剪") return x, y, width, height
步骤2:裁剪视频
使用FFmpeg进行裁剪,保证视频编码质量和音频同步:
import ffmpeg import os def magically_trim_black_boarders_from_vid(in_vid, out_vid=None): # 自动生成输出文件名(原文件名后加_cropped) if out_vid is None: name, ext = os.path.splitext(in_vid) out_vid = f"{name}_cropped{ext}" # 获取裁剪区域参数 x, y, w, h = get_crop_region(in_vid) # 调用FFmpeg执行裁剪,保留原音频编码 ( ffmpeg .input(in_vid) .filter('crop', w=w, h=h, x=x, y=y) .output(out_vid, vcodec='libx264', acodec='copy') .overwrite_output() # 覆盖已存在的输出文件 .run(capture_stdout=True, capture_stderr=True) ) print(f"裁剪完成,输出文件:{out_vid}") return out_vid
替代方案:用subprocess直接调用FFmpeg
如果不想安装ffmpeg-python,可以直接调用FFmpeg命令:
import subprocess import os def magically_trim_black_boarders_from_vid(in_vid, out_vid=None): if out_vid is None: name, ext = os.path.splitext(in_vid) out_vid = f"{name}_cropped{ext}" x, y, w, h = get_crop_region(in_vid) # FFmpeg命令行参数 cmd = [ 'ffmpeg', '-i', in_vid, '-filter:v', f'crop={w}:{h}:{x}:{y}', '-c:a', 'copy', '-y', # 强制覆盖输出文件 out_vid ] subprocess.run(cmd, check=True) print(f"裁剪完成,输出文件:{out_vid}") return out_vid
使用示例
# 传入输入视频路径即可 magically_trim_black_boarders_from_vid("your_video.mp4")
注意事项
- 阈值调整:如果黑边不是纯黑(带有轻微灰色),可以降低
threshold值(比如设为10);如果视频中有暗部内容,避免阈值过低误裁。 - 采样帧数:
sample_frames默认10帧,足够应对大多数场景;如果视频内容变化大,可以适当增加帧数提高检测准确性。 - FFmpeg安装:如果用
subprocess方案,需要确保系统已安装FFmpeg并添加到环境变量中。
内容的提问来源于stack exchange,提问作者perry_the_python
相关产品推荐
相关产品推荐

