# 从 91 到 254 项测试:dsh-voice-mode 的 60 天迭代故事 > 60 天,11 批次周全修复,测试基线从 91 项涨到 254 项。 > 仓库:https://github.com/qishuilalala/dsh-voice-mode · 当前版本 `dsh-voice-mode@0.7.7` ## 一个语音插件最难的不是识别,是"说话的规矩" dsh-voice-mode 是 DSH 的语音双工插件:你说话,它识别;它朗读,你打断。识别引擎、TTS、字幕、回声消除,这些是功能清单上的事。真正让语音体验翻车的是另外三件事——噪音里它乱插话、你打断它它不松手、它该闭嘴时还在念。 60 天前,这个插件的测试基线是 91 项。今天,`npm test` 18 个文件 254 项全绿。这篇文章讲这 163 项测试是怎么长出来的,以及它们各自守住了哪个真问题。 ## 四个真问题,决定了所有工作优先级 ### 1. 噪音:你说的话,引擎没听进去 热词偏置要解决的是"专有名词被识别成谐音"的问题。批 1(`9467c81`)把热词注入识别解码,配合可调偏置分,让 dsh、kokoro 这类词不再靠运气。批 2(`3025e1b`)接着做了两件事:锁语种,杜绝中英混识的抖动;逆文本归一化(ITN),把"三点五"落成"3.5"。识别质量从此有了一套可配置的旋钮,而不是黑盒。 ### 2. 打断:你说话时,它必须立刻闭嘴 打断体验的核心矛盾是"什么时候算你在说话,什么时候算你在附和"。批 5(`7f1a09f`)落地了 ADR-0008 的让位语义:短应答("嗯""好""对")不再触发打断,只有真正的插话才让它闭嘴。批 7E(`921334e`)补上了另一头的边界——短句确认从 0ms 提到 200ms 最小窗口(`CONFIRM_MIN_MS`),换气停顿不再把一句话切两半;SenseVoice 预热也前置到进入语音模式时,冷启动不再拖慢第一句。ADR-0006 的打断模式自动探测则在背后决定:外放时靠回声消除,耳机时直接放开门控。 ### 3. 让位:它念长文时,得知道你只想"嗯"一声 这是四个问题里最"社会-语用"的一个。发言权调度不是声学问题,是规矩问题——ADR-0008 把它拆成了明确的规则表:什么词算附和、附和多久算让位、超时怎么收场。backchannel 30 项测试就是这套规矩的回归门。 ### 4. 多语种与字幕:识别要对,显示也要对 批 2 锁语种 + ITN 之外,批 3(`0fe3f90`)做了字幕的无障碍档位:字号、宽度分档,窄屏和宽屏各有正确的呈现。批 7 系列里 `strings-coverage.test.mjs` 的 33 项断言把"设置界面文案必须中英双侧齐全"变成了机器守卫——漏一个键,测试直接红。 ## 60 天 11 批次:周全修复是怎么排的 节奏很朴素:先 P0 救命,再收口,再精修。 - **批 1-3(P0)**:热词偏置(`9467c81`)、锁语种 + ITN(`3025e1b`)、字幕档位(`0fe3f90`)。识别和显示的地基。 - **批 4-5(ADR 落地)**:ADR-0007 emotion 标签 DSL 步 1(`959c742` → `7b94653` → `d013193`),`` 停顿和 whisper 轻语进了 TTS 链路;ADR-0008 让位语义(`7f1a09f`)。 - **批 6(总收口)**:`14dfc5e`,一次性确认不变量 I1-I10 全部保住——finalize 幂等、TTS 帧协议零触碰、`client.inject` 9 个锚点逐字未动。 - **批 7A-J(10 批周全修复)**:从 `78574ad` 到 `2d646d9`,每批只做一类事——识别器懒重建、设置透传、文案覆盖守卫、TTS 静音拼帧顺序、端点确认 200ms、让位守卫、数字输入校验、TTS 失败提示、/preview 错误归类、死代码清理。 - **批 7K/7L(文档收口)**:`15be91a` 落真机验收清单,`1041929` 把文档锚点和数字与代码逐一对齐。文档与代码完全一致,不是口号,是测试外的另一道工序。 值得一提的还有那次 B1 险情:批 4 一度出现"单测 151/151 全绿、集成层 emotion 标签被分段器剥掉"的假阳性。收口 commit 加了 segmenter → emotion 全链路断言,从此这种"单测通过、集成断裂"有了专门的防回归门。 ## 兼容性:不拿用户当测试 0.7.7 的兼容声明是 `>=0.1.1-rc.2`(无上界),覆盖 dsh `0.1.1-rc.2 → 0.1.5-rc.2`,其中 0.1.5-rc.2 做了线上真实 LLM 端到端验证。四版本锚点检查 + 四线 typecheck + 隔离冒烟是每次发布的固定动作,不是"应该能跑"。 ## 下一步 - **F1**:emotion 标签 DSL 全量上线——从"解析了"走到"LLM 主动用得好",包括给 system prompt 注入标签使用指引。 - **ADR-0003**:client-side VAD 下沉,把语音活动检测从 host 侧移到客户端,进一步压延迟。 测试会继续涨,但衡量标准不变:每个新测试都必须守着一个真问题。 --- - 仓库:https://github.com/qishuilalala/dsh-voice-mode - npm:`dsh-voice-mode@0.7.7` - Release:https://github.com/qishuilalala/dsh-voice-mode/releases/tag/v0.7.7