Recursive AI

Transcribe an audio file in C#

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

Transcribe sample.flac (in the zip). First use downloads several GB of models.

Terminal
dotnet add package RecursiveAI.OneSpeech

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

C#
using OneSpeech;
var transcript = Speech.Transcribe(
    "sample.flac", language: "en");
File.WriteAllText(
    "transcript.txt", transcript.Text);
Console.WriteLine(transcript.Text);

Unzip the example, then dotnet run.

Prints:

Text
 stuffered into you, his belly counseled him.

This is the model’s real output on a real recording, mistake included; word.Text.Trim() removes a recognized word’s leading space.

The default recognizer is Whisper large-v3-turbo: its publisher weights are 1,617.8 MB (about 1.62 GB). This English run also loads Qwen3-ForcedAligner (1,835.5 MB of publisher weights) to time words and CAM++ English (29.4 MB) to group speakers; the built-in Silero detector finds speech. Converted runtime files take additional disk space. By default, models are cached in %LOCALAPPDATA%/OneSpeech/models on Windows, ~/Library/Caches/OneSpeech/models on macOS, or $XDG_CACHE_HOME/onespeech/models on Linux (falling back to ~/.cache/onespeech/models). ONESPEECH_MODEL_CACHE overrides that location. See Model files and pre-fetch and the download sizes.

The full program

The snippet at the top writes transcript.txt. The full program also saves the structured transcript as transcript.json; pass your own file with dotnet run -- recording.wav.

The input sample.flac is the unmodified LibriSpeech test-clean recording 1089-134686-0001: “stuff it into you his belly counselled him”. It ships in the zip under CC BY 4.0, credited to Vassil Panayotov, Guoguo Chen, Daniel Povey and Sanjeev Khudanpur (LibriSpeech).

C#
using OneSpeech;
 
string path = args.Length > 0 ? args[0] : "sample.flac";
Transcript transcript = Speech.Transcribe(path, language: "en");
File.WriteAllText("transcript.txt", transcript.Text);
File.WriteAllText("transcript.json", transcript.ToJson());
Console.WriteLine(transcript.Text);
Console.WriteLine("Saved transcript.txt and transcript.json");

dotnet run prints:

Text
 stuffered into you, his belly counseled him.
Saved transcript.txt and transcript.json

This is the recognizer’s actual output, including its “stuffered” mistake and leading spaces. Missing models download on first use; subsequent runs reuse verified cache files.

Invalid encoded audio throws UnsupportedAudioException; model download or integrity failures are reported as typed model errors.

Variations

Read an encoded audio stream. The stream stays caller-owned; await using disposes it after the call. Use the same sample.flac from the zip.

C#
using OneSpeech;
 
await using var input = File.OpenRead("sample.flac");
Transcript transcript = await Speech.TranscribeAsync(input, language: "en");
Console.WriteLine(transcript.Text);
Text
 stuffered into you, his belly counseled him.

The short answer

To transcribe an audio file in C#, call Speech.Transcribe(path, language: "en") and save the returned Text with File.WriteAllText. The program above writes both a plain-text transcript and structured JSON. It uses OneSpeech’s default file recognizer, Whisper large-v3-turbo, and runs in managed .NET 10 without a speech-service key.

The input is a real recording, not a stored transcript returned as a placeholder. Its reference wording is “stuff it into you his belly counselled him”. The output printed above is what the recognizer heard, including its mistake. Substitute your own path with dotnet run -- recording.wav; keep the language argument appropriate for your recording.

How can I transcribe an audio file to text?

Start with an existing audio file and choose the result you need. Plain text is useful for reading, indexing or editing; transcript JSON also keeps segments, words, timing methods, models and speaker turns. The full program writes both from the same result, so saving a second format does not run recognition again. See the JSON schema before building a consumer that depends on individual fields.

OneAudio is the .NET audio library that reads encoded sound and converts its sample rate for recognition. The audio-input docs list WAV, FLAC, MP3, Ogg Vorbis/Opus, AAC-LC in M4A/3GP/ADTS, and AMR-NB/WB; the core also handles A-law and μ-law WAV. This download uses FLAC so the exact recording can ship with the project. You don’t need to convert this sample to WAV first. An extension alone does not establish that damaged or unsupported encoded data can be read.

A normal whole-file call includes recognition, word timing and speaker clustering. Speaker labels are anonymous and local to a recording. They are not verified names, and the default diarizer does not detect overlapping speech. Missing word boundaries remain null rather than receiving guessed timestamps.

Can I transcribe audio offline in C#?

Yes, after preparing the models. Missing automatically fetched model files are downloaded on first use; verified existing files need no network request. The file recognizer is only one part of the work: word timing and speaker assignment can need additional models. The first-use model table is the deployment checklist for those dependencies.

Allow for publisher-weight conversion and temporary disk space during initial preparation. A tiny recognizer selection is not a promise of a tiny total download. ONESPEECH_MODEL_CACHE chooses the cache directory; keep it in a trusted location writable only by the intended user. The example zip is small because model weights stay in that cache rather than being copied beside every audio file.

What does a C# audio transcription example need?

For the path-based example, the requirements are the .NET 10 SDK, the pinned package, an input recording and space for the models. The zip supplies the first project and sample recording; NuGet restores the library. First use acquires missing model files. No microphone permission is needed because this program reads a file.

If your application receives a readable encoded stream instead of a path, use the variation above. TranscribeAsync does not own or close the caller’s stream. It spools encoded input to a temporary seekable file, with a 512 MiB bound, so recognition and timing replay can revisit the audio. It is not live microphone recognition, and an asynchronous method name does not make CPU inference asynchronous. For input beyond that stream bound, use a local file path. For cancellation or format failures, handle the documented typed errors rather than writing a success message before transcription finishes.

All onespeech recipes