EggEncoder 4.32.0
See the version list below for details.
dotnet add package EggEncoder --version 4.32.0
NuGet\Install-Package EggEncoder -Version 4.32.0
<PackageReference Include="EggEncoder" Version="4.32.0" />
<PackageVersion Include="EggEncoder" Version="4.32.0" />
<PackageReference Include="EggEncoder" />
paket add EggEncoder --version 4.32.0
#r "nuget: EggEncoder, 4.32.0"
#:package EggEncoder@4.32.0
#addin nuget:?package=EggEncoder&version=4.32.0
#tool nuget:?package=EggEncoder&version=4.32.0
π₯ EggEncoder
Audio encoding/decoding toolkit for .NET β 12 formats (AAC, AIFF incl. AIFC, ALAC, AU, FLAC, MP3, Opus, TTA, Vorbis, WAV incl. IMA/MS/Yamaha ADPCM and G.711, WavPack, WMA) plus MOV/MP4 probing, mostly pure C# alongside native MP3/FLAC/WavPack bindings, built-in waveform generation, and an opt-in PCM transform pipeline (resampling, gain/peak normalization, dynamics compression, noise gating, peak limiting, pan/balance, channel remix, fades, parametric EQ, FIR filtering, mixing), all behind one
IMediaEncoderinterface.
Sponsored by eggspot.app
Overview
EggEncoder gives you a single IMediaEncoder abstraction β Probe, ConvertFile, CutFile β implemented entirely in-process by NativeEncoder: pure .NET codec implementations (AAC, WAV, AIFF, AU, ALAC, TTA, WMA, Opus, Vorbis) plus native P/Invoke bindings to libmp3lame, libFLAC, and wavpackdll. No external process, no ffmpeg install, no subprocess overhead.
Why EggEncoder?
- π Fully native, in-process β direct P/Invoke to LAME (MP3), libFLAC, and WavPack, no subprocess/shell-out overhead
- βοΈ Native AOT compatible β no reflection, no dynamic code; publish with
PublishAot=trueand it just works - πΌ Broad format coverage β AAC, AIFF (incl. AIFC), ALAC, AU, FLAC, MP3, Opus, TTA, Vorbis, WAV, WavPack, WMA decode/encode; MOV/MP4 metadata probing + mono AAC-LC audio decode
- π Built-in waveform generation β normalized peak windows for any decoded stream
- βοΈ Sample-accurate cutting β trim audio files without a full decodeβencode round trip
- ποΈ PCM transform pipeline β resampling, gain/peak normalization, channel remix, bit-depth/float conversion, fades, parametric EQ (biquad + Butterworth) and general FIR filtering, mixing, and concatenation β opt-in, composable, and layered onto
Convert/Cutwithout touching the original API - πͺΆ Dependency-light β only
Microsoft.Extensions.*.AbstractionsandNLayer - π MIT licensed β see THIRD-PARTY-NOTICES.md for the bundled native codec licenses (LGPL-2.1 LAME, BSD-style libFLAC, BSD-style WavPack)
Installation
dotnet add package EggEncoder
Native codec binaries (libmp3lame.dll, libFLAC.dll, wavpackdll.dll) ship inside the package for win-x64 and are copied to your output directory automatically.
Quick Start
using EggEncoder;
// Dependency injection (recommended)
builder.Services.AddEggEncoder();
public class MediaService(IMediaEncoder mediaEncoder)
{
public async Task<ProbeResult> Inspect(string filePath) =>
await mediaEncoder.Probe(filePath);
public Task Transcode(string sourcePath, string destPath) =>
mediaEncoder.ConvertFile(sourcePath, destPath);
public Task Trim(string sourcePath, string destPath, int startSeconds, int endSeconds) =>
mediaEncoder.CutFile(sourcePath, destPath, startSeconds, endSeconds);
}
Without DI
using EggEncoder;
using Microsoft.Extensions.Logging.Abstractions;
IMediaEncoder encoder = new NativeEncoder(NullLogger<NativeEncoder>.Instance);
var probeResult = await encoder.Probe("track.flac");
PCM Transform Pipeline
AddEggEncoder() also registers IPcmTransformEncoder (same NativeEncoder instance as IMediaEncoder) β an opt-in PcmTransformPipeline of composable IPcmTransforms that runs between decode and the destination write:
using EggEncoder.Codecs;
using EggEncoder.Pcm;
var pipeline = new PcmTransformPipeline(
new ResamplingTransform(sourceRate: 44100, targetRate: 48000, channels: 2),
new VolumeTransform(gain: 1.5));
AudioCutter.Convert(sourcePath, destPath, pipeline);
// or via DI: await pcmTransformEncoder.ConvertFile(sourcePath, destPath, pipeline);
// (pcmTransformEncoder: IPcmTransformEncoder, injected the same way as IMediaEncoder above)
// Float WAV destination (source stays a normal 32-bit int/float WAV; Float32 only changes the
// on-disk encoding of the destination -- see "Important limits" below):
AudioCutter.Convert(sourcePath, floatDestPath, WavSampleFormat.Float32);
Covers resampling (ResamplingTransform), gain / peak normalization (VolumeTransform / PeakNormalizationTransform), dynamics compression (CompressorTransform, threshold/ratio/attack/release/makeup gain), noise gating (NoiseGateTransform, the mirror-image downward expander below threshold), peak limiting (LimiterTransform, infinite-ratio compression plus a final per-sample hard clip, guaranteeing the output never exceeds the ceiling), stereo pan/balance (PanTransform, linear or equal-power), channel remix (ChannelRemixTransform, monoβstereo and general NβM), bit-depth and float conversion (BitDepthFormatTransform for 8/16/24/32-bit, FloatSampleConverter for intβIEEE-float), fades on a cut (FadeTransform via CutOptions), mixing / concatenation (AudioCutter.Mix, AudioCutter.Concatenate), parametric EQ filters (BiquadTransform β RBJ Audio EQ Cookbook low/high pass, band pass, notch, all pass, peaking EQ, low/high shelf β and ButterworthTransform for steeper cascaded low/high pass), and general FIR convolution (FirFilterTransform, arbitrary caller-supplied taps). Full walkthrough and type reference: Advanced Features / API Reference.
Important limits:
- A
PcmTransformPipelineinstance carries state across blocks (resampler history, fade position, measured peak gain, biquad/Butterworth/FIR filter history) β build a fresh one perConvert/Cut/Mixcall, don't reuse across calls. - A pipeline containing
ResamplingTransform(or any stateful transform implementingIPcmTransform.Flush) needspipeline.Flush(...)called once after the last block, to drain output the transform was still holding back βAudioCutter.Convert(pipeline)/Cut(options)already do this for you; only a driver written againstPcmTransformPipelinedirectly needs to call it itself. - True whole-file peak normalization needs
AudioCutter.MeasurePeakAmplitudefollowed byPeakNormalizationTransform.MeasurePeakbefore the pipeline runs β otherwise it silently normalizes against only the first decode block. Mix/Concatenaterequire every source to share the same channels/sample rate/bit depth.Mixdecodes all sources fully into memory (clip-length material, not multi-hour streams).ResamplingTransformis a Kaiser-windowed-sinc polyphase filter (anti-aliasing on downsample, band-limited reconstruction on upsample) β callFlush()(see above) to get its last few frames, which it can't produce until it either sees more input or is told there isn't any.
Supported Formats
| Format | Probe | Decode | Encode |
|---|---|---|---|
| WAV | β | β βΆ ΒΉΒΉ | β βΆ β· ΒΉΒΉ |
| AIFF | β | β βΉ | β βΉ |
| AU (.au) | β | β | β ΒΉβ° |
| ALAC (.caf) | β | β | β Β² |
| TTA | β | β | β Β² |
| WavPack (.wv) | β | β | β β΅ |
| Opus (.opus) | β | β | β Β³ |
| Vorbis (.ogg) | β | β | β β΄ |
| FLAC | β | β | β |
| MP3 | β | β | β |
| AAC | β | β | β |
| WMA | β | β | β |
| MOV/MP4 | β | β ΒΉ | β |
ΒΉ MOV/MP4 decode is audio-only, mono AAC-LC tracks β video frames are never decoded. Files without a matching audio track still probe fine (metadata only).
Β² ALAC supports 16-bit and 24-bit PCM for decode and encode (20-bit is out of scope β see AlacDecoder's doc comment); TTA is 16-bit PCM only (see TtaDecoder's doc comment). Mono and stereo are both supported by both.
Β³ Opus is lossy and fixed at 48kHz (Opus's native/highest internal rate) regardless of the source's own rate β resample first via ResamplingTransform if it isn't already 48kHz. Mono and stereo, 16-bit PCM, channel mapping family 0 only.
β΄ Vorbis is lossy, mono/stereo, 16-bit PCM β unlike Opus, any sample rate is supported (no fixed-rate resampling requirement).
β΅ WavPack supports 16-bit and 24-bit lossless integer PCM (its own lossy/hybrid and floating-point modes are out of scope). Mono and stereo only. Unlike every other codec here, WavPack decode/encode is via a native binary (wavpackdll.dll, the official WavPack project's own prebuilt library) rather than a pure-managed implementation β no pure-managed WavPack decoder/encoder exists. Also unlike every other codec here, WavPack cannot represent an empty/zero-sample stream at all (confirmed from its own reference CLI, which refuses to encode one) β encoding one throws NotSupportedException rather than producing a file.
βΆ WavReader also decodes IMA ADPCM (WAVE_FORMAT_IMA_ADPCM, format tag 17) and MS ADPCM (WAVE_FORMAT_ADPCM, format tag 2, see footnote 8) β still a .wav file, just a different fmt chunk codec, so it's read automatically by Probe/Convert/Cut/pipeline sources with no extra API. Mono and stereo only; reports as 16-bit PCM once decoded (the coded width is 4 bits for both). WavWriter also encodes both (block-structured, buffered internally rather than one sample at a time β see WavSampleFormat.ImaAdpcm/ImaAdpcmEncoder and WavSampleFormat.MsAdpcm/MsAdpcmEncoder), selectable the same way Float32/MuLaw/ALaw are.
β· WavReader/WavWriter also decode/encode G.711 companded PCM (WAVE_FORMAT_ALAW/WAVE_FORMAT_MULAW, format tags 6/7) β again still a .wav file, read/written automatically with no extra API beyond WavSampleFormat.ALaw/MuLaw as a Convert/Cut/Mix/Concatenate destination, the same way Float32 works. Any channel count (G.711 has no structural reason to limit it, unlike every other codec here); reports/requires 16-bit PCM at the boundary (the coded width is 8 bits). Unlike IMA ADPCM's own block-structured encode, G.711 has no block structure or adaptive state at all, so its own encode is a simple one-sample-at-a-time companding formula.
βΈ MS ADPCM (WAVE_FORMAT_ADPCM, format tag 2), mono and stereo only β a genuinely different algorithm from IMA ADPCM (linear prediction from a per-file coefficient table carried in the fmt chunk itself, rather than IMA ADPCM's universal fixed step table), so it's its own decoder and encoder, not a variant of ImaAdpcmDecoder/ImaAdpcmEncoder. MsAdpcmEncoder always selects the standard table's simplest coefficient pair (predictor index 0) for every block β confirmed from FFmpeg's own real encoder that this, not a per-block search over the other 6 standard pairs, is what real-world encoders actually ship β and always writes that full 7-pair standard table into the file's own fmt chunk extension regardless.
βΉ AiffReader/AiffWriter also handle AIFC (FORM/AIFC), still under the .aiff/.aif/.aifc extensions β no separate dispatch, AiffReader just understands the AIFC form type's extra compressionType field in its COMM chunk. Covers NONE/twos (big-endian PCM, the same as plain AIFF), sowt (little-endian PCM), fl32/fl64 (big-endian IEEE float, decoded at this codebase's usual int32-native-range scale β both report 32-bit PCM resolution), and alaw/ulaw (G.711, reusing the same G711Codec the WAV side uses, not a second implementation) β all read AND write, selectable on write via AiffSampleFormat (see AudioCutter.Convert(..., AiffSampleFormat)/CutOptions.DestinationAiffFormat). ima4 (QuickTime IMA4 ADPCM, decode only) is also covered β a materially different bitstream from WAV's own IMA ADPCM (no verbatim first sample per block, and for stereo each channel's own 34-byte sub-block is written whole rather than nibble-interleaved), though the underlying per-nibble math is identical and reused directly from Wav.ImaAdpcmDecoder β see Ima4Decoder.
ΒΉβ° AU (Sun/NeXT, magic .snd) has no chunk structure at all β one fixed 24-byte header, optionally followed by an annotation string, then raw big-endian samples with no byte-alignment padding. Covers 8/16/24/32-bit signed integer PCM, 32/64-bit IEEE float (both reporting 32-bit PCM resolution, the same reasoning as AIFC's own fl64), and mu-law/A-law G.711 (again reusing G711Codec) β all read AND write, selectable on write via AuSampleFormat (see AudioCutter.Convert(..., AuSampleFormat)/CutOptions.DestinationAuFormat). Every other defined AU encoding (G.721/G.722/G.723 ADPCM, fragmented samples) is real but obscure and out of scope, the same way AIFC's MAC3/MAC6 (MACE) are.
ΒΉΒΉ Yamaha ADPCM (WAVE_FORMAT_YAMAHA_ADPCM, format tag 32), mono and stereo only, full decode AND encode (YamahaAdpcmDecoder/YamahaAdpcmEncoder) β still a .wav file, read automatically by Probe/Convert/Cut/pipeline sources with no extra API, selectable on write via WavSampleFormat.YamahaAdpcm. Unlike IMA/MS ADPCM, it has no block structure at all β no per-block header, no wSamplesPerBlock fmt chunk extension β each channel's predictor/step state just carries continuously across the whole stream. Like MS ADPCM's own encoder (and unlike IMA ADPCM's own search), its nibble is computed via a direct closed-form formula, confirmed structurally identical to FFmpeg's own real adpcm_yamaha_compress_sample.
IMediaEncoder.CutFile decodes any supported source (WAV, AIFF, AU, ALAC, TTA, WavPack, Opus, Vorbis, FLAC, MP3, AAC, WMA, and MOV/MP4 files with a mono AAC-LC audio track) and can cut into any supported destination format, including converting as it trims β sample-accurate, no re-encode of the untouched region.
WAV supports 8-bit unsigned, 16/24/32-bit signed integer, and 32-bit IEEE float PCM (read and write), plus IMA ADPCM decode+encode, MS ADPCM decode+encode, Yamaha ADPCM decode+encode, and G.711 mu-law/A-law decode+encode (see footnotes 6/7/8/11 above). AIFF (.aiff/.aif/.aifc) supports 8/16/24/32-bit signed integer PCM, read and write (plain FORM/AIFF), plus AIFC (FORM/AIFC) read and write for NONE/twos/sowt integer PCM, fl32/fl64 float, and alaw/ulaw G.711, plus ima4 (QuickTime IMA4 ADPCM) decode (see footnote 9). AU (.au) supports 8/16/24/32-bit signed integer PCM, 32/64-bit float, and mu-law/A-law G.711, all read and write (see footnote 10). ALAC (.caf, Apple Lossless in a CAF container) supports mono and stereo, 16-bit or 24-bit integer PCM, read and write. TTA (.tta, True Audio) supports mono and stereo, 16-bit integer PCM, read and write. WavPack (.wv) supports mono and stereo, 16-bit or 24-bit lossless integer PCM, read and write. Opus (.opus, in a from-scratch OggOpus container) supports mono and stereo, 16-bit integer PCM at a fixed 48kHz, read and write. Vorbis (.ogg) supports mono and stereo, 16-bit integer PCM at any sample rate, read and write. A float WAV source always decodes transparently into int PCM, the same as any other bit depth. For a float, mu-law, A-law, IMA ADPCM, MS ADPCM, or Yamaha ADPCM WAV destination, pass WavSampleFormat.Float32/MuLaw/ALaw/ImaAdpcm/MsAdpcm/YamahaAdpcm to AudioCutter.Convert/Cut (via CutOptions.DestinationWavFormat)/Mix/Concatenate β the default (WavSampleFormat.Integer) is unchanged; Float32 requires the destination's bit depth to already be 32, MuLaw/ALaw/ImaAdpcm/MsAdpcm/YamahaAdpcm require 16 (widen/narrow with BitDepthFormatTransform first if needed), and ImaAdpcm/MsAdpcm/YamahaAdpcm additionally require mono or stereo. AudioCutter.ReadWavAsFloat/WriteWavFromFloat/FloatSampleConverter remain available for working with float[] directly instead of driving int PCM through a pipeline.
License
MIT β see LICENSE. EggEncoder bundles pre-built libmp3lame.dll (LGPL-2.1),
libFLAC.dll (BSD-style), and wavpackdll.dll (BSD-style) as separate, dynamically-loaded
native binaries; see THIRD-PARTY-NOTICES.md for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Concentus (>= 2.2.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.0)
- NLayer (>= 2.0.1)
- NVorbis (>= 1.0.0-rc.2)
- OggVorbisEncoder (>= 1.2.2)
-
net8.0
- Concentus (>= 2.2.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.0)
- NLayer (>= 2.0.1)
- NVorbis (>= 1.0.0-rc.2)
- OggVorbisEncoder (>= 1.2.2)
-
net9.0
- Concentus (>= 2.2.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.0)
- NLayer (>= 2.0.1)
- NVorbis (>= 1.0.0-rc.2)
- OggVorbisEncoder (>= 1.2.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.42.0 | 0 | 10/11/2026 |
| 4.41.1 | 0 | 10/11/2026 |
| 4.41.0 | 0 | 10/11/2026 |
| 4.40.0 | 0 | 10/11/2026 |
| 4.39.0 | 39 | 10/10/2026 |
| 4.38.1 | 39 | 10/10/2026 |
| 4.38.0 | 43 | 10/10/2026 |
| 4.37.0 | 42 | 10/10/2026 |
| 4.36.0 | 44 | 10/10/2026 |
| 4.35.0 | 46 | 10/10/2026 |
| 4.34.0 | 41 | 10/10/2026 |
| 4.33.0 | 41 | 10/10/2026 |
| 4.32.1 | 45 | 10/10/2026 |
| 4.32.0 | 48 | 10/10/2026 |
| 4.31.0 | 40 | 10/9/2026 |
| 4.30.0 | 42 | 10/9/2026 |
| 4.29.3 | 44 | 10/9/2026 |
| 4.29.2 | 47 | 10/8/2026 |
| 4.29.1 | 43 | 10/8/2026 |
| 4.29.0 | 43 | 10/8/2026 |