Nemotron Streaming

Two NVIDIA streaming ASR models share the NemotronStreamingASR Swift target. Both are 600M-parameter cache-aware FastConformer encoders paired with an RNN-T decoder, both emit native punctuation and capitalization as regular BPE tokens, both run on the Apple Neural Engine via CoreML, and the multilingual variant additionally has MLX bundles for GPU-resident inference. Pick the one that matches your application:

VariantCoverageDefault chunkUpstream
Nemotron 3.5 Multilingual40 language-locales (en-US, en-GB, es-ES, fr-FR, de-DE, ja-JP, ko-KR, zh-CN, hi-IN, ar, …)320 msnvidia/nemotron-3.5-asr-streaming-0.6b
Nemotron Speech Streaming (English)English only — smaller bundle, lower default latency160 msnvidia/nemotron-speech-streaming-en-0.6b

Shared properties

Architecture

Three CoreML models pipelined per audio chunk:

ComponentDescription
Encoder24-layer cache-aware FastConformer, 1024 hidden. Takes a 32-frame mel chunk (320 ms default) plus six state tensors — attention KV cache [24, 1, 56, 1024], depthwise conv cache [24, 1, 1024, 8], pre_cache mel loopback, and a language_mask 128-slot one-hot that drives the prompt kernel.
Prompt kernelLinear(1152→2048) → ReLU → Linear(2048→1024) — folds the language one-hot into every encoded frame so the same 600M weights serve all 40 language-locales.
DecoderTwo-layer LSTM prediction network, 640 hidden. Consumes the previous non-blank token, emits an embedding plus updated (h, c) state.
JointFuses encoder and decoder outputs into logits over 13 087 BPE tokens + blank. Punctuation, capitalization, and per-language tags are just more tokens in the BPE vocab — no extra heads.

No EOU head

Unlike Parakeet-EOU, Nemotron does not emit a dedicated end-of-utterance token. Two ways to segment continuous audio into utterances:

  1. External VAD — pair the session with Silero VAD; on sustained silence, call finalize() to commit the current utterance and createSession() for the next one.
  2. Punctuation boundary — when the partial transcript ends in ., ?, or !, treat that as a natural commit cue. No extra model, but depends on the audio actually inducing terminal punctuation.

Bundles

Four published variants of Nemotron-3.5-ASR-Streaming-0.6B, plus the older English-only model on the same Swift target:

VariantOn-diskStreaming peak (M5 Pro)HuggingFace
CoreML INT8 (default)612 MB1238 MBaufklarer/Nemotron-3.5-ASR-Streaming-0.6B-CoreML-INT8
MLX bf161217 MB1474 MBaufklarer/…MLX-bf16
MLX 8-bit732 MB997 MBaufklarer/…MLX-8bit
MLX 4-bit473 MB747 MBaufklarer/…MLX-4bit
English-only (CoreML INT8)~580 MBaufklarer/Nemotron-Speech-Streaming-0.6B-CoreML-INT8

Upstream: nvidia/nemotron-3.5-asr-streaming-0.6b (multilingual) and nvidia/nemotron-speech-streaming-en-0.6b (English-only).

Quantization is essentially lossless: CoreML INT8, MLX bf16, and MLX 8-bit are within ±0.3 pp WER of the fp32 NeMo source. MLX 4-bit costs ~6 pp avg WER for the smallest disk and streaming RSS.

Quick start — batch transcription

Conforms to SpeechRecognitionModel, so it drops into any code path that takes a generic STT model:

import NemotronStreamingASR

let model = try await NemotronStreamingASRModel.fromPretrained()
let text = try model.transcribeAudio(audioSamples, sampleRate: 16000, language: "en-US")

Quick start — async streaming

for await partial in model.transcribeStream(audio: samples, sampleRate: 16000, language: "ja-JP") {
    if partial.isFinal { print("FINAL: \(partial.text)") }
    else               { print("... \(partial.text)") }
}

Each PartialTranscript carries text, isFinal (true only for the last partial after finalize()), confidence, and a monotonic segmentIndex.

Long-lived session API (mic input)

let session = try model.createSession(language: "en-US")

// each mic chunk:
let partials = try session.pushAudio(float32Chunk16kHz)
for p in partials { showPartial(p.text) }   // isFinal is false mid-stream

// when the utterance ends (VAD silence or explicit stop):
let trailing = try session.finalize()
for p in trailing { commit(p.text) }

CLI

speech transcribe recording.wav --engine nemotron --language en-US                    # batch
speech transcribe recording.wav --engine nemotron --language en-US --stream           # streaming final
speech transcribe recording.wav --engine nemotron --language ja-JP --stream --partial # partials, Japanese
speech transcribe meeting.wav   --engine nemotron --language de-DE                    # any of the 40 locales

Nemotron vs Parakeet-EOU

Nemotron Streaming 0.6BParakeet-EOU 120M
Parameters600M120M
Encoder24-layer FastConformer, 1024 hidden17-layer FastConformer, 512 hidden
Decoder2-layer LSTM, RNN-T1-layer LSTM, RNN-T
EOU detectionExternal (VAD or punctuation)Built-in <EOU> token
PunctuationNative inline BPE tokensNo (post-process)
Languages40 language-locales (en-US, en-GB, es-ES, fr-FR, de-DE, ja-JP, ko-KR, zh-CN, hi-IN, ar, …)25 European
Default chunk320 ms320 ms
Bundle size612 MB (CoreML INT8); 473 MB (MLX 4-bit)~150 MB
Pick Nemotron when…

…you need multilingual streaming transcription (any of 40 language-locales) with punctuation and capitalization out of the box, and you're OK segmenting utterances yourself (VAD or punctuation cue). For constrained-device iOS dictation that's English-only with a built-in EOU signal, Parakeet-EOU is still the smaller choice.