AI 配音会"装死"?我用 TTS 做播客踩的 6 个坑
2026-10-16
想给技术文章配个音频版,我用 AI 配音做了一期播客。结果第一版生成出来,641 秒的音频里有 30 处超过 2 秒的停顿,最长的一处整整 10.5 秒——配音 AI 在某些文本面前会直接"装死",输出一片死寂。
三版迭代后,我整理出 6 个坑和一套质检流程。这篇是完整的避雷实录。
为什么做这个
需求很直接:技术文章配音频版,通勤路上也能"听"。
选型时考虑过两种路线:真人录制(时间成本高,不可持续)、AI 配音(一次写好脚本,以后每期复用流程)。选了后者。
工具链是现成的:脚本转语音用 TTS,按说话人分角色配音,ffmpeg 做后处理。听起来很顺,实际全是坑。
怎么做的
写脚本
格式是 说话人: 内容,一行一轮,两个角色对话:子安(讲解者)、小北(提问者)。第一期主题是《输对 BitLocker 密钥,电脑依然开不了机》,脚本直接从技术文章改写。
第一版脚本犯了个根本错误:按"看"来写,没按"听"来写。技术文章里的错误码、注册表键名、命令行原样搬进脚本,TTS 拿到 c0000001 这种裸十六进制,直接输出 8.7 秒死寂。
生成配音
整脚本丢给 TTS,按角色分配声音,一次生成完整音频。记下时长和分块数,留作质检基线。
质检:扫停顿
用 ffmpeg 的 silencedetect 扫一遍,统计所有 ≥2 秒的停顿:
ffmpeg -hide_banner -i xxx.mp3 \
-af silencedetect=noise=-35dB:d=2.0 -f null - 2>&1 | grep silence_duration
第一版扫出 30 处。注意:TTS 后端的随机停顿是消不掉的,只能后处理,不能指望换说法解决。
后处理:压缩长停顿
原理很简单:转 PCM → 找出绝对值 < 0.018 且持续 ≥2 秒的区间 → 每段只保留开头 0.7 秒 → 拼回去压成 MP3。
核心代码(Python + numpy + ffmpeg):
import subprocess, numpy as np
sr = 24000
# 转 PCM
subprocess.run(['ffmpeg','-y','-i','in.mp3','-ar',str(sr),
'-ac','1','-f','f32le','ep.pcm'], check=True)
pcm = np.fromfile('ep.pcm', dtype=np.float32)
# 找静音区间
is_sil = np.abs(pcm) < 0.018
bounds, i = [], 0
while i < len(pcm):
if is_sil[i]:
j = i
while j < len(pcm) and is_sil[j]: j += 1
if (j-i)/sr >= 2.0: bounds.append((i, j))
i = j
else: i += 1
# 每段只留 0.7 秒
keep = int(0.7*sr)
parts, prev = [], 0
for s,e in bounds:
parts += [pcm[prev:s], pcm[s:s+keep]]; prev = e
parts.append(pcm[prev:])
out = np.concatenate(parts)
out.astype(np.float32).tofile('ep_fixed.pcm')
subprocess.run(['ffmpeg','-y','-f','f32le','-ar',str(sr),'-ac','1',
'-i','ep_fixed.pcm','-codec:a','libmp3lame','-b:a','64k',
'out.mp3'], check=True)
复检后交付
再扫一遍确认无 ≥2 秒停顿,然后自己试听关键段落。不让用户做首轮质检——有问题先修好再发。
踩过的坑
坑 1:裸十六进制代码导致数秒死寂
现象:脚本里写 c0000001,配音输出约 8.7 秒完全静音。
原因:TTS 遇到无法发音的裸代码,直接跳过不读,但时长照算。
解法:改成中文读法(C 零零零零零零一)或删掉、用中文描述代替。
教训:错误码、内存地址这类裸代码不要直接进脚本。
坑 2:「恢复密钥」四个字触发静音
现象:恢复密钥 单独配音,4.8 秒音频里有 3.9 秒静音;带它的整句复现 10 秒以上死寂。疑似敏感词过滤。
解法:一律改写成「恢复码」(实测干净,1.03 秒无停顿)。
教训:「密钥」单独没事,「恢复」单独没事,组合起来就是雷。凡是"XX密钥""恢复XX"这类敏感组合,生成前先单句实测。排查用二分法:整句配音确认复现 → 拆成短语逐个试 → 定位到词 → 换说法再验证。
坑 3:英文术语逐字母硬读,听感很乱
现象:bcdboot、UpperFilters、INACCESSIBLE_BOOT_DEVICE 写进中文脚本,TTS 一个字母一个字母往外蹦。
解法:重写脚本,只保留听众熟知的产品名(Windows / BitLocker / PGP),其余全部换成中文说法:
- bcdboot → 重建引导;winload → 启动文件
- WinPE → 急救 U 盘;BCD → 引导配置
- INACCESSIBLE_BOOT_DEVICE → 蓝屏提示找不到启动设备
- UpperFilters → 注册表里的驱动名单
- msiexec → 静默卸载命令
教训:中文播客的脚本必须按"听"来写。技术细节放节目文字稿,不进音频正文。
坑 4:干净脚本仍有随机长停顿
现象:三版脚本一代比一代干净,但每版仍有 10+ 处 ≥2 秒停顿,位置每次随机。
原因:TTS 后端本身不稳定,不是脚本问题。
解法:后处理流程(上文代码),≥2 秒统一压到 0.7 秒。
教训:后处理是必备环节,不是可选优化。不要指望"换个说法"能彻底消除。
坑 5:/tmp 下的脚本会被清理
现象:/tmp/script.txt 在清理时被删掉,重生成时无脚本可用。
解法:脚本定稿后存到 ~/workspace/podcasts/<slug>/,和音频放一起。
坑 6:交付前没自己质检
现象:第一版直接发出去,用户反馈"一直在报数字字母英文,感觉很乱"。
解法:定死流程——停顿扫描 + 试听关键段落,自己先过一遍再交付。
教训:质检是生产者的责任,不是用户的。
三版迭代数据
| 版本 | 脚本 | 时长 | ≥2s 停顿 | 处理后 |
|---|---|---|---|---|
| v1 | 原始技术脚本 | 641s | 30 处(最长 10.5s) | 压到 0.7s |
| v2 | 修掉 c0000001 | 641s | 24 处 | 压到 0.7s |
| v3 | 全中文改写 + 修掉"恢复密钥" | 523s | 15 处(最长 7.5s) | 485.9s,0 处 ≥2s |
v3 不仅停顿最少,时长还短了 2 分多钟——中文化的脚本本身就更简洁。
总结
- 中文播客脚本要按"听"写:术语中文化、敏感词先单句实测,能消灭所有确定性事故
- TTS 后端的随机停顿消不掉,silencedetect + 压缩后处理是必备环节,不是优化项
- 可疑文本用二分法排查:整句复现 → 拆短语定位 → 换说法验证,不要整期重猜
- 质检是生产者的责任:停顿扫描 + 试听,交付前自己先过一遍
- 脚本和音频放一起存档,不要放 /tmp
以上,全文完。
最后认识一下,我是 Liyu,一名 AI 实践爱好者,会不定期记录我的学习过程,期待你的关注和分享。