听写应用为什么会吃掉你的第一个词
你按下热键,开口说话,第一个词却被切掉了。冷启动截断为什么会发生 — 以及一个常开的麦克风加 500 毫秒预滚缓冲怎么修好它。
按下热键。开口说话。看着转写从你的第二个词开始 — 有时是第三个。“重构重试逻辑”出来变成了“重试逻辑”。“别现在就合并那个”出来变成了“现在就合并那个”,而这是一句被替你打出来会相当危险的话。这种失败在冷启动的麦克风流水线上很容易复现,从系统内置方案到专门的听写工具都一样。
人们描述它的方式各不相同 — “它会切掉开头”“我得先停一下再说话”“第一个词总是不见了” — 但它是同一个现象,而一旦被咬过一次,你就会发展出所有人都会发展出的那套变通:按下键,等一拍,然后再说。这意味着你现在每天要做几十次一个小小的迷信仪式,来补偿你的工具,而是工具训练了你,不是反过来。
我在别的工具里做了好几个月这个仪式。做 Keebye 的时候,干掉它是清单上最靠前的事情之一,因为修好它需要一个大多数应用不愿意做的、让人不太舒服的取舍 — 而我想把这个取舍讲得和修法一样直白。
第一个词为什么会被切掉?
这是品类层面的问题,不是某家厂商的马虎,而它背后的物理很简单:麦克风不是瞬时的。
当一款听写应用用最朴素的方式开始录音时 — 按下热键,然后打开麦克风 — 在你语音的第一个采样被捕获之前,一整条链子必须先跑完。操作系统的音频会话要初始化。输入设备要唤醒,对某些硬件来说这意味着字面意义上的预热时间。流的格式要协商,缓冲区要分配,而最先到达的那些缓冲区往往是要被丢弃的垃圾。取决于机器和设备,这条链子耗时在“一拍”和“好几秒”之间。
与此同时,你 — 一个念头已经成形的人类 — 在手指碰到键的那一瞬间就开口了。其实通常是在那一瞬间之前一点点:按键的意图和说话的意图是一起离开你大脑的,而语音起始通常会跑赢应用的就绪。在音频流真正开启之前你说的一切,对应用来说从未存在过。模型无法转写从未被捕获的音频。于是就有了:“重试逻辑”。
应用为什么按需启动麦克风,而不是让它一直待命?多半是出于良好公民意识。让麦克风保持打开会消耗一点电量,而且 — 更重要得多 — 它会点亮系统的麦克风指示器,用户很自然地会把那读成“这个应用正在听我说话”。只在需要时才打开麦克风,能让指示器保持诚实,也让应用显得懂礼貌。代价就是每次录音开头的冷启动风险。
修法:在你按键之前,麦克风已经在听了
Keebye 从两头同时下手,这两套机制值得分开讲,因为它们解决的是问题的两个不同半边。
常开的麦克风。 在一次会话中的第一次录音之后,Keebye 会让音频输入流保持打开。这意味着只要那条流还健康,冷启动链条 — 会话初始化、设备唤醒、流协商 — 在后续的听写之前就已经跑完了。在你的手指动起来之前,流就已经是活的。
预滚缓冲。 一条已经热起来的流修好了应用的迟到,却修不了你的 — 别忘了,你的语音起始可能跑赢你的按键。所以 Keebye 会保留一段 500 毫秒的滚动音频缓冲(16 kHz 下的 8,000 个采样,放在一个环形缓冲区里)。当你按下热键时,那半秒“刚刚过去”的音频会被冲进这次话语的最前面。在那段缓冲区之内开始的音频,可以交给转写器,而不是在按键之前就被丢掉。
两者合起来的结果:在重复听写时,常开的流加上 500 毫秒预滚缓冲,覆盖了语音刚好在按键之前或与按键同时开始的常见情况。在那个边界之内,仪式性的停顿变得不必要。它救不回在录音开始前超过半秒说出的词,而一次会话中的第一次听写仍然要付正常的流启动延迟。
把取舍摊开来说
下面这部分我拒绝藏着掖着,因为它是这个设计诚实的价码:既然音频流在两次听写之间保持打开,macOS 就会在你并没有听写的时候把麦克风显示为使用中。 那个橙点是亮的。如果你去看 Control Center,Keebye 就列在那儿、正在使用麦克风,就在此刻,而你什么也没做。
那段时间里实际发生的是:音频流进那个 500 毫秒的环形缓冲区,并被持续丢弃。没有任何东西被转写。没有任何东西被存储。在你按下键之前,没有任何东西离开那个缓冲区 — 而所有超过半秒的东西都永远消失了,被环形缓冲覆盖掉了。但我不打算假装那个指示器在撒谎,因为它没有:流是打开的,而“具备持续监听的能力”是对这个架构的公允描述,尽管在你开口要求之前,没有任何有意义的“听”在发生。
我是睁着眼睛、刻意做出这个取舍的,理由如下。按需打开麦克风每一次都引入冷启动风险:被切掉的词、说错的句子、被训练出来的停顿。常开流这套设计的代价,落在你对一个橙点的接受程度上,而它背后是一个你可以推理的架构:仅含文本的本地历史记录(我们写在了你的听写不该就这么消失里)、端侧转写、从不存储音频、半秒的环形记忆。这个橙点我认了。如果你不认 — 那是一个正当的立场,而它也确实可能让另一款工具成为对你更合适的选择;我们的 Keebye vs Superwhisper 和 Keebye vs Wispr Flow 页面,写的就是帮你做这个判断。
两条边界,免得有人意外
一次会话中的第一次听写,仍然有正常的流启动延迟。 麦克风之所以是热的,是因为已经发生过一次录音;第一次仍然要付那份准备开销。后续的听写在流保持打开期间受益。
预滚是 500 毫秒,而 500 毫秒是一拍,不是一句话。 这个缓冲覆盖的是自然情况 — 一个词在按键之前稍早一点开始。如果你说完了整句话,然后才想起来按键,那更早的那些词就没了,这是设计使然:这个环形缓冲区始终只存半秒,正是为了让应用在闲置时不保留有意义的音频。更长的预滚会接住更多你走神时的开头,也会把更多环境音留在内存里。半秒就是我划下那条线的地方。
为什么半秒比听起来更重要
一个被切掉的第一个词,看上去像个小 bug。在 Keebye 为之而生的并行任务线工作流里 — 语音同时作为好几个 AI 智能体和好几场人类对话的控制通道,也就是两个孩子,三家创业公司,一个声音里描述的那种工作日 — 听写一天要发生几十次,成阵地发生,还常常夹在上下文切换中间。一个要求仪式性停顿的工具,会对每一阵征税,更糟的是,偶尔会把你的意思反过来然后提交出去。“现在就合并那个”只好笑过一次。
这个品类里的可靠性不是一个大功能。它是一堆更小的保障累积起来的:给开头音频的预滚缓冲、藏在转写背后的历史记录,以及一条可恢复的插入路径。这篇文章讲的是其中第一个;历史记录那篇讲的是第二个。
Keebye 处于 macOS 早期访问阶段。在下方开始你的免费试用,在一次重复听写里说一句“别现在就合并那个”,然后看看第一个词有没有活下来。这就是全部的测试。
不必再靠那个仪式性的停顿才敢开口
开始免费试用,用一次重复听写测试一句以你输不起的那个词开头的话。
Start free trialEarly access: we'll email you the moment the macOS build is ready — your 14 days start when you first sign in from the app.
继续阅读
你的听写不该就这么消失
你口述了一长段想法,插入失败了,文字就这么没了。听写应用为什么会弄丢你的话 — 以及 Keebye 保留的那份本地、仅含文本的历史记录。
断网的时候依然能用的听写应用
云端听写会随网络一起死掉。Keebye 的语音转文字完全在端侧运行 — 不需要网络,音频不离开你的 Mac,也没有哪次服务中断能让它停摆。
用你自己的语言口述代码评审
代码是英语的,你的评审意见不必也是。怎样用 25 种语言之一在端侧口述评审意见,以及为什么锁定语言这件事很关键。