parakeet-primeline-de-coreml
An unofficial CoreML conversion of
primeline/parakeet-primeline — a German fine-tune of
nvidia/parakeet-tdt-0.6b-v3 — for offline speech-to-text on Apple Neural Engine via
FluidAudio.
All credit for the model itself goes to primeline (German fine-tuning) and NVIDIA (base FastConformer-TDT architecture and pretraining). This repository only provides a CoreML/ANE re-export of their weights; no retraining or fine-tuning was done here.
Why this exists
nvidia/parakeet-tdt-0.6b-v3 auto-detects language per utterance with no way to force it, so short German commands are sometimes misdecoded as English. primeline's fine-tune fixes this and improves German WER generally (see benchmarks below, reproduced from the
primeline/parakeet-primeline model card). This repo makes that fine-tune usable on-device on Apple Silicon through FluidAudio's CoreML pipeline, instead of via NeMo/PyTorch on GPU.
| Model | All (Avg) | Tuda-De | Multilingual LibriSpeech | Common Voice 19.0 |
|---|
| primeline-parakeet | 2.95 | 4.11 | 2.60 | 3.03 |
| nvidia-parakeet-tdt-0.6b-v3 | 3.64 | 7.05 | 2.95 | 3.70 |
Conversion
Converted with FluidInference's own
mobius export tooling (
models/stt/parakeet-tdt-v3-0.6b/coreml/convert-parakeet.py), pointed at primeline's
.nemo checkpoint instead of the base NVIDIA model — no changes to the conversion script were needed, since primeline's fine-tune uses an unmodified tokenizer and architecture (verified byte-identical against the base model's vocabulary before conversion). Exported at FP16,
iOS17 deployment target, fixed 15-second audio window per FluidAudio's
v3 contract.
Validated after conversion: exported component shapes match FluidAudio's expected Preprocessor / Encoder / Decoder / JointDecisionv3 I/O contract exactly (including the top_k_ids/top_k_logits outputs FluidAudio's v3 decode path requires). See Benchmarks below for the accuracy validation — full German test sets, cross-checked against unconverted NeMo/PyTorch inference on the same checkpoint.
conversion_metadata.json in this repo records the exact export settings.
Benchmarks
Ran the full Tuda-De (4,096 utterances), Multilingual LibriSpeech German (3,394), and Common Voice 19.0 German (16,188) test sets — no sampling — through this converted CoreML model, and cross-checked against native NeMo/PyTorch inference on the same unconverted checkpoint (no CoreML anywhere in that second run) to isolate conversion fidelity from everything else.
| Corpus | Published (primeline card) | This CoreML/ANE model | Native NeMo/PyTorch (same checkpoint) |
|---|
| Tuda-De | 4.11 | 5.21 | 5.46 |
| Multilingual LibriSpeech | 2.60 | 5.44 | 5.25 |
| Common Voice 19.0 | 3.03 | 5.16 | 5.15 |
| Average | 2.95 | 5.27 | 5.29 |
WER%, umlaut-folded (ä→ae, ö→oe, ü→ue, ß→ss — our own normalization, since primeline didn't publish theirs; unfolded numbers run ~1-1.5pp higher and are in the eval scripts referenced below).
Reading this table: the CoreML conversion and the untouched original checkpoint land within a quarter point of each other on every corpus (average delta −0.02pp) — that's the number that matters for trusting this repo's export, and it's as clean a "no conversion damage" result as this kind of test produces. The ~2.3pp gap between both of our measurements and the primeline card's published average is real but external to this conversion: it's differences in decode configuration and/or WER text-normalization methodology that were never published, not a degraded model. If you're deciding whether to trust this conversion, compare column 2 to column 3, not to column 1.
This model was built for a Home Assistant Wyoming-protocol STT server; the scoring script and German text normalization used above will be published alongside that project.
Usage
Drop-in for FluidAudio's
AsrModels.load(from:version:.v3, ...) — same file layout as
FluidInference/parakeet-tdt-0.6b-v3-coreml, just German weights:
1import FluidAudio
2
3let models = try await AsrModels.load(
4 from: modelsDirectory, // a local directory literally named `parakeet-tdt-0.6b-v3`
5 version: .v3,
6 encoderPrecision: .int8, // filename mapping only — this encoder is FP16, see note below
7 encoderComputeUnits: .cpuAndNeuralEngine
8)
9let manager = AsrManager(config: .default)
10try await manager.loadModels(models)
Note on the directory name: FluidAudio's loader derives the model folder name from its internal Repo enum and expects it to be exactly parakeet-tdt-0.6b-v3, regardless of which weights are inside. Place these files in a folder with that exact name.
Note on precision: encoderPrecision: .int8 selects the filename FluidAudio looks for (Encoder.mlmodelc), not the actual on-disk precision — this export is FP16, not int8-quantized, so it will be larger (~1.2 GB) than FluidAudio's official English encoder (~425 MB, which is quantized). Int8 quantization was not applied here to avoid an extra accuracy-validation pass; feel free to quantize further at your own risk.
Set DownloadUtils.enforceOffline = true before loading if you're pointing at a private local path — otherwise a load failure will cause FluidAudio to delete the folder and attempt to re-download the official English v3 from HuggingFace.
Files
| File | Description |
|---|
Preprocessor.mlmodelc | Mel-spectrogram frontend |
Encoder.mlmodelc | FastConformer encoder (FP16) |
Decoder.mlmodelc | TDT prediction network |
JointDecisionv3.mlmodelc | Joint + greedy decision head (incl. top-K for FluidAudio's language-script filter) |
parakeet_vocab.json | SentencePiece vocabulary (identical to base v3's, 8192 tokens) |
conversion_metadata.json | Export settings and component I/O shapes from the conversion run |
License
CC-BY-4.0, inherited from primeline's fine-tune (itself CC-BY-4.0, derived from NVIDIA's CC-BY-4.0 base model). Attribution:
- Base architecture and pretraining: NVIDIA
parakeet-tdt-0.6b-v3
- German fine-tuning: primeline
parakeet-primeline
- CoreML conversion tooling: FluidInference
mobius
- Runtime SDK this is built for: FluidInference
FluidAudio