dotnet add package RecursiveAI.OneSpeechRequires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.
sample.flac is included in the example zip.
using OneSpeech; await foreach (var segment in Speech.TranscribeStream( "sample.flac", model: "nvidia/nemotron-3.5-asr-streaming-0.6b")) Console.WriteLine(segment.Text);
First use downloads about 2.55 GB of Nemotron publisher files and caches them and locally converted graphs in ~/.cache/onespeech/models on Linux (change the cache location).
The snippet streams final segments; the full program below also prints live partials.
Stuffed into you his belly counselled himUnzip the example, then dotnet run.
Full program
The zip includes sample.flac, the unmodified mono 16 kHz LibriSpeech test-clean utterance 1089-134686-0001: “Stuff it into you, his belly counseled him.” Attribution: Vassil Panayotov, Guoguo Chen, Daniel Povey and Sanjeev Khudanpur (2015), CC BY 4.0. Recognition output can differ from that reference.
The full program explicitly loads the publisher checkpoint, then feeds the supplied recording through a live session. It does not capture a microphone. The checkpoint is not a default model; its OpenMDW-1.1 license grants free permission to “deal in the Model Materials without restriction,” while distribution requires retaining the agreement and applicable notices.
For microphone input, see Real-time speech recognition in C#; this example feeds a recording rather than capturing a device.
First use downloads about 2.55 GB of Nemotron publisher files and caches them and locally converted graphs in ~/.cache/onespeech/models on Linux (change the cache location).
using OneSpeech; using OneSpeech.Audio; using OneSpeech.Catalog; using OneSpeech.FastConformer; using OneSpeech.Vad; var resolved = await ModelStore.Default.PullAsync( "nvidia/nemotron-3.5-asr-streaming-0.6b"); using var recognizer = NemotronAsrRecognizer.Load(resolved); using var vad = new SileroVad(); using var live = recognizer.CreateLiveSession(vad, language: "en"); using var input = AudioFileSource.Open("sample.flac", CancellationToken.None); var buffer = new float[1600]; int count; while ((count = input.Read(buffer, CancellationToken.None)) != 0) Show(live.Push(new AudioBuffer(buffer.AsMemory(0, count), 16000))); Show(live.Complete()); static void Show(IEnumerable<LiveEvent> updates) { foreach (var update in updates) if (update is PartialEvent partial) Console.WriteLine("Partial: " + partial.Segment.Text); else if (update is FinalEvent final) Console.WriteLine("Final: " + final.Segment.Text); }
Output:
Partial: Partial: Partial: Stuffed Partial: Stuffed into you Partial: Stuffed into you his Partial: Stuffed into you his belly Partial: Stuffed into you his belly coun Final: Stuffed into you his belly counselled him
Invalid or corrupt audio is rejected; I/O and model acquisition failures propagate as exceptions.
Variations
Select an 80 ms attention chunk
Replace the recognizer declaration in the full program with:
using var recognizer = NemotronAsrRecognizer.Load(resolved, new NemotronAsrOptions { ChunkMilliseconds = 80, Threads = 1 });
First use downloads about 2.55 GB of Nemotron publisher files and caches them and locally converted graphs in ~/.cache/onespeech/models on Linux (change the cache location).
The output below shows this option’s actual partials and final; changing the chunk setting can change recognition text.
Partial: Partial: Partial: Partial: Stu Partial: Stu Partial: Stuff Partial: Stuff Partial: Stuffed Partial: Stuffed in Partial: Stuffed into Partial: Stuffed into you Partial: Stuffed into you Partial: Stuffed into you Partial: Stuffed into you his Partial: Stuffed into you his Partial: Stuffed into you his bel Partial: Stuffed into you his belly Partial: Stuffed into you his belly Partial: Stuffed into you his belly Partial: Stuffed into you his belly coun Partial: Stuffed into you his belly couns Final: Stuffed into you his belly counselle
Related recipes
The short answer
Explicitly load nvidia/nemotron-3.5-asr-streaming-0.6b, then create a live session with a speech detector. Push finite mono 16 kHz PCM, consume partial and final events, and call Complete at end-of-input. OneSpeech does not choose this checkpoint as a default. The model is acquired from publisher files, not shipped in a redistributed weight package.
How do I stream Nemotron ASR in C#?
Use ModelStore.PullAsync to resolve the checkpoint and NemotronAsrRecognizer.Load to open the verified local files. Keep the recognizer and Silero detector alive while the live session uses them. The example deliberately feeds a short recording through PCM blocks, so no microphone device or platform capture dependency is needed to run it. A live capture application must supply its own correctly formatted PCM.
The file snippet and full live program serve different output needs. Speech.TranscribeStream returns final segments. The low-level session exposes intermediate hypotheses as PartialEvent and committed text as FinalEvent. The sample prints both. For a UI, replace the previous partial for that utterance instead of appending it to the permanent transcript. Once the final arrives it cannot be revised; an endpoint closes the utterance.
Select how much audio the model processes at once
An attention chunk is the amount of new audio the model processes together while retaining earlier context; the default is 320 ms, matching the documented publisher configuration. Low-level options also accept 80, 560 and 1120 ms. The variation selects 80 ms. OneSpeech refuses 160 ms because the released reference processor rejects it; it does not silently substitute a supported value.
Attention chunk size is not a promise about end-to-end delivery time. Events cannot be published before the application pushes the audio they need. Caller block size and the VAD endpoint policy also affect when an update becomes available. The program’s 1600-sample blocks are a reproducible input choice, not a latency result or a recommended capture setting for every application.
Keep cache state inside the session
The cache-aware encoder carries attention and convolution history across chunks. Subsampling history also preserves its stride phase. State resets between utterances; it must not leak from a completed utterance into the next one. Sessions and recognizer instances are not thread-safe, so serialize their processing and create separate sessions for independent streams.
At end-of-input, the live implementation zero-extends the final context to the required chunk geometry. That padding never advances the caller’s real audio clock. Complete flushes the accepted audio; disposing the session does not do the same job. After a processing failure, create a fresh session rather than retrying the same block against uncertain decoder state.
Interpret word timing and confidence narrowly
This family provides native RNN-T word intervals at its documented 80 ms frame scale. A partially covered final frame is clipped to real audio. Words wholly beyond that horizon remain untimed instead of receiving fabricated times. Word confidence is an average of token softmax confidence, not a calibrated probability that the written word is correct.
The default controller bounds utterances at 30 seconds. Longer input is segmented rather than retained as one unbounded live utterance. Translation is not supported. For supported languages and automatic prompting, follow the cache-aware family documentation, which distinguishes transcription-ready language tags from adaptation-only locales. Do not infer a supported language from a model name or from another checkpoint with a similar name.