Pyinstaller打包exe后调用FFmpeg设置quiet=True报WinError6句柄无效错误
错误产生原因
该错误是Windows平台下PyInstaller无控制台打包的典型兼容性问题,触发逻辑如下:
- 当你使用
PyInstaller -w/--noconsole参数打包为无控制台窗体程序时,Windows系统不会为程序分配标准输入(stdin)、标准输出(stdout)、标准错误(stderr)三个标准流的有效句柄 - ffmpeg-python的
quiet=True参数底层会调用subprocess尝试将ffmpeg的stdout、stderr重定向到管道,同时关闭stdin,此时读取不存在的流句柄就会抛出WinError 6 句柄无效错误,独立线程调用的场景会进一步放大该句柄获取异常 - 当
quiet=False时,ffmpeg直接继承父进程的输出,不需要重定向流,所以不会触发错误,但会弹出独立的ffmpeg控制台黑窗
可行解决方案
方案1:手动配置subprocess启动参数(最推荐,无黑窗+无报错)
不用ffmpeg-python封装的quiet参数,手动通过Windows原生的STARTUPINFO配置隐藏黑窗,同时主动捕获输出避免重定向异常,修改后的代码如下:
import os import sys import subprocess import ffmpeg if getattr(sys, 'frozen', False): application_path = sys._MEIPASS elif __file__: application_path = os.path.dirname(__file__) ffmpegName = 'ffmpeg.exe' ffmpegPath = os.path.join(application_path, ffmpegName) # 配置Windows下隐藏控制台窗口的启动参数 startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW startupinfo.wShowWindow = subprocess.SW_HIDE video_stream = ffmpeg.input(file[0]) audio_stream = ffmpeg.input(file[1]) ffmpeg.output(audio_stream, video_stream, path).run( overwrite_output=True, cmd=ffmpegPath, # 去掉quiet=True,改用下面两个参数捕获输出,同时传启动参数隐藏窗口 capture_stdout=True, capture_stderr=True, startupinfo=startupinfo )
方案2:调整PyInstaller打包参数
如果可以接受程序运行时保留主控制台窗口,打包时去掉-w/--noconsole参数即可,此时系统会分配有效的标准流句柄,原本的quiet=True参数可以正常使用,也不会弹出额外的ffmpeg黑窗。
方案3:手动指定ffmpeg日志级别
直接给ffmpeg传入静默日志参数,不需要依赖ffmpeg-python的流重定向逻辑,同时配置启动参数隐藏窗口:
# 其他代码不变,output时添加日志参数 ffmpeg.output(audio_stream, video_stream, path, loglevel='quiet').run( overwrite_output=True, cmd=ffmpegPath, startupinfo=startupinfo )
内容的提问来源于stack exchange,提问作者Taufiq Abdur Rahman
相关产品推荐
相关产品推荐

