← Research
Engineering note

Same weights, 21–23% lower WER across CUDA, MLX and CPU

Runtime engineering across NVIDIA NeMo, Apple MLX and CPU—without retraining the model.

TL;DR

Word error rate (WER) fell 21–23% versus our earlier runtime results. We pinned a better CUDA recipe, fixed feature parity on MLX and made long-audio cuts safer on CPU.

One checkpoint · three qualified paths weights unchanged
The checkpoint is fixed. The three lower paths are the platform-specific choices tested in the public runtime.

The result

We expected the checkpoint to set the quality ceiling. It didn’t. Feeding and decoding the same weights more carefully improved every platform.

NVIDIA CUDA
8.30%6.54%
21.2% lower WER
Apple MLX q8
8.61%6.65%
22.8% lower WER
CPU GGUF q8_0
9.12%7.10%
22.1% lower WER

Earlier rows used older runners. The current results are reproducible.

CUDA is now our choice for the best WER and throughput, MLX q8 for the best canonical M-WER on Apple Silicon, and CPU as the portable fallback.

No dictionary, biasing or transcript cleanup. The MIT runtime is on GitHub, the CC-BY-4.0 weights are on Hugging Face, and the package is on PyPI.

Accuracy

1,513 clips / 7.18 hours of English medical audio.
RuntimeHardwareWERM-WERDrug M-WER
NVIDIA NeMo BF16L46.54%2.23%4.75%
Apple MLX q8M4 Max6.65%2.12%4.52%
CPU GGUF q8_0Linux / Windows CPU7.10%2.16%4.30%

On this benchmark, CUDA and MLX beat every open model we tested, plus the tested configurations of OpenAI GPT-Transcribe, Google Gemini 3.1 Pro Preview and AssemblyAI Universal-3.5 Pro Medical.

Speed

NVIDIA L4
216×audio under 30 s
201×audio 30 s or longer
Apple M4 Max
89×audio under 30 s
152×audio 30 s or longer
Linux / Windows CPU
11.8×audio under 30 s
4.7×audio 30 s or longer

Times faster than audio duration. Hardware-specific.

How we tested

We tried ideas on 112 non-board clips, stress-tested long and sequential audio, then ran the final recipes once on the 1,513-clip benchmark.

CUDA

NVIDIA: pin the whole recipe

NeMo could load the checkpoint, but its defaults were not our best recipe. The adapter now pins precision, attention, decoding, batching and audio normalization.

BF16

Faster than FP32 on the full board, with a slightly better WER point estimate.

attention = [256,256]

Bounded context that keeps arbitrary recording lengths practical.

greedy_batch · max_symbols=10

The selected TDT decoder. Beam size two was slower and less accurate.

batch ≤ 8 · audio ≤ 900 s

Duration-sorted work with caller order restored after decoding.

PCM16 · mono · 16 kHz

One FFmpeg normalization contract for every supported input format.

whole-record transcribe

The normal command no longer inserts a boundary after 240 seconds.

The selected L4 run scored 6.54% WER and 2.23% M-WER. Short and long slices ran at 216× and 201× realtime respectively.

MLX q8

Apple Silicon: fix the input, then bound memory

The biggest Apple fix happened before the model. MLX placed the Hann window at the edge of the FFT buffer; the training and GPU paths center it. We made them match.

centered Hann window

Restores model-input parity instead of trying to repair words after decoding.

local attention [256,256]

Keeps long recordings bounded. Full attention gained only 0.03 WER points.

mx.clear_cache()

Clears allocator state between files and prevents sequential long-run collapse.

U+2047 unknown token

Matches the reference runtime’s visible output and scoring contract.

Clearing the MLX cache stopped sequential long-file failures. Local attention then ran 23% faster and cut the longest-recording allocation high-water by about 71%, while moving WER only from 6.62% to 6.65%.

Why q8 stayed the Mac default

The 0.94 GB q8 weights matched the 2.50 GB unquantized export on the development gate, so the larger export did not earn a full run.

CPU GGUF

CPU: make necessary cuts less harmful

CPU handles recordings up to 240 seconds whole. For longer audio, it uses overlapping 180-second chunks and moves each cut to the quietest nearby 300-millisecond window. CUDA and MLX transcribe the recording whole.

Long-audio boundary selection
fixed 180-second cutselected quiet window

Silence-aware cuts moved full-board WER from 7.17% to 7.10% and reduced missed medical and drug mentions, with no measurable speed cost.

Where CPU optimization stops

parakeet.cpp still builds the full attention matrix. The next meaningful CPU gain needs real windowed attention in C++, not another flag.

Run the qualified runtime

The CLI applies the complete NVIDIA recipe automatically.

terminal · NVIDIA CUDA
# NeMo 3.0 is pinned by the package extra
pip install -U "omi-med-stt[nemo]"
omi-med-stt recording.m4a --runtime nemo

The same adapter works inside Python.

python · NVIDIA CUDA
from omi_stt.nemo_runtime import transcribe_nemo

text = transcribe_nemo(
    ["recording.wav"],
    repo_id="omi-health/omi-med-stt-v1",
)[0]

print(text)

Apple Silicon and CPU use the same package.

terminal · Apple Silicon and CPU
# Apple Silicon
pip install -U "omi-med-stt[mlx]"
omi-med-stt recording.wav --runtime mlx

# Linux / Windows CPU
pip install -U omi-med-stt
omi-med-stt install-cpp --cpp-backend cpu
omi-med-stt recording.wav --runtime cpp

What we tested

Inspect the runtime.

Run it or inspect the settings in source.