3分钟拯救颠倒视频:ffmpeg-python零代码修复方向错误文件

3分钟拯救颠倒视频:ffmpeg-python零代码修复方向错误文件

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

你是否遇到过这样的情况:手机拍摄的视频导入电脑后方向错乱,本该横向全屏的画面变成了竖屏小窗口?旅行中记录的美景因方向问题无法正常观看,客户发来的素材需要紧急调整方向?本文将用最简单的方式,教你用ffmpeg-python解决视频旋转与翻转问题,无需专业剪辑软件,3行代码即可修复方向错误的视频文件。

视频方向问题的根源与检测

智能手机拍摄视频时,常因握持方向导致画面方向与实际播放需求不符。这种情况下,视频元数据中会记录方向信息,但并非所有播放器都能正确识别。使用ffmpeg-python可先检测视频当前方向:

import ffmpeg

def get_video_rotation(input_file):
    probe = ffmpeg.probe(input_file)
    video_stream = next((stream for stream in probe['streams'] if stream['codec_type'] == 'video'), None)
    return int(video_stream.get('tags', {}).get('rotate', 0))

rotation = get_video_rotation('input.mp4')
print(f"视频当前旋转角度: {rotation}度")

上述代码片段改编自examples/video_info.py,通过解析视频元数据获取旋转角度。常见的错误方向包括90度、180度和270度旋转,以及水平/垂直翻转。

核心旋转功能实现

ffmpeg-python提供了两种主要的视频旋转方式:基于元数据的无损旋转和基于滤镜的像素级旋转。当视频包含rotate元数据时,可使用以下代码实现无损旋转:

import ffmpeg

input_file = 'input.mp4'
output_file = 'output_rotated.mp4'

# 获取视频当前旋转角度
probe = ffmpeg.probe(input_file)
video_stream = next((stream for stream in probe['streams'] if stream['codec_type'] == 'video'), None)
rotation = int(video_stream.get('tags', {}).get('rotate', 0))

if rotation in [90, 270]:
    # 处理90/270度旋转,需要交换宽高
    width = video_stream['height']
    height = video_stream['width']
else:
    width = video_stream['width']
    height = video_stream['height']

# 应用旋转滤镜
(
    ffmpeg.input(input_file)
    .filter('transpose', 1 if rotation == 90 else 2 if rotation == 270 else 0)
    .output(output_file, vcodec='copy' if rotation == 0 else None, acodec='copy', s=f'{width}x{height}')
    .overwrite_output()
    .run()
)

对于没有旋转元数据或需要更复杂旋转的视频,ffmpeg-python的transpose滤镜支持四种旋转模式:

transpose参数旋转效果
0顺时针旋转90度并垂直翻转
1顺时针旋转90度
2逆时针旋转90度
3逆时针旋转90度并垂直翻转

水平翻转与垂直翻转实现

除了旋转,ffmpeg-python还提供了hflip和vflip两个便捷滤镜,分别实现水平翻转和垂直翻转功能。这两个滤镜在ffmpeg/_filters.py中定义,可直接通过Stream对象调用:

# 水平翻转(左右镜像)
(
    ffmpeg.input('input.mp4')
    .hflip()
    .output('horizontal_flip.mp4')
    .overwrite_output()
    .run()
)

# 垂直翻转(上下镜像)
(
    ffmpeg.input('input.mp4')
    .vflip()
    .output('vertical_flip.mp4')
    .overwrite_output()
    .run()
)

# 同时应用旋转和翻转
(
    ffmpeg.input('input.mp4')
    .filter('transpose', 1)  # 顺时针旋转90度
    .hflip()                 # 水平翻转
    .output('rotate_and_flip.mp4')
    .overwrite_output()
    .run()
)

进度监控与批量处理

对于多个视频文件的批量处理,可结合进度监控功能实现可视化处理过程。以下代码示例结合了examples/show_progress.py中的进度条功能,实现带进度显示的批量旋转处理:

import ffmpeg
import os
from tqdm import tqdm

def process_video(input_path, output_path, rotation=0, hflip=False, vflip=False):
    # 获取视频总时长用于进度条
    probe = ffmpeg.probe(input_path)
    total_duration = float(probe['format']['duration'])
    
    # 创建进度条
    with tqdm(total=round(total_duration, 2), desc=os.path.basename(input_path)) as pbar:
        def update_progress(duration):
            pbar.update(duration - pbar.n)
        
        # 构建处理管道
        stream = ffmpeg.input(input_path)
        
        # 应用旋转
        if rotation == 90:
            stream = stream.filter('transpose', 1)
        elif rotation == 180:
            stream = stream.filter('transpose', 1).filter('transpose', 1)
        elif rotation == 270:
            stream = stream.filter('transpose', 2)
        
        # 应用翻转
        if hflip:
            stream = stream.hflip()
        if vflip:
            stream = stream.vflip()
        
        # 输出并监控进度
        (
            stream.output(output_path, acodec='copy')
            .global_args('-progress', 'pipe:1')
            .run(quiet=True, capture_stdout=True, capture_stderr=True)
        )

# 批量处理目录中的视频文件
input_dir = 'videos_to_fix'
output_dir = 'fixed_videos'
os.makedirs(output_dir, exist_ok=True)

for filename in os.listdir(input_dir):
    if filename.lower().endswith(('.mp4', '.mov', '.avi')):
        input_path = os.path.join(input_dir, filename)
        output_path = os.path.join(output_dir, filename)
        process_video(input_path, output_path, rotation=90)  # 根据实际需求调整参数

实战案例:修复手机拍摄的旋转视频

以下是一个完整的实战案例,展示如何检测并修复手机拍摄的旋转视频。假设我们有一个由iPhone横向拍摄但错误保存为竖屏的视频文件:

import ffmpeg
import os

def auto_fix_video_orientation(input_file, output_file):
    try:
        # 探测视频信息
        probe = ffmpeg.probe(input_file)
        video_stream = next((stream for stream in probe['streams'] if stream['codec_type'] == 'video'), None)
        
        if not video_stream:
            print("未找到视频流")
            return False
            
        rotation = int(video_stream.get('tags', {}).get('rotate', 0))
        width = video_stream['width']
        height = video_stream['height']
        
        print(f"检测到视频旋转角度: {rotation}度")
        print(f"原始分辨率: {width}x{height}")
        
        # 创建处理管道
        stream = ffmpeg.input(input_file)
        
        # 根据旋转角度应用相应滤镜
        if rotation == 90:
            stream = stream.filter('transpose', 1)  # 顺时针旋转90度
            new_width, new_height = height, width
        elif rotation == 180:
            stream = stream.filter('transpose', 1).filter('transpose', 1)  # 旋转180度
            new_width, new_height = width, height
        elif rotation == 270:
            stream = stream.filter('transpose', 2)  # 逆时针旋转90度
            new_width, new_height = height, width
        else:
            print("视频方向正常,无需旋转")
            return False
            
        # 输出处理后的视频
        (
            stream.output(
                output_file,
                vcodec='libx264',
                acodec='copy',
                s=f'{new_width}x{new_height}'
            )
            .overwrite_output()
            .run(quiet=True)
        )
        
        print(f"视频已修复并保存至: {output_file}")
        print(f"新分辨率: {new_width}x{new_height}")
        return True
        
    except Exception as e:
        print(f"处理失败: {str(e)}")
        return False

# 执行修复
auto_fix_video_orientation('input.mp4', 'output_fixed.mp4')

常见问题解决方案

在视频旋转过程中,可能会遇到黑边、分辨率异常等问题。这通常是由于旋转后宽高比未正确调整导致的。以下是一个解决旋转后黑边问题的优化版本代码:

import ffmpeg

def rotate_video_with_padding(input_file, output_file, rotation_degrees):
    # 获取视频信息
    probe = ffmpeg.probe(input_file)
    video_stream = next((stream for stream in probe['streams'] if stream['codec_type'] == 'video'), None)
    original_width = video_stream['width']
    original_height = video_stream['height']
    
    # 计算旋转后的尺寸和填充
    if rotation_degrees in [90, 270]:
        new_width = original_height
        new_height = original_width
    else:
        new_width = original_width
        new_height = original_height
    
    # 计算填充以保持原始比例
    original_ratio = original_width / original_height
    new_ratio = new_width / new_height
    
    if original_ratio > new_ratio:
        # 宽度过大,需要垂直填充
        pad_height = int(new_width / original_ratio)
        pad_top = (new_height - pad_height) // 2
        pad_bottom = new_height - pad_height - pad_top
        pad = f"0:{pad_top}:0:{pad_bottom}:color=black"
    elif original_ratio < new_ratio:
        # 高度过大,需要水平填充
        pad_width = int(new_height * original_ratio)
        pad_left = (new_width - pad_width) // 2
        pad_right = new_width - pad_width - pad_left
        pad = f"{pad_left}:0:{pad_right}:0:color=black"
    else:
        pad = None
    
    # 构建处理管道
    stream = ffmpeg.input(input_file)
    
    # 应用旋转
    if rotation_degrees == 90:
        stream = stream.filter('transpose', 1)
    elif rotation_degrees == 180:
        stream = stream.filter('transpose', 1).filter('transpose', 1)
    elif rotation_degrees == 270:
        stream = stream.filter('transpose', 2)
    
    # 应用填充去除黑边
    if pad:
        stream = stream.filter('pad', pad)
    
    # 输出视频
    (
        stream.output(output_file, vcodec='libx264', acodec='copy')
        .overwrite_output()
        .run()
    )

# 使用示例
rotate_video_with_padding('input.mp4', 'output_padded.mp4', 90)

总结与扩展应用

ffmpeg-python提供了简洁而强大的API,使得复杂的视频旋转与翻转操作变得简单。通过组合使用transpose、hflip和vflip等滤镜,可实现任意角度的视频旋转和翻转效果。本文介绍的方法不仅适用于修复方向错误的视频,还可应用于以下场景:

  1. 批量处理手机拍摄的视频素材
  2. 实现视频播放器的旋转控制功能
  3. 预处理视频数据以适应特定显示设备
  4. 创建视频特效(如镜像效果、旋转动画)

建议结合官方文档doc/html/index.html深入学习更多滤镜组合方式,探索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、付费专栏及课程。

余额充值