Getting Started

Install

dotnet add package EggEncoder

Targets net8.0, net9.0, and net10.0. No native binaries, no extra install steps — just the package. EggEncoder runs anywhere .NET 8/9/10 runs (Windows, Linux, macOS).

One Interface, 100% Pure Managed

EggEncoder exposes one interface, IMediaEncoder, implemented by NativeEncoder — pure .NET codecs for every supported format, with no native binary or P/Invoke binding anywhere in this project. No external process, no ffmpeg install.

Register with DI

using EggEncoder;

// Program.cs
builder.Services.AddEggEncoder();

No options, no configuration — the native codec binaries ship inside the package and are resolved automatically at runtime.

Inject and Use

public class MediaService(IMediaEncoder mediaEncoder)
{
    public Task<ProbeResult> Inspect(string filePath) =>
        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

Every type works standalone if you'd rather not use the DI extension:

using EggEncoder;
using Microsoft.Extensions.Logging.Abstractions;

IMediaEncoder encoder = new NativeEncoder(NullLogger<NativeEncoder>.Instance);
var probeResult = await encoder.Probe("track.flac");

Console.WriteLine($"{probeResult.SampleRate}Hz, {probeResult.DurationSeconds}s");

Reading a ProbeResult

Probe always returns the same ProbeResult shape. Only fields this library can genuinely compute are populated:

public class ProbeResult
{
    public string FormatName { get; init; }        // e.g. "wav", "flac", "mp3", "aac", "asf", "mov", "mp4"
    public string FormatLongName { get; init; }     // e.g. "WAV / WAVE (Waveform Audio)"
    public long SizeBytes { get; init; }
    public double DurationSeconds { get; init; }
    public string CodecType { get; init; }          // "audio" or "video"
    public string? CodecName { get; init; }         // e.g. "pcm_s16le", "flac", "mp3", "aac", "wmav2"
    public string? CodecLongName { get; init; }
    public int? SampleRate { get; init; }
    public int? Channels { get; init; }
    public string? ChannelLayout { get; init; }     // "mono", "stereo", or "{n} channels"
    public int? BitsPerSample { get; init; }
    public int? BitRate { get; init; }
    public bool? IsVariableBitRate { get; init; }   // MP3 only
    public long? DurationInSamples { get; init; }
    public string? TimeBase { get; init; }          // e.g. "1/44100"
    public int? Width { get; init; }                // set for video containers (MOV/MP4), null for audio
    public int? Height { get; init; }
    public IReadOnlyList<double>? Waveform { get; init; }  // normalized peak windows, or null
    public double? PeakAmplitude { get; init; }     // loudest absolute sample across the whole decode, normalized to [0,1]
    public double? RmsLevel { get; init; }          // root-mean-square level across every sample, normalized to [0,1]
}

See Advanced Features for waveform generation, sample-accurate cutting, and the PCM transform pipeline (resampling, normalization, pan/balance, remix, fades, parametric EQ, FIR filtering, mixing) details, or the API Reference for the full type list.