Summary
On windowed/long-form transcription, parakeet-tdt-0.6b-v3-coreml intermittently drops or mangles a word when that word lands within roughly the first ~5.5s of the 15s encoder window covering it. The identical weights via NeMo (PyTorch) and parakeet-mlx transcribe the same audio correctly, so this is specific to the CoreML export + windowing path, not the model weights.
Reproduction (deterministic; Ukrainian; .cpuOnly; ASRConfig(melChunkContext: false))
118s clip. Speaker says "…вимкнути фоновий процес…" at 43.6–46.6s.
- FluidAudio (whole clip, chunked): "…вимкнути там кнопкою фоновиц" — "процес" dropped, "фоновий"→"фоновиц".
- NeMo
nvidia/parakeet-tdt-0.6b-v3 (whole audio): "…фоновий процес" ✓
- parakeet-mlx
mlx-community/parakeet-tdt-0.6b-v3 (whole audio): "…фоновий процес" ✓
Isolated cause — a left-context cliff
Single-shot inference (no chunk merge), varying the left audio context before the phrase:
| left context before phrase |
output |
| 1s / 3s / 4s |
mangled / "фоновиц" (word dropped) |
| 5.5s / 7s |
"фоновий процес" ✓ |
The CoreML Encoder is stateless and fixed-shape (mel [1,128,1501] = 15.01s, hasShapeFlexibility: 0, empty stateSchema); the 15s window is baked at trace time (mobius .../coreml/convert-parakeet.py, max_audio_seconds = 15.0). With melChunkContext: false, the only left context a window gets is the sliding overlap (default 2s), so a word near a window's start sits below the ~5.5s the encoder needs and is dropped/mangled.
Widening the sliding overlap does NOT fix it
Raising ChunkProcessor.overlapSeconds 2→6s (the covering window then has ~7.76s of left context) still drops the word: the merge/token-selection picks the adjacent short-context window's tokens in the overlap zone. It also costs ~8–24% compute on multi-window clips.
Suggested directions
- Export the encoder with a larger context window (e.g. 30s) or a stateful/streaming variant, so positions aren't starved of left context.
- Make merge/token-selection in overlap zones prefer the window where a token had more left context (i.e. is deeper into its window), rather than the window where it sits near the start.
Environment
FluidAudio 0.15.3+, parakeet-tdt-0.6b-v3-coreml, macOS 26 / iOS, .cpuOnly, melChunkContext: false.
Correction / refined mechanism (further ablation)
Additional isolation shows this is window-composition instability, not purely a left-context cliff. Holding the word fixed and truncating the surrounding audio:
- word decodes correctly with adequate left context AND ≤~2s of trailing audio after it in the window;
- word corrupts ("фоновиц", "процес" dropped) once there is ≥~4s of audio after the word inside the same 15s window.
So the non-causal (bidirectional-within-window) encoder's encoding of a word is unstable to what follows it in the fixed window, not just what precedes it. Widening the sliding overlap therefore can't help (the word sits in a single window with no competing decode), and simply enlarging the window may add more trailing context rather than less. Reference runtimes with full-file attention (NeMo, parakeet-mlx) don't exhibit this. This points to the fixed-window / non-causal CoreML export (possibly interacting with INT8 quantization) rather than the chunk-merge or the weights.
Summary
On windowed/long-form transcription,
parakeet-tdt-0.6b-v3-coremlintermittently drops or mangles a word when that word lands within roughly the first ~5.5s of the 15s encoder window covering it. The identical weights via NeMo (PyTorch) and parakeet-mlx transcribe the same audio correctly, so this is specific to the CoreML export + windowing path, not the model weights.Reproduction (deterministic; Ukrainian;
.cpuOnly;ASRConfig(melChunkContext: false))118s clip. Speaker says "…вимкнути фоновий процес…" at 43.6–46.6s.
nvidia/parakeet-tdt-0.6b-v3(whole audio): "…фоновий процес" ✓mlx-community/parakeet-tdt-0.6b-v3(whole audio): "…фоновий процес" ✓Isolated cause — a left-context cliff
Single-shot inference (no chunk merge), varying the left audio context before the phrase:
The CoreML Encoder is stateless and fixed-shape (
mel [1,128,1501]= 15.01s,hasShapeFlexibility: 0, emptystateSchema); the 15s window is baked at trace time (mobius .../coreml/convert-parakeet.py,max_audio_seconds = 15.0). WithmelChunkContext: false, the only left context a window gets is the sliding overlap (default 2s), so a word near a window's start sits below the ~5.5s the encoder needs and is dropped/mangled.Widening the sliding overlap does NOT fix it
Raising
ChunkProcessor.overlapSeconds2→6s (the covering window then has ~7.76s of left context) still drops the word: the merge/token-selection picks the adjacent short-context window's tokens in the overlap zone. It also costs ~8–24% compute on multi-window clips.Suggested directions
Environment
FluidAudio 0.15.3+,
parakeet-tdt-0.6b-v3-coreml, macOS 26 / iOS,.cpuOnly,melChunkContext: false.Correction / refined mechanism (further ablation)
Additional isolation shows this is window-composition instability, not purely a left-context cliff. Holding the word fixed and truncating the surrounding audio:
So the non-causal (bidirectional-within-window) encoder's encoding of a word is unstable to what follows it in the fixed window, not just what precedes it. Widening the sliding overlap therefore can't help (the word sits in a single window with no competing decode), and simply enlarging the window may add more trailing context rather than less. Reference runtimes with full-file attention (NeMo, parakeet-mlx) don't exhibit this. This points to the fixed-window / non-causal CoreML export (possibly interacting with INT8 quantization) rather than the chunk-merge or the weights.