---
title: "Encode Opus in C#"
url: https://recursiveai.org/oneaudio/cookbook/encode-opus/
description: "Encode WAV, FLAC or MP3 to Ogg Opus in C# with oneaudio, a managed Opus encoder: choose the bitrate and mode, add tags, and encode speech with the VoIP…"
version: "1.2.1"
---

# Encode Opus in C#

Encode WAV, FLAC or MP3 to Ogg Opus in C# with oneaudio, a managed Opus encoder: choose the bitrate and mode, add tags, and encode speech with the VoIP application.

```csharp
using OneAudio;
using OneAudio.Opus;

// One call with the defaults: VBR at the encoder's automatic bitrate.
Audio.Transcode("music.wav", "music-auto.opus");
Console.WriteLine($"music-auto.opus: {new FileInfo("music-auto.opus").Length:N0} bytes");

// Choose the bitrate and add tags.
var settings = new OpusFileWriterSettings
{
    Encoder = new OpusEncoderSettings
    {
        BitrateBps = 64_000,
        BitrateMode = OpusBitrateMode.ConstrainedVbr,
    },
    Comments = ["TITLE=Four chords", "ARTIST=Test signal"],
};
Audio.Transcode("music.flac", "music-64k.opus", new TranscodeOptions { Opus = settings });
Console.WriteLine($"music-64k.opus: {new FileInfo("music-64k.opus").Length:N0} bytes");

// Speech: the VoIP application, mono, 16 kbit/s. The writer resamples the
// 16 kHz input to 48 kHz.
AudioClip voice = Audio.Load("voice.wav");
var voiceSettings = new OpusFileWriterSettings
{
    Channels = 1,
    InputSampleRate = voice.Format.SampleRate,
    Encoder = new OpusEncoderSettings
    {
        Application = OpusApplication.Voip,
        BitrateBps = 16_000,
    },
};
using (var writer = new OpusFileWriter(File.Create("voice-16k.opus"), voiceSettings,
                                       leaveOpen: false))
{
    writer.Write(voice.Samples.Span);       // call as often as you like
    writer.Finish();
    Console.WriteLine($"voice-16k.opus: {writer.FramesWritten} frames, pre-skip {writer.PreSkip}, " +
                      $"{new FileInfo("voice-16k.opus").Length:N0} bytes");
}

// Read them back: the decoded length is the audio written, at 48 kHz.
foreach (string f in new[] { "music-64k.opus", "voice-16k.opus" })
{
    using IAudioDecoder d = Audio.Open(f);
    Console.WriteLine($"{f}: {d.Format.SampleRate} Hz, {d.Format.Channels} ch, " +
                      $"{d.LengthFrames / 48000.0:F3} s");
}
```

```text
music-auto.opus: 404,461 bytes
music-64k.opus: 260,511 bytes
voice-16k.opus: 289201 frames, pre-skip 312, 11,805 bytes
music-64k.opus: 48000 Hz, 2 ch, 32.000 s
voice-16k.opus: 48000 Hz, 1 ch, 6.025 s
```

## Settings

- `OpusEncoderSettings.BitrateBps` takes 500 to 300,000 bits per second per channel, or `OpusEncoderSettings.AutoBitrate` (the default) or `MaxBitrate`. `BitrateMode` is `Vbr` (the default), `ConstrainedVbr` or `Cbr`.
- `Application` is `Audio` for music and general sound, `Voip` for speech, or `RestrictedLowDelay`. `Complexity` runs from 0 to 10, and the default is 10.
- The encoder picks SILK, hybrid or CELT for each packet, the way the reference encoder does. `Bandwidth` and `MaxBandwidth` pin the bandwidth. `InBandFec` with a `PacketLossPercent` above 0 adds forward error correction, and `Dtx` makes silence cost one byte per packet.
- Input that isn’t at 48 kHz is resampled by the file writer, which is why `voice-16k.opus` has about three times as many frames as the 16 kHz source. The header records the original rate.
- `OpusFileWriterSettings` takes 48 kHz stereo input unless you set `InputSampleRate` and `Channels`. `Audio.Transcode` sets both from the source. `FrameMilliseconds` sets the packet length: 2.5, 5, 10, 20 (the default), 40 or 60 ms.

## Good to know

- With the same settings and 16-bit input, the packets are byte-identical to the RFC 6716 reference encoder on all 269 configurations the project tested. The same input gives the same bytes on a platform.
- More than two channels are written as channel mapping family 1, up to eight channels, in WAV speaker order.
- `OpusEncoder` alone encodes raw packets of 2.5 to 60 ms at 48 kHz, for a network stream. See [Decode Opus](https://recursiveai.org/oneaudio/cookbook/decode-opus/) for a round trip through it.
- Encoding allocates nothing after the encoder is built.

Opus files and raw packets, compared with Concentus and OpusSharp: [Opus in C#](https://recursiveai.org/oneaudio/articles/opus-csharp/).
