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,或者反之。这时候可以结合使用crop和scale过滤器来实现。
以下是一个调整视频画面比例的示例:
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提供了丰富的过滤器和功能,除了本文介绍的裁剪和缩放,还有许多其他强大的功能等待我们去探索。例如,我们可以使用hflip或vflip过滤器来翻转视频,使用drawtext过滤器在视频上添加文字,或者使用concat过滤器来拼接多个视频片段。相关实现可以参考ffmpeg/_filters.py中的函数定义。
希望本文对你有所帮助,如果你有任何问题或建议,欢迎在评论区留言讨论。
如果你觉得本文有用,请点赞、收藏并关注我们,以便获取更多关于ffmpeg-python的实用教程。下期我们将介绍如何使用ffmpeg-python进行视频转码和压缩,敬请期待!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



