Voz
Every word, with the time it was said.
On-device speech recognition: transcripts with word-level timestamps, 25 languages.
- SDKs, install and examples: https://github.com/Desert-Ant-Labs/desert-ant-core/blob/main/docs/models/voz.md
Transcribes speech to text with word-level timestamps, in 25 languages, with the whole graph resident on the Neural Engine. Half an hour of audio takes about seven seconds on an M3 Ultra, and peak memory does not grow with the length of the recording.
"We made the bet to build for iOS"- each word with a start and an end, so a range is enough to cut on.
Try it
Ships as an Apple SwiftPM package: Desert-Ant-Labs/desert-ant-core.
- iOS / iPadOS / Mac Catalyst / macOS / tvOS / visionOS: the Swift SDK (Swift Package Manager). The models below are downloaded on demand and cached, so nothing is bundled into your app.
- Apple-only. The SDK drives Core ML directly to keep the graph on the Neural Engine, which has no equivalent on the other backends.
let voz = try await Voz()
let result = try await voz.transcribe(url)
result.text // "We made the bet to build for iOS..."
result.words.first?.start // 0.32
result.words.first?.end // 0.58
Files
| File | What it is |
|---|---|
encoder.mlmodelc |
Acoustic encoder |
mel.mlmodelc |
Audio frontend |
decoder.mlmodelc |
Decoder |
meta.json |
Geometry the runtime reads instead of hardcoding |
vocab.json |
SentencePiece vocabulary |
embedding.f16 |
Token embedding table |
Artifact names describe roles rather than the network behind them, so replacing the recogniser is a new upload rather than an SDK change.
The models are shipped compiled (.mlmodelc). Keep them that way: an
.mlpackage is recompiled on every launch and loads far more slowly.
Architecture
A three-stage Core ML cascade over a log-mel spectrogram, dispatched from Swift:
- Frontend: a log-mel spectrogram computed inside Core ML, normalized over the frames that hold audio rather than the whole padded window.
- Encoder: a conformer-style acoustic encoder over a fixed 15 s window, producing one frame every 80 ms.
- Decoder: a transducer that emits a token and a duration at each step, run with sixteen independent windows batched into the lanes of a single dispatch.
Longer audio is cut into consecutive windows at pauses, transcribed independently, and joined on the longest run of words two neighbouring windows agree on. Every stage runs on the Neural Engine with no CPU or GPU fallback.
Inputs and outputs
- Input: mono audio at any sample rate; the SDK resamples and downmixes.
- Output: the transcript, plus every word with a start and an end in seconds.
Accuracy
Ten minutes of audio on an M3 Ultra, release build, warm:
| Speed | 2.1 s for 611 s of audio (~290x real time) on long files; 50-62x transcribing single short utterances, where every clip pays for a full 15 s window |
| Word error rate | 7.40% averaged over six Open ASR Leaderboard sets, against 7.00% for Whisper large-v3-turbo |
| Long-form word error rate | 2.83% on half an hour of narration scored against the book, against 2.72% for Whisper large-v3-turbo on the same span |
| Word timestamps | starts 83 ms, ends 95 ms mean absolute error against a forced aligner |
| Neural Engine residency | 100%, with no CPU or GPU fallback |
| Size on disk | 467 MB |
| Load | ~0.2 s warm; ~20 s once per install while Core ML specializes |
English, on the Open ASR Leaderboard
Scored on the Open ASR Leaderboard datasets with its own text normalizer. Whisper's figures are the leaderboard's, on the same dataset configurations.
| dataset | Voz | Whisper large-v3-turbo |
|---|---|---|
| LibriSpeech test-clean | 2.19% | 2.13% |
| LibriSpeech test-other | 3.86% | 3.70% |
| GigaSpeech | 9.70% | 8.47% |
| SPGISpeech | 3.86% | 2.79% |
| Earnings-22 | 12.97% | 11.07% |
| AMI | 11.84% | 13.87% |
| average | 7.40% | 7.00% |
Close overall, two points better on meetings, behind on prepared and read speech. It gets there in 467 MB entirely on the Neural Engine, against 1.6 GB for Whisper large-v3-turbo.
Expect the conversational figures, not the LibriSpeech one. Read speech in a clean recording scores around 2%; meetings, earnings calls and podcast audio score 10-13%, and most real material is nearer the second group. Roughly one word in ten wanting a look is the honest expectation for a podcast.
VoxPopuli and TEDLIUM are omitted: the leaderboard's scripts name a 628-utterance shard of the former, which is not the audio its published figure measures, and the latter's config carries no rows.
Word timestamps
Every word carries a start and an end, scored against torchaudio's MMS_FA forced aligner:
| words | start | end | ends within 80 ms | within 200 ms | |
|---|---|---|---|---|---|
| English, LibriSpeech | 6295 | 83 ms | 95 ms | 60% | 90% |
| German, FLEURS | 939 | 80 ms | 92 ms | 62% | 92% |
Ends are the harder of the two. The recogniser reports how far to skip after each token rather than where a word stops, which overshoots into the pause that follows it, so ends are trimmed back using the audio. Forced alignment is itself approximate at the tens of milliseconds level, so treat these as agreement with a good aligner rather than absolute truth. Much of the residual is the 80 ms frame resolution, which is the floor for any word time this export produces.
Every supported language, on long audio
Ten minutes per language, built by concatenating FLEURS test utterances so that each file crosses about forty analysis boundaries. A single FLEURS utterance is shorter than one window and so measures nothing about how consecutive windows are joined, which is most of what happens on real material. 4.2 hours in total.
| WER | WER | WER | |||
|---|---|---|---|---|---|
| it | 3.31% | cs | 14.27% | hu | 21.26% |
| pt | 6.08% | sk | 15.42% | et | 21.37% |
| uk | 6.40% | hr | 16.92% | sv | 21.67% |
| ru | 6.57% | fi | 18.17% | mt | 22.01% |
| en | 7.36% | ro | 20.95% | da | 24.32% |
| de | 8.12% | lt | 26.89% | ||
| es | 9.01% | lv | 30.57% | ||
| nl | 9.84% | sl | 33.85% | ||
| pl | 9.99% | el | 39.46% | ||
| bg | 12.39% | ||||
| fr | 12.78% |
Aggregate 16.58%, median 283x real time. Throughput varies only 12% across languages, because cost follows how much audio there is rather than what is in it.
Read the spread before choosing a language. The nine best are usable as-is; the tail above 20% will cost more to correct than to retype for many uses, and reflects where the underlying recogniser is already known to be weak rather than anything specific to this export. This is read speech in clean recordings, so treat it as a ranking rather than as a number to expect on your own audio.
Languages
Bulgarian, Croatian, Czech, Danish, Dutch, English, Estonian, Finnish, French, German, Greek, Hungarian, Italian, Latvian, Lithuanian, Maltese, Polish, Portuguese, Romanian, Russian, Slovak, Slovenian, Spanish, Swedish, and Ukrainian.
Accuracy varies widely across them; see the per-language table above before choosing one.
Built on
- Parakeet TDT 0.6B v3 - NVIDIA (CC BY 4.0): the base recogniser, converted to Core ML and compressed for this export. Weight values are otherwise unchanged.
- FLEURS (CC BY 4.0): evaluation audio for the per-language table above.
See THIRD_PARTY_NOTICES.md. FLEURS is not redistributed here.
License
Desert Ant Labs Source-Available License. Free for most apps, and a commercial license is required at scale. Full terms are at the link. Licensing: licensing@desertant.com.
Citation
@software{voz_2026,
title = {Voz: On-device speech recognition: transcripts with word-level timestamps, 25 languages},
author = {Desert Ant Labs},
year = {2026},
url = {https://huggingface.co/desert-ant-labs/voz},
}
© 2026 Desert Ant Labs · https://desertant.com