---
title: "Transcribe a long audio file in C#"
url: https://recursiveai.org/onespeech/cookbook/transcribe-long-audio/
description: "Transcribe long audio files in C# with bounded audio chunks. Print final segments as they finish, with a runnable OneSpeech example and sample audio."
version: "1.0.0"
---

# Transcribe a long 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.

[NuGet](https://www.nuget.org/packages/RecursiveAI.OneSpeech) · [GitHub](https://github.com/recursive-ai-oss/onespeech-csharp) · [Docs](https://recursiveai.org/onespeech/docs/) · [Download example (.zip)](https://recursiveai.org/onespeech/cookbook/transcribe-long-audio/transcribe-long-audio.zip)

Print text piece by piece, so audio memory stays flat on long files. This streaming call does not assign whole-recording speaker labels.

```shell
dotnet add package RecursiveAI.OneSpeech
```

Requires [.NET 10](https://dotnet.microsoft.com/download/dotnet/10.0) (net10.0); .NET 9 and earlier aren’t supported.

```csharp
using OneSpeech;
await foreach (var segment in
    Speech.TranscribeStream("speech.flac", "en",
    "moonshine-ai/moonshine-streaming-tiny"))
    Console.WriteLine(segment.Text);
```

Prints final text as chunks finish. `speech.flac` is in the zip:

Unzip [the example](https://recursiveai.org/onespeech/cookbook/transcribe-long-audio/transcribe-long-audio.zip), then `dotnet run`.

```text
Stuff it into you, his belly counseled him.
```


## Full program

speech.flac is the unmodified LibriSpeech test-clean recording 1089-134686-0001, renamed for this example. It contains:

> Stuff it into you, his belly counselled him.

[LibriSpeech](https://www.openslr.org/12), Vassil Panayotov, Guoguo Chen, Daniel Povey and Sanjeev Khudanpur (2015); [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). The zip includes attribution. The sample is short so the download stays small. The model really prints “counseled,” even though the supplied text uses “counselled.”

The full program accepts your recording with `dotnet run -- meeting.wav`. Missing models download on first use; this example selects the English Moonshine streaming-tiny recognizer explicitly. Cancellation throws `OperationCanceledException`; invalid audio throws `UnsupportedAudioException`.

```csharp
using OneSpeech;

string path = args.Length == 0 ? "speech.flac" : args[0];

await foreach (var segment in Speech.TranscribeStream(
    path, language: "en",
    model: "moonshine-ai/moonshine-streaming-tiny"))
    Console.WriteLine(segment.Text);
```

Output from `dotnet run`:

```text
Stuff it into you, his belly counseled him.
```

## Variations

**Read encoded audio streams instead of paths.** This replaces the full program and prints the same output above. The streams remain open until the `using` declarations dispose them.

```csharp
using OneSpeech;
using var stream = File.OpenRead("speech.flac");
await foreach (var segment in Speech.TranscribeStream(
    stream, language: "en",
    model: "moonshine-ai/moonshine-streaming-tiny"))
    Console.WriteLine(segment.Text);
```

**Print segment timestamps on a long file.** This replaces the full program. For a reproducible 131-second recording, repeat the zip’s redistributable LibriSpeech clip 40 times. The source is [LibriSpeech test-clean utterance 1089-134686-0001](https://github.com/recursive-ai-oss/onespeech-csharp/blob/63002de486786163a0a7800a51811e76d511fae6/testdata/1089-134686-0001.flac), released under CC BY 4.0 with the attribution above. This repeated clip demonstrates chunked output, not recognition quality on a varied conversation.

```csharp
using OneSpeech;

string path = args.Length == 0 ? "speech.flac" : args[0];
await foreach (var segment in Speech.TranscribeStream(
    path, language: "en",
    model: "moonshine-ai/moonshine-streaming-tiny"))
    Console.WriteLine($"{segment.Start?.TotalSeconds:0.00}–{segment.End?.TotalSeconds:0.00}: {segment.Text}");
```

With FFmpeg installed, create the longer file from `speech.flac` and run it:

```shell
ffmpeg -v error -stream_loop 39 -i speech.flac -c:a flac long.flac -y
dotnet run -- long.flac
```

The first six of 40 segments from that run (times are seconds):

```text
0.55–2.91: Stuff it into you, his belly counseled him.
3.62–6.17: Stuff it into you, his belly counseled him.
6.88–9.47: Stuff it into you, his belly counseled him.
10.15–12.73: Stuff it into you, his belly counseled him.
13.44–16.00: Stuff it into you, his belly counseled him.
16.71–19.29: Stuff it into you, his belly counseled him.
```

The final segment ran from 128.07 to 130.62 seconds. “Counseled” is the model’s actual output, not a corrected transcript. The longer recording is generated locally rather than included in the zip.

## Related recipes

- [Align a transcript to audio](https://recursiveai.org/onespeech/cookbook/forced-alignment/)
- [Compare two speaker recordings](https://recursiveai.org/onespeech/cookbook/speaker-verification/)

---

## The short answer

Use `Speech.TranscribeStream` and consume each segment with `await foreach`. It decodes the recording in bounded chunks and lets you write each result without building one large transcript. Choose `Speech.Transcribe` instead when you need a complete document with whole-recording speaker labels. Neither call needs to retain the entire PCM waveform, according to the [long-file documentation](https://recursiveai.org/onespeech/docs/long-files/).

## How do I transcribe a long audio file?

Start by choosing what your application needs to retain. For a running text log, print or save each final segment and let it go. For a complete transcript, use the document-returning API and budget memory for the returned words, turns and text. Bounded audio storage does not make the result document constant-size.

The program above uses file streaming. Its chunks are found by voice activity detection: the library locates speech rather than treating every part of the recording as spoken text. Results are final segments, not replacing partial hypotheses. They arrive as chunks finish, not one word at a time on the microphone’s clock. You do not need to build a manual audio-splitting loop for this file API.

Pass the path to an existing, unchanged file. Do not overwrite or append to it while the decoder is processing it. If you use a caller-owned encoded stream, the library may spool it to a temporary seekable file. Allow disk space for that temporary copy. Finish enumeration or dispose it early to release the decoder, models and temporary resources. A `break` from `await foreach` disposes the enumerator; abandoning work without disposing it is not a cleanup strategy.

The tiny English recognizer used here is an explicit selection, not the default for every transcription call. The [file default](https://recursiveai.org/onespeech/docs/transcribing-files/) is Whisper large-v3-turbo. Model IDs select roles, not an entire set of companion models. Switching from segment streaming to a full document can introduce additional timing and diarization work.

## How long does it take to transcribe 30 minutes of audio?

There is no fixed duration ratio for every machine and model. First-use downloads and local model conversion can dominate startup. A warm-cache run and a first run are different workloads. Budget time for acquisition separately from recognition, and pre-fetch models before an interactive request if startup latency matters.

Cancellation is cooperative: the token is checked at audio blocks, chunk boundaries and supported model operations. It is not an instruction-level interrupt. Similarly, audio time processed is not an estimate of remaining wall-clock time. For a cancellable job, pass your application’s token as `cancellationToken` and handle `OperationCanceledException` at the job boundary.

Chunk-boundary speech can affect output. The library does not promise that streamed text is token-identical to a whole-file reference policy. Test representative recordings with long pauses, speech near chunk edges and changing voices. The short downloadable sample demonstrates how to consume results; it is not a long-recording performance claim.

## Can I transcribe a long audio file for free in C#?

OneSpeech is free and open source; the example runs local open-weight inference rather than a metered transcription endpoint. You still supply storage, memory and compute. Missing model files download on first use, so the NuGet package alone is not an offline deployment. See the [model download guide](https://recursiveai.org/onespeech/docs/model-downloads/) for cache preparation and the selected model’s license. OneSpeech is unaffiliated with other products or companies named OneSpeech.
