Python调用FFmpeg处理音视频文件的几种方式
Python调用FFmpeg处理音视频文件主要有三种方式:subprocess.run执行一次性任务、Popen实时获取进度、配合Pathlib批量处理。需注意设置超时、检查FFmpeg路径、处理文件锁及中文路径编码问题,不同版本进度格式需做兼容匹配。
做后端开发的,多少都会遇到需要程序自动处理音视频文件的场景——给用户上传的视频压缩一下、从录屏里提取音频、或者把一堆图片合成一个视频。FFmpeg 是这类任务的事实标准,但 Python 里怎么调它效率最高、最稳定,这里把踩过的坑和总结出来的方案一次性说清楚。

一、最基础的方式:subprocess.call
最简单的做法就是直接传命令字符串:
import subprocess
# 提取音频
subprocess.call([
'ffmpeg', '-i', 'input.mp4',
'-vn', '-c:a', 'mp3', 'output.mp3'
])
call 会阻塞直到命令执行完,返回退出码。好处是简单,坏处是如果命令耗时很长(比如压缩一个 2GB 的视频),程序界面就会卡住。
二、推荐方式:subprocess.run
Python 3.5+ 推荐用 run,它返回一个 CompletedProcess 对象,可以拿到退出码、标准输出和标准错误:
import subprocess
result = subprocess.run(
['ffmpeg', '-i', 'input.mp4', '-vf', 'scale=1280:720', 'output.mp4'],
capture_output=True,
text=True,
timeout=300
)
if result.returncode == 0:
print('转换成功')
else:
print('转换失败:', result.stderr)
这里有一个容易忽略的点:timeout 参数。不加的话,FFmpeg 因为某些原因卡住(比如输入文件损坏),你的 Python 进程也会一直挂着。设一个合理的超时时间是个好习惯。
三、进阶:实时获取处理进度
FFmpeg 处理大文件时进度信息是输出到 stderr 的,格式大概这样:
frame= 120 fps=30.0 time=00:00:04.00 bitrate=128.0kbits/s speed=1.0x
如果你需要实时显示进度条,可以用 stderr 的管道逐行读取:
import subprocess
import re
def convert_with_progress(input_path, output_path):
cmd = [
'ffmpeg', '-i', input_path,
'-c:v', 'libx264', '-preset', 'medium',
'-progress', 'pipe:1', # 进度信息输出到 stdout
output_path
]
process = subprocess.Popen(
cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
universal_newlines=True, bufsize=1
)
for line in process.stdout:
match = re.search(r'out_time_us=(d+)', line)
if match:
us = int(match.group(1))
seconds = us / 1_000_000
print(f'已处理: {seconds:.1f} 秒', end='r')
process.wait()
if process.returncode == 0:
print('n处理完成')
else:
error = process.stderr.read()
print(f'n处理失败: {error[:200]}...')
convert_with_progress('large_video.mp4', 'compressed.mp4')
这里用 -progress pipe:1 让 FFmpeg 把进度信息输出到 stdout 而不是 stderr,方便 Python 读取。bufsize=1 确保逐行读取而不是等缓冲区满。
四、批量处理:结合 Pathlib
处理文件夹下的所有文件时,用 pathlib 搭配 FFmpeg 比 os.path 顺手得多:
from pathlib import Path
import subprocess
def batch_convert_to_mp3(input_dir: str, output_dir: str, bitrate='192k'):
src = Path(input_dir)
dst = Path(output_dir)
dst.mkdir(parents=True, exist_ok=True)
files = list(src.glob('*.*'))
for i, file in enumerate(files, 1):
if file.suffix.lower() not in ('.mp4', '.mkv', '.mov', '.a vi'):
continue
output = dst / f'{file.stem}.mp3'
print(f'[{i}/{len(files)}] {file.name}')
subprocess.run([
'ffmpeg', '-y', '-i', str(file),
'-vn', '-c:a', 'libmp3lame',
'-b:a', bitrate,
str(output)
], capture_output=True)
batch_convert_to_mp3('./videos', './audios')
-y 参数自动覆盖已有文件,避免交互式确认导致脚本卡住。这在批量处理时几乎必加。
五、几个常见的错误及处理
1. FFmpeg 不在 PATH 里
Windows 上最容易遇到。建议在脚本开头检查:
import shutil
ffmpeg_path = shutil.which('ffmpeg')
if not ffmpeg_path:
raise RuntimeError('未找到 FFmpeg,请确认已安装并加入系统 PATH')
2. 输入文件被占用
Windows 上如果文件正在被其他程序使用(比如你刚用播放器打开了它),FFmpeg 会报 Permission denied。建议操作前先尝试用只读模式打开文件确认没被锁:
def is_file_locked(filepath):
try:
with open(filepath, 'rb') as f:
return False
except PermissionError:
return True
3. 中文字符路径
Windows 下路径包含中文时,建议用 Path 对象的 resolve() 获取绝对路径传给 FFmpeg,避免编码问题。
4. 进度信息解析失败
不同版本的 FFmpeg 输出的进度格式可能有细微差异。建议做两层匹配,先试新版格式再试旧版:
match = re.search(r'out_time_us=(d+)', line)
if not match:
match = re.search(r'time=(d+):(d+):(d+).(d+)', line)
总结
Python 调 FFmpeg 的核心模式就三个:subprocess.run 跑一次性任务、Popen 读进度、配合 pathlib 做批量。大部分坑都出在路径编码、超时处理、文件锁这三个地方,写脚本时注意绕开就行。
WPS Office是一款面向macOS用户的综合办公套件,将文字处理、电子表格、演示文稿、PDF工具、模板与云协作整合在同一应用中。它兼容常见Microsoft Office格式,支持Intel及Apple芯片Mac,基础功能可免费使用,
Shapr3D是一款面向工业设计、机械工程、建筑概念和三维打印工作流的CAD软件。Mac版采用Parasolid建模内核,支持草图约束、实体建模、工程图、可视化渲染及常见CAD格式交换,并可通过账户在多台设备之间同步项目。
REAPER是Cockos开发的数字音频工作站,提供多轨音频与MIDI录制、剪辑、处理、混音和母带制作工具。Mac版兼容Intel与Apple芯片,支持AU、VST、VST3、CLAP等插件格式,并提供高度可定制的工作流程。
Adobe Photoshop 是面向摄影师、设计师和内容创作者的专业图像处理工具,可在 Windows 上完成照片修饰、选区抠图、图层合成、文字排版、绘画及生成式编辑。软件采用订阅授权,由 Creative Cloud 管理安装、更新与许
Adobe InDesign 是面向印刷与数字出版的专业页面排版工具,可制作书籍、杂志、宣传册、海报、交互式 PDF 和电子书。它提供精细的文字样式、多页面管理、印前检查及多格式输出能力,并能与 Photoshop、Illustrator
Adobe Illustrator 是用于绘制矢量图形、插画、图标、徽标和版式的专业设计工具。它以路径和锚点为核心,作品放大后仍能保持清晰,并提供画板、文字、渐变、图像描摹及精确变换等功能,适合品牌视觉、印刷物料、数字界面和商业插画创作。













