作者使用 Parakeet TDT(25 语言覆盖)+ Paraformer(汉英双语)构建纯 CPU 语音输入系统,为 Claude Code 等编码 Agent 提供本地 push-to-talk 能力。
我整天都在用语音向编码 Agent(Claude Code、Cursor)输入提示词。打长段落式的提示词曾是我的瓶颈,而我希望语音端完全本地化——按键说话、仅用 CPU、不留数据到外部。模型的选择出乎我意料,以下是技术方案。
基于 sherpa-onnx 用 Rust 构建:
NVIDIA Parakeet TDT v3 面向欧洲语言:一套模型覆盖 25 种语言并自动检测,TDT 解码在我使用中对 CPU 的压力明显比 Whisper 类 encoder-decoder 模型更轻。而且它自带标点输出。
Paraformer(中英双语)面向普通话:代码切换("??? function ?? async")是通用多语种模型的软肋,专用双语模型处理得好得多。标点来自单独的本地 CT-Transformer 环节。
模型按需下载(每个几百 MB),之后全部离线运行。
Whisper 本身没问题——但对于 CPU 上的实时按键说话,TDT 的延迟/质量平衡更适合我,而 Paraformer 在双语普通话上的表现超越了我试过的所有方案。我刻意不公布延迟数字(太依赖硬件,没法诚实),所以这是个人经验,不是基准测试。
没人谈的部分:文本插入
文本插入比识别更难。如何把识别出的干净文本送入焦点的那个字段——终端、编辑器、浏览器——在 Windows 和 macOS 上各有各的坑。最坑的一个:Windows 在 Chromium 类窗口获得焦点时会静默停止投递低级键盘钩子(WH_KEYBOARD_LL)。这事 Tauri 和 CEF 也中招,而且钩子内部写什么代码都修不了——回调根本进不去。解法是架构层面的:焦点窗口自己响应自己的 keydown 事件,全局钩子只管辖失焦的情况。这一条花了我一周。
对于这个使用场景,缩写处理比 WER(词错误率)更重要:"m c p" 必须输出为 MCP,一个用户可编辑的替换字典用来处理模型不可能认识的业务术语。
这是个小额付费应用——VocalCode,一次性 4.99 美元,30 天免费试用,地址 vocalcode.app——所以我有利益关联。不过本文的重点是模型讨论:如果你在用 TDT 系列模型做实时听写,或者在别的本地方案里实现了不错的中英代码切换,欢迎在评论区交流心得。