---
title: "Audio in .NET without FFmpeg"
url: https://recursiveai.org/oneaudio/articles/audio-without-ffmpeg-dotnet/
description: "When you can drop FFmpeg, FFMpegCore or Xabe.FFmpeg for audio in .NET: ffmpeg commands mapped to managed C# calls, and the jobs that still need FFmpeg."
date: 2026-10-27
author: OneAudio team
---

# Audio in .NET without FFmpeg

When you can drop FFmpeg, FFMpegCore or Xabe.FFmpeg for audio in .NET: ffmpeg commands mapped to managed C# calls, and the jobs that still need FFmpeg.

October 27, 2026 · OneAudio team

You can do audio in .NET without FFmpeg when your inputs are WAV, MP3, Ogg Vorbis, Opus or FLAC, your outputs are WAV, FLAC or Opus, and the work is converting, resampling, mixing, measuring loudness or normalizing. A managed library such as OneAudio does all of that in-process, with no ffmpeg binary to install, ship or keep patched, and it publishes with NativeAOT and trimming. You still need FFmpeg for AAC and M4A, for MP3 or Vorbis encoding, for video, and for the long tail of other formats. This page maps the common ffmpeg audio commands to C# calls, with every sample compiled and run against OneAudio 1.2.1 and FFMpegCore 5.5.0 on .NET 10.

## What an FFmpeg wrapper brings with it

The .NET FFmpeg wrappers run the ffmpeg program for you. [FFMpegCore](https://www.nuget.org/packages/FFMpegCore/5.5.0) 5.5.0 (MIT) is a “FFMpeg/FFProbe wrapper”, and its README’s “Binaries” section has you install ffmpeg and ffprobe through a package manager, download them, or fetch them at run time with the `FFMpegCore.Extensions.Downloader` package; by default it expects to find them on the `PATH`. Converting a file with it, on a machine with ffmpeg installed from the distribution’s packages:

*Program.cs · FFMpegCore 5.5.0 · Linux*

```
using FFMpegCore;
 
// FFMpegCore runs the ffmpeg and ffprobe programs; here they come from PATH (apt install ffmpeg).
FFMpegArguments
    .FromFileInput("music.mp3")
    .OutputToFile("music-ffmpeg.wav", true)
    .ProcessSynchronously();
 
IMediaAnalysis info = FFProbe.Analyse("music-ffmpeg.wav");
Console.WriteLine($"{info.PrimaryAudioStream?.SampleRateHz} Hz, {info.PrimaryAudioStream?.Channels} ch, {info.Duration}");
```

*Output · Console*

```
44100 Hz, 2 ch, 00:00:30
```

That works, and for video or unusual formats it is the right tool. The costs are around it: every server, container and desktop install needs an ffmpeg build of the right architecture, the codecs you get depend on how that build was configured, each conversion starts a separate process, and errors come back as process output. [Xabe.FFmpeg](https://www.nuget.org/packages/Xabe.FFmpeg/6.1.1) 6.1.1 wraps the same program; its [license page](https://ffmpeg.xabe.net/license.html) (read October 27, 2026) offers it under CC BY-NC-SA 3.0 for non-commercial projects and points to paid plans on its [pricing page](https://ffmpeg.xabe.net/pricing.html) otherwise. Read the license text for your own case.

## The same jobs in managed C#

*Terminal · NuGet*

```
dotnet new console -o NoFfmpeg
cd NoFfmpeg
dotnet add package RecursiveAI.OneAudio --version 1.2.1
```

*Program.cs · OneAudio 1.2.1 · .NET 10*

```
using OneAudio;
using OneAudio.Loudness;
using OneAudio.Opus;
 
// ffmpeg -i music.mp3 music-from-mp3.wav
Audio.Transcode("music.mp3", "music-from-mp3.wav");
 
// ffmpeg -i music.mp3 -ar 16000 -ac 1 speech.wav
Audio.Transcode("music.mp3", "speech.wav", new TranscodeOptions { SampleRate = 16000, Channels = 1 });
 
// ffmpeg -i music.wav -c:a flac music.flac      and      ffmpeg -i music.wav -c:a libopus -b:a 128k music.opus
Audio.Transcode("music.wav", "music.flac");
Audio.Transcode("music.wav", "music.opus", new TranscodeOptions
{
    Opus = new OpusFileWriterSettings { Encoder = new OpusEncoderSettings { BitrateBps = 128_000 } },
});
 
// ffmpeg -i music.wav -af ebur128=peak=true -f null -
LoudnessResult r = Audio.Measure("music.wav");
Console.WriteLine($"{r.IntegratedLufs:F1} LUFS, {r.LoudnessRange:F1} LU, {r.TruePeakDbtp:F1} dBTP");
 
// Gain to -14 LUFS with a -1 dBTP ceiling, one linear gain for the whole file.
NormalizeResult n = Audio.Normalize("music.wav", "music-14.wav");
Console.WriteLine($"gain {n.GainDb:+0.0;-0.0} dB, limited by peak: {n.LimitedByPeak}");
 
foreach (string f in new[] { "music-from-mp3.wav", "speech.wav", "music.flac", "music.opus", "music-14.wav" })
{
    using IAudioDecoder d = Audio.Open(f);
    Console.WriteLine($"{f}: {d.Format.SampleRate} Hz, {d.Format.Channels} ch, {d.LengthFrames / (double)d.Format.SampleRate:F3} s");
}
```

*Output · Console*

```
-14.3 LUFS, 2.8 LU, -5.1 dBTP
gain +0.3 dB, limited by peak: False
music-from-mp3.wav: 44100 Hz, 2 ch, 30.000 s
speech.wav: 16000 Hz, 1 ch, 30.000 s
music.flac: 44100 Hz, 2 ch, 30.000 s
music.opus: 48000 Hz, 2 ch, 30.000 s
music-14.wav: 44100 Hz, 2 ch, 30.000 s
```

| ffmpeg | OneAudio 1.2.1 |
|---|---|
| `ffmpeg -i in.mp3 out.wav` | `Audio.Transcode("in.mp3", "out.wav")` |
| `-ar 48000`, `-ac 1` | `TranscodeOptions { SampleRate = 48000, Channels = 1 }` |
| `-c:a pcm_s24le` | `Wav = new WavEncoderSettings { SampleType = NativeSampleType.PcmSigned24 }` |
| `-c:a flac -compression_level 8` | `Flac = new FlacEncoderSettings { CompressionLevel = 8 }` |
| `-c:a libopus -b:a 128k` | `Opus = new OpusFileWriterSettings { Encoder = new OpusEncoderSettings { BitrateBps = 128_000 } }` |
| `-af ebur128=peak=true` | `Audio.Measure(path)`: integrated LUFS, loudness range, true peak |
| `-af loudnorm` (linear, two passes) | `Audio.Normalize(input, output)`: −14 LUFS and −1 dBTP by default |
| `-af aresample` | `Audio.Resample`, or `SampleRate` in the options |
| `-filter_complex amix` | `AudioMixer`: voices, buses, ducking, effects |
| Pipes: `-i pipe:0 -f wav pipe:1` | `Audio.Transcode(inputStream, outputStream, options)` with `Format` set |

- The output format comes from the extension, or from `TranscodeOptions.Format` for streams. Conversion streams block by block, so memory doesn’t grow with the file, and a failed file conversion deletes the partial output.
- The loudness figures match ffmpeg’s: its `ebur128` filter with `peak=true` reports −14.3 LUFS integrated, 2.8 LU of loudness range and a −5.1 dBFS true peak for the same file.
- `Audio.Normalize` applies one gain to the whole file and holds it back if the true peak would pass the ceiling. FFmpeg’s [loudnorm documentation](https://ffmpeg.org/ffmpeg-filters.html#loudnorm) describes “both dynamic and linear normalization modes”; the linear one is the equivalent. There is no dynamic mode in OneAudio. More in [loudness normalization in C#](https://recursiveai.org/oneaudio/articles/loudness-normalization-csharp/).
- A lossless source written as WAV or FLAC without conversion is bit-exact, and MP3 decoding trims the encoder’s padding, so lengths match the original (30.000 s above).

## What you gain by dropping the binary

- **Deployment:** one NuGet package of managed code. `dotnet publish` for linux-arm64, a Windows installer or a slim container image needs nothing else, and a NativeAOT app with every decoder is 1.96 MB on linux-x64, per the project’s [README](https://github.com/recursive-ai-oss/oneaudio-csharp/blob/v1.2.1/README.md).
- **Errors as exceptions:** malformed input raises `AudioFormatException`, an unsupported format `UnsupportedAudioFormatException`, and a file that exceeds a configured limit `AudioLimitExceededException`, in your process, with no output to parse.
- **Untrusted uploads:** sizes read from a file are checked against `AudioLimits` before anything is allocated, and each of the six parsers was fuzzed with libFuzzer for 660 seconds with no crashes, hangs or out-of-memory failures, per the README’s fuzzing table.
- **Samples in your code:** decode to a float span, process it, and encode it, without pipes or temporary files. The same package plays and records through its Devices companion ([play audio in C#](https://recursiveai.org/oneaudio/articles/play-audio-csharp/)).

## When you still need FFmpeg

- **AAC, M4A, ALAC, WMA** and other formats outside WAV, MP3, Ogg (Vorbis, Opus, FLAC) and FLAC.
- **MP3 or Vorbis output.** OneAudio encodes WAV, FLAC and Opus. If a destination requires MP3 or AAC, keep FFmpeg for that step.
- **Video:** extracting audio from MP4 or MKV, muxing audio into video, or anything with frames.
- **Dynamic loudness processing** such as loudnorm’s dynamic mode, compressors and other ffmpeg filters beyond the mixer’s filters, reverb and limiter.

You can also combine them: handle WAV, MP3, Ogg and FLAC in process, and call FFmpeg only for the formats that need it. Then only the services that see those formats need an ffmpeg binary.

## Where next

- [Convert audio files](https://recursiveai.org/oneaudio/cookbook/convert-audio-files/) and [trim unused codecs](https://recursiveai.org/oneaudio/cookbook/trim-codecs/), the cookbook recipes.
- [Decode MP3 in C#](https://recursiveai.org/oneaudio/articles/decode-mp3-csharp/), [encode Opus](https://recursiveai.org/oneaudio/articles/opus-csharp/) and [write FLAC](https://recursiveai.org/oneaudio/articles/flac-csharp/).
- [Choosing a C# audio library](https://recursiveai.org/oneaudio/articles/csharp-audio-library/), with FFMpegCore, NAudio and OwnAudioSharp side by side.
