> v1.0.1(2026-09-04):修复 subprocess 调 ffmpeg 用 text=True 导致含中文路径时切段崩溃的 bug(详见「关键坑」第 5 条)。
WAV → MP3 / MP3 切段 Skill
把本机音频转换工具封装为 skill,用户说"wav转mp3"或"mp3切段"即可触发。脚本为纯标准库(os/re/ctypes/subprocess)+ 打包内置 ffmpeg(imageio-ffmpeg),无需系统安装 ffmpeg。
使用方法(环境无关)
> 运行此 skill 的 agent 自带 binary_context,其中给出本机 managed python 绝对路径(形如 …\binaries\python\versions\3.x.x\python.exe)。下文以 <PY> 代指——切勿写死用户名或绝对路径,换机器就跑不了。
脚本支持命令行非交互模式,agent 直接调用:
<PY> <本skill目录>/scripts/audio_converter.py <文件路径> [单段上限MB]
| 参数 | 必填 | 说明 |
|---|---|---|
<文件路径> |
是 | 要处理的 .wav 或 .mp3 文件 |
[单段上限MB] |
否 | 默认 50;切段目标上限 |
输出到源文件同目录:
- 输入 .wav → 生成同名 .mp3(若 >上限再切段)
- 输入 .mp3 → 若 >上限,切成 原名_part1.mp3、原名_part2.mp3…
不带参数运行 = 双击弹文件选择框(GUI 模式),选完自动处理并弹结果框。
触发词 → 动作映射
- "wav转mp3" / "音频转mp3" / "转mp3" → 转码 + 判断是否切段(默认 50MB 上限)
- "mp3太大" / "mp3切段" / "mp3压缩到50MB" → 只对已有 mp3 做无损切段
- "转成小于XXMB" → 传第二个参数
XX自定义上限
技术要点
- 无损切段:用
-c copy(流复制)按 mp3 帧边界切,零重编码、音质零损失;切点 ±几十毫秒(电话录音无感)。只在帧独立格式(mp3/aac)上安全,wav/wma 等 pcm 流不能切字节。 - 转码保持源参数:不指定
-ac/-ar,完全保持源声道数与采样率,只做编码。 - 码率自适应:探测源 ≤16kHz 单声道(电话录音)→ 192k;否则(音乐等)→ 256k。
- 切段留 10% 余量(
SAFE_RATIO=0.9):按比例分段并留余量,避免 mp3 帧边界波动导致单段超限。
打包成 exe(给没装 Python 的同事双击用)
python -m PyInstaller -F --noconfirm --console --name "音频转换工具" \
--collect-all imageio_ffmpeg \
--workpath F:\WorkBuddy\AgentTemp\pyinstaller_build \
--distpath F:\WorkBuddy\AgentTemp\pyinstaller_dist \
--specpath F:\WorkBuddy\AgentTemp\pyinstaller_spec \
scripts/audio_converter.py
- 产物
dist/音频转换工具.exe(单文件,约 80–100MB,含内置 ffmpeg ~70MB) - 必须
--collect-all imageio_ffmpeg:把 ffmpeg.exe 打进包,否则 exe 运行时找不到 ffmpeg - 必须 TEMP/TMP + workpath/distpath 全指向非 C 盘(作者本机 C 盘紧张,PyInstaller 中间产物易写满 C 盘)
- 双击 exe = 弹文件选择框;命令行
音频转换工具.exe 文件.wav 50也能直接转
关键坑(血泪经验)
- ffmpeg 是 Windows 原生程序,不认 Git Bash 的
/f/...路径:subprocess 传参必须用 Windows 原生路径(F:\...反斜杠),否则报No such file or directory。 - ctypes 调 GetOpenFileNameW 必须声明
restype = wintypes.BOOL:不声明则 64 位系统返回值被截断(沿用 C 盘工具 SHBrowseForFolderW 的教训)。 - 打包后 ffmpeg 定位要多重降级:
imageio_ffmpeg.get_ffmpeg_exe()在--collect-all打包后会从_MEIPASS找到;但需再兜底_MEIPASS/ffmpeg*.exe、exe 同目录、系统 PATH,防止不同打包方式失效。 - 首次运行 exe 稍慢:
--onefile会把 ~70MB ffmpeg 解压到%TEMP%再执行,正常现象(几秒~十几秒)。 - subprocess 调 ffmpeg 别用
text=True:含中文路径时 ffmpeg 探测输出混含 GBK 中文,text=True按 locale 解码会抛UnicodeDecodeError,r.stderr变 None 后_probe_duration崩AttributeError: 'NoneType' object has no attribute 'splitlines'。修复:_run用 bytes 模式(不带 text=True),_probe_duration/_pick_bitrate全程用bytes解析(b"Duration"、rb"(\d+)Hz"等)。教训:纯英文路径测试不暴露,真实中文路径现形——凡 subprocess 读 ffmpeg/外部命令输出,一律 bytes 容错,别信任默认解码。