Whistle 16.9 MB Speech‑to‑Text Model: Tiny, Fast, Multilingual On‑Device ASR
TL;DR – What Whistle delivers and why it matters
- What: Whistle is a 16.9 MB on‑device speech‑to‑text model that runs entirely on the CPU, requires no external dependencies, and shares the same C++ runtime as the Needle language model.
- Why it matters: At sub‑20 MB size it provides multilingual transcription, word‑level timestamps, and speech embeddings with latency‑to‑first‑token of ~11 ms—far faster than OpenAI’s Whisper‑base (73 ms) and comparable to much larger models, enabling real‑time STT on mobiles, wearables, micro‑controllers, and edge devices.
Core capabilities
- Transcription – 16 kHz mono audio, up to 30 s, in English, German, French, Spanish, Italian, Dutch, Polish. Language is auto‑detected unless explicitly set.
- Word timestamps – Each word is returned with start/end times and a confidence score, derived from the decoder’s attention mechanism.
- Speech embedding – The encoder outputs a frame‑wise embedding (one 80 ms row per frame) without decoding, useful for downstream tasks such as speaker identification or audio retrieval.
"The first press downloads the 16.9 MB model, and audio never leaves your device." – Cactus Compute blog
Architecture at a glance
| Component | Design details | Shared with Needle |
|---|---|---|
| Front‑end | 25 ms window, 10 ms hop, 80 log‑mel bins, band‑limited 250‑3500 Hz, per‑channel normalisation. 30 s → 3,000 frames → 375 frames after three stride‑2 convolutions. | Yes |
| Encoder | 8 Simple Attention blocks (4 mHC residual lanes + Monarch Hadamard MLP). Non‑causal attention allows long‑range context (e.g., a frame at 3 s can attend to 12 s). | Yes |
| Decoder | 8 Laddered Simple Attention blocks, width 512, 8 query heads → 2 KV heads, 48‑dim Q/K, 64‑dim V, 3‑tap causal conv on Q/K/V, engram look‑ups (layers 3 & 7, 18,432 slots). | Yes |
| Cross‑attention | Gated cross‑attention per decoder layer: x ← x + σ(g)·softmax(q̂K̂ᵀ/√d)V. Encoder projections are computed once per clip (375 frames) and reused across beams. |
– |
| Decoding | 5‑beam search, length‑normalised log‑probability, keyword biasing via Aho‑Corasick automaton, max 320 tokens, vocab 8,192 pieces + 7 language tokens. | – |
| Silence handling | Pre‑decode loudness check; below threshold returns empty transcript and language without entering beam search. | – |
Laddered depth selection
The --audio-depth flag selects a decoder depth at load time (2‑layer up to full 8‑layer). All encoder layers always run; the decoder can be sliced to trade speed for accuracy.
Benchmark highlights
All numbers are measured on an Apple M4 Pro CPU unless otherwise noted.
| Metric | Whistle | Whisper‑base (145 MB) | Moonshine tiny v2 (42 MB) |
|---|---|---|---|
| Model size | 16.9 MB | 145.3 MB | 41.9 MB |
| Time‑to‑first token | 11.1 ms (10 s clip) | 73.2 ms | 22.8 ms |
| Decode speed | 1,319 tokens/s | 266 tokens/s | 262 tokens/s |
| LibriSpeech test‑clean WER | ahead of Whisper & Moonshine | – | – |
| SPGISpeech WER | ahead | – | – |
| Earnings‑22 WER | ahead | – | – |
| FLEURS average WER | ahead | – | – |
| TED‑LIUM WER | behind Whisper | – | – |
| AMI WER | behind Whisper | – | – |
| MLS average WER | behind Whisper | – | – |
"Whistle is ahead on LibriSpeech test‑clean and test‑other, on SPGISpeech, on Earnings‑22 and on the FLEURS average." – Cactus Compute blog
Interpretation of results
- Speed: Whistle’s first‑token latency scales with clip length (5.9 ms at 5 s, 36.3 ms at 30 s), whereas Whisper pads all inputs to 30 s, giving a flat latency.
- Accuracy: For English‑centric benchmarks Whistle matches or exceeds Whisper‑base, despite being >8× smaller. Multilingual performance is competitive on the seven supported languages, though some community comments note degradation on Spanish and Dutch‑German confusion.
- Resource usage: The entire pipeline runs on a single CPU core with no GPU, making it suitable for low‑power devices (micro‑controllers, RISC‑V, MIPS, Android, iOS, etc.).
Integration and API surface
Command‑line usage (same binary for text and speech)
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
The third command performs end‑to‑end voice‑controlled tool invocation, returning JSON:
{
"function_calls": [{"name": "set_lights", "arguments": {"room": "kitchen", "on": false}}],
"confidence": 0.94,
"audio_text": "turn off the kitchen lights",
"audio_language": "en"
}
Python wrapper (pip package cactus-needle)
import needle
print(needle.transcribe("clip.wav")["text"]) # → turn off the kitchen lights
Optional flags:
word_timestamps=True– returns per‑word timing and probability.keywords=["Siobhan", "Krzysztof"]– boosts those phrases during beam search.language="de"– forces German detection.needle.Whistle()– creates an object for repeatedembed(audio)calls.
Cross‑platform binaries
Pre‑built binaries exist for 17 targets, including macOS (ARM/x86), Linux, Android, iOS, watchOS, Windows‑ARM, RISC‑V, MIPS, browsers (WebAssembly), and a WASI component. Each folder contains:
needleexecutablelibneedle.aneedle.hAll binaries load any.cactmodel file without environment‑variable configuration.
Community feedback (selected HN comments)
- Positive reception: Users praise the tiny footprint and speed, especially for embedding in web apps or edge devices. (e.g., "For something you could plausibly ship inside a webapp, it’s very good.")
- Accuracy concerns: Several commenters report language‑specific issues (Spanish, Dutch vs. German, Polish) and occasional hallucinations on challenging audio. One user observed a 60‑second segment repeatedly outputting "Thank you." indicating a failure mode on long dialogues.
- Feature requests: Real‑time streaming transcription (output while recording) is missing; users note it as essential for live applications.
- Comparisons: Users compare Whistle to Parakeet, Whisper, and Moonshine, noting Whistle’s speed advantage but mixed accuracy relative to larger models.
- Hardware curiosity: Questions about running on micro‑controllers (ESP32, STM) and RISC‑V were raised; the project already ships a RISC‑V build, but full micro‑controller support remains unverified.
Practical use‑cases
- Voice‑controlled IoT devices – Local transcription eliminates latency and privacy concerns for smart‑home commands.
- Robotics – On‑board speech interfaces for robots without GPU acceleration.
- Wearables & automotive – Low‑power, on‑device STT for hands‑free interaction.
- Edge inference pipelines – Combine Whistle embeddings with a small LLM for context‑aware command parsing.
How to get started
- Download the model and runtime
needle download whistle # pulls the 16.9 MB .cact file needle download macos-arm64 # example for Apple Silicon - Run a quick test
./macos-arm64/needle --model whistle.cact --audio clip.wav --audio-word-timestamps - Integrate via Python – install
cactus-needleand callneedle.transcribeorneedle.embedas shown above. - Explore depth trade‑offs – experiment with
--audio-depth 2…8to balance speed vs. WER for your target hardware.
Limitations and open questions
- Language coverage: Only seven European languages are supported; no Chinese, Japanese, or other high‑demand languages.
- Streaming output: Current API provides a final transcript after the audio clip is fully processed; real‑time token‑by‑token streaming is not yet available.
- Robustness to accents: Community reports indicate degraded performance on strong accents (e.g., Polish, Dutch‑German, Indian English), suggesting the training data may be biased toward standard accents.
- Micro‑controller feasibility: While a RISC‑V binary exists, running on ultra‑low‑power MCUs (ESP32, STM32) has not been demonstrated publicly.
Where to find the code and models
- Model weights: https://huggingface.co/Cactus-Compute/whistle
- Engine & platform binaries: https://huggingface.co/Cactus-Compute/needle3
- Source repository: https://github.com/cactus-compute/needle
Whistle demonstrates that high‑quality, multilingual speech‑to‑text can be delivered in a sub‑20 MB CPU‑only package, opening the door to truly offline voice interfaces on a wide range of edge hardware.
Sources
Related
- Project
- Dispatch
- Project
- Project
- Dispatch