口哨(Whistle)是一个开源语音识别模型,与针(Needle)运行在同一 CPU 引擎上,支持七种语言,首个 token 用时 11 毫秒,可与针(Needle)一同加载,让单个二进制文件把音频片段直接转为工具调用。2026年10月2日,它正式发布,面向移动设备、可穿戴设备、机器人、智能家居、汽车和微控制器,是一个 16.9 MB 的文件,在 CPU 上运行且无依赖,并从同一容器和量化方式载入到与针(Needle)相同的 C++ 引擎中。
正文
Whistle 是一个开放的语音识别模型,与 Needle 运行在同一个 CPU 引擎上。它能转写七种语言,首 token 延迟为 11 ms,并可和 Needle 一起加载,让同一个二进制文件把音频片段直接变成工具调用。
今天,我们发布 Whistle,一个面向手机、可穿戴设备、机器人、智能家居、汽车和微控制器的语音识别模型。它是一个 16.9 MB 的文件,在 CPU 上运行、无依赖,并加载到与 Needle 相同的 C++ 引擎中,来自相同的容器和相同的量化方式。
在 Whistle 沙盒中,你可以对着设备说话并由 Whistle 本地转写:模型 16.9 MB,直接在该标签页运行,可选择语言和关键词。按下麦克风并说话,支持英语、德语、法语、西班牙语、意大利语、荷兰语或波兰语,最长 30 秒。首次按下会下载这个 16.9 MB 的模型,音频永远不会离开你的设备。
Whistle 在设备上完成三项工作:
- 转写。 16 kHz 单声道音频,一次最长 30 秒,支持英语、德语、法语、西班牙语、意大利语、荷兰语和波兰语。除非你指定,否则会自动检测语言。
- 词级时间戳。 每个词都带有开始时间、结束时间和概率,由解码器的注意力对齐得到。
- 语音嵌入。 编码器的输出,每 80 ms 一帧对应一行,无需解码出转写文本。
标记为共享的模块运行的是 Needle 的代码,而不是其副本。--audio-depth 选择解码器层数;编码器始终运行全部八层。
前端。 16 kHz 单声道音频按 25 ms 窗口、10 ms 跳跃分帧为 80 个 log-mel 滤波器组,频带限制在 250–3500 Hz,并按通道归一化。30 秒就是 3,000 帧。一个 128 通道、卷积核为 9 的卷积 stem 把帧数减半三次,剩下 375 帧,每 80 ms 一帧。此后的每一阶段都按这个速率运行,embed 每帧返回一行。
编码器。 八个 Simple Attention 模块:四条 mHC 残差通道,以及一个替代前馈网络的 Monarch Hadamard MLP,与 Needle 使用的模块相同。注意力不是因果的:3 秒处的帧可以注意到 12 秒处的帧。
解码器。 八个 Laddered Simple Attention 模块,宽度 512,8 个 query 头对应 2 个 KV 头,48 维 query 和 key,64 维 value,Q、K、V 上有一个 3-tap 因果卷积,并在第 3 层和第 7 层通过 18,432 个槽进行 engram 查找。这就是 Needle 的模块列表,只是层数不同。
与语音相关的部分是在每层加了一个模块。每个解码器层通过一个门控交叉注意力读取编码器:x ← x + σ(g) · softmax(q̂ K̂ᵀ/√d) V,其中门控是每层学习得到的,K 和 V 来自音频片段。这些投影在片段到来时只运行一次——375 帧经过 8 层——然后在整个解码过程中保持不变。因此五条 beam 只需要五份简短的转写缓存,而不是对音频做五次遍历。
解码。 五条 beam 按长度归一化的对数概率打分。关键词偏倚会沿着 Aho-Corasick 自动机在你传入的短语上前进,与 beam 同步,并在自动机前进时提升它们的对数概率。转写上限为 320 个 token。词表是 8,192 个文本片段加上七个语言 token(每种语言一个),因此检测到的语言是作为一个 token 发出的,而不是在带外返回。
阶梯位于解码器上。 从 2 层往上的每一个深度都作为独立模型训练过,加载时由 --audio-depth 选择其一。编码器从不切片:所有深度都运行全部八个模块。
静音。 引擎在解码器启动前会测量音频片段的响度范围。低于阈值时,它返回空的转写和空的语言,并且根本不进入 beam search。
Whistle、Whisper base、Moonshine tiny v2
词错误率,越低越好。缺失的柱形表示该模型作者从未发布过该基准:Moonshine 仅支持英语,Whisper 没有报告 SPGISpeech、Earnings-22 或 AMI cleaned。Whisper 的 AMI 数字是 AMI-IHM,是另外两个模型所报告的 AMI 的不同子集。
Whistle 在 LibriSpeech test-clean 和 test-other、SPGISpeech、Earnings-22 以及 FLEURS 平均值上领先。Whisper base 在 TED-LIUM、AMI 和 MLS 平均值上领先,但其大小是 145.3 MB,而 Whistle 是 16.9 MB。
大小(MB,越小越好): Whistle 16.9 MB Whisper base 145.3 MB Moonshine tiny v2 41.9 MB
首 token 时间(毫秒,越小越好): Whistle 11.1 ms Whisper base 73.2 ms Moonshine tiny v2 22.8 ms
解码速度(tokens/秒,越大越好): Whistle 1,319/s Whisper base 266/s Moonshine tiny v2 262/s
以上是在 Apple M4 Pro CPU 上处理 10 秒音频的结果,每个面板内的柱形按比例缩放。
每个模型都以其官方运行时的默认设置运行:Whistle 的 C++ 引擎使用 5 条 beam,openai-whisper,以及在完整音频上非流式的 moonshine-voice。首 token 时间是从音频输入到第一个 token 的时间。解码速度是其后的 token 数除以墙钟时间,因此编码器不会被计算两次。Whisper 会把每个输入填充到 30 秒,所以它的首 token 时间在不同片段长度上保持不变。Whistle 的则随片段长度变化:5 秒时 5.9 ms,10 秒时 11.1 ms,30 秒时 36.3 ms。
词错误率使用 Whisper normalizer 评分。Whistle 的结果是在 86,174 条语音上测得的。Whisper 和 Moonshine 的数字是其作者发布的,来自多语言 checkpoint 而非纯英语 checkpoint。通过对比每个报告测试集的音频校验和与说话人 ID,可以确认 Whistle 的训练或验证数据中没有出现任何测试音频。
因为 needle_load 会读取 .cact 文件中所含的模型,同一个二进制文件可以处理语音、文本,或两者都处理:
needle --model whistle.cact --audio clip.wav
needle --model needle3.cact --tools tools.json --prompt "turn off the kitchen lights"
needle --model needle3.cact --model whistle.cact --tools tools.json --audio clip.wav
在第三行中,needle_complete 直接接收音频片段。引擎会转写它,根据你的工具对转写结果作答,并返回一个 JSON 对象,其中包含调用和语音字段,语音字段以 audio_ 为前缀。调用方无需处理转写文本。
返回的 JSON 例如:{"function_calls":[{"name":"set_lights","arguments":{"room":"kitchen","on":false}}], "confidence":0.94, "audio_text":"turn off the kitchen lights", "audio_language":"en"}。
通过 pip install cactus-needle 安装后,在 Python 中引入 needle 并调用 needle.transcribe("clip.wav")["text"] 即可得到转写文本,例如输出 “turn off the kitchen lights”。16 kHz WAV 或原始采样只需基础安装即可;其他采样率和麦克风采集需要额外安装 [mic],它会加入 soxr 和 sounddevice。
每次调用都会返回文本、语言、首 token 的毫秒数以及其后解码器的 tokens/秒。word_timestamps=True 会额外返回每个词及其时间和概率。keywords=["Siobhan", "Krzysztof"] 会在搜索过程中提升这些短语的对数概率。language="de" 会强制使用指定语言,而不是检测语言。needle.Whistle() 是同一个模型的对象形式,可用于 embed(audio),或持有一个调优过的 .cact。
needle whistle playground 在终端中从麦克风转写,needle whistle compare 则把同一个音频片段依次通过 Whistle、Whisper 和 Moonshine,并并排显示它们的耗时。
引擎为十七个目标平台提供了预构建版本,涵盖 macOS、Linux、Android、iOS、watchOS、Windows on ARM、RISC-V、MIPS、浏览器以及一个 WASI 组件。每个文件夹都包含一个 needle 二进制文件、libneedle.a 和 needle.h,并能加载你交给它的任何 .cact。
needle download macos-arm64
needle download whistle
./macos-arm64/needle --model whistle.cact --audio clip.wav --audio-word-timestamps
needle_load、needle_transcribe 和 needle_embed 构成了完整的语音 C API。引擎不读取任何环境变量。每个行为要么是编译时的默认值,要么来自显式的标志。
权重在 Hugging Face 上,引擎及其平台文件夹在 Cactus-Compute/needle3 中,源代码在 GitHub 上。
评论
讨论气氛偏积极,很多人被 Whistle 这类 sub-20MB、纯 CPU 优先的模型在英文上的准确度和极小体积所惊艳;但分歧主轴是它是否真能替代现有语音转写方案——肯定者认为它已适合本地、网页和嵌入式落地,质疑者则强调非英语与口音拉胯、有 30 秒限制、不能流式输出,且自由转写时明显不如 Parakeet、Qwen 等更大模型。
认为 Whistle 以极小体积和纯 CPU 推理实现了惊艳的英文转写,已适合本地与网页嵌入
- 在 sub-20MB、无 GPU 的约束下,Whistle 的英文识别不仅准确,还能处理复杂句式、timing 和多种口音(如印度、西班牙口音);基准表现被认为在这个体积下“惊人”,有人已经想到把它塞进网页应用或本地工具链,也有人表示欢迎更多这种 CPU 优先的小模型。(较多人) > 在如此小的体积下,它把带有复杂 timing 和用词的多句话都转写出来了,让我非常惊讶,也很期待基于它构建应用(@kamranjon)
认为非英语与带口音场景是硬伤,实际准确度仍不如 Parakeet 等现有模型
- 多人在西语、日语、波兰语下测试都不理想:西语会生成不存在的词,日语被识别成蹩脚西语,波兰语除非大声、清晰、慢速否则很差;英语也会把 cleaning 误成 training。相比之下 Parakeet 在同样场景下明显更稳,因此有人要求增加更多语言。(较多人) > 波兰语除非说得又大慢又清晰,否则表现不好,Parakeet 明显更好(@pzo)
认为当前版本受工程限制,离实时、长音频和日常鲁棒使用还有距离
- Whistle 目前有 30 秒音频上限,demo 也不支持边说边出字的流式转写,而这正是通用实时语音转写的关键;还有人在转写剧集时遇到它卡住、连续 60 秒重复输出 “Thank you.” 的情况。移动端方面,iPhone 键盘集成体验被吐槽,Android 版本仍被期待;此外,真正的挑战也被认为不是模型体积,而是中风后口齿不清等受损语音——现有系统会把说话人嘴里发出的每个杂音都写进文本。(较多人) > 这个 demo 没有展示边说边出字的流式转写,而这对大多数通用实时语音转写应用来说是必备功能(@albert_e)
少数人认为 STT 已接近边际收益,应组合更大模型或加 LLM 后处理,而非押注 Whistle
- 现有 Qwen STT 在开放权重榜领先,Parakeet v2 在英文上已又快又准,ZWhispr 通过串联三个 SOTA 模型追求更高准确率;因此 Whistle 这类小模型带来的提升可能有限,更实用的是在后处理阶段用小模型做一次 LLM 清理。(少数人) > Qwen 的 STT 模型目前正领跑开放权重榜,Parakeet v2 在英文上又快又准,而且之后还能直接用小模型做一遍 LLM 后处理(@TomGarden)
有价值的补充
- 有开发者把 Whistle 用在改造 Echo Show 上,完全本地处理、不再连亚马逊;但自由转写时 170 条只认对 70 条(对比 Qwen 的 168 条),后来改成只识别有限命令模板,并用 1 万条生成语句训练一个小网络把 Whistle 的最终状态映射到模板概率,准确率升到 164/170,几乎追平 Qwen,且适用于重口音——说明对弱 ASR 做严格模板约束能大幅补救。
- 同理念的 CPU 本地替代方案还有 yapsnap:基于 Zipformer 的流式 ASR,带说话人分离和时间戳,支持 10 种语言,无 GPU、无云且免费无限转写;此外 Vosk-browser、跨平台的 Handy(常搭配 Parakeet Unified EN 0.6B)以及串接多个 SOTA 模型的 ZWhispr 也被提及。
- 名称冷知识:Google Play 上已有一个同名的 Whistle Android 语音转写应用,讨论中有人因此混淆;也有人尝试把新模型嵌入该 App 以缩小体积,但因支持语言太少而受限。