我做了个桌面语音数字人(能对话、能出声、能对口型),动手前先给它做了一轮全链路实测。这篇是实测真账:每一条链路能跑还是不能跑、延迟多少、坑在哪,全部摊开。先说结论:语音链全通,口型能离线跑通但没接进实时链路——细节在下面。
一、这个项目长什么样
- 后端:一个本地常驻服务,负责对话、语音合成、语音识别
- 前端:桌面透明浮窗,一个头像待在那儿
- 能力:中文对话 → 流式文字 + 流式语音;语音输入 → 转文字;头像视频 → 嘴跟着声音动
听起来很顺,但"听起来能跑"和"实测能跑"是两回事。所以我逐条链路打了真账。
二、真能跑的(实测数据)
1. 对话链路 ✅
发一句话进去,首字延迟约 6 秒,流式吐字。回复干净,没有内部推理文本漏出来(这个后面细说,修过)。
2. 语音合成(TTS)✅
edge-tts 中文女声。单句合成 2-7 秒,整段音频实测推流成功(一次拿到 23KB mp3,服务端到客户端全链路验证过)。
3. 语音识别(ASR)✅ 但有边界
faster-whisper base 模型、CPU int8 量化。关键数字:
- 热载后单次识别约 2 秒(冷启动含模型加载约 6 秒)
- 验证方法:先用 TTS 合成已知内容再喂给 ASR 对答案。16 字长句逐字还原;但 14 字短句实测错 2 字("语音识别"被识别成"语一诗别",两次重测稳定复现)——干净合成音频、无口音无噪声都会错,base 模型的边界就在这
- 冷启动时曾测出 26 秒——那是识别链顺序问题,修完后就是上面的数字
4. 口型同步(wav2lip)✅ 离线跑通
用一段 3.8 秒音频 + 一张头像,离线合成出 3.68 秒、512×512、25fps 的嘴动视频。
怎么验证"嘴真的在动"而不是视频噪声?帧差法:
- 嘴部区域:91 个相邻帧对里 72 对在动,平均帧间差 2.26
- 额头对照区:平均帧间差 0.01,基本静止
嘴动是真驱动,不是抖动。推理速度 0.58x 实时(比实时慢约 1.8 倍),全程含加载约 39 秒。
5. 回归测试锁 ✅
上面每一条都写进了自动化回归脚本(3 项:对话全链路 / ASR 已知内容还原 / 推理文本过滤器单元测试),改一次代码跑一遍,防止修好的东西又坏回去。
三、坑(自曝清单)
这部分才是这篇文的重点。
坑 1:口型没接进实时链路(最大的坑)
上面那段嘴动视频是离线生成的。实时对话链路里,口型分支的代码其实写了,但被一段提前 return 短路,永远不会执行——等于死代码。也就是说:现在实时对话时头像的嘴是不动的。接通要改服务代码 + 配环境,估计半天到一天工作量,还没动。
坑 2:推理速度撑不起实时口型
0.58x 实时意味着说一句话、嘴要动将近两倍时长才追得上。要做实时,得分块策略配合(先出声后补嘴,或者预生成常用表情),目前没做。
坑 3:对话首字 6 秒,偏慢
本地部署的模型 API,首 token 6 秒。日常闲聊能忍,长回复体验一般。
坑 4:edge-tts 是免费公共服务
稳定性不由我控制,微软那头一抖,整条语音链就哑。已经备了降级链,但降级路径的声音质量不如主路。
坑 5:ASR 的验证是"已知内容回环",而且已经测出错字
用 TTS 合成已知语音测 ASR:长句逐字还原,短句错 2 字且稳定复现——这证明链路通,但 base 模型的识别精度有真实边界。真人语音、口音、环境噪声的鲁棒性更没测过。要实用,至少得换更大的模型或者加领域纠错,这是下一步。
坑 6:两条备选口型方案都不适合实时
- musetalk:能跑,但 23 倍慢于实时,只配做非实时预生成
- sadtalker:环境就绪,但 3DMM 数据缺失,重跑大概率卡在数据准备
坑 7:修过的三个红级 bug(不修就是"一碰就碎")
实测第一轮揪出来的,都已修复并进了回归锁:
- 内部推理文本泄漏:模型输出的推理过程标签没过滤干净,直接串进了前端显示和 TTS——数字人会"把心里话说出来"。修法是写了个跨 chunk 的状态机过滤器(推理块可能被打散在多个流式片段里,简单字符串替换防不住)
- 路径对象崩溃:语音识别链路里,一个文件系统路径对象没转字符串就直接进了 shell 命令拼接,Windows 上必崩
- 降级链断裂:识别失败后的兜底逻辑永远走不到(第一手失败就直接返回失败),等于没有兜底。重排顺序 + 装齐依赖后,26 秒空转降到 1.9 秒
四、产物
- 嘴动验证视频(3.68 秒)+ 帧对比图 + 独立复现脚本(pip install opencv-python numpy 即可跑,不依赖我的任何代码):github.com/SONG1979-PI…
- 数字对不上就开 issue 打脸——比"做得好"有用得多
五、想听的真话
这个项目推到外部评审阶段了,我最想知道三件事:
- 桌面语音数字人这个东西,到底有没有人想要?还是自嗨?
- 如果嘴不动(现在的实时状态),只有声音+文字,你还会用吗?
- 首字 6 秒的延迟,在你的忍耐线内还是线外?
评论区骂醒我也行,数据打脸我也行——比"做得好"有用得多。