如何在Python中获取ffprobe元数据并转为可解析变量(解决subprocess调用异常)
解决Python中调用ffprobe获取元数据的问题
我来帮你拆解下问题根源,再给出实用的解决方案:
为什么你的代码没生效?
1. shell=True时变量为空的原因
ffprobe默认会把视频元数据输出到标准错误流(stderr),而非标准输出流(stdout)。你之前的代码只捕获了stdout,所以变量data是空字符串;但终端能看到输出,是因为stderr默认会直接打印到控制台。
2. 不用shell=True时报“文件未找到”的原因
当禁用shell=True时,subprocess要求你把命令拆分成参数列表传递,而不是传一个完整的字符串。如果你直接传f'ffprobe {vid}',subprocess会把整个字符串当作要执行的程序名,而非调用ffprobe并把视频路径作为参数,自然会报错找不到文件。
正确的解决方案
方法1:捕获stderr(基础版)
如果只想拿到和终端一致的原始输出,可以这样写:
import subprocess video_path = "../directConversion/200mbs105_55.mp4" # 用列表形式传递命令参数,规避shell=True的安全风险 cmd = ['ffprobe', video_path] # 同时捕获stdout和stderr,text=True让输出为字符串而非字节 result = subprocess.run(cmd, capture_output=True, text=True) # 元数据存储在stderr中 raw_metadata = result.stderr print(raw_metadata)
方法2:输出JSON格式(推荐,方便解析)
ffprobe支持直接输出JSON格式的元数据,这样在Python里可以直接用json模块解析成字典,省去自己处理文本的麻烦:
import subprocess import json video_path = "../directConversion/200mbs105_55.mp4" # 构建ffprobe命令,添加参数让输出更简洁且标准化 cmd = [ 'ffprobe', '-v', 'quiet', # 隐藏ffprobe版本等冗余信息 '-print_format', 'json',# 指定输出格式为JSON '-show_format', # 输出容器格式的元数据 '-show_streams', # 输出视频、音频流的详细信息 video_path ] result = subprocess.run(cmd, capture_output=True, text=True) # 此时输出会存储在stdout中 metadata = json.loads(result.stdout) # 直接通过字典访问所需信息 print(f"视频时长: {metadata['format']['duration']} 秒") print(f"视频编码格式: {metadata['streams'][0]['codec_name']}") print(f"音频比特率: {metadata['streams'][1]['bit_rate']} bps")
额外提示
- 尽量避免使用
shell=True,它存在命令注入的安全风险,且处理带空格、中文或特殊字符的路径时容易出问题。 - 用参数列表传递命令时,subprocess会自动处理路径中的特殊字符,无需手动转义。
内容的提问来源于stack exchange,提问作者connor449
相关产品推荐
相关产品推荐

