FFmpegKit.Net.Full.Android 6.1.6.4

There is a newer version of this package available.
See the version list below for details.
dotnet add package FFmpegKit.Net.Full.Android --version 6.1.6.4
                    
NuGet\Install-Package FFmpegKit.Net.Full.Android -Version 6.1.6.4
                    
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="FFmpegKit.Net.Full.Android" Version="6.1.6.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FFmpegKit.Net.Full.Android" Version="6.1.6.4" />
                    
Directory.Packages.props
<PackageReference Include="FFmpegKit.Net.Full.Android" />
                    
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 FFmpegKit.Net.Full.Android --version 6.1.6.4
                    
#r "nuget: FFmpegKit.Net.Full.Android, 6.1.6.4"
                    
#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 FFmpegKit.Net.Full.Android@6.1.6.4
                    
#: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=FFmpegKit.Net.Full.Android&version=6.1.6.4
                    
Install as a Cake Addin
#tool nuget:?package=FFmpegKit.Net.Full.Android&version=6.1.6.4
                    
Install as a Cake Tool

FFmpegKit.Android

NuGet Bindings: MIT Packages: LGPL-3.0 or GPL-3.0

.NET for Android and .NET MAUI bindings for the native FFmpegKit library.

GitHub reports this repository as MIT because that is what it contains: binding source only, no native binaries. The published packages are not MIT — they embed native FFmpeg builds and are additionally covered by LGPL-3.0, or GPL-3.0 for the -gpl variants. See License.

Built against the prebuilt Android binaries from ffmpegkit-maintained/ffmpeg — see Where the native binaries come from for why that fork and not the original.

About

This repository contains .NET bindings (AndroidClassParser=class-parse) on top of the FFmpegKit .aar build for Android. One project, FFmpegKit.Android, produces all eight package variants — the variant is selected with the FFmpegKitBuildType MSBuild property.

Packages target net8.0-android34.0, net9.0-android35.0 and net10.0-android36.0.

Each .NET SDK's Android workload supports only two target frameworks — the .NET 9 band ships Microsoft.Android.Sdk.net8 and .net9, the .NET 10 band ships .net9 and .net10 — so no single dotnet pack can produce all three. BuildNugets.sh packs once per band and build/merge-packages.py merges the lib/ trees and nuspec dependency groups into one package per variant.

Where the native binaries come from

FFmpegKit has three relevant repositories, and only one of them still ships usable Android binaries:

Repository State Prebuilt .aar
arthenica/ffmpeg-kit archived none — the v5.1.LTS release assets were deleted; Maven Central stops at 6.0.LTS
arthenica/ffmpeg-kit-next active, the official continuation none — releases up to v8.1.0 carry source only, zero binary assets
ffmpegkit-maintained/ffmpeg active community fork yes — published to Maven Central as dev.ffmpegkit-maintained, currently 8.1.7

So the .aar files come from the community fork, via Maven Central — see FetchJars.sh. It keeps the original com.arthenica.ffmpegkit Java API, so the binding and its Ffmpegkit.Droid namespace are unaffected by the switch. Should ffmpeg-kit-next start publishing binaries, moving over would be a change to FetchJars.sh and FFmpegKitNativeVersion only.

The version is set by FFmpegKitNativeVersion in Directory.Build.props, which FetchJars.sh reads, so the download and the .aar the project expects cannot drift apart.

The fork currently publishes three lines, each with all eight variants:

FFmpegKit Bundled FFmpeg ABIs minSdk
6.0.3 n6.1.6 arm64-v8a, x86_64 24
7.1.6 n7.1.5 arm64-v8a, x86_64 24
8.1.7 n8.1.2 arm64-v8a, x86_64 24

FFmpegKit's version is not FFmpeg's. FFmpegKit 8.1.7 packages FFmpeg n8.1.2; the fork versions its own releases independently of the FFmpeg it pins. The bundled version above is read out of the shipped libavcodec.so, and every generated release note states it, because upstream's own notes mention other FFmpeg versions in passing and are easy to misread.

None of them ship 32-bit binaries, so dropping back to an older line does not restore armeabi-v7a or x86 support.

Releasing an older line

Tags name the FFmpeg version: v6.1.6.4 publishes 6.1.6.4 and builds against the FFmpegKit release that packages FFmpeg 6.1.6, looked up in build/native-versions.tsv. The fourth component is the binding revision and any prerelease suffix is ignored when resolving (v8.1.2.4-rc.1 → FFmpeg 8.1.2). A tag naming a version that is not in the mapping fails the release with the list of known builds, so an old-style tag like v8.1.7.4 cannot be published by mistake. No branch or Directory.Build.props edit is needed.

Locally, pass the native version as the second argument:

./FFmpegKit.Android/Jars/FetchJars.sh 6.0.3       # .aar files are named after the FFmpegKit release
./FFmpegKit.Android/BuildNugets.sh 6.1.6.4 6.0.3  # package version, FFmpegKit release

NuGet orders 8.1.2 above 6.1.6, so publishing an older line later does not change what dotnet add package resolves by default.

FFmpegKitConfig also needs the two smart-exception jars at runtime. They are not bundled in the .aar and not declared in its .pom, so they are fetched separately and embedded into the binding.

License

This section describes what the upstream project states. It is not legal advice — if the distinction matters for your product, get it reviewed.

The C# binding code in this repository is MIT. The published NuGet packages are not, because each one embeds native FFmpeg binaries built by ffmpegkit-maintained/ffmpeg, which carry their own copyleft terms. Each package therefore declares MIT AND <native license>:

Package Native license SPDX expression
FFmpegKit.Net.Audio.Android LGPL-3.0 MIT AND LGPL-3.0-only
FFmpegKit.Net.Full.Android LGPL-3.0 MIT AND LGPL-3.0-only
FFmpegKit.Net.Https.Android LGPL-3.0 MIT AND LGPL-3.0-only
FFmpegKit.Net.Min.Android LGPL-3.0 MIT AND LGPL-3.0-only
FFmpegKit.Net.Video.Android LGPL-3.0 MIT AND LGPL-3.0-only
FFmpegKit.Net.FullGpl.Android GPL-3.0 MIT AND GPL-3.0-only
FFmpegKit.Net.HttpsGpl.Android GPL-3.0 MIT AND GPL-3.0-only
FFmpegKit.Net.MinGpl.Android GPL-3.0 MIT AND GPL-3.0-only

The -gpl variants enable x264, x265, xvid and vidstab, which are GPL — upstream keeps them as separate artifacts specifically so they never contaminate the LGPL ones. Upstream's guidance is direct: if your app is closed-source, use a non-GPL variant.

Upstream states version 3.0 with no "or later" wording, hence the -only SPDX identifiers.

Every package ships the texts it is covered by under licenses/LICENSE (MIT, the bindings) and LGPL-3.0.txt or GPL-3.0.txt (the native binaries). The same texts are in this repository under licenses/. Per-dependency notices for the individual codecs (x264, dav1d, freetype, …) travel inside each .aar at res/raw/license_*.txt and end up in your app's resources.

Installation

Install the package via NuGet. There are various packages depending on what you plan to use and if you require a GPL compatible package or not. These package variants match the different variants built in the FFmpegKit repository. The -gpl variants are GPL-3.0 — see License before choosing one.

Package Link
FFmpegKit.Net.Audio.Android NuGet
FFmpegKit.Net.Full.Android NuGet
FFmpegKit.Net.FullGpl.Android NuGet
FFmpegKit.Net.Https.Android NuGet
FFmpegKit.Net.HttpsGpl.Android NuGet
FFmpegKit.Net.Min.Android NuGet
FFmpegKit.Net.MinGpl.Android NuGet
FFmpegKit.Net.Video.Android NuGet

Supported tracks

Three FFmpegKit lines are published in parallel, so you can pin to the FFmpeg generation your commands are validated against. All three are built from the same bindings and carry the same target frameworks, ABIs and licensing — only the native FFmpeg build differs. The badges above show the newest version overall, which is always the 8.x one.

Track FFmpeg From FFmpegKit Install
8.* (recommended) n8.1.2 8.1.7 dotnet add package FFmpegKit.Net.Video.Android --version "8.*"
7.* n7.1.5 7.1.6 dotnet add package FFmpegKit.Net.Video.Android --version "7.*"
6.* n6.1.6 6.0.3 dotnet add package FFmpegKit.Net.Video.Android --version "6.*"

A package version is <FFmpeg version>.<binding revision>8.1.2.4 is FFmpeg 8.1.2, binding revision 4. It deliberately names FFmpeg rather than FFmpegKit, because FFmpegKit's own release numbers do not track FFmpeg: FFmpegKit 8.1.7 packages FFmpeg n8.1.2. build/native-versions.tsv maps between the two and is what the release workflow uses to turn a tag into the .aar to download.

A floating range therefore always resolves to the newest bindings for that FFmpeg line and never crosses into another one, which is what makes 8.* safe to leave in a project file. Pin an exact version instead if you would rather approve every binding update yourself.

Versions up to 8.1.7.3, 7.1.6.3 and 6.0.3.3 used the older FFmpegKit-based numbering and are unlisted. 8.1.2.4 is not a downgrade from 8.1.7.3 — it is the same build, renamed to state the FFmpeg it contains.

Substitute any variant from the table above for Video. Every track ships arm64-v8a and x86_64 at minSdkVersion 24, so choosing an older one is not a way to regain 32-bit support — see Where the native binaries come from.

For what changed in each, see the release notes.

Migrating from Xamarin.FFmpegKit.*

These packages replace the Xamarin.FFmpegKit.*.Android ones, which are no longer published. Change the package id and nothing else:

-<PackageReference Include="Xamarin.FFmpegKit.Video.Android" Version="4.5.1" />
+<PackageReference Include="FFmpegKit.Net.Video.Android" Version="8.1.7" />

The Ffmpegkit.Droid namespace is unchanged, so your using directives and calls stay as they are. It deliberately does not follow the package name: a namespace rooted at FFmpegKit containing a type also called FFmpegKit makes FFmpegKit.Execute(...) resolve the namespace instead of the class and fail to compile.

The assembly is now FFmpegKit.Net.<Variant>.Android (was FFmpegKit.<Variant>.Android), which matters only if you reference it by assembly name or use reflection.

Note that the native library also moved on from the archived arthenica builds — see Where the native binaries come from — so upgrading from 4.5.1 is a jump from FFmpegKit 4.5 to 8.1.7, not just a repackaging.

Usage

Include Ffmpegkit.Droid namespace

using Ffmpegkit.Droid;

Execute your FFmpeg command

FFmpegKit.Execute("-i input.mov -c:v libx264 output.mp4");

More examples and usage can be found in the original FFmpegKit wiki. That repository is archived, but the Java API it documents is the one these bindings expose, so it remains the reference.

Beyond the generated binding

The binding is a faithful projection of FFmpegKit's Java API, which is not always what you want from C#. These packages add a thin layer on top of it, in the Ffmpegkit.Droid namespace alongside everything else.

Await a command instead of blocking. FFmpegKit.Execute blocks for the length of the transcode, which on the UI thread means a frozen app:

var session = await FFmpegKit.ExecuteAsync("-i in.mov -c:v mpeg4 out.mp4", cancellationToken);
if (session.Succeeded()) { /* ... */ }

A failing command completes normally with a non-success ReturnCode rather than throwing, matching FFmpeg's own semantics. Cancelling asks FFmpeg to stop and the session completes with a cancelled code — a partial output file may exist.

Report progress. Supply the source duration and you get a percentage and an estimate:

var duration = (await FFprobeKit.GetMediaInformationAsync(input)).MediaInformation?.DurationOrNull;

await FFmpegKit.ExecuteAsync(command, new Progress<FFmpegProgress>(p =>
{
    ProgressBar.Progress = p.Percent ?? 0;   // null when no duration was supplied
}), duration);

Progress arrives on an FFmpegKit worker thread; Progress<T> marshals it back to the thread that created it.

Read media information without parsing strings. FFprobe reports numbers as invariant-format strings and sizes as boxed Java Longs. Parsing them yourself is a live bug: double.Parse("12.345000") returns 12,345,000 under a German locale and throws under a French one. The typed accessors parse invariantly and return null rather than throwing when a field is absent:

info.DurationOrNull      // TimeSpan?      (vs. Duration, a string)
info.BitrateBps          // long?
info.SizeBytes           // long?
info.TagValues           // IReadOnlyDictionary<string, string>  (vs. Tags, a Java JSONObject)

stream.PixelWidth        // int?           (vs. Width, a Java.Lang.Long)
stream.AverageFrameRateFps  // double?     evaluates "30000/1001"
stream.IsVideo / IsAudio

Pass a lambda where an interface is expected, for the log and statistics hooks:

FFmpegKitConfig.EnableLogCallback(log => Debug.WriteLine(log.Message));

Use managed enums. SessionState and Level are Java enums, so they cannot be used in a switch, and comparing them with == compares managed peer references rather than the underlying constants. ToManaged() converts at the boundary.

Working with user-picked files

On Android 10 and later a file the user picks arrives as a content:// URI, and FFmpeg cannot open one. Register it first:

var input = FFmpegKitConfig.GetSafParameterForRead(pickedUri);
await FFmpegKit.ExecuteAsync($"-i {input} -c:v mpeg4 \"{output}\"");

The returned value is a complete argument — do not wrap it in quotes. GetSafParameterForWrite does the same for output, but the document has to exist already, so create it with ACTION_CREATE_DOCUMENT first. Registrations last for the life of the process, so obtain them per operation rather than for every item in a long list.

MAUI's FilePicker copies the picked file into the cache and hands back a real path, so it needs none of this; SAF matters when you hold the raw URI, such as from a share intent or the photo picker.

Session history

FFmpegKit keeps every session in memory, each holding its full log output, up to FFmpegKitConfig.SessionHistorySize. An app running many conversions will accumulate them with no obvious cause. Call FFmpegKitConfig.ClearSessions() when you are done with a batch, or lower the history size.

Building

Prerequisites

The .NET 8, 9 and 10 SDKs, each with the Android workload installed — every band supplies a different reference pack (Ref.34, Ref.35, Ref.36). The SDK is chosen by the global.json in the working directory, so install each band from a directory pinned to it:

for major in 8 9 10; do
  dir=$(mktemp -d) && cd "$dir"
  dotnet new globaljson --sdk-version "$(dotnet --list-sdks | grep "^${major}\." | tail -1 | cut -d' ' -f1)" --force
  dotnet workload install android
done

Python 3 is also needed, for the package merge step.

All variants

./FFmpegKit.Android/Jars/FetchJars.sh          # downloads the .aar/.jar files
./FFmpegKit.Android/BuildNugets.sh             # packs all 8 variants into ./artifacts
./FFmpegKit.Android/BuildNugets.sh 8.1.7-rc.1  # ...or with an explicit package version

FetchJars.sh reads the FFmpegKit version from FFmpegKitNativeVersion in Directory.Build.props, the same property the .csproj uses to pick the .aar, so the two cannot drift apart. Pass a version to override it (./FetchJars.sh 8.2.0) when trying a newer upstream build before committing to it.

A single variant

# net8 + net9 assets (.NET 9 SDK, per global.json)
dotnet pack FFmpegKit.Android/FFmpegKit.Android.csproj \
    -c Release -p:FFmpegKitBuildType=Video -p:FFmpegKitSdkBand=net9 -o artifacts

FFmpegKitBuildType is one of Audio, Full, FullGpl, Https, HttpsGpl, Min, MinGpl, Video. FFmpegKitSdkBand is net9 or net10 and must match the SDK actually running the build. Each variant builds into its own obj/ and bin/ subdirectory, so they can be built in sequence without interfering with each other.

Tests

Package tests run anywhere and inspect the packed .nupkg files — assembly present for both target frameworks, correct .aar for the variant, bound API surface, embedded smart-exception classes, nuspec metadata:

dotnet test tests/FFmpegKit.Android.PackageTests
FFMPEGKIT_VARIANTS=Video dotnet test tests/FFmpegKit.Android.PackageTests  # only what you packed

Device tests install the packed package into a small app and run real FFmpeg commands on a device or emulator (encode raw frames to mp4, probe the result, check failure reporting). They consume the package from ./artifacts via the local feed in NuGet.config, so they exercise exactly what gets published:

# builds, installs, runs and reports - the same script CI uses
FFMPEGKIT_DEVICE_RID=android-arm64 \
    ./.github/scripts/run-device-tests.sh Video 8.1.7 net10.0-android36.0

Arguments are the variant, the package version in ./artifacts, and which of the package's target frameworks to exercise. The emulator must be x86_64 or arm64-v8a; the .aar ships no other ABIs.

Example app

FFmpegKit.Android.Example is a small .NET MAUI app that runs real conversions against the package you just built — resize, grayscale and audio extraction — with a before/after video preview.

./FFmpegKit.Android/BuildNugets.sh                    # produce ./artifacts first
dotnet build FFmpegKit.Android.Example -t:Install     # deploy to a running device/emulator

It resolves FFmpegKit.Net.Full.Android from ./artifacts through the local feed in NuGet.config, not from nuget.org, so it always exercises your local build. The version defaults to FFmpegKitNativeVersion; pass -p:FFmpegKitVersion=8.1.7-rc.1 to point it at a specific build.

It references the Full (LGPL) variant deliberately — swapping to a -gpl one would make the sample itself GPL-3.0.

The sample targets API 26 rather than the package's own floor of 24, because it previews results with CommunityToolkit's MediaElement, which requires 26. Your own app can still target 24.

The app is intentionally not part of FFmpegKit.sln and not built in CI: it needs the MAUI workload, which would add several minutes to every run while proving less than the device tests already do.

CI

Workflow Trigger What it does
pr.yml pull request Builds and packs all 8 variants as <version>-beta.<pr>.<run>, runs package tests and the emulator smoke test, then publishes the betas to nuget.org. Forked PRs build and test but skip publishing, since they cannot read secrets.
release.yml tag v* Same build and tests at the tag's version, publishes to nuget.org, then creates a GitHub release with the changelog since the previous tag and links to every package.

Both call the reusable build.yml.

Publishing credentials

Publishing uses nuget.org Trusted Publishing — no long-lived API key. Each publish job requests a GitHub OIDC token (id-token: write), exchanges it via NuGet/login@v1 for an API key valid for one hour, and pushes with that.

Setup on nuget.org (Account → Trusted Publishing): a policy binds to exactly one workflow file, so this repository needs two, identical apart from the workflow file name:

Field Value
Package Owner s.bokatuk
Repository Owner sbokatuk
Repository FFmpegKit.Android — the name only, not a URL
Workflow File pr.yml for one policy, release.yml for the other
Environment nuget.org — must match environment: on the publish job exactly

No repository secrets are required. The workflows pass the nuget.org profile name (s.bokatuk, not an email address) to NuGet/login, defaulted inline since it is already public as the package author. Set a NUGET_USER secret to override it if the owner ever changes.

Policies created against a private repository start out active for 7 days only; they become permanent after the first successful publish, which supplies the repository and owner IDs that lock the policy down.

Note that prereleases pushed to nuget.org cannot be deleted, only unlisted — every pull request push publishes eight packages.

Product Compatible and additional computed target framework versions.
.NET net8.0-android34.0 is compatible.  net9.0-android was computed.  net9.0-android35.0 is compatible.  net10.0-android was computed.  net10.0-android36.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0-android36.0

    • No dependencies.
  • net8.0-android34.0

    • No dependencies.
  • net9.0-android35.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on FFmpegKit.Net.Full.Android:

Package Downloads
FFmpegKit.Net.Full

One API over the FFmpegKit bindings for Android, iOS and macOS: run FFmpeg/FFprobe commands with awaitable calls, typed media information, progress reporting, failure output on the result and an injectable IFFmpegKit, instead of writing a per-platform adapter over Ffmpegkit.Droid, Ffmpegkit.Ios and Ffmpegkit.Mac by hand. Pulls in the platform binding that matches whichever target framework you build. For .NET MAUI apps, FFmpegKit.Net.Maui adds the app-builder wiring.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
8.1.2.5 144 7/24/2026
8.1.2.4 115 7/22/2026
8.1.2-beta.19.29 25 7/30/2026
8.1.2-beta.19.28 33 7/30/2026
8.1.2-beta.19.27 31 7/30/2026
8.1.2-beta.18.26 38 7/30/2026
8.1.2-beta.17.25 27 7/29/2026
8.1.2-beta.16.24 32 7/28/2026
8.1.2-beta.16.23 32 7/28/2026
8.1.2-beta.15.22 44 7/26/2026
8.1.2-beta.14.20 47 7/24/2026
8.1.2-beta.13.19 57 7/24/2026
8.1.2-beta.13.18 47 7/24/2026
8.1.2-beta.13.17 44 7/24/2026
8.1.2-beta.13.16 57 7/24/2026
8.1.2-beta.12.15 58 7/23/2026
8.1.2-beta.11.14 48 7/22/2026
8.1.2-beta.10.13 44 7/22/2026
7.1.5.4 88 7/22/2026
6.1.6.4 88 7/22/2026
Loading failed