Dependency Injection

What AddEggEncoder Registers

services.AddEggEncoder() registers one scoped NativeEncoder instance, and maps both IMediaEncoder and IPcmTransformEncoder to resolve it — inject whichever interface fits the call site; resolving both in the same scope gives you the same underlying instance. IPcmTransformEncoder is the PCM transform pipeline's DI-friendly entry point (resampling, gain/peak normalization, dynamics compression, noise gating, peak limiting, echo/delay, pan/balance, channel remix, bit-depth/float conversion, fades, parametric EQ, FIR filtering, mixing, concatenation) — see PCM Transform Pipeline. Inject either interface into a controller, a scoped service, or resolve it from an IServiceScope in a background worker. Pass AddEggEncoder(enableLogging: false) to silence NativeEncoder's logging entirely — see Configuration.

Typical Registration

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

Consuming IMediaEncoder

public class TrackController(IMediaEncoder mediaEncoder) : ControllerBase
{
    [HttpPost("probe")]
    public async Task<IActionResult> Probe(string filePath)
    {
        var result = await mediaEncoder.Probe(filePath);
        return Ok(result);
    }
}

Consuming IPcmTransformEncoder

public class TranscodeService(IPcmTransformEncoder pcmEncoder)
{
    public Task Resample(string sourcePath, string destPath, int targetSampleRate, int sourceSampleRate, int channels)
    {
        var pipeline = new PcmTransformPipeline(new ResamplingTransform(sourceSampleRate, targetSampleRate, channels));
        return pcmEncoder.ConvertFile(sourcePath, destPath, pipeline);
    }
}

Resolving From a Background Worker

In a non-request context (a cron task, a queue consumer), create a scope explicitly:

public class TranscodeWorker(IServiceProvider serviceProvider)
{
    public async Task RunAsync(string sourcePath, string destPath)
    {
        await using var scope = serviceProvider.CreateAsyncScope();
        var mediaEncoder = scope.ServiceProvider.GetRequiredService<IMediaEncoder>();

        await mediaEncoder.ConvertFile(sourcePath, destPath);
    }
}

Without a DI Container

Every implementation has a plain constructor and works standalone — see Getting Started.