【问题标题】:PortAudio library not found by sounddevice during runtime [WINDOWS]运行时声音设备未找到 PortAudio 库 [WINDOWS]
【发布时间】:2019-12-19 06:31:21
【问题描述】:

问题:this question for Linux 类似,在使用pyinstaller 打包我的应用程序并执行.exe 后,我遇到了OSError: PortAudio library not found。 (注意,当我通过 shell 运行未打包的应用程序时,我没有遇到任何问题。这只发生在我使用 pyinstaller 打包它时)。

虽然通过包管理器安装portaudio 似乎适用于Linux,但这似乎不是Windows 的选项,因为sounddevice docs 说,“如果您使用的是Mac OS X 或Windows,该库将使用 pip 自动安装”并执行 pip search portaudio 仅返回包装器

问题 我需要做什么才能让sounddevice 在我的 Windows 环境中工作? 为什么它在我的 shell 中可以工作,但在打包应用程序后却不行?

完全错误:

(venv) λ my-app.exe
Traceback (most recent call last):
  File "site-packages\sounddevice.py", line 71, in <module>
OSError: PortAudio library not found

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "point-of-service-recorder.py", line 11, in <module>
    import sounddevice as sd
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "c:\path\to\my\app\venv\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 627, in exec_module
    exec(bytecode, module.__dict__)
  File "site-packages\sounddevice.py", line 83, in <module>
OSError: cannot load library 'C:\Users\TYLER~1.HIT\AppData\Local\Temp\_MEI250242\_sounddevice_data\portaudio-binaries\libportaudio32bit.dll': error 0x7e
[23156] Failed to execute script point-of-service-recorder

构建输出

  • 运行 pyinstaller build 的选定输出:
[...]

22251 INFO: Looking for dynamic libraries
22260 INFO: Cannot get manifest resource from non-PE file c:\users\path\to\app\venv\lib\site-packages\_soundfile_data\COPYING
22262 WARNING: Can not get binary dependencies for file: c:\users\path\to\app\venv\lib\site-packages\_soundfile_data\COPYING
22262 WARNING:   Reason: 'DOS Header magic not found.'

安装包

  • 请注意,cffisounddevicesetuptools 存在,如要求所指定。 portaudio 未列出,但我认为它包含在 sounddevice 中,就像文档说的 (?)
(venv) λ pip list            
Package        Version       
-------------- ---------     
altgraph       0.16.1              
certifi        2019.6.16     
cffi           1.12.3        
chardet        3.0.4         
Click          7.0           
Flask          1.1.1         
Flask-WTF      0.14.2        
future         0.17.1        
idna           2.8           
itsdangerous   1.1.0         
Jinja2         2.10.1        
MarkupSafe     1.1.1         
numpy          1.17.0        
pefile         2019.4.18     
pip            19.2.2        
pycparser      2.19          
pydub          0.23.1        
PyInstaller    3.5           
pywin32-ctypes 0.2.0         
requests       2.22.0        
setuptools     41.0.1        
sounddevice    0.3.13        
SoundFile      0.10.2        
urllib3        1.25.3        
waitress       1.3.0         
Werkzeug       0.15.5        
wheel          0.33.4        
WTForms        2.2.1         

【问题讨论】:

    标签: python portaudio python-sounddevice


    【解决方案1】:

    对此有些尴尬,但我没有在构建中包含所需的端口音频 .dll。将它们复制到 env\site-packages 并更新 sounddevice.py 以指向正确的 .dll 对我有用


    编辑

    可以在以下位置找到预构建的 dll:https://github.com/spatialaudio/portaudio-binaries

    我将它们添加到 /bin 目录并更新 sounddevice.py 以使用它们(代码如下)


    这是我从 v0.3.13 更新的 sounddevice.py(手动更改以 #! 标记)

    import atexit as _atexit
    import os as _os
    import platform as _platform
    import sys as _sys
    from ctypes.util import find_library as _find_library
    from _sounddevice import ffi as _ffi
    
    
    #! built path to my dlls (in my `bin` dir)
    #! use _platform.architecture to infer whether to use 32 or 64-bit dll
    try:
        _libname = 'libportaudio' + _platform.architecture()[0] + '.dll'
        _libname = _os.path.join('bin', _libname)
        _lib = _ffi.dlopen(_libname)
    except OSError:
        if _platform.system() == 'Windows':  #! use Windows, not default 'Darwin'
            _libname = 'libportaudio' + _platform.architecture()[0] + '.dll'
        else:
            #! custom error
            raise OSError('PortAudio library not found! Make sure the system is Windows 64 or 32 bit and you have the '
                          'correct libportaudio dll saved in  site-packages')
    
    #! keep rest the same
    

    在设置我的开发环境时,我运行这个 bat 脚本以使用我的自定义环境更新虚拟环境中的默认 sounddevice.py

    echo Updating sounddevice.py ...
    copy .\sounddevice.py .\venv\Lib\site-packages\sounddevice.py /y
    copy .\libportaudio32bit.dll .\venv\Lib\site-packages\libportaudio32bit.dll /y
    copy .\libportaudio64bit.dll .\venv\Lib\site-packages\libportaudio64bit.dll /y
    
    

    提示:确保您锁定 sounddevice 版本(例如在 requirements.txt 中),这样以后的版本就不会破坏这个 hack

    【讨论】:

    • 我遇到了这个问题。您能否更详细地说明您在何处找到要复制到 env\site-packages 文件夹中的 .dll,以及您如何准确地更新 sounddevice.py 以指向 .dll 将不胜感激。我已经看到其他类似的问题没有解决。
    【解决方案2】:

    我将libportaudio32bit.dll打包到我的exe文件中,并删除了这些代码:

    # import _sounddevice_data
    # _libname = _os.path.join(
    #     next(iter(_sounddevice_data.__path__)), 'portaudio-binaries', _libname)
    _lib = _ffi.dlopen(_libname)
    

    在 sounddevice.py 中,现在它可以工作了。

    【讨论】:

    • 你从哪里得到那个 .dll 以及你是如何将它打包到 exe 中的?非常感谢您的进一步阐述。
    【解决方案3】:

    我设法解决了这个问题,而无需对 sounddevice 源代码进行任何更改。这对我很有用,所以我不必记住我的 sounddevice 源代码被黑了。

    我使用 sounddevice 0.4.3,它正在几个不同的位置寻找 DLL。

    我可以通过将 dll 复制到不同的名称和文件夹下来欺骗它找到 DLL,如下所示:

    from pathlib import Path
    import shutil    
    
    # copy the sounddevice dll under a different name and path
    infile = Path('../pyenv/Lib/site-packages/_sounddevice_data/portaudio-binaries/libportaudio64bit.dll')
    outfile = Path('dist/bin/libportaudio-2.dll')
    outfile.parent.mkdir()
    shutil.copy(infile,outfile)
    

    【讨论】:

      猜你喜欢
      • 2020-05-16
      • 1970-01-01
      • 1970-01-01
      • 2012-09-18
      • 2019-11-10
      • 2021-11-28
      • 2018-05-24
      • 2013-12-08
      • 1970-01-01
      相关资源
      最近更新 更多