You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 13:35:26