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.
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"); }
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.BitrateBpstakes 500 to 300,000 bits per second per channel, orOpusEncoderSettings.AutoBitrate(the default) orMaxBitrate.BitrateModeisVbr(the default),ConstrainedVbrorCbr.ApplicationisAudiofor music and general sound,Voipfor speech, orRestrictedLowDelay.Complexityruns 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.
BandwidthandMaxBandwidthpin the bandwidth.InBandFecwith aPacketLossPercentabove 0 adds forward error correction, andDtxmakes silence cost one byte per packet. - Input that isn’t at 48 kHz is resampled by the file writer, which is why
voice-16k.opushas about three times as many frames as the 16 kHz source. The header records the original rate. OpusFileWriterSettingstakes 48 kHz stereo input unless you setInputSampleRateandChannels.Audio.Transcodesets both from the source.FrameMillisecondssets 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.
OpusEncoderalone encodes raw packets of 2.5 to 60 ms at 48 kHz, for a network stream. See 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#.