杰瑞科技汇

python ffmpeg 合并视频

下面我将为你提供几种不同的方法,从最简单到最灵活,并附上详细的代码示例和解释。

python ffmpeg 合并视频-图1
(图片来源网络,侵删)

核心概念:合并视频的方式

在 FFmpeg 中,合并视频主要有两种方式,它们对视频文件的要求完全不同:

  1. Concat (连接/拼接)

    • 原理:将视频文件一个接一个地连接起来,就像把几段胶带粘在一起一样。
    • 要求所有视频文件的编码格式(H.264, H.265等)、分辨率、帧率、音频轨道等参数必须完全相同,如果参数不同,合并后的视频可能会出现花屏、音画不同步等问题。
    • 命令ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4
  2. Concat (Demuxer)

    • 原理:不重新编码,而是将视频的“容器”(.mp4, .mkv等)像文件夹一样合并,只将各个文件的索引信息连接起来。
    • 要求比 Concat (Demuxer) 稍微宽松一些,它允许视频有不同的编码格式,但要求它们是“兼容的容器格式”(都是 .mp4 文件),这种方法本质上只是将文件“拼接”在一起,而不是“融合”。
    • 命令ffmpeg -i "concat:input1.mp4|input2.mp4|input3.mp4" -c copy output.mp4

对于绝大多数情况,尤其是从同一设备或同一来源导出的视频片段,我们推荐使用 concat demuxer,因为它最简单、最高效。

python ffmpeg 合并视频-图2
(图片来源网络,侵删)

使用 subprocess 模块(最基础、最灵活)

这是最直接的方法,Python 的 subprocess 模块可以让你直接在代码中执行命令行指令。

步骤 1:安装 FFmpeg

你的系统上必须安装了 FFmpeg ffmpeg 命令可以在终端/命令行中直接使用。

  • Windows: 从 FFmpeg 官网 下载,并将 bin 目录添加到系统环境变量 PATH 中。
  • macOS: 使用 Homebrew 安装:brew install ffmpeg
  • Linux (Ubuntu/Debian): 使用 apt 安装:sudo apt update && sudo apt install ffmpeg

步骤 2:编写 Python 脚本

我们将使用 concat demuxer 方法,因为它通常更方便。

import subprocess
import os
def merge_videos_with_concat_demuxer(video_list, output_filename):
    """
    使用 FFmpeg 的 concat demuxer 合并视频。
    注意:此方法要求所有视频文件是兼容的容器格式(如 .mp4)。
    """
    # 检查输出文件是否已存在,如果存在则删除
    if os.path.exists(output_filename):
        os.remove(output_filename)
        print(f"已删除已存在的输出文件: {output_filename}")
    # 构建 concat demuxer 的输入字符串
    # 格式为: "concat:file1.mp4|file2.mp4|file3.mp4"
    concat_input = "|".join(video_list)
    # 构建 FFmpeg 命令
    # -i: 输入文件
    # -c copy: 直接复制流,不进行重新编码,速度极快且保证质量
    # -y: 覆盖输出文件(如果已存在)
    command = [
        'ffmpeg',
        '-y',  # 覆盖输出文件
        '-i', f'concat:{concat_input}',
        '-c', 'copy',
        output_filename
    ]
    print(f"正在执行命令: {' '.join(command)}")
    try:
        # 执行命令
        # subprocess.run 会等待命令执行完成
        # check=True 会在命令返回非零退出码(即出错)时抛出异常
        subprocess.run(command, check=True, capture_output=True, text=True)
        print(f"视频合并成功!输出文件: {output_filename}")
    except subprocess.CalledProcessError as e:
        print(f"视频合并失败!错误信息: {e.stderr}")
    except FileNotFoundError:
        print("错误:未找到 ffmpeg 命令,请确保 FFmpeg 已安装并添加到系统 PATH 中。")
# --- 使用示例 ---
if __name__ == "__main__":
    # 1. 准备要合并的视频文件列表
    # 确保这些文件存在于当前目录下
    videos_to_merge = [
        'part1.mp4',
        'part2.mp4',
        'part3.mp4'
    ]
    # 2. 指定输出文件的名称
    output_video = 'merged_video.mp4'
    # 3. 调用函数进行合并
    merge_videos_with_concat_demuxer(videos_to_merge, output_video)

如何运行:

  1. 将上面的代码保存为 merge.py
  2. 准备好 part1.mp4, part2.mp4, part3.mp4 等视频文件,并与 merge.py 放在同一个文件夹下。
  3. 在终端/命令行中运行:python merge.py

使用 ffmpy 库(更简洁的封装)

ffmpy 是一个简单的 Python 封装库,它让调用 FFmpeg 变得更 Pythonic,无需手动构建命令列表。

步骤 1:安装 ffmpy

pip install ffmpy

步骤 2:编写 Python 脚本

import os
from ffmpy import FFmpeg
def merge_videos_with_ffmpy(video_list, output_filename):
    """
    使用 ffmpy 库合并视频。
    """
    if os.path.exists(output_filename):
        os.remove(output_filename)
        print(f"已删除已存在的输出文件: {output_filename}")
    # 构建 concat demuxer 的输入字符串
    concat_input = "|".join(video_list)
    # 创建 FFmpeg 实例
    # options 参数对应 FFmpeg 的命令行选项
    ff = FFmpeg(
        inputs={f'concat:{concat_input}': None},  # 输入文件,None 表示没有额外参数
        outputs={output_filename: '-c copy'}     # 输出文件及其参数
    )
    print(f"正在执行命令: ff.command")
    try:
        # 执行
        ff.run()
        print(f"视频合并成功!输出文件: {output_filename}")
    except Exception as e:
        print(f"视频合并失败!错误信息: {e}")
# --- 使用示例 ---
if __name__ == "__main__":
    videos_to_merge = [
        'part1.mp4',
        'part2.mp4',
        'part3.mp4'
    ]
    output_video = 'merged_video_ffmpy.mp4'
    merge_videos_with_ffmpy(videos_to_merge, output_video)

优点:

  • 代码更简洁,易于阅读。
  • 自动处理了命令的引号和转义问题。

使用 moviepy 库(更高级的视频编辑)

moviepy 不仅仅是一个 FFmpeg 封装,它是一个功能强大的 Python 视频编辑库,合并视频只是它的一个小功能。

步骤 1:安装 moviepy

pip install moviepy

步骤 2:编写 Python 脚本

注意moviepy 在合并视频时,默认会进行重新编码,这意味着它对视频的格式要求不那么严格(可以合并不同编码的视频),但处理速度会慢很多,并且可能会有轻微的质量损失。

from moviepy.editor import VideoFileClip, concatenate_videoclips
import os
def merge_videos_with_moviepy(video_list, output_filename):
    """
    使用 moviepy 库合并视频。
    注意:moviepy 默认会重新编码,速度较慢但兼容性更好。
    """
    if os.path.exists(output_filename):
        os.remove(output_filename)
        print(f"已删除已存在的输出文件: {output_filename}")
    clips = []
    try:
        # 1. 加载所有视频片段
        for video_file in video_list:
            print(f"正在加载视频: {video_file}")
            clip = VideoFileClip(video_file)
            clips.append(clip)
        # 2. 合并视频片段
        # method='compose' 是默认行为,会重新编码
        # 如果所有视频参数都一样,可以尝试 method='concat',它可能更快
        final_clip = concatenate_videoclips(clips, method="compose")
        # 3. 写入输出文件
        print(f"正在合并视频并写入到: {output_filename}...")
        final_clip.write_videofile(
            output_filename,
            codec='libx264',  # 常见的视频编码器
            audio_codec='aac'  # 常见的音频编码器
        )
        print(f"视频合并成功!输出文件: {output_filename}")
    except Exception as e:
        print(f"视频合并失败!错误信息: {e}")
    finally:
        # 4. 释放内存,关闭所有视频片段
        for clip in clips:
            clip.close()
# --- 使用示例 ---
if __name__ == "__main__":
    videos_to_merge = [
        'part1.mp4',
        'part2.mp4',
        'part3.mp4'
    ]
    output_video = 'merged_video_moviepy.mp4'
    merge_videos_with_moviepy(videos_to_merge, output_video)

优点:

  • 兼容性最好,可以处理不同编码、不同分辨率的视频(它会自动调整)。
  • 除了合并,还可以进行剪辑、添加文字、叠加视频等复杂操作。

缺点:

  • 速度慢,因为涉及重新编码。
  • 安装包较大,依赖更多。

总结与选择建议

方法 优点 缺点 适用场景
subprocess 最灵活,不依赖第三方库,完全控制 FFmpeg 命令 需要手动构建命令,稍显繁琐 需要使用 FFmpeg 的高级特性,或项目不允许安装额外库时
ffmpy 代码简洁,易于使用,是 FFmpeg 的优秀 Pythonic 封装 需要安装一个额外的库 推荐首选,当你只是想简单地调用 FFmpeg 功能时
moviepy 功能强大,兼容性好,能处理复杂视频编辑任务 速度慢(会重新编码),安装包大 需要在合并的同时进行其他视频处理(如裁剪、加字幕等)

给你的建议:

  • 如果你的视频片段来自同一来源(如同一部电影的多个部分),请优先使用 subprocessffmpyconcat demuxer 方法,这是最快、质量最高的方式。
  • 如果你的视频片段参数各不相同(如不同手机录制的视频),并且你不想手动处理,可以考虑使用 moviepy,但要接受它较慢的速度。
  • 对于大多数自动化脚本和工具开发,ffmpy 是一个平衡了简洁和功能的绝佳选择。
分享:
扫描分享到社交APP
上一篇
下一篇