Python subprocess调用FFmpeg提取场景变化时间戳无输出问题求助
解决Subprocess调用FFmpeg批量提取场景变化时间戳的输出重定向问题
嘿,我懂你的困扰——之前单个视频用命令行时,靠>就能把FFmpeg的场景检测输出存到文件,但用subprocess批量处理时直接加这个参数完全不管用,对吧?这是因为命令行里的>重定向是shell的专属功能,而subprocess默认是直接执行FFmpeg程序,不会把这些符号当成重定向指令来解析,自然达不到你想要的效果。
下面给你两种靠谱的实现方式,完美适配你批量处理数百个视频的需求:
方法1:直接通过subprocess的stdout参数写入文件(推荐,更安全)
这种方式不需要依赖shell,能完美避开文件名含空格、特殊字符(比如引号、括号)时的坑,非常适合批量处理场景:
import os import subprocess # 替换成你的视频文件夹路径 source_dir = "/your/video/folder/path" # 替换成你想保存时间戳文件的路径 output_dir = "/your/output/folder/path" # 先确保输出文件夹存在,避免报错 os.makedirs(output_dir, exist_ok=True) # 遍历文件夹里的所有mpg视频 for filename in os.listdir(source_dir): if filename.lower().endswith(".mpg"): video_full_path = os.path.join(source_dir, filename) # 生成对应的输出文件名,比如把"video.mpg"改成"video_scenes.txt" output_filename = f"{os.path.splitext(filename)[0]}_scenes.txt" output_full_path = os.path.join(output_dir, output_filename) # 打开输出文件,让subprocess把FFmpeg的输出直接写入 with open(output_full_path, "w", encoding="utf-8") as output_file: try: # 这里替换成你完整的FFmpeg场景检测命令 subprocess.check_output( [ "ffmpeg", "-i", video_full_path, "-vf", "select='gt(scene,0.4)',showinfo", # 0.4是场景变化阈值,可调整 "-f", "null", "-" # 丢弃视频流,只输出日志信息 ], stdout=output_file, stderr=subprocess.STDOUT # 如果需要把FFmpeg的错误信息也写入文件,就加这行 ) print(f"✅ 处理完成:{filename}") except subprocess.CalledProcessError as e: # 注意:FFmpeg有时会返回非0状态码但实际完成了检测,你可以根据实际情况调整这里的逻辑 print(f"⚠️ 处理{filename}时出现异常:{e}")
方法2:用shell=True直接沿用命令行重定向写法(适合熟悉shell的情况)
如果你想直接照搬命令行里的重定向写法,可以开启shell=True,但一定要注意用shlex.quote处理文件路径,避免文件名含特殊字符时出现错误:
import os import subprocess import shlex source_dir = "/your/video/folder/path" output_dir = "/your/output/folder/path" os.makedirs(output_dir, exist_ok=True) for filename in os.listdir(source_dir): if filename.lower().endswith(".mpg"): video_full_path = os.path.join(source_dir, filename) output_filename = f"{os.path.splitext(filename)[0]}_scenes.txt" output_full_path = os.path.join(output_dir, output_filename) # 构造完整的shell命令,用shlex.quote转义路径,防止特殊字符搞砸命令 cmd = f"""ffmpeg -i {shlex.quote(video_full_path)} \ -vf 'select=gt(scene,0.4)',showinfo -f null - > {shlex.quote(output_full_path)}""" try: subprocess.check_output(cmd, shell=True) print(f"✅ 处理完成:{filename}") except subprocess.CalledProcessError as e: print(f"⚠️ 处理{filename}时出现异常:{e}")
额外小技巧
如果你只想提取干净的场景变化时间戳,而不是FFmpeg的完整showinfo日志,可以把showinfo换成更针对性的滤镜,比如:
-vf "select='gt(scene,0.4)',print_ts=format=hms"
这样FFmpeg会直接输出类似00:01:23.456的时间戳,后续处理起来更方便。
内容的提问来源于stack exchange,提问作者Ashuiegi
相关产品推荐
相关产品推荐

