# 2026-06-14 X-ASR 尾字掉字排查 ## 用户目标 用户反馈当前 X-ASR 版本偶尔会掉最后一两个字,例如实际说“技术总监让我问你一下”,识别成“技术总监让我问你”或类似结果,要求判断原因和解决方案。 ## 已完成排查 - 读取全局与项目规则。 - 检查当前日志与源码: - `/Users/ar/Library/Application Support/PrivateVoice Input/app.log` - `privatevoice.src/app.go` - `privatevoice.src/internal/audio/recorder.go` - `privatevoice.src/internal/engine/engine_darwin.go` - 当前运行版本为 `2.1.30 (20260613.2201)`。 - 当前模型为 `x-asr-zh-en-960ms backend=x_asr_streaming`。 ## 关键证据 - 日志中存在用户提到的近似失败样本: - `2026-06-14 19:54:47 Recognized: 技术总监让我问你一` - 该结果在 `Recognized:` 日志阶段已经缺少最后尾字,说明不是粘贴链路、剪贴板或上屏阶段丢字,而是 ASR 最终文本阶段已经掉尾。 - 当前 X-ASR 已经在 `Finish()` 中追加 `1.5s` 静音 padding: - `xasrTailPaddingSamples = 24000` - `AcceptWaveform(..., xasrTailPadding)` 后再 `InputFinished()` - 失败样本录音时长约 `2609ms`,实际采样 `37600`,约 `2.35s`,说明松键停止和音频缓冲之间仍可能遗漏最后约 `100-300ms` 的真实声音。 ## 判断 问题更像是“松开热键后立刻停止录音导致最后尾音没被采进 buffer”,而不是单纯的 X-ASR flush 不充分。 已有的静音 padding 只能帮助模型处理已经捕获的音频;如果最后一个字的真实声音在松键瞬间还没有进入 `pcmBuf`,后续补静音无法恢复。 ## 建议修复 低风险方案:只针对 X-ASR 增加松键后的短尾采集保护。 - 新增一个 engine 能力接口,例如 `ReleaseTailCaptureDelay() time.Duration`。 - 只有 `xasrStreamingEngine` 返回 `250-350ms`,建议先用 `300ms`。 - `stopRecordingLocked(false)` 中,在真正 `StopAndGetSamples()` 前,如果当前引擎声明需要 tail capture,则保持 recorder 继续采集这段时间。 - SenseVoice、Qwen3-ASR、Moonshine、Parakeet 不实现该接口,延迟为 `0`,不受影响。 - 保留现有 X-ASR `1.5s` 静音 padding,它仍负责模型 flush。 ## 风险与验证 - 风险:X-ASR 每次松键后增加约 `300ms` 识别等待;如果用户立刻开始下一句话,可能多采到一点环境声或下一个字。 - 回归范围:X-ASR hold-to-talk 为主,不触碰正式上架线模型。 - 建议验证: - 重复测试短句尾音:“技术总监让我问你一下”“你看一下”“确认一下”“可以了”“好了”。 - 每句至少 20 次,重点观察尾字缺失率。 - 日志应显示采样数平均增加约 `4800` samples(300ms * 16kHz)。 - 确认 live caption 浮窗仍正常,松键后只增加可接受的短暂处理延迟。