Python FFmpeg 实战指南:从安装到视频处理
1. 为什么选择 Python 和 FFmpeg 这对黄金搭档?
如果你经常和视频、音频文件打交道,比如做自媒体、处理家庭录像,或者开发一些需要处理多媒体的应用,那你肯定听说过 FFmpeg。它就像一个无所不能的“瑞士军刀”,几乎能处理所有你能想到的音视频格式转换、剪辑、合并、加水印、提取音频等等操作。但它的操作方式主要是命令行,对很多朋友来说,那一长串参数看着就头疼,记不住,也容易出错。
这时候,Python 就该登场了。Python 以其简洁易懂的语法著称,被誉为“胶水语言”,特别擅长把各种强大的工具“粘合”起来,让它们变得更易用。用 Python 来调用 FFmpeg,就像是给这把强大的“瑞士军刀”装上了一套智能、自动化的手柄。你不用再去记忆复杂的命令行参数,而是通过写几行清晰的 Python 代码,就能完成复杂的视频处理任务。这不仅能大大提高你的工作效率,还能让你的工作流程变得可重复、可管理,甚至能集成到更大的自动化系统中去。
我自己在项目中就深有体会。以前手动用 FFmpeg 命令行处理一批视频,不仅容易输错命令,每次修改参数也很麻烦。自从用 Python 脚本封装后,我只需要修改一下脚本里的几个变量,比如输入输出路径、裁剪的时间点,然后一键运行,上百个视频文件就能自动按我的要求处理好,省时省力还不出错。所以,无论你是想批量处理视频的普通用户,还是需要在应用中集成多媒体处理功能的开发者,掌握 Python + FFmpeg 的组合,都能让你如虎添翼。
2. 手把手搞定 FFmpeg 的安装与环境配置
万事开头难,但第一步走稳了,后面就顺畅了。我们先来把 FFmpeg 这个核心工具安装好,并确保它在你的系统上能随时被调用。
2.1 在 Windows 系统上安装 FFmpeg
对于 Windows 用户,最直接的方式是从 FFmpeg 的官方网站获取编译好的版本。你不需要自己从源码编译,那样太复杂了。
访问官网下载:打开浏览器,搜索“FFmpeg”或者直接访问其官方网站。找到 “Download” 页面,你会看到几个版本。我建议下载标有 “release” 或 “essentials” 的版本,比如
ffmpeg-release-full.7z。带 “full” 的版本包含了所有编解码器,功能最全。至于 “shared” 和 “static” 的区别,简单来说,“shared” 版本把一些功能模块放在了单独的.dll文件里,而 “static” 版本把所有东西都打包进了ffmpeg.exe这一个文件。对于新手,选哪个都行,功能没区别。我通常下载 “shared” 版本,因为文件结构更清晰。解压到合适位置:下载下来的是一个压缩包(通常是
.7z或.zip格式)。你需要把它解压到一个你容易找到且不会轻易删除的目录。比如,我习惯在C:\Tools目录下新建一个ffmpeg文件夹,然后把所有文件解压进去。解压后,你会看到里面有bin、doc、presets等文件夹。我们最关心的是bin文件夹,因为里面存放着可执行文件ffmpeg.exe、ffplay.exe(一个简单的播放器)和ffprobe.exe(用于查看媒体文件信息)。配置环境变量(关键步骤):这一步是为了让你在系统的任何地方(比如命令行、PowerShell 或者 Python 脚本里)都能直接输入
ffmpeg命令来调用它,而不需要每次都输入它的完整路径。右键点击“此电脑”或“我的电脑”,选择“属性”,然后找到“高级系统设置”。点击“环境变量”,在下面的“系统变量”区域里,找到并选中名为Path的变量,点击“编辑”。然后点击“新建”,把你刚才解压的ffmpeg目录下的bin文件夹的完整路径(例如C:\Tools\ffmpeg\bin)添加进去。一路点击“确定”保存。验证安装:打开一个新的命令提示符(CMD)或 PowerShell 窗口(重要:一定要新开一个窗口,环境变量才会生效)。输入命令
ffmpeg -version然后回车。如果你看到输出了 FFmpeg 的版本信息、编译配置等一大堆文字,那么恭喜你,安装成功了!如果提示“不是内部或外部命令”,请回头检查环境变量路径是否填写正确,以及是否在新开的终端里测试。
2.2 在 macOS 和 Linux 系统上安装
对于 macOS 用户,最方便的方法是使用包管理器 Homebrew。如果你还没安装 Homebrew,可以先去它的官网按照指引安装。安装好 Homebrew 之后,打开终端(Terminal),只需要一行命令:brew install ffmpeg。Homebrew 会自动处理下载、编译和依赖,安装完成后通常也自动配置好了环境变量,非常省心。
对于 Linux 用户(如 Ubuntu、CentOS),使用系统自带的包管理器即可。例如在 Ubuntu 上,可以打开终端,运行sudo apt update更新软件列表,然后运行sudo apt install ffmpeg。其他发行版如 Fedora 可以用dnf,Arch 可以用pacman,命令类似。Linux 系统安装后一般也无需额外配置环境变量。
2.3 安装 Python 的 FFmpeg 包装库
虽然配置好环境变量后,我们已经可以在 Python 中用subprocess模块调用 FFmpeg 命令了,但还有更优雅的方式——使用专门的 Python 库。这里我推荐两个:
- ffmpeg-python:这是一个对 FFmpeg 命令行参数进行了 Python 化封装的库。它的 API 设计非常直观,像链式调用一样,写出来的代码就像在描述你要做什么,可读性极高。安装它很简单:
pip install ffmpeg-python。 - pydub:如果你主要处理音频,或者需要更简单的音频操作接口,
pydub是个绝佳选择。它底层也调用 FFmpeg,但提供了更高级、更 Pythonic 的音频处理功能(如切片、淡入淡出、调整音量等)。安装:pip install pydub。注意,pydub需要系统已安装 FFmpeg。
我个人的习惯是,对于纯粹的视频处理或复杂的滤镜链,用ffmpeg-python;对于以音频为中心或快速简单的任务,用pydub。本文接下来的例子会主要使用ffmpeg-python,因为它更贴近原生命令,功能也更全面。
3. 从零开始:你的第一个 Python FFmpeg 脚本
理论说再多,不如动手敲一行代码。让我们从一个最简单的任务开始:用 Python 调用 FFmpeg 转换视频格式。假设你有一个input.mp4文件,想把它转换成output.avi格式。
3.1 方法一:使用 ffmpeg-python 库(推荐)
首先确保你已经用pip install ffmpeg-python安装好了这个库。然后创建一个新的 Python 文件,比如叫做convert_video.py。
import ffmpeg # 定义输入和输出文件路径 input_file = "path/to/your/input.mp4" # 请替换为你的视频实际路径 output_file = "output.avi" # 核心代码就这一行! stream = ffmpeg.input(input_file) stream = ffmpeg.output(stream, output_file) ffmpeg.run(stream) print(f"转换完成!文件已保存为:{output_file}")是不是简单得不可思议?ffmpeg.input()指定输入源,ffmpeg.output()指定输出目标和格式,ffmpeg.run()执行任务。代码清晰得像在写注释。你可以把这段代码保存下来,每次要转换格式时,改一下文件路径和输出格式后缀(如.mkv,.mov)就行了。FFmpeg 会根据你给的后缀名自动选择相应的编码器。
3.2 方法二:使用 subprocess 模块(更底层,更灵活)
如果你不想安装额外的库,或者需要对 FFmpeg 命令有百分之百的控制权,Python 内置的subprocess模块是你的好帮手。它允许你直接运行任何系统命令。
import subprocess import sys def convert_video(input_path, output_path): """ 使用 subprocess 调用 FFmpeg 转换视频格式 """ # 构建 FFmpeg 命令列表 # 相当于在命令行输入:ffmpeg -i input.mp4 output.avi command = [ 'ffmpeg', '-i', input_path, # -i 表示输入文件 output_path ] try: # 运行命令 # `check=True` 表示如果命令执行失败(返回非零状态码)会抛出异常 # `stdout=subprocess.PIPE, stderr=subprocess.PIPE` 可以捕获输出信息,方便调试 result = subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) print("命令执行成功!") # 可以打印 FFmpeg 的输出信息(通常是进度信息) # print(result.stderr) except subprocess.CalledProcessError as e: # 如果命令执行出错 print(f"转换过程中出现错误,返回码:{e.returncode}") print(f"错误信息:{e.stderr}") sys.exit(1) # 非正常退出 # 使用函数 input_video = "input.mp4" output_video = "output.avi" convert_video(input_video, output_video)这种方法虽然代码量稍多,但优势在于灵活。你可以完全自定义命令参数,并且能很好地捕获和处理 FFmpeg 运行过程中的输出和错误,这对于构建健壮的自动化脚本非常重要。比如,你可以解析stderr中的信息来获取实时转码进度。
3.3 第一个脚本可能遇到的“坑”
新手在运行第一个脚本时,最常见的问题就是文件路径错误和编码器不支持。
- 路径问题:确保
input.mp4这个文件确实存在于你代码指定的路径下。我强烈建议使用文件的绝对路径(如C:/Users/Name/Videos/input.mp4或/home/name/videos/input.mp4),或者在 Python 脚本中使用os.path模块来构建可靠的路径。相对路径(如./input.mp4)依赖于你运行脚本的当前目录,容易出错。 - 编码器错误:如果你遇到类似 “Unable to find a suitable output format for ‘output.xyz’” 或编码器不存在的错误,可能是因为 FFmpeg 没有编译进对应的格式支持。确保你安装的是 “full” 版本。对于 AVI 格式,通常没问题。如果转换其他特殊格式失败,你可能需要寻找编译了更多编码器的 FFmpeg 版本,或者在线搜索特定格式的 FFmpeg 编译参数。
4. 玩转视频处理:剪辑、合并与基础特效
掌握了格式转换,我们就来点更实用的。视频剪辑和合并是日常处理中最频繁的需求。
4.1 精准视频剪辑:截取你想要的片段
想象一下,你有一个长视频,只想截取其中从第1分30秒开始,持续15秒的一个精彩片段。
使用ffmpeg-python可以非常优雅地实现:
import ffmpeg input_file = "long_video.mp4" output_file = "highlight_clip.mp4" # ss: 指定开始时间 (start time),格式可以是秒数(如90),也可以是 `时:分:秒`(如 `00:01:30`) # t: 指定持续时间 (duration),格式同上 stream = ffmpeg.input(input_file, ss=90, t=15) # 从90秒开始,截取15秒 stream = ffmpeg.output(stream, output_file) ffmpeg.run(stream)这里的关键参数是ss和t。ss也可以放在output后面,但含义略有不同:放在input后,FFmpeg 会先定位到输入文件的该时间点再开始解码,速度更快;放在output后,会先解码整个文件再丢弃前面的部分,更精确但慢。对于简单的剪切,用前者就好。
如果你想指定结束时间点,而不是持续时间,可以用to参数(注意不是t)。例如ss=90, to=105同样表示截取90秒到105秒。
4.2 合并多个视频文件
把多个短视频合并成一个,比如合并几次会议录像。这里需要注意,直接合并不同编码参数的文件可能会失败。最稳妥的方法是先确保它们具有相同的编码格式、分辨率、帧率等。如果源文件一致,可以使用“连接协议”来合并。
首先,创建一个文本文件filelist.txt,内容如下:
file 'clip1.mp4' file 'clip2.mp4' file 'clip3.mp4'然后使用 Python 脚本调用 FFmpeg:
import ffmpeg # 方法:使用 concat demuxer stream = ffmpeg.input('filelist.txt', format='concat', safe=0) stream = ffmpeg.output(stream, 'merged_output.mp4', c='copy') # c copy 表示流复制,不重新编码,速度极快 ffmpeg.run(stream)c='copy'参数非常重要,它告诉 FFmpeg 直接复制音视频流,而不进行重新编码,所以合并速度几乎是瞬间完成的。但前提是所有片段必须兼容。如果不兼容,你需要去掉c='copy',让 FFmpeg 重新编码,但这会慢很多。
4.3 添加水印与基础缩放
给视频加个 Logo 水印,或者调整一下分辨率,也是常见需求。
添加静态图片水印:
import ffmpeg input_video = "main.mp4" watermark_image = "logo.png" output_video = "output_with_logo.mp4" # 使用 overlay 滤镜 # 这里将logo放在右上角,距离右边框10像素,上边框10像素 stream = ffmpeg.input(input_video) logo = ffmpeg.input(watermark_image) stream = ffmpeg.filter(stream, 'overlay', logo, x='main_w-overlay_w-10', y=10) stream = ffmpeg.output(stream, output_video) ffmpeg.run(stream)overlay滤镜功能强大,x和y参数可以控制水印位置。main_w和overlay_w分别代表主视频和水印的宽度,利用它们可以方便地计算相对位置。
调整视频分辨率(缩放):
import ffmpeg input_file = "input_hd.mp4" output_file = "output_480p.mp4" # 使用 scale 滤镜将视频缩放至854x480分辨率 stream = ffmpeg.input(input_file) stream = ffmpeg.filter(stream, 'scale', 854, 480) # 宽,高 # 或者使用字符串格式:'scale=854:480' # 如果想保持原宽高比,可以只设置宽度或高度,另一个用-1代替,如:'scale=854:-1' stream = ffmpeg.output(stream, output_file) ffmpeg.run(stream)滤镜(Filter)是 FFmpeg 的灵魂,scale只是其中之一。通过组合不同的滤镜,你能实现非常复杂的视频处理效果。
5. 音频处理与流提取:不只是视频
FFmpeg 处理音频同样在行。很多时候我们只需要视频里的声音,或者想给视频替换一个背景音乐。
5.1 从视频中提取纯音频
这个需求太常见了,比如把一段演讲视频转换成 MP3 放在手机里听。
import ffmpeg input_video = "presentation.mp4" output_audio = "audio_only.mp3" # -vn 参数表示禁止视频流(no video) # -acodec copy 表示音频流复制,但通常MP4里的音频格式(如AAC)和MP3不兼容,所以需要指定编码器 # 更通用的方法是让 FFmpeg 自动转码 stream = ffmpeg.input(input_video) stream = ffmpeg.output(stream, output_audio, **{'q:a': 0, 'map': 'a'}) # 参数解释: # 'q:a': 0 设置音频质量,范围通常是0-5,0表示最高质量。 # 'map': 'a' 明确指定只处理音频流。 ffmpeg.run(stream)使用subprocess的方式命令更直观:ffmpeg -i presentation.mp4 -q:a 0 -map a audio_only.mp3。
5.2 替换或添加背景音乐
有时候视频原声嘈杂,想换一首干净的背景音乐。
import ffmpeg # 假设我们有一个无声的视频片段和一个音乐文件 video_input = "silent_clip.mp4" audio_input = "background_music.mp3" output_file = "video_with_bgm.mp4" # 分别输入视频和音频 video = ffmpeg.input(video_input) audio = ffmpeg.input(audio_input) # 使用 concat 滤镜?不对,这里应该用复杂的滤镜图,但更简单的方法是直接合并流 # 方法:使用 `-shortest` 参数,以较短的输入流结束 # 在 ffmpeg-python 中,可以通过 output 的参数实现 stream = ffmpeg.output(video, audio, output_file, **{'c:v': 'copy', 'c:a': 'aac', 'shortest': None}) # 参数解释: # 'c:v': 'copy' 视频流直接复制,不重新编码 # 'c:a': 'aac' 音频流编码为 AAC 格式(MP4常用) # 'shortest': None 以视频和音频中较短的那个为准结束输出 ffmpeg.run(stream)这个例子中,我们同时输入了视频和音频源,然后在输出时指定视频编码为复制,音频编码为 AAC,并设置shortest标志。这样生成的视频会使用新的背景音乐,并且长度与原视频一致(如果音乐更长,会被截断)。
5.3 调节音量大小
觉得视频声音太小?用volume滤镜轻松放大。
import ffmpeg input_file = "quiet_video.mp4" output_file = "louder_video.mp4" stream = ffmpeg.input(input_file) # 使用 volume 滤镜,将音量放大为原来的2倍 stream = ffmpeg.filter(stream, 'volume', 2.0) stream = ffmpeg.output(stream, output_file) ffmpeg.run(stream)volume=2.0表示音量翻倍。你也可以使用分贝(dB)单位,例如volume=10dB。减小音量则用小于1的倍数或负的分贝值。
6. 高级技巧与实战问题排查
当你熟悉了基本操作后,可能会遇到一些更复杂的需求或棘手的问题。这里分享几个我踩过坑后总结的高级技巧和排查方法。
6.1 使用滤镜图实现复杂效果
FFmpeg 真正的威力在于滤镜(Filter)。简单的操作如缩放、加水印是单个滤镜,复杂的则需要构建“滤镜图”。比如,你想先给视频缩放,然后加水印,最后再调整对比度。
在命令行中,这需要用复杂的-filter_complex参数。在ffmpeg-python中,虽然语法有所抽象,但逻辑一致。
import ffmpeg input_video = "input.mp4" output_video = "processed.mp4" # 创建输入流 stream = ffmpeg.input(input_video) # 应用一系列滤镜:先缩放,再叠加水印 # 注意:ffmpeg-python 的滤镜调用是链式的,但每个filter都返回一个新的流 scaled_stream = ffmpeg.filter(stream, 'scale', 1280, 720) watermark = ffmpeg.input('logo.png') # 将水印叠加到缩放后的流上,位置在左下角 watermarked_stream = ffmpeg.filter(scaled_stream, 'overlay', watermark, x=10, y='main_h-overlay_h-10') # 再调整一下对比度 final_stream = ffmpeg.filter(watermarked_stream, 'eq', contrast=1.2) # 输出最终流 stream = ffmpeg.output(final_stream, output_video) ffmpeg.run(stream)这个例子展示了滤镜的链式调用。每一步操作都清晰可读。eq是均衡器滤镜,可以调节对比度(contrast)、亮度(brightness)、饱和度(saturation)等。
6.2 获取视频的元信息(时长、分辨率、码率)
在处理视频前,我们常常需要先知道它的基本信息。FFmpeg 的姊妹工具ffprobe就是干这个的。我们可以用 Python 的subprocess调用它并解析 JSON 输出。
import subprocess import json def get_video_info(file_path): """获取视频文件的详细信息""" command = [ 'ffprobe', '-v', 'quiet', # 减少冗余输出 '-print_format', 'json', # 输出为JSON格式,便于解析 '-show_format', # 显示容器格式信息 '-show_streams', # 显示各个流(视频、音频)的信息 file_path ] result = subprocess.run(command, capture_output=True, text=True, check=True) info = json.loads(result.stdout) # 提取常用信息 format_info = info.get('format', {}) streams = info.get('streams', []) video_stream = next((s for s in streams if s['codec_type'] == 'video'), None) audio_stream = next((s for s in streams if s['codec_type'] == 'audio'), None) video_info = {} if video_stream: video_info['duration'] = float(video_stream.get('duration', format_info.get('duration', 0))) video_info['width'] = video_stream.get('width', 0) video_info['height'] = video_stream.get('height', 0) video_info['codec'] = video_stream.get('codec_name', 'N/A') video_info['bit_rate'] = int(video_stream.get('bit_rate', 0)) if audio_stream: video_info['audio_codec'] = audio_stream.get('codec_name', 'N/A') video_info['sample_rate'] = audio_stream.get('sample_rate', 'N/A') video_info['format_name'] = format_info.get('format_name', 'N/A') video_info['size'] = int(format_info.get('size', 0)) # 文件大小,单位字节 return video_info # 使用示例 info = get_video_info("your_video.mp4") print(f"视频时长:{info['duration']:.2f} 秒") print(f"分辨率:{info['width']}x{info['height']}") print(f"视频编码:{info['codec']}") print(f"文件大小:{info['size'] / (1024*1024):.2f} MB")这个函数返回一个字典,包含了视频的核心信息。在批量处理前先获取这些信息,可以用来判断文件是否完整、编码是否支持,或者动态决定处理参数。
6.3 常见错误与调试技巧
即使代码写对了,运行中也可能报错。学会看 FFmpeg 的错误信息是关键。
- “No such file or directory”:这是最典型的路径错误。再次检查你的文件路径字符串是否正确,特别是 Windows 下的反斜杠
\需要转义或使用原始字符串(r"path")或正斜杠(/)。 - “Invalid argument” / “Unrecognized option”:参数错误。仔细检查你传递给
ffmpeg-python函数的参数名和值,或者subprocess命令列表中的每一个元素。去 FFmpeg 官方文档查证参数的正确写法。 - 编码器错误(如 “Encoder ‘libx265’ not found”):你的 FFmpeg 版本没有编译进该编码器。运行
ffmpeg -encoders可以查看所有可用的编码器。对于常见的 H.264 (libx264)、H.265 (libx265),一般 full 版本都包含。如果缺失,你需要寻找包含该编码器的编译版本,或者自己编译 FFmpeg。 - 进程卡住或无输出:有时候脚本执行了,但似乎没反应。可能是 FFmpeg 在等待输入,或者处理大文件需要时间。在
subprocess.run()中,可以设置timeout参数来避免无限等待。同时,将stdout和stderr输出打印出来(就像我们之前的例子那样),是追踪进程状态的最佳方式。FFmpeg 通常会把进度信息输出到stderr。
一个实用的调试技巧:当你用ffmpeg-python写了一个复杂命令但出错时,可以先用.compile()方法看看它生成的实际 FFmpeg 命令行是什么。
stream = ffmpeg.input('in.mp4').output('out.mp4', vf='scale=640:480') cmd = ffmpeg.compile(stream) print("生成的FFmpeg命令:", ' '.join(cmd))把打印出来的命令复制到终端里直接运行,如果也出错,就能确定是 FFmpeg 命令本身的问题,而不是 Python 包装器的问题。这能极大缩小排查范围。
7. 构建一个简单的批量视频处理器
学以致用,最后我们来整合前面学到的知识,写一个实用的脚本:批量压缩某个文件夹下的所有视频文件,并生成一份处理报告。这个场景非常实际,比如整理手机相册、为网站准备素材等。
假设我们的目标是:遍历指定文件夹,找到所有.mp4和.mov文件,将它们的分辨率统一压缩至 720p 高度(宽度按比例自适应),并转换为 H.264 编码的 MP4 格式,以节省空间。同时,记录每个文件处理前后的体积变化。
import os import subprocess import json from pathlib import Path def compress_video(input_path, output_folder, crf=23): """ 压缩单个视频文件。 :param input_path: 输入视频文件路径 :param output_folder: 输出文件夹路径 :param crf: 压缩质量参数,范围18-28,值越大压缩率越高、质量越低。23是常用平衡值。 :return: 字典,包含处理结果信息 """ input_file = Path(input_path) # 构建输出文件名,在原文件名后加 `_compressed` output_filename = input_file.stem + '_compressed' + input_file.suffix output_path = Path(output_folder) / output_filename # 使用FFmpeg命令进行压缩 # 参数解释: # -i 输入文件 # -vf "scale=-2:720" 缩放视频,高度为720像素,宽度自动按比例计算(-2表示保持宽高比且宽度为偶数) # -c:v libx264 使用H.264编码器 # -crf 23 质量系数 # -preset medium 编码速度与压缩率的平衡预设。可选:ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow # -c:a aac 音频编码为AAC # -b:a 128k 音频比特率 command = [ 'ffmpeg', '-i', str(input_file), '-vf', 'scale=-2:720', '-c:v', 'libx264', '-crf', str(crf), '-preset', 'medium', '-c:a', 'aac', '-b:a', '128k', '-y', # 自动覆盖输出文件(如果存在) str(output_path) ] result_info = { 'input': str(input_file), 'output': str(output_path), 'success': False, 'error': None, 'original_size': input_file.stat().st_size, 'compressed_size': None } try: # 运行命令,并捕获输出 process = subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, timeout=300) # 设置5分钟超时 output_path_obj = Path(output_path) if output_path_obj.exists(): result_info['compressed_size'] = output_path_obj.stat().st_size result_info['success'] = True compression_ratio = (1 - result_info['compressed_size'] / result_info['original_size']) * 100 print(f"成功: {input_file.name} -> 压缩率 {compression_ratio:.1f}%") else: result_info['error'] = "输出文件未生成" except subprocess.CalledProcessError as e: result_info['error'] = f"FFmpeg错误: {e.stderr[:200]}" # 截取前200字符错误信息 print(f"失败: {input_file.name} - {result_info['error']}") except subprocess.TimeoutExpired: result_info['error'] = "处理超时" print(f"超时: {input_file.name}") except Exception as e: result_info['error'] = f"其他错误: {str(e)}" print(f"异常: {input_file.name} - {result_info['error']}") return result_info def batch_compress_folder(input_folder, output_folder, extensions=('.mp4', '.mov', '.avi', '.mkv')): """ 批量压缩文件夹内的视频文件。 """ input_folder = Path(input_folder) output_folder = Path(output_folder) output_folder.mkdir(parents=True, exist_ok=True) # 创建输出文件夹 report = [] # 遍历文件夹,查找指定扩展名的视频文件 for file_path in input_folder.iterdir(): if file_path.is_file() and file_path.suffix.lower() in extensions: print(f"开始处理: {file_path.name}") result = compress_video(file_path, output_folder) report.append(result) # 生成简单的处理报告 print("\n===== 批量处理报告 =====") successful = [r for r in report if r['success']] failed = [r for r in report if not r['success']] print(f"总计处理文件: {len(report)} 个") print(f"成功: {len(successful)} 个") print(f"失败: {len(failed)} 个") if successful: total_original = sum(r['original_size'] for r in successful) total_compressed = sum(r['compressed_size'] for r in successful) avg_ratio = (1 - total_compressed / total_original) * 100 print(f"总体积变化: {total_original / (1024**3):.2f} GB -> {total_compressed / (1024**3):.2f} GB") print(f"平均压缩率: {avg_ratio:.1f}%") if failed: print("\n失败文件列表:") for r in failed: print(f" - {r['input']}: {r['error']}") # 可以将报告保存为JSON文件 report_file = output_folder / 'compression_report.json' with open(report_file, 'w', encoding='utf-8') as f: json.dump(report, f, indent=2, ensure_ascii=False) print(f"\n详细报告已保存至: {report_file}") # 使用示例 if __name__ == "__main__": # 请修改为你的实际文件夹路径 input_dir = "./videos_to_compress" # 待处理的视频文件夹 output_dir = "./compressed_videos" # 输出文件夹 batch_compress_folder(input_dir, output_dir)这个脚本展示了如何将零散的知识点整合成一个实用的工具。它包含了文件遍历、路径处理、子进程调用、错误处理、超时控制、结果统计和报告生成。你可以根据自己的需求修改压缩参数(如crf、preset)、支持更多视频格式,或者添加更复杂的功能,比如并行处理(使用concurrent.futures模块)来加速大批量任务。
运行这个脚本,你就能体会到用 Python 驾驭 FFmpeg 进行自动化批量处理的效率和乐趣了。它把原本需要手动重复操作几十次、上百次的工作,变成了一杯咖啡时间就能完成的自动任务。这正是 Python + FFmpeg 组合的魅力所在——将强大的专业工具变得平易近人,让复杂的多媒体处理任务变得简单可控。
