Local speech-to-text at GPU speed
wavo turns speech into text locally, on the GPU, in pure Rust. Give it a recording of any
length, a voice note or a two-hour meeting, and get the text with timestamps. It runs the open ASR
models that transcribe.cpp publishes with
practically the same output, faster than transcribe.cpp on Apple Silicon and NVIDIA GPUs, on par
or slower on integrated Intel GPUs for some models. Use it as a command-line tool with an
ollama-like model manager, or as a library that builds with a plain cargo build.
🌟 Features
- 📏 Audio of any length: long recordings are split at pauses and joined back, no chunking on your side
- 🎧 Any common format: wav, mp3, m4a, flac, ogg (Vorbis), resampled for you
- 🦀 Pure Rust library: no CMake, C++ toolchain, Python or ONNX Runtime to install
- ⚡ Runs on the GPU: Metal on Apple Silicon, Vulkan on Linux and Windows (DX12 without Vulkan)
- 🏎️ Faster than transcribe.cpp on the same model files on Apple Silicon and NVIDIA (see Speed), and loads in about 0.1 s on an M2
- 🎯 Same text, tokens and timestamps as transcribe.cpp on its test clips
- 📦
pull/list/rmmodels, shared with the Hugging Face cache thathfuses - 📝 Plain text, JSON with a start time for every token, or SRT subtitles
- 🌍 English, Russian, 25 European languages, and 100 with Whisper
🤖 How it's made
wavo is written by AI agents (Claude Code, Codex) following agents.md; I choose what to build and review every pull request. Each model's output is checked against transcribe.cpp's own (fixtures), and every speed change is measured and logged in docs/perf.md. This isn't a weekend prompt: I've written software by hand for years — macmon (Rust, Apple Silicon system monitor), twscrape (Python, X/Twitter scraping) and ecloop (C, low-level elliptic-curve math) — and agents are how I build now.
🧠 Models
| Name | Size | Languages | Output |
|---|---|---|---|
parakeet-v3 (default) |
0.74 GB | 25 European languages | cased, punctuated |
parakeet-v2 |
0.73 GB | English | cased, punctuated |
gigaam-v3 |
0.27 GB | Russian | cased, punctuated |
gigaam-v3-e2e-ctc |
0.27 GB | Russian | cased, punctuated |
gigaam-v3-rnnt |
0.27 GB | Russian | lowercase, no punctuation |
gigaam-v3-ctc |
0.27 GB | Russian | lowercase, no punctuation |
whisper-turbo |
0.89 GB | 100 languages | cased, punctuated |
whisper-tiny |
0.05 GB | 99 languages | cased, punctuated |
whisper-base |
0.08 GB | 99 languages | cased, punctuated |
whisper-small |
0.27 GB | 99 languages | cased, punctuated |
whisper-medium |
0.83 GB | 99 languages | cased, punctuated |
whisper-large-v3 |
1.67 GB | 100 languages | cased, punctuated |
whisper-tiny.en |
0.05 GB | English | cased, punctuated |
whisper-base.en |
0.08 GB | English | cased, punctuated |
whisper-small.en |
0.27 GB | English | cased, punctuated |
whisper-medium.en |
0.83 GB | English | cased, punctuated |
whisper-large |
1.67 GB | 99 languages | cased, punctuated |
whisper-large-v2 |
1.67 GB | 99 languages | cased, punctuated |
breeze-asr-25 |
1.67 GB | Taiwanese Mandarin and English | cased, punctuated |
moonshine-tiny |
0.04 GB | English | cased, punctuated |
moonshine-base |
0.08 GB | English | cased, punctuated |
Parakeet is NVIDIA's Parakeet TDT 0.6B,
GigaAM is Sber's GigaAM v3, Whisper is OpenAI's
Whisper, Breeze-ASR-25 is MediaTek
Research's Whisper large-v2 fine-tune
and Moonshine is Useful Sensors' Moonshine,
small and fast. Moonshine has no timestamps: its tokens all start at 0, and --srt gives one cue
per piece of the split audio.
Short names stand for the published ones: parakeet-v3 is parakeet-tdt-0.6b-v3, parakeet-v2
is parakeet-tdt-0.6b-v2, gigaam-v3 is gigaam-v3-e2e-rnnt, whisper-turbo is
whisper-large-v3-turbo and breeze-asr-25 is Breeze-ASR-25; full names and a path to a
.gguf work too.
📥 Installation
Download the binary for macOS (Apple Silicon), Linux or Windows from the
latest release and put wavo (wavo.exe)
into a folder on your PATH, such as ~/.local/bin. Or build it with Rust, which takes a few
minutes:
wavo runs through Vulkan, so it needs a Vulkan driver and access to the GPU:
GPUs other than Apple's use simpler kernels for now: an Intel N100 transcribes 11 s of audio in 1.3–2.2 s.
Rust on Windows needs Microsoft's C++ build tools for its linker. In PowerShell:
winget install Rustlang.Rustup
winget install Microsoft.VisualStudio.2022.BuildTools --override "--quiet --wait --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended"
wavo uses the GPU through its Vulkan driver (NVIDIA, AMD and Intel ship one); on a laptop with
two GPUs it takes the discrete one. GPUs other than Apple's use simpler kernels for now, apart
from matrix multiplication and attention on NVIDIA's tensor cores: an RTX 4060 laptop transcribes
11 s of audio in 42 ms (gigaam-v3), 79 ms (parakeet-v3) or 0.2 s (whisper-turbo).
Without a Vulkan driver (e.g. a VM) wavo falls back to DirectX 12 with the simpler kernels only;
WGPU_BACKEND=dx12 forces it.
Newest version
This readme follows main, which may be ahead of the latest release. Binaries of main are in the dev release, or build it with Rust:
🚀 Usage
When the model isn't downloaded yet, wavo run asks before downloading it, in a terminal; -y
downloads without asking, for scripts. Without a terminal and -y it fails with the wavo pull
command to run, and wavo bench never downloads. Long recordings are split at their quietest
moments and transcribed piece by piece, so an hour of audio works as well as a minute;
--segment SECS sets the piece length, --segment 0 runs one pass. Models are stored in the
Hugging Face cache (~/.cache/huggingface/hub), so a model fetched with hf download is found by
wavo and the other way round.
⚡ Speed
Transcribe times are warm medians of wavo bench MODEL CLIP against transcribe-bench of
transcribe.cpp at 5bb2deb, on the same Q8_0 file and clip; cells are wavo / transcribe.cpp. Bold
marks the better side where the gap is over 3%.
Apple M2 (10-core GPU, 24 GiB, macOS 27) against transcribe.cpp on Metal, an 11 s clip (jfk,
GigaAM ru-short), 2026-10-09 to 11; the GPU changes since left these models within noise on the
M2.
| Model | Transcribe, ms | Load, ms | Peak memory, MiB |
|---|---|---|---|
gigaam-v3 |
96 / 100 | 44 / 104 | 302 / 325 |
parakeet-v2 |
143 / 199 | 81 / 245 | 740 / 820 |
parakeet-v3 |
154 / 215 | 89 / 245 | 763 / 884 |
whisper-turbo |
1240 / 1390 | 105 / 298 | 1018 / 1055 |
For dictation, where a model is loaded for each recording, load plus the first call takes 142 /
217 ms (gigaam-v3), 256 / 468 ms (parakeet-v3) and 1437 / 1756 ms (whisper-turbo).
Whisper's other sizes and Moonshine are faster too
(Whisper plan,
Moonshine plan).
Apple M5 (10-core GPU, macOS 27.0.1) against transcribe.cpp on Metal, 2026-10-12. On the M5
both multiply on the GPU's neural accelerators through the Metal 4 tensor API. Clips: jfk 11 s,
ru 4.5 s, ru-long 34 s, dots 35 s.
| Model | Clip | wavo, ms | transcribe.cpp, ms |
|---|---|---|---|
gigaam-v3 |
ru / ru-long |
17.3 / 87 | 20.7 / 120 |
parakeet-v3 |
jfk / dots |
60 / 185 | 94 / 313 |
whisper-turbo |
jfk |
420 | 573 |
moonshine-tiny |
jfk |
20.3 | 70 |
moonshine-base |
jfk |
30.9 | 120 |
NVIDIA RTX 4060 Laptop (Windows 11, Vulkan) against transcribe.cpp's Vulkan build, 2026-10-11
to 13. Clips: jfk 11 s, ru 4.5 s, ru-long 34 s, dots 35 s.
| Model | Clip | wavo, ms | transcribe.cpp, ms |
|---|---|---|---|
gigaam-v3 |
ru / ru-long |
16.9 / 70 | 134 / 1064 |
parakeet-v3 |
jfk / dots |
68 / 180 | 88 / 249 |
parakeet-v3, first call |
jfk |
77 | 99 |
whisper-turbo |
jfk / ru-long |
197 / 452 | 226 / 503 |
whisper-small |
jfk |
69 | 101 |
whisper-medium |
jfk |
198 | 226 |
whisper-large-v3 |
jfk |
375 | 427 |
whisper-tiny |
jfk / dots |
23 / 89 | 43 / 135 |
moonshine-tiny |
dots |
90 | 144 |
moonshine-base |
dots |
141 | 227 |
Intel N100 (integrated GPU, Linux, portable kernels) against transcribe.cpp's Vulkan build,
2026-10-12. whisper-turbo against the reference's CPU build, as its Vulkan build times out there.
Details in the speed plan.
| Model | Clip | wavo, ms | transcribe.cpp, ms |
|---|---|---|---|
gigaam-v3 |
ru / ru-long |
524 / 4170 | 1091 / 7994 |
parakeet-v3 |
jfk / dots |
2199 / 5702 | 3271 / 8830 |
whisper-tiny |
jfk / dots |
649 / 1696 | 1340 / 3052 |
whisper-turbo |
jfk |
23224 | 41676 (CPU) |
📚 Library usage
use ControlFlow;
use Hub;
let hub = new; // the Hugging Face cache, shared with `hf` and `wavo pull`
let path = match hub.find ;
let model = load?;
eprintln!; // e.g. Apple M2 (Metal, integrated)
let transcript = model.transcribe?; // pcm: 16 kHz mono f32 in [-1, 1]
println!;
for token in &transcript.tokens
The hub feature downloads models by name (it adds an HTTP client); leave it out to load .gguf
files you fetch yourself, with a pure Rust build. Decoding and resampling audio and splitting long
recordings are up to you: model.max_audio_ms() tells how long a piece the model was trained on
(25 s for GigaAM, 30 s for Whisper and Moonshine). The API docs have the details,
including downloading on a thread with progress and cancel, as
examples/hub.rs does.
🤝 Contributing
Pull requests are welcome, and so are your agents: point them at agents.md.
🙏 Credits
wavo's kernels and algorithms are built from the ideas and code of these projects:
- transcribe.cpp (MIT): the reference wavo matches, its GGUF format and converters, the published models and the test clips. wavo's FFT, mel frontends, TDT and Whisper decoding, repetition guard and SentencePiece decoding follow its code.
- ggml (MIT): kernels adapted from it. Flash attention after
Vulkan's
flash_attn_cm1.comp, the Q8_0 matrix multiplication after ggml-metal'skernel_mul_mm, and GELU's erf. - whisper.cpp (MIT), Hugging Face transformers and NVIDIA NeMo (Apache-2.0): algorithms that reached wavo through transcribe.cpp's ports.
Models. wavo ships no weights: wavo pull downloads the GGUF conversions that
handy-computer publishes on Hugging Face, under the
original licenses:
- Parakeet TDT (v2, v3) © NVIDIA, CC-BY-4.0
- GigaAM v3 © Sber, MIT
- Whisper © OpenAI, MIT for large-v3-turbo and Apache-2.0 for the other sizes (such as large-v3), as their model cards state
- Moonshine (tiny, base) © Useful Sensors, MIT
- Breeze-ASR-25 © MediaTek Research, Apache-2.0
📝 License
Distributed under the MIT License.
🔍 See also
- handy-computer/transcribe.cpp – The reference wavo follows: C++ on ggml, many model families.
- ggml-org/whisper.cpp – Whisper in C++ on ggml.
- k2-fsa/sherpa-onnx – Many models on ONNX Runtime, streaming included.
- senstella/parakeet-mlx – Parakeet in Python on MLX, Apple Silicon only.