Xabe.FFmpeg builds FFmpeg command lines from C# instead of binding libav
.NET Standard wrapper for FFmpeg. It allows to process media without know how FFmpeg works, and can be used to pass customized arguments to FFmpeg from dotnet core application.
At a glance
- What is it?
- Xabe.FFmpeg is a .NET Standard wrapper that assembles FFmpeg and FFprobe arguments and starts the executables, so a C# application can convert media without knowing the command line. It suits teams that want typed helpers and still need access to every FFmpeg option.
- Who is it for?
- Adopt Xabe.FFmpeg if your C# application has to run FFmpeg and you want probe-based defaults, conversion snippets and a typed stream builder without giving up access to raw options. Do not adopt it if you need in-process native decoding or if your deployment cannot ship ffmpeg and ffprobe binaries, because the wrapper starts those executables and nothing else.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 28 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A command line builder, not a binding to libav
Xabe.FFmpeg is a .NET Standard wrapper for FFmpeg that runs the ffmpeg and ffprobe executables for you from C#. The mechanism matters more than the feature list, and the README states it directly: the library does not bind to the native libav libraries. It builds an FFmpeg argument string and starts the executables that exist on your machine, or the ones you point it at.
That single decision sets the character of the whole library. Because it is a process wrapper, everything the FFmpeg command line can do stays available, and you are never limited to what the wrapper models. The cost is that you are still shipping and managing FFmpeg binaries, and the library is an argument generator with a result object around it rather than an in-process media engine.
The same reasoning explains why the API is layered. There is a facade class, a snippets collection for common jobs, a stream builder for selecting and reconfiguring streams, and a raw parameter path for everything the model does not cover. All three levels produce the same IConversion object, so the choice is about how much you want to say and how much you want the library to say for you.
Executable lookup ends in FFmpegNotFoundException
Before any conversion runs, the library has to find two executables, and the order is documented. The first location is the directory you pointed it at with FFmpeg.SetExecutablesPath(...). The second is the directory containing your application's entry assembly. The third is the directories listed in the PATH environment variable.
Lookup is by executable name, ffmpeg and ffprobe, with .exe added on Windows, and it is case-insensitive. If neither executable is found, the library throws an FFmpegNotFoundException whose message points at the locations it searched, namely the configured directory if any and PATH.
The entry assembly rule is a nice touch for deployment. If you drop ffmpeg and ffprobe next to your application binary, they are found without touching PATH, which is how a self-contained deployment usually ships its tools. The error message design follows from the same idea: a failure tells you where it looked rather than just that it failed.
dotnet add package Xabe.FFmpeg and a two-binary prerequisite
The package is distributed on NuGet, and installation is a single command in a .NET project:
dotnet add package Xabe.FFmpegor, in the NuGet Package Manager console:
PM> Install-Package Xabe.FFmpegThe stated prerequisite is that both the ffmpeg and ffprobe executables must be available. The README gives two ways to satisfy that: install them from your platform's package manager, or use the separate Xabe.FFmpeg.Downloader package, which fetches a build for you.
That second option is why the project is split into two NuGet packages rather than one. The core package builds command lines, runs the executables, and surfaces results and progress. The Downloader package is separate and optional, and it downloads an ffmpeg or ffprobe build for the current operating system into a directory you choose. Keeping the downloader out of the core means a production build that already ships its own binaries does not carry the download code.
If you do point the library at a specific directory, it is a single call:
using Xabe.FFmpeg;
FFmpeg.SetExecutablesPath(@"C:\Tools\ffmpeg");The project homepage is xabe.net/product/xabe_ffmpeg/, and the fuller guide lives at ffmpeg.xabe.net/docs.html.
A snippet is one line of code, and the -n flag will bite you
The quickest way in is a snippet. The README's example converts a local file to MP4:
using System;
using Xabe.FFmpeg;
string input = "movie.mkv";
string output = "movie.mp4";
IConversion conversion = await FFmpeg.Conversions.FromSnippet.ToMp4(input, output);
IConversionResult result = await conversion.Start();
Console.WriteLine(result.Arguments);The snippet probes the input, selects the first video and audio streams, and retargets them to H.264 and AAC in an MP4 container. Against a two-stream MKV input, the emitted command has this shape:
-i "movie.mkv" -c:v h264 -c:a aac -map 0:0 -map 0:1 -n "movie.mp4"Look at the -n. The snippet does not overwrite an existing output file, so running it a second time fails with a ConversionException until you delete or rename movie.mp4. That is a deliberate default for a snippet, and it is exactly the kind of behaviour that turns into a support question in a scheduled job that reruns on the same path. The result object also exposes the Arguments string, so you can log exactly what was run, which is the first thing you want when a conversion behaves differently on two machines.
The wider snippet list covers MP4, TS, WebM, OGV and GIF targets, audio extraction and addition, snapshots, splitting, concatenation, watermarks, M3U8 capture, and sending files to an RTSP server.
Three API levels for the same conversion object
The README frames the API as three levels, and advises picking the lowest one that expresses the operation. All of them return or build the same IConversion.
The first is a snippet, as above. The second is the stream builder, used when you need to select or change streams and codecs:
using System.Linq;
using Xabe.FFmpeg;
IMediaInfo mediaInfo = await FFmpeg.GetMediaInfo(input);
IVideoStream videoStream = mediaInfo.VideoStreams
.First()
.SetCodec(VideoCodec.h264)
.SetSize(VideoSize.Hd480);
IConversion conversion = FFmpeg.Conversions.New()
.AddStream(videoStream)
.SetOutput(output)
.SetOverwriteOutput(true);
await conversion.Start();Note that SetOverwriteOutput(true) is explicit here, in contrast to the snippet default. The stream interfaces IVideoStream, IAudioStream and ISubtitleStream are where the model lives, and they cover selecting, copying or reconfiguring individual streams including codec, bitrate, size, rotation and filters. Probing is available through FFmpeg.GetMediaInfo(...), which is backed by ffprobe, and through raw Probe access for custom ffprobe arguments.
The third level is raw parameters, for options the API does not model.
Custom parameters need a position because FFmpeg options are position sensitive
FFmpeg options are position-sensitive, which is the one piece of the command line that a naive wrapper gets wrong. The library handles it by requiring a ParameterPosition when you add an option: PreInput places the option before the input definition, and PostInput, which is the default, places it after.
using Xabe.FFmpeg;
IMediaInfo mediaInfo = await FFmpeg.GetMediaInfo(input);
IConversion conversion = FFmpeg.Conversions.New()
.AddStream(mediaInfo.Streams)
.AddParameter("-re", ParameterPosition.PreInput)
.AddParameter("-ss 00:00:01 -t 00:00:05")
.SetOutput(output)
.SetOverwriteOutput(true);
string arguments = conversion.Build(); // inspect before running
await conversion.Start();The example shows both halves in use. -re is an input option and is placed before the input, while the seek and duration options are given in a single AddParameter call and land after it, which is where they belong.
The Build() call is the other line worth noticing. Because the object is a description rather than a side effect, you can inspect the assembled argument string before starting the process. On top of that the library exposes OnProgress, OnDataReceived and OnVideoDataReceived, the last of them paired with PipeOutput for streaming video data, and UseHardwareAcceleration(...) for pass-through of cuvid, NVENC, QuickSync, VideoToolbox and VAAPI options without the wrapper needing to model each one.
Two releases on one day, and a licence GitHub cannot classify
The release history shows v6.1.0 tagged on 2026-09-23 and v6.1.1 the same day, three hours later, and the last push to the repository was on 2026-09-25. An older entry in the list is a release of executables, Zeranoe FFmpeg builds, dated 2020-09-06, which is a reminder that the project has been shipping binaries alongside the library for a long time.
The licence is the part that needs a decision rather than a glance. It is not one GitHub recognises, and the repository carries a LICENSE.md file rather than a recognised licence name, so any automated scanning of your dependencies will need a manual entry for this package. That is a fact about the packaging, not a judgement about the terms.
The repository itself is a Visual Studio solution named Xabe.FFmpeg.sln with src/ and test/ directories, an Assets folder, a .editorconfig and a .git-blame-ignore-revs file. There is also a SECURITY.md and a CONTRIBUTING.md at the top level, and the CI badge points at a workflow file in the repository's .github directory.
The dependency on external binaries is the thing to keep in mind when you look at the version numbers. The wrapper can be updated independently of FFmpeg itself, and the README's promise that everything the command line can do stays available is really a statement that the wrapper rarely needs to change.
Editorial conclusion
Adopt Xabe.FFmpeg if your C# application has to run FFmpeg and you want probe-based defaults, conversion snippets and a typed stream builder without giving up access to raw options. Do not adopt it if you need in-process native decoding or if your deployment cannot ship ffmpeg and ffprobe binaries, because the wrapper starts those executables and nothing else. Before you wire it in, decide how the binaries reach the machine, using FFmpeg.SetExecutablesPath or the Xabe.FFmpeg.Downloader package, and check the overwrite behaviour of the snippet you plan to use, since the -n flag makes a second run throw a ConversionException.
Frequently asked questions
Do I need to install FFmpeg separately to use Xabe.FFmpeg?
Yes, both the ffmpeg and ffprobe executables must be available, either from your platform's package manager or through the optional Xabe.FFmpeg.Downloader package, which fetches a build into a directory you choose.
How do I tell Xabe.FFmpeg where ffmpeg is installed?
Call FFmpeg.SetExecutablesPath with the directory holding the executables. Otherwise the library looks in the directory of your application's entry assembly and then in PATH, and throws an FFmpegNotFoundException naming the places it searched.
Why does my second conversion attempt fail with a ConversionException?
The conversion snippets do not overwrite an existing output file, so the emitted command includes -n. Delete or rename the output file, or build the conversion yourself and call SetOverwriteOutput(true).
How do I pass an option that Xabe.FFmpeg does not model?
Use AddParameter and give it a ParameterPosition, because FFmpeg options are position sensitive. PreInput places an option before the input definition and PostInput, the default, places it after.
Can I see the FFmpeg command before it runs?
Yes. Build the conversion object and call Build() to get the argument string, or read the Arguments property on the IConversionResult after the run.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/tomaszzmuda-xabe-ffmpeg)Was this useful?