Hex为何松手后0.1秒完成识别?流式语音转写引擎原理全解析
【免费下载链接】hexLocal voice dictation for mac, windows and linux项目地址: https://gitcode.com/GitHub_Trending/hex19/hex
Hex 是一款本地优先(local-first)的语音听写工具:按住快捷键说话、松手即粘贴,语音转文字全程在设备本地完成,不经过云端。而它最令人印象深刻的体验是——按下松开的那一刻,转写结果几乎"瞬间"出现。在 Apple Silicon 上,从松手到拿到最终文本实测仅140~253 毫秒(10 秒和 131 秒录音),对比整段离线识别的 156~2,838 毫秒。这份指南带你拆解 Hex 背后的流式语音转写引擎:为什么边录音就能边识别,松手后只剩最后一两秒音频需要解码。
一、先看体验:Hex 语音听写的三步流程
Hex 的使用方式极简,核心是一条"按住—说话—松手"的时间线:
- 按住快捷键(macOS 默认 Option 键):录音立即开始,并附带最多450 ms 的 pre-roll(预录音),即使你按下快捷键后才开口,开头的音节也不会丢;
- 说话过程中:音频一边被记录,一边同步喂给语音识别模型;
- 松手:保留松手后200 ms 的尾巴(保住最后一个词的尾部),然后完成转写并粘贴到当前焦点应用。
按下不到 300 ms 就松手会被判定为误触并直接丢弃,不会触发任何转写。
关键问题来了:如果录音结束后才开始识别,10 秒的语音至少要等 10 秒的模型推理。Hex 的做法恰恰相反——把识别挪到了"说话"这个阶段。这就是整篇文章的主角:流式语音转写引擎。
二、核心原理:边录音、边转写的流式引擎
Hex 的转写由一个专职线程拥有整个模型,录音捕获只是持续向它"喂块"。整套机制可以概括为三句话:
- 录音和识别并行。当按住快捷键越过 300 ms 意图阈值后,Hex 打开一条实时流(live stream),从第一个采样(含 pre-roll)开始,每满160 ms(
STREAM_FEED_SAMPLES = 2560个 16 kHz 采样)就把一块新音频发给引擎; - 松手只解码尾部。说话期间模型已经消化了绝大部分音频,松手后只需要把剩下的一两秒"喂完"并收尾,这就是 0.1 秒级出字的根本原因;
- 完成时永远携带完整音频。即使流式失败,Hex 也会用完整音频做一次离线识别兜底,绝不丢字。
对应的入口在 src/dictation.rs 的begin_stream:捕获"拥有"自己的流,音频到达时喂流,录音结束或取消时流也随之结束。引擎侧的指令队列与"完成即回退"策略定义在 src/transcription_engine.rs 的文件头注释中——"release only decodes the last second or two of audio"。
8 秒预热:为什么第一次听写不会卡
GPU 推理引擎第一次遇到某种输入规模时要现场编译计算内核,代价很高。Hex 在加载/切换模型时用一段静默音频做一次流式探测(probe),顺便充当预热:src/gguf_session.rs 中STREAM_PREWARM_SAMPLES被设为8 秒(128,000 个采样),足以覆盖听写会遇到的所有流窗口形状。注释里记录了一个教训:用 1 秒探测时,新构建的首次听写会在收尾阶段编译内核,在 RTX 5070 Ti 上多花了 3~4 秒。
流式还有明确的准入条件,见 src/gguf_session.rs 的probe_stream:
- 模型必须声明支持流式(目前目录里是 Parakeet Unified English,见 src/transcription_models.rs);
- 必须在GPU 设备上(macOS 走 Metal,Linux 与 x64 Windows 走 Vulkan)。CPU 流式会重复编码每个重叠窗口,成本数倍于离线,因此不启用;
- 诊断场景可用环境变量
HEX_STREAMING=1强制在任意设备上开流、HEX_STREAMING=0关闭。
三、松手那一刻:200 ms 尾巴与 1.5 秒熔断
松手(release)触发一条精确的收尾时间线,规则来自 docs/features/dictation.md 的 "Streaming Finish" 一节:
松手 ├── 1. 保留松手后 200 ms 的音频(POST_RELEASE_TAIL) ├── 2. 把尚未喂入的剩余音频全部喂进流 ├── 3. finalize → 拿到最终文本 │ ├── 正常完成 → 直接用流的结果(source=stream) │ ├── 流失败 / 没产出文本 / 喂入超过音频终点 250 ms │ │ → 回退整段离线识别(source=fallback) │ └── 1.5 秒内拿不到最终文本 → 中止流 → 整段离线识别 └── 4. 转写完成前,任何文本都不会被粘贴其中 1.5 秒熔断是 src/transcription_engine.rs 的STREAM_FINISH_DEADLINE:一次健康的收尾只解码一两秒缓冲音频,超过这个时间说明流"卡住"了,果断弃流走离线路径。每次听写都会记录source=stream|offline|fallback和finish_ms,方便定位是哪条路径生效。
四、实测数据:0.1 秒是怎么来的
项目文档记录了两组真实测量(同一批音频,流式 vs 整段离线):
| 设备 | 10 秒录音 | 27 秒录音 | 131 秒录音 |
|---|---|---|---|
| RTX 5070 Ti(Vulkan) | 55 ms/ 82 ms | 55 ms/ 185 ms | 93 ms/ 873 ms |
| MacBook Air M4(Metal) | 140 ms/ 156 ms | — | 253 ms/ 2,838 ms |
加粗为流式路径的"松手→出文本"耗时。几个值得注意的细节:
- 长录音差距悬殊:131 秒录音离线要 2.8 秒,流式只要 253 ms——因为长音频的 99% 早在说话期间就被消化了;
- 流式期间GPU 占用仅 3.1%~3.6%,131 秒实时流下进程峰值内存 214 MB,几乎不占核心算力;
- 更细的粒度实验(Apple Silicon,13.1 秒
say合成音频实时回放):文本更新 12 次、每次对应一个约 1.04 秒的 chunk,最终文本在松手后154 ms出齐,与整段离线识别逐词一致(0/40 词差异)。
Hex 还在实验中提供live-text:说话时 HUD 下方就会逐块长出行内文字(已稳定的词 + 灰色的暂态词),比语音落后约 1~2 秒——相当于流式引擎的"副产品"直接给了用户视觉反馈。
五、兜底与资源管理:流式失败怎么办
流式再快也不能牺牲"一个字都不能丢"的承诺,Hex 的兜底链条相当完整:
- 非 GPU / 不支持流式的模型:走整段离线识别(
source=offline),体验略慢但功能等价; - 流中途失败或超时:自动回退为完整音频离线重识别(
source=fallback); - 会话轮换控内存:模型权重常驻保持"热",但每次推理后轮换一次轻量 session,释放按输入尺寸膨胀的调度器临时内存(见 src/gguf_session.rs 与 docs/features/dictation.md "Ongoing Jobs" 一节);
- 静音闸门 + 语音检测:几乎全静或没有语音的录音在推理前就被丢弃,防止模型在空气上"幻觉"出结尾客套话(src/speech_detector.rs);
- 长录音切块:超长录音按模型窗口切块(如 Cohere 参考窗口 35 秒)逐段转写再按原顺序拼接,避免整段推理丢失中段内容。
六、开发者扩展:/streams 本地流式转写 API
Hex 把同一套流式引擎开放给了本机其他应用:docs/streams.md 描述了/streams接口——第三方程序推送 16 kHz 单声道采样,Hex 实时回传partial(stable已提交文本 +tentative暂态文本)、segment和最终文本。规则是听写永远优先:一旦你按下 Hex 快捷键,yielding 流立即让路,音频在积压区等待追赶,绝不阻塞听写的 0.1 秒体验。配合 sdk/typescript/ 的 TypeScript SDK,这是把 Hex 的本地语音识别能力嵌进自己应用的最低成本方式。
七、源码导读:从哪几个文件读懂流式引擎
想动手深挖,建议按数据流顺序读这 5 个文件:
- src/dictation.rs — 捕获状态机:450 ms pre-roll、200 ms release 尾巴、
begin_stream/feed_stream; - src/transcription_engine.rs — 引擎线程与指令队列:流、熔断、回退全部在这里裁决;
- src/gguf_session.rs —
probe_stream准入探测、8 秒预热、Parakeet 缓冲参数; - src/parakeet.rs — Parakeet 适配层与词汇偏置重打分;
- docs/features/dictation.md — 行为规格地图(本文时间线的出处),配合 docs/research/performance-2026-09-04.md 的推理性能调研。
一句话总结:Hex 把"识别"从松手之后搬到了说话期间——GPU 上每 160 ms 喂一块音频,松手后只剩一两秒尾部要解码,再配上 1.5 秒熔断和完整音频离线兜底,这就是它敢承诺"松手即出字"的全部底气。
【免费下载链接】hexLocal voice dictation for mac, windows and linux项目地址: https://gitcode.com/GitHub_Trending/hex19/hex
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考