在使用 PyInstaller 打包包含 pydub
的 Python 应用程序时,由于 pydub
需要依赖 ffmpeg
,你需要确保 ffmpeg
被正确包含进打包后的程序。以下是操作步骤:
1. 准备 ffmpeg
-
首先,确保你已经下载并安装了
ffmpeg
。可以通过以下方式获取:-
Windows :从 FFmpeg 官网 下载预编译的二进制文件,并将其解压。
-
Linux/MacOS :可以通过包管理器(如
apt
或brew
)安装:bashsudo apt install ffmpeg # Linux brew install ffmpeg # MacOS
-
-
注意 :需要记录下
ffmpeg
的路径,因为稍后需要将其包括在打包中。
2. 使用 PyInstaller 打包并包含 ffmpeg
PyInstaller 的默认行为不会自动包括外部的可执行文件,因此你需要显式指定 ffmpeg
。
方法 1:使用 PyInstaller 的 --add-binary
参数
假设 ffmpeg
的路径是 path/to/ffmpeg
,使用以下命令打包:
bash
pyinstaller --onefile --add-binary "path/to/ffmpeg:./" your_script.py
--add-binary
的格式为:源路径:目标路径
。- 这里
path/to/ffmpeg
是ffmpeg
的实际路径。 ./
表示将ffmpeg
放到打包后的可执行文件同目录下。
- 这里
打包完成后,可执行文件运行时会在同目录找到 ffmpeg
。
方法 2:修改 PyInstaller
的规范文件(更灵活)
-
生成
.spec
文件:bashpyinstaller --onefile --name your_script your_script.py
-
编辑生成的
.spec
文件,在binaries
部分添加ffmpeg
:pythona = Analysis( ... binaries=[('path/to/ffmpeg', './')], # 添加这行 ... )
-
使用
.spec
文件重新打包:bashpyinstaller your_script.spec
3. 确保运行时 pydub
能找到 ffmpeg
在代码中显式指定 ffmpeg
的路径(推荐),避免路径问题导致 pydub
找不到 ffmpeg
。可以在脚本中加上以下代码:
python
from pydub import AudioSegment
from pydub.utils import which
# 显式指定 ffmpeg 的路径
AudioSegment.converter = which("ffmpeg") or "path/to/ffmpeg"
参考spec文件如下:
bash
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['server.py'],
pathex=[],
binaries=[("./ffmpeg.exe","./ffmpeg.exe")],
datas=[("./prompts","prompts"),('./logo.ico','.')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='server',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=['logo.ico'],
)
注1 :prompts是文件,我的一些资源基本都放进这个文件夹。
不过文件读取的时候需要注意一点,文件的路径不能直接用相对路径这会报not such file or directory的错误。
注2:如果使用到ffmpeg,还报错。可以添加进路径中不直接使用,比如你是如果是pydub就可以在开头加二行代码
from pydub.utils import which
# 显式指定 ffmpeg 的路径
AudioSegment.converter = which("ffmpeg")
python
# 获取当前程序所在的路径
if getattr(sys, 'frozen', False):
# 如果是打包后的程序,使用临时目录路径
base_path = sys._MEIPASS
else:
# 如果是开发环境,使用当前脚本所在路径
base_path = os.path.dirname(__file__)
# 拼接文件的绝对路径
file_path = os.path.join(base_path, 'prompts', '晓语systemPrompt_.txt')
with open(file_path, encoding='utf-8') as r:
systemprompt = '\n'.join(r.readlines())
memory.append({'role':'system','content':
systemprompt})
总结
通过以上方法,将 ffmpeg
和 pydub
一起打包即可实现完整的功能。--add-binary
参数和修改 .spec
文件是常见的解决方案,确保 ffmpeg
在运行环境中可用,同时代码中显式指定路径以避免找不到依赖的问题。