pyinstaller打包PySide2写的GUI程序,调用ffmpeg隐藏CMD控制台解决方案

1 问题描述

使用PySide2写了一个GUI程序,调用ffmpeg命令行工具,做简单的批量视频处理(调整帧宽度、帧高度、视频变速、降低视频码率达到限制视频大小),使用了ffmpeg、 ffmpeg-python库;
挺简单的事儿,但遇到一个问题:

pyinstaller打包程序时:

  1. 不加 -w 或 --noconsole,有CMD丑黑框,程序可以正常运行,但是程序界面背后一个大大的CMD黑框真心难看。。。
  2. 加上 -w 或 --noconsole,没有CMD黑框,程序会直接无限等待,无法正常运行,猜测是调用 ffmpeg 时需要一个shell环境供PIPE的输入输出

2 解决方案

心急的直接看 2.2 隐藏CMD黑框。。。

2.1 CMD黑框依旧在,不显示verbose信息(治标不治本)

  1. 使用subprocess.call():

    调用CMD命令时,在 ffmpeg 后面的参数加上 -loglevel quiet,就只有黑框,不显示实时进度信息

  2. 使用ffmpeg、ffmpeg-python库

    ffmpeg.run(quiet=True),将quiet设置为 True,就只有黑框,不显示实时进度信息

2.2 隐藏CMD黑框(啊哈哈哈舒服了)

(我使用到了ffmpeg库的 probe(调用ffprobe.exe获取视频流信息)和run(调用ffmpeg.exe执行操作)方法)

  1. 找到ffmpeg库的 **_probe.py** 和 **_run.py** 文件

    备份这两个文件,修改完、打包完程序后再恢复原样

    把这两文件复制到桌面修改好再放回去(这步坑了我一点时间,win10没用管理员权限打开文件,由于ffmpeg库安装在C盘的Program...路径下,在PyCharm中做出的修改一直没保存。。。)

  2. 修改 _probe.py

    源码: p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    Popen 参数添加 shell=True, stdin=subprocess.PIPE

    def probe(filename, cmd='ffprobe', **kwargs):
        """Run ffprobe on the specified file and return a JSON representation of the output.
    
        Raises:
            :class:`ffmpeg.Error`: if ffprobe returns a non-zero exit code,
                an :class:`Error` is returned with a generic error message.
                The stderr output can be retrieved by accessing the
                ``stderr`` property of the exception.
        """
        args = [cmd, '-show_format', '-show_streams', '-of', 'json']
        args += convert_kwargs_to_cmd_line_args(kwargs)
        args += [filename]
    
        # 源码: p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        # Popen 参数添加 shell=True, stdin=subprocess.PIPE,
    
        p = subprocess.Popen(args, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        out, err = p.communicate()
        if p.returncode != 0:
            raise Error('ffprobe', out, err)
        p.wait()
        return json.loads(out.decode('utf-8'))
  3. 修改 _run.py

    源码: return subprocess.Popen(args, stdin=pipe_stdin, stdout=stdout_stream, stderr=stderr_stream)
    添加 shell=True, 修改 stdin=subprocess.PIPE 或者修改 pipe_stdin=True

    def run_async(
            stream_spec,
            cmd='ffmpeg',
            pipe_stdin=False,
            pipe_stdout=False,
            pipe_stderr=False,
            quiet=False,
            overwrite_output=False,
    ):
        args = compile(stream_spec, cmd, overwrite_output=overwrite_output)
        stdin_stream = subprocess.PIPE if pipe_stdin else None
        stdout_stream = subprocess.PIPE if pipe_stdout or quiet else None
        stderr_stream = subprocess.PIPE if pipe_stderr or quiet else None
    
        # 源码: return subprocess.Popen(
        #            args, stdin=pipe_stdin, stdout=stdout_stream, stderr=stderr_stream)
        # 添加 shell=True, 修改 stdin=subprocess.PIPE或者修改 pipe_stdin=True
    
        return subprocess.Popen(
            args, shell=True, stdin=subprocess.PIPE, stdout=stdout_stream, stderr=stderr_stream
        )
  4. 将修改完的 _probe.py 和 _run.py 放回 ffmpeg库
  5. pyinstaller 打包程序时,添加 -w 或 --noconsole参数,这时CMD黑框就不显示了

    ==黑框没有了,一切都舒服了==

附1:不用ffmpeg库,而是直接使用 subprocess调用ffmpeg.exe的,只需要在调用subprocess.Popen()时指定参数 shell=True, stdin=subprocess.PIPE 即可

**附2:打包完程序,把备份的 _probe.py 和 _run.py 恢复到ffmpeg库里,不知道这么写有啥不好的影响,还是恢复原样吧**

参考1:https://blog.csdn.net/polyhedronx/article/details/82432148 ------ subprocess.Popen设置shell=True,stdin=subprocess.PIPE
参考2:https://my.oschina.net/u/2396236/blog/1610765 ------ subprocess.Popen设置shell=True,stdin=subprocess.PIPE
参考3:https://blog.csdn.net/iserfj/article/details/94487538 ------ creationflags=0x08000000 或者 creationflags=subprocess.CREAT_NO_WINDOW(这个方法我尝试无效)

原文地址:https://www.cnblogs.com/hard-snail/p/12154532.html

时间: 2024-08-27 22:36:54

pyinstaller打包PySide2写的GUI程序,调用ffmpeg隐藏CMD控制台解决方案的相关文章

pyinstaller 打包python文件成.exe程序

使用pycharm写好的代码,每次都要使用pycharm来执行比较麻烦,打包成.exe程序后可以直接运行,还可以发到别的电脑上执行,比较方便. 1.打开cmd命令提示符窗口,cd到pip.exe所在的目录,使用pip.exe install pyinstaller命令安装pyinstaller模块(前提是你的电脑已经安装了python),安装完成后会在目录下生成很多py文件. 2.使用命令pyinstaller -c -F weixin.py生成weixin.exe程序 执行完之后会在当前目录下

使用PyInstaller打包Python程序

使用PyInstaller打包Python程序 PyInstaller介绍: PyInstaller是一个能将Python程序转换成单个可执行文件的程序, 操作系统支持Windows, Linux, Mac OS X, Solaris和AIX.并且很多包都支持开箱即用,不依赖环境. 环境为windows7操作系统,python2.7.8 virtual environment 官网:https://github.com/pyinstaller/pyinstaller 详细步骤: 1. win7下

笔记: c开发gui程序 (WM_CREATE, WS_CLIPCHILDREN , SetWindowPos)

过去两年,用c写的gui程序我一般使用的套路是: 在 winMain()中, 先创建一个主窗口, 紧接着就是在下面创建子窗口(子控件). 可能是因为写这方面的程序较少,所以也没遇到什么大问题,之前就是想枚举主窗口所有子窗口,然后设置所有子窗口的字体时使用:EnumChildWindows()会意外的抛内存访问错误,记得当时就是把EnumChildWindows()在winMain()中向前或向后移了一下位置,就没有报内存访问错误了. 我还以为只需要移动一下EnumChildWindows()在w

Qt GUI程序显示控制台调试信息

1.在.pro文件中添加CONFIG += console 2.在运行设置中勾选"Run in terminal" 在测试GUI程序时,想在控制台查看打印信息,设置上面两步就可以实现 原文地址:https://www.cnblogs.com/JiaoAbel/p/8440423.html

用PyInstaller打包用PyQt5编写的python程序

0.背景 本弱初学PyQt5,写了一个GUI小程序,但在用PyInstaller打包时出现了不少问题,现将几个比较大的问题记录如下,希望以后能记住. 1. 资源打包 首先是资源打包的问题,我写的程序引用了一张图片,那么在没经过特殊处理的情况下如果想让程序正常运行,就必须把图片放在和程序同一个目录下,但这样总觉得不太舒服.我在网上看到有三种解决方法:一是通过修改PyInstall配置文件*.spec来实现打包,但是在我的环境下不成功:二是自己写程序对图片进行Base64编码存在字符串里并存储在另一

普通 java 工程调用 arcobject 功能,打包成独立可运行程序后,用脚本调用

写在前面: 在实验 java 调用 ArcObject(下文简称AO),开发业务功能时,遇到了普通 java 工程可以正常运行,而在将工程改为 web 后台,放在 tomcat 中运行时,出现了错误,具体错误信息已在其他文章说明,在些不在赘述,开发功能是不可少的,既然出现了问题,就要解决问题,遂想到将开发的 AO 程序,打包可独立可运行 jar 包,以 cmd 的方式调用,不也能解决问题吗,于是开始测试,不想测试成功,在此记录,以备将来查询. (注:打包的独立可运行的调用了 AO 接口 jar

pyinstaller打包程序 带图片

首选说一下,这种打包方式只能在本电脑上使用运行正常 准备:.py文件:你的程序 gif文件:你要用的图片 第一步: 在上面文件所在目录打开cmd 输入 pyi-makespec FP.py 会生成一个FP.spec 他是pyinstaller打包程序的指导书 fp是我自己取得名字,你要按照你的.py文件取名字. 第二步: 上面的变量其实就是你的图片的path 使用图片: photo = tk.PhotoImage(file='./socket_one.gif')  这是我正常写代码不打包时使用图

C#程序调用C++写的dll传递string出现bad ptr

本来是做C/C++的,因为项目需要,所以才搞的C#,说实话,很鄙视做C#的,总结起来,扯淡的DllImport,有本事别用这破玩意,看你C#还能干啥? 参考网上的按照下面的方式来,结果在C++的dll库中打断点,第二个参数怎么都是bad ptr,郁闷至极,耗费了两天的功夫,都没有搞定,也参考了:http://blog.csdn.net/yongshengsilingsa/article/details/7917877 的文章,也无济于事.最后就索性自己再写个简单的dll和exe,只有一个接口,调

Delphi7程序调用C#写的DLL解决办法(转)

近来,因工作需要,必须解决Delphi7写的主程序调用C#写的dll的问题.在网上一番搜索,又经过种种试验,最终证明有以下两种方法可行:    编写C#dll的方法都一样,首先在vs2005中创建一个"类库"项目TestDll,using System.Runtime.InteropServices;namespace TestDll{public interface  I TestClass  {     void YourProcedure(stirng param1);}[Cla