FFmpegRunner 1.0.0

dotnet add package FFmpegRunner --version 1.0.0
                    
NuGet\Install-Package FFmpegRunner -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FFmpegRunner" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FFmpegRunner" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="FFmpegRunner" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FFmpegRunner --version 1.0.0
                    
#r "nuget: FFmpegRunner, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FFmpegRunner@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FFmpegRunner&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=FFmpegRunner&version=1.0.0
                    
Install as a Cake Tool

FFmpegRunner

A .NET FFmpeg wrapper library providing a Fluent API-style chained interface for building and executing FFmpeg commands. Supports pipe data transfer, frame-level data callbacks, RTSP/RTMP streaming and more.

Installation

dotnet add package FFmpegRunner

Requirements

  • .NET Standard 2.0 or .NET 8.0+
  • FFmpeg must be installed on the system (in PATH or configured manually)

Quick Start

using FFmpegRunner;

var exitCode = new FFmpegBuilder()
    .FromSource("input.avi")
    .WithVideoCodec("libx264")
    .WithAudioCodec("aac")
    .WithCrf(23)
    .WithOverwrite(true)
    .ToFile("output.mp4")
    .Build()
    .Start();

It is recommended to always use .WithOverwrite(true) to prevent FFmpeg from blocking on user input when the output file already exists.

Features

FFmpeg Configuration

Three ways to configure, priority: Builder.WithFFmpegPath() > FFmpegConfig.SetFFmpegPath() > auto detection

// Global configuration
FFmpegConfig.SetFFmpegPath(@"C:\ffmpeg\bin\ffmpeg.exe");

// Per-builder configuration
new FFmpegBuilder().WithFFmpegPath("/usr/local/bin/ffmpeg");

// Auto detection (default)
// Searches PATH → common installation directories

Media Information

Query media stream information via ffprobe:

var runner = new FFmpegBuilder()
    .FromSource("input.mp4")
    .ToFile("dummy.mp4")
    .Build();

var streams = runner.GetStreamInfo();

foreach (var s in streams)
{
    Console.WriteLine($"#{s.Index}: {s.CodecType} - {s.CodecName}");
    if (s.CodecType == "video")
        Console.WriteLine($"  {s.Width}x{s.Height}, {s.RFrameRate}");
}

StreamPipe

Raw byte stream passthrough without frame parsing, suitable for custom protocols or data forwarding:

new FFmpegBuilder()
    .FromSource("input.mp4")
    .WithVideoCodec("h264")
    .WithOverwrite(true)
    .ToPipe(pipe => pipe
        .WithPipeType(PipeType.Stream)
        .WithBufferCapacity(100)
        .WithCallback((data, metadata) =>
        {
            Console.WriteLine($"Received {data.Length} bytes");
        }))
    .Build()
    .Start();

FramePipe

Uses IFrameSplitter to split raw byte streams at frame boundaries, then IFrameAnalyzer to identify frame types. The default CompositeFrameSplitter uses a chain of responsibility (H.264 → H.265 → MJPEG), which can be customized:

new FFmpegBuilder()
    .FromSource("input.mp4")
    .WithVideoCodec("h264")
    .WithOverwrite(true)
    .ToPipe(pipe => pipe
        .WithPipeType(PipeType.Frame)
        .WithBufferCapacity(50)
        .WithFrameAnalyzer(new H264FrameAnalyzer())
        .WithCallback((data, metadata) =>
        {
            Console.WriteLine(
                $"Type={metadata?.Type}, KeyFrame={metadata?.IsKeyFrame}, " +
                $"Size={data.Length / 1024} KB");
        }))
    .Build()
    .Start();
Custom Frame Splitter

Use WithFrameSplitter() to precisely control frame boundary detection and support new codec formats:

// Only handle H.264 and MJPEG, exclude H.265
var customSplitter = new CompositeFrameSplitter(
    new H264FrameSplitter(),
    new MjpegFrameSplitter()
);

new FFmpegBuilder()
    .FromSource("input.mp4")
    .WithVideoCodec("h264")
    .WithOverwrite(true)
    .ToPipe(pipe => pipe
        .WithPipeType(PipeType.Frame)
        .WithFrameSplitter(customSplitter)
        .WithFrameAnalyzer(new H264FrameAnalyzer())
        .WithCallback((data, metadata) => { ... }))
    .Build()
    .Start();

Supported analyzers:

Analyzer Description
H264FrameAnalyzer H.264 frame analysis, identifies I/P/B frames and keyframes
H265FrameAnalyzer H.265 frame analysis, identifies IRAP keyframes
MjpegFrameAnalyzer MJPEG frame analysis, splits by SOI/EOI markers
CompositeFrameAnalyzer Combines multiple analyzers (default)

Supported splitters:

Splitter Description
H264FrameSplitter H.264 Annex B NAL splitting + AU aggregation
H265FrameSplitter H.265 Annex B NAL splitting + AU aggregation
MjpegFrameSplitter MJPEG SOI/EOI frame boundary detection
CompositeFrameSplitter Combines multiple splitters (default, chain of responsibility)
Extending with Custom Splitters

Implement the IFrameSplitter interface to register into the chain:

public class MyCodecSplitter : IFrameSplitter
{
    public bool TryExtractFrame(List<byte> buffer, out byte[]? frame) { ... }
    public bool TryFlush(out byte[]? frame) { ... }
    public void Reset() { ... }
}

// Register
var splitter = new CompositeFrameSplitter();
splitter.AddSplitter(new MyCodecSplitter());

// Remove a default splitter
splitter.RemoveSplitter<H265FrameSplitter>();

MJPEG Image Capture

With MJPEG encoding, each frame is a complete JPEG image. The underlying MjpegFrameSplitter automatically splits frames by SOI(0xFFD8)/EOI(0xFFD9) markers — no additional decoding required:

new FFmpegBuilder()
    .FromSource("input.mp4")
    .WithVideoCodec("mjpeg")
    .WithCustomArguments("-q:v 5")
    .WithOverwrite(true)
    .ToPipe(pipe => pipe
        .WithPipeType(PipeType.Frame)
        .WithCallback((data, metadata) =>
        {
            File.WriteAllBytes($"frame_{DateTime.Now.Ticks}.jpg", data);
        }))
    .Build()
    .Start();

Streaming

Supports RTMP/RTSP streaming:

// RTMP
new FFmpegBuilder()
    .FromSource("input.mp4")
    .WithVideoCodec("libx264")
    .WithAudioCodec("aac")
    .WithCrf(23)
    .ToNetwork("rtmp://live.example.com/app/streamkey")
    .Build()
    .Start();

// RTSP
new FFmpegBuilder()
    .FromSource("input.mp4")
    .WithVideoCodec("libx264")
    .WithAudioCodec("aac")
    .ToRtsp("rtsp://server:554/live/stream", "tcp")
    .Build()
    .Start();

Hardware Acceleration

Supports hardware acceleration via InputOptions.WithHardwareAcceleration():

  • Auto, Vdpau, Dxva2, D3d11va, Vaapi, Qsv, Amf

Resource Disposal

runner.Dispose();

// or using statement
using var runner = new FFmpegBuilder()
    .FromSource("input.mp4")
    .ToFile("output.mp4")
    .Build();

Exception Handling

All business exceptions in the library use FFmpegRunnerException, which provides an ErrorCode for precise identification and ContextData for diagnostic context:

try
{
    var path = FFmpegConfig.GetFFmpegPath();
}
catch (FFmpegRunnerException ex) when (ex.ErrorCode == "FFMPEG_NOT_FOUND")
{
    Console.WriteLine($"FFmpeg not found: {ex.Message}");
}

try
{
    var streams = runner.GetStreamInfo();
}
catch (FFmpegRunnerException ex)
{
    Console.WriteLine($"Query failed (ErrorCode={ex.ErrorCode}): {ex.Message}");
    // ContextData contains ExitCode, SourcePath, etc.
}

Common error codes:

ErrorCode Description
FFMPEG_NOT_FOUND FFmpeg executable not found
FFPROBE_NOT_FOUND ffprobe executable not found
FFPROBE_FAILED ffprobe execution failed
FFMPEG_TIMEOUT FFmpeg process timed out
FFMPEG_ALREADY_RUNNING FFmpeg process is already running
BUILD_MISSING_SOURCE Source path not set during build
BUILD_MISSING_TARGET Output target not set during build
BUILD_RTSP_FORMAT_CONFLICT RTSP streaming mode format conflict

Full Documentation

For complete documentation and sample projects, visit the GitHub repository.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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 was computed.  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 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
1.0.0 52 6/7/2026
0.0.1 85 5/16/2026