ffmpeg-python视频裁剪:去除黑边与调整画面比例

ffmpeg-python视频裁剪:去除黑边与调整画面比例

【免费下载链接】ffmpeg-python Python bindings for FFmpeg - with complex filtering support 【免费下载链接】ffmpeg-python 项目地址: https://gitcode.com/gh_mirrors/ff/ffmpeg-python

你是否遇到过这样的情况:下载的电影上下有难看的黑边,手机拍摄的视频在电脑上播放时画面拉伸变形?本文将教你如何使用ffmpeg-python轻松解决这些问题,让视频画面更符合观看需求。读完本文后,你将能够:识别视频黑边区域、精准裁剪画面、调整视频比例以适应不同播放设备。

准备工作

在开始之前,请确保你已经安装了ffmpeg-python库。如果尚未安装,可以通过以下命令进行安装:

pip install ffmpeg-python

同时,你需要准备一个待处理的视频文件。本文将以项目中的示例视频处理流程为例进行讲解,相关示例代码可以参考examples/get_video_thumbnail.py

视频裁剪基础

视频裁剪(Crop)是指去除视频画面中不需要的部分,保留感兴趣的区域。在ffmpeg-python中,我们可以使用crop过滤器来实现这一功能。该过滤器的定义位于ffmpeg/_filters.py文件中,其函数签名如下:

def crop(stream, x, y, width, height, **kwargs):
    """Crop the input video.
    Args:
        x: The horizontal position, in the input video, of the left edge of the output video.
        y: The vertical position, in the input video, of the top edge of the output video.
        width: The width of the output video. Must be greater than 0.
        height: The height of the output video. Must be greater than 0.
    """

这个函数需要四个主要参数:x和y是裁剪区域左上角的坐标,width和height是裁剪区域的宽度和高度。

自动检测黑边

手动确定裁剪区域的参数比较麻烦,特别是当视频中存在黑边时。幸运的是,FFmpeg提供了blackdetect过滤器,可以自动检测视频中的黑边区域。虽然ffmpeg-python没有直接封装这个过滤器,但我们可以使用filter函数来调用它,相关实现可参考ffmpeg/_filters.py中的filter函数定义。

以下是一个检测视频黑边的示例代码:

import ffmpeg

def detect_black_borders(input_file):
    try:
        # 使用blackdetect过滤器检测黑边
        probe = ffmpeg.probe(input_file)
        video_stream = next((stream for stream in probe['streams'] if stream['codec_type'] == 'video'), None)
        width = int(video_stream['width'])
        height = int(video_stream['height'])
        
        # 运行blackdetect过滤器
        result = ffmpeg.input(input_file).filter('blackdetect', d=0.1, pix_th=0.1).output('pipe:', format='null').run(capture_stderr=True)
        
        # 解析输出结果
        stderr = result.stderr.decode('utf-8')
        black_border_info = {}
        for line in stderr.split('\n'):
            if 'black_start' in line:
                black_border_info['black_start'] = float(line.split('=')[1])
            elif 'black_end' in line:
                black_border_info['black_end'] = float(line.split('=')[1])
            elif 'black_duration' in line:
                black_border_info['black_duration'] = float(line.split('=')[1])
            elif 'left' in line and 'black_border' in line:
                black_border_info['left'] = int(line.split('=')[1])
            elif 'right' in line and 'black_border' in line:
                black_border_info['right'] = int(line.split('=')[1])
            elif 'top' in line and 'black_border' in line:
                black_border_info['top'] = int(line.split('=')[1])
            elif 'bottom' in line and 'black_border' in line:
                black_border_info['bottom'] = int(line.split('=')[1])
        
        return black_border_info
        
    except ffmpeg.Error as e:
        print(f"Error detecting black borders: {e.stderr.decode('utf-8')}")
        return None

这段代码通过分析blackdetect过滤器的输出,获取视频中黑边的位置和大小信息。

去除黑边的完整实现

结合黑边检测和裁剪功能,我们可以实现一个自动去除视频黑边的函数:

import ffmpeg
import sys

def remove_black_borders(input_file, output_file):
    # 检测黑边
    black_borders = detect_black_borders(input_file)
    if not black_borders:
        print("No black borders detected or error occurred.")
        return
    
    # 提取黑边信息
    left = black_borders.get('left', 0)
    right = black_borders.get('right', 0)
    top = black_borders.get('top', 0)
    bottom = black_borders.get('bottom', 0)
    
    # 如果黑边太小,不进行裁剪
    if left + right < 10 and top + bottom < 10:
        print("Black borders are too small to crop.")
        return
    
    try:
        # 获取原始视频信息
        probe = ffmpeg.probe(input_file)
        video_stream = next((stream for stream in probe['streams'] if stream['codec_type'] == 'video'), None)
        width = int(video_stream['width'])
        height = int(video_stream['height'])
        
        # 计算裁剪后的尺寸
        new_width = width - left - right
        new_height = height - top - bottom
        
        # 应用裁剪过滤器,相关实现参考[ffmpeg/_filters.py](https://link.gitcode.com/i/96d936a5e3c698c5740a5cfe3db364c3)
        (
            ffmpeg
            .input(input_file)
            .crop(x=left, y=top, width=new_width, height=new_height)
            .output(output_file, codec='copy')
            .overwrite_output()
            .run(capture_stdout=True, capture_stderr=True)
        )
        print(f"Successfully cropped video. Output saved to {output_file}")
        
    except ffmpeg.Error as e:
        print(f"Error cropping video: {e.stderr.decode('utf-8')}")
        sys.exit(1)

这个函数首先检测视频中的黑边,然后使用crop过滤器去除这些黑边,最后将处理后的视频保存到输出文件。

调整画面比例

有时候,我们需要将视频调整为特定的画面比例,例如将16:9的视频转换为4:3,或者反之。这时候可以结合使用cropscale过滤器来实现。

以下是一个调整视频画面比例的示例:

def adjust_aspect_ratio(input_file, output_file, target_ratio="16:9"):
    try:
        # 获取原始视频信息
        probe = ffmpeg.probe(input_file)
        video_stream = next((stream for stream in probe['streams'] if stream['codec_type'] == 'video'), None)
        width = int(video_stream['width'])
        height = int(video_stream['height'])
        original_ratio = width / height
        
        # 解析目标比例
        target_width, target_height = map(int, target_ratio.split(':'))
        target_ratio_val = target_width / target_height
        
        # 根据比例决定裁剪策略
        if original_ratio > target_ratio_val:
            # 原始视频更宽,裁剪左右两侧
            new_width = int(height * target_ratio_val)
            new_height = height
            x = (width - new_width) // 2
            y = 0
        else:
            # 原始视频更高,裁剪上下两侧
            new_width = width
            new_height = int(width / target_ratio_val)
            x = 0
            y = (height - new_height) // 2
        
        # 应用裁剪和缩放,参考[examples/get_video_thumbnail.py](https://link.gitcode.com/i/a69043d6089a1be424feb0217339e981)中的缩放实现
        (
            ffmpeg
            .input(input_file)
            .crop(x=x, y=y, width=new_width, height=new_height)
            .filter('scale', width, height)  # 保持原始分辨率
            .output(output_file, codec='copy')
            .overwrite_output()
            .run(capture_stdout=True, capture_stderr=True)
        )
        print(f"Successfully adjusted aspect ratio to {target_ratio}. Output saved to {output_file}")
        
    except ffmpeg.Error as e:
        print(f"Error adjusting aspect ratio: {e.stderr.decode('utf-8')}")
        sys.exit(1)

这个函数根据目标画面比例计算需要裁剪的区域,然后使用crop过滤器进行裁剪,最后使用scale过滤器将视频缩放到原始尺寸。

实际应用案例

现在,让我们来看一个完整的视频处理流程,包括去除黑边和调整画面比例:

def process_video(input_file, output_file, target_ratio=None):
    # 首先去除黑边
    temp_file = "temp_cropped.mp4"
    remove_black_borders(input_file, temp_file)
    
    # 如果指定了目标比例,调整画面比例
    if target_ratio:
        adjust_aspect_ratio(temp_file, output_file, target_ratio)
        # 删除临时文件
        import os
        os.remove(temp_file)
    else:
        # 直接使用去除黑边后的视频
        import shutil
        shutil.move(temp_file, output_file)
    
    print(f"Video processing completed. Final output saved to {output_file}")

# 使用示例
process_video("input.mp4", "output.mp4", "16:9")

这个示例展示了如何将去除黑边和调整画面比例的功能结合起来,形成一个完整的视频处理流程。

总结与展望

通过本文的介绍,我们学习了如何使用ffmpeg-python来去除视频黑边和调整画面比例。这些技术可以帮助我们改善视频的观看体验,使视频画面更加符合我们的需求。

ffmpeg-python提供了丰富的过滤器和功能,除了本文介绍的裁剪和缩放,还有许多其他强大的功能等待我们去探索。例如,我们可以使用hflipvflip过滤器来翻转视频,使用drawtext过滤器在视频上添加文字,或者使用concat过滤器来拼接多个视频片段。相关实现可以参考ffmpeg/_filters.py中的函数定义。

希望本文对你有所帮助,如果你有任何问题或建议,欢迎在评论区留言讨论。

如果你觉得本文有用,请点赞、收藏并关注我们,以便获取更多关于ffmpeg-python的实用教程。下期我们将介绍如何使用ffmpeg-python进行视频转码和压缩,敬请期待!

【免费下载链接】ffmpeg-python Python bindings for FFmpeg - with complex filtering support 【免费下载链接】ffmpeg-python 项目地址: https://gitcode.com/gh_mirrors/ff/ffmpeg-python

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值