Moonshine Micro:80美分芯片跑完整语音流水线,500KB内存装下VAD+STT+TTS

一块售价 80 美分、SRAM 只有 520 KiB 的微控制器能干什么?Pete Warden 给出的答案是:跑完一条完整的语音交互流水线——语音活动检测(VAD)、语音识别(STT)、神经文本转语音(TTS),全部在端侧完成,不联网、不调云 API、不需要账号或密钥。这个名为 Moonshine Micro 的开源项目本周登顶 Hacker News,把「80 美分芯片 + 不到 500 KiB RAM 跑完整语音界面」这件事从概念演示拉到了可复现的工程实现。

Pete Warden 是前 Google Brain 工程师,2017 年他在 Google 内部提出的「登月计划」就是在 50 美分芯片上跑一套能用一年的语音识别系统。九年后,Moonshine Micro 在树莓派 RP2350 上交付了这条流水线的开源版本:说话报出 WiFi 名称和密码,芯片听懂后完成配网,再把 IP 地址语音播报回来。整套交互在设备本地完成,延迟在秒级。

为什么 Whisper 跑不到这种芯片上

要理解 Moonshine Micro 的意义,先看它要替代的是什么。OpenAI 开源的 Whisper 家族是过去几年端侧语音识别的事实标准,但它在设计上做了几个对微控制器极不友好的假设:

  • 固定 30 秒输入窗口。Whisper 的 encoder/decoder 永远在 30 秒音频上运行,对批处理文件没事,对实时语音界面就是灾难——人一句话通常只有 5-10 秒,剩下的全是零填充,白白浪费编码算力,延迟被拉长。
  • 不缓存中间状态。流式应用需要边说边反馈,每来一段新音频就重新跑一遍 encoder,对前面已经处理过的音频做大量重复计算。
  • 多语言平均用力。Whisper 把 82 种语言塞进一个模型,根据 OpenAI 自己公布的数据,只有 33 种语言在 1.5B 参数的最大模型上能压到 20% WER 以下;常用在边缘设备上的 Base 模型,只有 5 种语言达标。韩语、日语这些市场巨大的语言,精度根本不够用。

Moonshine Voice 架构:从音频捕获到事件回调的完整流水线

Moonshine 把这几条全部推翻:输入窗口长度可变,只对实际音频计算;encoder 状态可缓存,流式增量推理时跳过重复计算;不做「一个大模型管所有语言」,而是为每种语言单独训练专精模型,用同样的参数量和算力换更高精度。在 HuggingFace 的 OpenASR 排行榜上,Moonshine Medium Streaming(245M 参数)英文 WER 6.65%,低于 Whisper Large v3(1.5B 参数)的 7.44%。在树莓派 5 上,前者 802ms 出结果,后者直接跑不动。

Moonshine Micro 是这条路线推到极致的产物——连微控制器都要拿下。

流水线拆解:三个模块共享一块 384 KiB 内存

Moonshine Micro 的参考平台是树莓派 RP2350:双核 Arm Cortex-M33 @ 250 MHz,520 KiB SRAM,4 MiB flash。整条流水线由三个独立神经网络模块组成,全部基于 TensorFlow Lite Micro,在 C++ 层用 CMSIS-NN 的 int8 SIMD 内核加速:

组件模型Flash 占用SRAM(峰值 arena)算力
VAD(语音活动检测)int8 TinyVadCNN~89 KiB~36 KiB~25 MMAC/s
STT(命令词识别)int8 SpellingCNN,51 类分类~1.3 MiB~346 KiB~36 MMAC/s
Neural TTS(神经语音合成)RVQ 解码器 + WORLD-lite 声码器 @ 16 kHz~1.8 MiB voice pack~340 KiB~65 MMAC/s(输出)
总计(demo 固件)~3.6 MiB~468 KiB分类+播报 ~0.7–1.0 s

关键工程细节在于:VAD、STT、TTS 三个模块顺序执行,共享同一块约 384 KiB 的 TFLM tensor arena,内存不是累加的。三个模块轮流进场用同一片内存,RP2350 实际只预分配了 468 KiB(含应用缓冲区和栈),在 520 KiB 的 SRAM 里还留出余量。这是整条流水线能压进不到 500 KiB 的核心——三个模型并没有被压缩到能并列共存,而是通过严格的内存时分复用轮流占用同一片 arena。

VAD:每 32 毫秒一次的「有人在说话吗」

VAD 模块是 always-on 的守门人。每 32 ms 的音频帧(一个 hop)经过一次 FFT 算出 log-mel 特征,喂给 int8 的 TinyVadCNN,输出一个 [0,1] 的语音概率。一个移动平均平滑器把逐帧概率聚合成语音段边界——什么时候开始说、什么时候说完。

VadSegmenter 故意不存音频,只存边界,内存占用近乎为零。当它判定一段语音结束时,应用从环形缓冲里把对应的 1 秒音频 clip 抠出来,交给 STT。为了让这 1 秒 clip 的中心对准发音能量峰值(避免把开头的辅音切掉或把词甩到窗口边缘),代码用 EnergyCentroidIndex 算能量质心,再把 clip 在缓冲里滑到居中位置。这个对齐小动作在 host 仿真里几乎补平了流式 VAD 相对离线 VAD 的精度差。

STT:51 类的 SpellingCNN

嵌入版的 STT 并非通用大词表语音识别,它是一个面向孤立发音的 51 类分类器——一次只识别一个字母、数字或命令词,输入是约 1 秒 @ 16 kHz 的 clip。词表分三类:

  • 字母 26 个az
  • 数字 10 个zeronine
  • 命令/符号词 15 个capitaluppercasestardollarunderscoreexclamationpercentdeletefinishcancelwifiipyesnohey rp

SpellingCNN 接收 64×128 的归一化 log-mel 特征平面,输出 51 维 logits,再经 softmax 取 argmax。在 RP2350 双核 @ 250 MHz 上,一次推理约 314 ms(单核 507 ms),对应约 36 MMAC/s 的有效算力。特征生成和推理共用同一片 arena 字节——fp32 的 log-mel 先写进空闲 arena 的 overlay 区域,推理时直接从同一片内存读,省掉一份独立特征缓冲。

这套设计明确划定了能力边界:不支持 NATO/ICAO 字母表(alpha/bravo)、不支持连续语音、不支持拼写单词。要换词表,替换 .tfliteclasses.* 两个 blob 即可(通过 generate_embedded_data.py 脚本生成),但 flash 和 arena 尺寸要重新校验。Moonshine AI 官方说明,针对产品名、特定语言字母、自定义命令集的定制词表模型通过商业授权提供。

Neural TTS:16 kHz 神经双音素合成

TTS 是整条流水线里最让人意外的部分。在亚 1 美元的 MCU 上做 TTS,传统做法是拼波形拼接或 Klatt 共振峰合成,质量勉强能听。Moonshine Micro 走的是神经双音素(diphone)合成路线:英文文本经 G2P 规则引擎转音素,Klatt 时长规则给每个音素分配时长,再做双音素单元挑选,RVQ 解码器把压缩的神经码本解成波形帧,最后 WORLD-lite 声码器合成 16 kHz 单声道 int16 PCM。

整条 TTS 链路不在内存里缓存整句 PCM,而是流式逐块吐出——Synthesize() 通过回调反复把连续的 int16 chunk 推给应用注册的 sink(I2S、USB、DAC、环形缓冲都可以),引擎内部没有完整语音 PCM 缓冲。典型的一个字母回复(如「bee」)算力约 37 MMAC,0.4-0.7 秒合成完成;合成速度大致等于实时(1× real-time)。

对专有名词,规则 G2P 会猜错发音(例如宾州地名 Reading 会被规则按动词读成 REE-ding,本地人读 RED-ing),对此 SynthesizeIpa() 直接跳过 G2P,让应用直接传 IPA 音素串,绕过词前端。这种「规则引擎 + 可控 IPA 后门」的设计在嵌入式 TTS 里不算常见,但对产品化场景(品牌名、产品名)很实用。

把 WiFi 配网变成一段对话

官方 demo 远不止「听一个字母回声一个字母」这么简单,它是一个完整的语音驱动 WiFi 配网流程:说出触发词 wifi → 设备进入配网模式 → 用户一个字母一个字母地报 SSID → 报密码 → 设备连接 → 用 ip 命令查询分配到的地址。每个步骤都有 TTS 语音引导,全程无屏幕、无手机 App、无云。

这个 demo 的工程价值在于展示了「无屏设备的零配置入网」这条路:IoT 设备最痛的环节就是配网,传统方案要么靠蓝牙+手机 App 引导,要么靠 SmartConfig 抓包,要么干脆出厂带硬编码 SSID。Moonshine Micro 给出的方案是用 80 美分的芯片+几个美元的麦克风喇叭,让用户直接对着设备说话完成配网,不需要任何额外基础设施。

它没做到的事,和它的边界

Moonshine Micro 在 README 里对自己很坦诚:

「We're not quite at general speech recognition on this class of hardware yet.」

不是通用语音助手。当前版本是命令词识别 + 字母数字拼读,不是连续语音转写,也不是开放域对话。要做「听懂一句话」级别的 STT,最小可用模型也要几十 MB 起,远超 RP2350 的 4 MiB flash 和 520 KiB SRAM。

但它的意义在于验证了一条路径:完整的语音交互流水线(VAD + STT + TTS)可以全部端侧跑在一块 80 美分的 MCU 上,RAM 占用不到 500 KiB,MIT 许可证开源。把这条路从「学术 demo」推到「可复现的固件工程」,本身就是一个里程碑——过去几年端侧 AI 的讨论焦点一直在手机和 PC 上,MCU 这一层几乎被默认「不可能」。Moonshine Micro 把这条默认假设撕开了一道口子。

对嵌入式开发者来说,三个模块(VAD/STT/TTS)都是独立 CMake 库,可以单独集成:只想要一个 always-on 的 wake word 检测就只接 VAD;想要语音反馈就只接 TTS;想做完整对话链路再接全部。整套代码 MIT 许可证,可商用,模型权重也以 MIT 发布。对于做 IoT、可穿戴、家电、玩具的团队,这是一个可以直接拿去改的起点,而不是一个只能看的论文 demo。

Pete Warden 这九年的坚持

这个项目背后是 Pete Warden 个人的一条技术主线。2017 年他在 Google Brain 提出「50 美分芯片 + 纽扣电池跑一年」的端侧语音识别目标,当时被多数人当作不可能完成的工程题。离开 Google 后他创办 Useful Sensors(后更名 Moonshine AI),持续在端侧语音方向投入:第一代 Moonshine 模型去掉了 Whisper 的固定输入窗口、引入流式缓存,在实时语音场景下比 Whisper 快 5 倍以上;这一代 Moonshine Micro 进一步把战线推到 MCU。

他在 LinkedIn 上写这段经历时说得很直白:「九年后我还在朝这个目标走,Moonshine Micro 的发布是往前的一大步。」对一个被多数人判定「端侧做不到」的方向,九年的持续投入本身就是一种答案。

Moonshine Micro 的 GitHub 仓库在 moonshine-ai/moonshinemicro/ 目录下,参考平台固件在 micro/examples/rp2350/,完整的内存预算、构建步骤、烧录方法、I2S 麦克风和功放的接线图都在 README 里——不需要特殊硬件,用笔记本的麦克风和扬声器通过 USB bridge 就能跑通整个 demo。对嵌入式 AI 感兴趣的开发者,这是一个周末就能上手复现的项目。

推荐阅读