Recursive AI

Offline speech recognition in C#

OneSpeech is a free, open-source speech recognition library for .NET from Recursive AI. MIT or Apache-2.0, no native dependencies.

Recognize English speech without downloading models at runtime. The model package supplies the weights during NuGet restore, so restore the project before disconnecting.

Terminal
dotnet add package RecursiveAI.OneSpeech
dotnet add package RecursiveAI.OneSpeech.Models.MoonshineStreamingTiny

Requires .NET 10 (net10.0); .NET 9 and earlier aren’t supported.

sample.flac is included in the zip; you can substitute your own 16 kHz mono recording. VAD (voice activity detection) finds the speech parts, Silero is the VAD model, and Moonshine is the English recognition model.

C#
using OneSpeech;
using OneSpeech.Moonshine;
using OneSpeech.Vad;
using OneSpeech.Pipeline;
 
using var recognizer = await MoonshineRecognizer.LoadAsync();
using var vad = new SileroVad();
var pipeline = new VadTranscriptionPipeline(recognizer, vad);
Console.WriteLine(pipeline.Transcribe("sample.flac", "en").Text);

The snippet at the top loads the packaged weights; the full program additionally refuses network model fetches.

Prints:

Text
Stuff it into you, his belly counseled him.

Unzip the example, then dotnet run.

Full program

The zip includes sample.flac: a short English reading, “Stuff it into you, his belly counseled him.” Source: LibriSpeech test-clean utterance 1089-134686-0001, Vassil Panayotov, Guoguo Chen, Daniel Povey and Sanjeev Khudanpur (2015), CC BY 4.0. The FLAC is unmodified, mono, 16 kHz.

The full program refuses network model fetches. Restore packages before going offline; keep the onespeech-models directory beside the app.

C#
using OneSpeech;
using OneSpeech.Catalog;
using OneSpeech.Moonshine;
using OneSpeech.Vad;
using OneSpeech.Pipeline;
 
var store = new ModelStore("model-cache", new NoNetwork());
using var recognizer = await MoonshineRecognizer.LoadAsync(store);
using var vad = new SileroVad();
var pipeline = new VadTranscriptionPipeline(recognizer, vad);
Console.WriteLine(pipeline.Transcribe("sample.flac", "en").Text);
 
sealed class NoNetwork : ModelSource
{
    public override ValueTask<Stream> OpenReadAsync(
        CatalogEntry model, CatalogFile file, CancellationToken cancellationToken)
        => throw new IOException("Missing offline model file: " + file.Name);
}

Output:

Text
Stuff it into you, his belly counseled him.

Unsupported or corrupt input throws UnsupportedAudioException; file-system errors remain I/O errors.

Variations

Save transcript JSON

Replace the last line with:

C#
var transcript = pipeline.Transcribe("sample.flac", "en");
File.WriteAllText("transcript.json", transcript.ToJson());
Console.WriteLine(transcript.Text);

Output:

Text
Stuff it into you, his belly counseled him.

The short answer

Reference an offline model package alongside core, restore while connected, and keep the copied model files with the app. The example uses Moonshine streaming tiny for English recognition and embedded Silero VAD. Its full program supplies a ModelSource that throws if any network fetch is attempted, so missing offline files fail instead of downloading.

How do I do offline speech recognition in C#?

Prepare three things before disconnecting: the .NET runtime or a suitable deployment, all NuGet dependencies and the model files needed by your chosen pipeline. The sample’s project pins the packages and uses an explicit pipeline with recognition and VAD only. It does not rely on a previously populated model cache to supply a hidden aligner or speaker model.

The offline package guide explains what build and publish copy: a onespeech-models directory beside the executable. Retain that directory when deploying, including single-file and NativeAOT deployments. A single executable is not sufficient if you leave its model files behind.

At runtime the loader checks packaged files before its configured source, verifies file sizes and hashes, and performs required local conversion into the per-user model cache. Offline does not mean conversion-free, cache-free or instantaneous startup. Allow the application to create and write its model cache on the target machine.

Is there a free offline speech recognition library for C#?

OneSpeech is free and open source under MIT or Apache-2.0. The code above performs recognition locally; it needs no recognition service account or API key. Model licenses are separate from the C# library’s license. The selected model is listed in the published model table, and the package carries its notices.

This example recognizes English. Offline availability does not change language capabilities. Passing an unsupported language hint throws CapabilityNotSupportedException; it does not turn the model into a multilingual recognizer. Test with representative audio, accents and recording conditions before relying on a transcript.

Can offline speech recognition produce JSON?

Yes. The variation serializes the returned transcript with ToJson() and writes transcript.json. This preserves the document schema rather than flattening everything into a plain string. It does not create timing or speaker evidence that the selected models never produced.

The example intentionally omits companion aligners and diarization. Unknown word times remain unknown, and you should not infer speaker identities from recognized text. For text-only use, the pipeline’s Text is sufficient; use JSON when your application needs the rest of the actual transcript fields and model provenance.

How do I deploy an offline speech-to-text example?

Try an empty cache and disable model fetches, as the full program does, before moving the application onto a disconnected host. Restore itself still needs packages, whether from NuGet or a local feed. Keep the deployed model folder intact and retain its notices.

An offline package covers its own model, not every role of a high-level convenience call. Replacing this pipeline with Speech.Transcribe can add speaker embeddings and timing companions. Use the per-verb model download table to prepare the complete dependency set for that different task. A missing or corrupt model should be an explicit preparation error, not a surprise download during production use.

All onespeech recipes