一个 16.9MB 的语音模型,想让你家音箱、机器人、手表都在本地把话听明白
Cactus Compute 发了新模型 Whistle,名字起得挺随意,东西倒不小——一个语音识别模型,整个打包成一个 16.9MB 的单文件,跑在 CPU 上,和它家之前的 Needle 是同一套引擎、同一个容器、同一种量化方式,没有任何依赖,也不碰 GPU。说人话就是:不用云端、不用显卡,一个小文件就能让设备自己听懂人说话。
一个模型干三件事,全在设备上
Whistle 一共干三件事,全都在设备上完成。
一是转写。接收 16kHz 单声道音频,一次最多处理 30 秒,支持英语、德语、法语、西班牙语、意大利语、荷兰语和波兰语七种语言。语言可以在调用时指定,也可以让模型自己检测。比较值得留意的一点是:如果检测到静音,它返回空转写文本,而不是随便编一句「嗯嗯嗯」凑数——这种细节在真实产品里挺影响体验的。
二是词级时间戳。每个词都带开始时间、结束时间和概率,对齐用的是解码器自己的注意力输出,应用可以直接在某个词上做高亮、跳转或裁切。用途很明确,比如视频字幕逐词跟读、录音里点某个词跳到对应位置。
三是语音嵌入。直接取编码器输出,每 80ms 帧一行,用于不经过转写就能做的匹配和检索——比如给用户的声音建档、按语义找人说话片段,这些任务根本不需要先出一份文本。
它还有一个关键词加权(keyword biasing)功能,用户真正会念的名字、地名、产品词可以被优先搜到,生僻名词不容易被听错。
和 Needle 共用一套引擎,这是它的底牌
架构上是 log-mel 前端加卷积主干喂给音频编码器,再由一个 Needle 形状的解码器通过每层的门控交叉注意力来读。翻译成大白话:它复用了 Needle 的 .cact 容器、量化、SIMD 内核和 KV cache,所以一台已经能跑 Needle 的设备,能在同一个二进制里直接跑 Whistle,不用再装第二套运行时。这和旧方案到处堆依赖、凑环境的做法完全是两回事。
解码器也是和 Needle 一样的「阶梯式」设计,从 2 层往上每一层深度都是一个可以部署的模型,加载时用 --audio-depth 参数选。这个仓库里放的是 whistle.cact,引擎和各平台文件夹在 Cactus-Compute/needle3 里。
更实用的是它俩能同时加载。同一个二进制里 needle_load 读哪个 .cact 就是哪个模型,于是可以一个调用既转录语音、又对着工具回答问题,最后返回一个 JSON,语音字段带 audio_ 前缀。转写全程留在引擎内部,输入一段音频、输出一串工具调用,一次搞定。这其实就是把「听懂话」和「干事情」焊在一个通道里,省了中间那层胶水代码。
关于跑分,说几句实在的
官方数据里有几个点值得拆开讲。转写质量上,Whistle 用 Whisper 的归一化方式在全量测试集打分,一共测了 86,174 条语音;标称精度是 2 到 4 bit 量化,对比的 Whisper 是 CPU 上 fp32 内存态、Moonshine 是 int8。也就是说这不是在同精度下比,而是在「我就是要做轻量化」的前提下比出来的。
有个细节挺加分:官方说没有一条测试音频出现在 Whistle 的训练或验证数据里,是用音频校验和跟说话人 ID 在全部报告过的测试集上比对核实的。这起码回应了「是不是拿测试题刷分」的怀疑。
当然也要说明白:Moonshine 只支持英语,Whisper 若干测试集没公布分数,所以图表里有的栏是空的。做产品的别只看 WER 数字,还得看模型支持的语言、设备约束和你自己场景的音频条件。
上手和部署都很轻
Python 侧装个 pip install cactus-needle,16kHz 的 WAV 或裸采样不需要额外装什么,其他采样率或麦克风采集才需要 [mic] 这个 extra。一行 needle.transcribe("clip.wav")["text"] 就出文本,每次调用会返回文本、语言、到首个 token 的毫秒数和首 token 之后的解码速度。要词时间戳就加 word_timestamps=True,要加权关键词就传 keywords=[...],想强制语言传 language="de"。needle whistle playground 从麦克风直接转写,needle whistle compare 能把 Whistle、Whisper 和 Moonshine 放到同一段音频上对比。
部署层面,引擎各平台文件夹都在 Cactus-Compute/needle3,每个文件夹带 needle 二进制、libneedle.a 和 needle.h,能加载任何交给它的 .cact。C API 就三个函数:needle_load、needle_transcribe、needle_embed,外加一个直接吃音频、内部替你做转写的 needle_complete。还有个细节:引擎不读任何环境变量,所有行为要么编译默认值要么明确参数,所以同一个二进制每次跑出来结果一致——这对可复现和稳定上线挺重要。
保留意见的地方也有。一是这模型定位「小设备上不依赖 GPU」,确实合很多嵌入式场景,但真要跑完整对话、要接工具链,还是得看它跟 Needle 这套框架熟不熟、愿不愿意跟着它的生态走;二是对比标称的精度差(2–4 bit 对上 fp32 / int8)意味着横向数字不能照单全收,得用自己的数据实测。它目前上传在 Hugging Face,过去一个月下载量 5,558 次,看得出圈子里有人在试。至于它能不能成为 TTS 之后那个被大量板子收编的默认语音入口,还要看真实设备上的表现——反正 16.9MB 是实打实的,跑不跑得动、好不好用,上手才知道。
相关链接