Skip to content

Using FFmpegKitNext in Unity

Taner Sener edited this page Jul 15, 2026 · 2 revisions

FFmpegKitNext does not provide a dedicated Unity package or C# wrapper. Use the native Android and Apple libraries from a local FFmpegKitNext build, then call them from Unity through platform interop.

The examples below show the minimal synchronous path. For long-running commands, avoid blocking Unity's main thread; use the async FFmpegKit APIs through a platform bridge or call the synchronous wrapper from a worker thread.

1. Android

Build the Android AAR locally first. Nix is the recommended build entry point:

./nix-android.sh -p android-r27d

Calling the direct Android script is also supported when you provide the required Android SDK, NDK, CMake, Java/Kotlin and host tools yourself:

./scripts/start-android.sh

Add any FFmpeg features you need at build time, for example:

./nix-android.sh -p android-r27d --enable-freetype --enable-harfbuzz --enable-fontconfig
./scripts/start-android.sh --enable-freetype --enable-harfbuzz --enable-fontconfig

The build creates a local Maven repository under:

prebuilt/bundle-android-aar-24-maven/

The AAR is published inside that local repository as:

com.arthenica:ffmpeg-kit-next:<version>

FFmpegKitNext for Android supports API Level 24 or later. Set the Unity Android minimum API level to 24 or higher, unless you intentionally built with a higher --api-level.

1.1 Integrate the AAR

Prefer Gradle/Maven integration because it resolves smart-exception-java, the runtime dependency declared by the local POM.

Enable a custom Gradle template in Unity, then add the local Maven repository and dependency to the Gradle file that resolves app dependencies. Depending on the Unity version, this may be mainTemplate.gradle, launcherTemplate.gradle, baseProjectTemplate.gradle or a settings-level repository template.

repositories {
    maven { url "<ffmpeg-kit-next>/prebuilt/bundle-android-aar-24-maven" }
    mavenCentral()
}

dependencies {
    implementation "com.arthenica:ffmpeg-kit-next:<version>"
}

If you copy the generated ffmpeg-kit-next-<version>.aar directly into Assets/Plugins/Android, make sure smart-exception-java:0.2.1 and its transitive dependencies are also available to the Unity Android build. Copying only the AAR can fail at runtime with missing smart-exception classes.

1.2 Call FFmpegKit from C#

Disable SIGXCPU handling before the first execution. This is required by Mono-based runtimes such as Unity.

using UnityEngine;

public static class FFmpegKitAndroid
{
#if UNITY_ANDROID && !UNITY_EDITOR
    public static void IgnoreSigxcpu()
    {
        using (var configClass = new AndroidJavaClass("com.arthenica.ffmpegkit.FFmpegKitConfig"))
        using (var signalClass = new AndroidJavaClass("com.arthenica.ffmpegkit.Signal"))
        {
            AndroidJavaObject sigxcpu = signalClass.GetStatic<AndroidJavaObject>("SIGXCPU");
            configClass.CallStatic("ignoreSignal", sigxcpu);
        }
    }

    public static int Execute(string command)
    {
        using (var ffmpegKit = new AndroidJavaClass("com.arthenica.ffmpegkit.FFmpegKit"))
        using (AndroidJavaObject session = ffmpegKit.CallStatic<AndroidJavaObject>("execute", command))
        using (AndroidJavaObject returnCode = session.Call<AndroidJavaObject>("getReturnCode"))
        {
            return returnCode == null ? -1 : returnCode.Call<int>("getValue");
        }
    }
#endif
}

Example usage:

#if UNITY_ANDROID && !UNITY_EDITOR
FFmpegKitAndroid.IgnoreSigxcpu();
int rc = FFmpegKitAndroid.Execute("-version");
Debug.Log("FFmpegKit return code: " + rc);
#endif

For generated commands or paths that may contain spaces, prefer FFmpegKit's argument-array APIs through executeWithArguments instead of building one large command string.

2. iOS, iPadOS, tvOS and visionOS

Build Apple artifacts locally first. Nix is the recommended entry point:

./nix-ios.sh -p xcode26 -x
./nix-tvos.sh -p xcode26 -x
./nix-visionos.sh -p xcode26 -x

Calling the direct scripts is also supported when you provide Xcode, command line tools and the required host build tools yourself:

./scripts/start-ios.sh -x
./scripts/start-tvos.sh -x
./scripts/start-visionos.sh -x

Add any FFmpeg features you need at build time:

./nix-ios.sh -p xcode26 -x --enable-freetype --enable-harfbuzz --enable-fontconfig
./scripts/start-ios.sh -x --enable-freetype --enable-harfbuzz --enable-fontconfig

Unity's iOS build target covers both iPhone and iPad devices. There is no separate FFmpegKitNext build script for iPadOS; use the iOS artifacts for iPadOS.

The generated Apple outputs are under prebuilt, for example:

prebuilt/bundle-apple-xcframework-ios-12.1/
prebuilt/bundle-apple-xcframework-tvos-11.0/
prebuilt/bundle-apple-xcframework-visionos-1.0/

Import ffmpegkit.xcframework and every generated FFmpeg xcframework it depends on, such as libavcodec.xcframework, libavformat.xcframework, libavutil.xcframework, libavfilter.xcframework, libavdevice.xcframework, libswresample.xcframework and libswscale.xcframework. Link every generated external-library framework as well when your build enables optional libraries.

Set Unity's Apple deployment targets to at least:

  • iOS and iPadOS: 12.1
  • tvOS: 11.0
  • visionOS: 1.0

2.1 Add a native Unity bridge

Unity C# cannot call Objective-C methods directly. Add a small Objective-C++ bridge file, for example Assets/Plugins/iOS/FFmpegKitUnityBridge.mm, and expose C-callable functions. For tvOS or visionOS builds, place the bridge file and plugin import settings where Unity includes native source files for that target.

#import <ffmpegkit/FFmpegKit.h>
#import <ffmpegkit/FFmpegKitConfig.h>
#import <ffmpegkit/ReturnCode.h>

extern "C" {

void FFmpegKitUnityIgnoreSIGXCPU(void) {
    [FFmpegKitConfig ignoreSignal:SignalXcpu];
}

int FFmpegKitUnityExecute(const char *command) {
    @autoreleasepool {
        NSString *commandString = command == NULL ? @"" : [NSString stringWithUTF8String:command];
        FFmpegSession *session = [FFmpegKit execute:commandString];
        ReturnCode *returnCode = [session getReturnCode];

        return returnCode == nil ? -1 : [returnCode getValue];
    }
}

}

Call that bridge from C#:

using System.Runtime.InteropServices;
using UnityEngine;

public static class FFmpegKitApple
{
#if (UNITY_IOS || UNITY_TVOS) && !UNITY_EDITOR
    [DllImport("__Internal")]
    private static extern void FFmpegKitUnityIgnoreSIGXCPU();

    [DllImport("__Internal")]
    private static extern int FFmpegKitUnityExecute(string command);

    public static void IgnoreSigxcpu()
    {
        FFmpegKitUnityIgnoreSIGXCPU();
    }

    public static int Execute(string command)
    {
        return FFmpegKitUnityExecute(command);
    }
#endif
}

Example usage:

#if (UNITY_IOS || UNITY_TVOS) && !UNITY_EDITOR
FFmpegKitApple.IgnoreSigxcpu();
int rc = FFmpegKitApple.Execute("-version");
Debug.Log("FFmpegKit return code: " + rc);
#endif

For asynchronous execution, expose a separate native bridge around executeAsync and send completion/log/statistics events back to Unity, for example with UnitySendMessage.

3. Notes

  • FFmpegKit.execute() parses command strings by spaces and quote characters. For paths or filter values generated at runtime, prefer argument arrays
  • If Android packaging reports duplicate libc++_shared.so files, resolve it in the Unity Gradle template with Android Gradle Plugin packaging options
  • Check build.log in the FFmpegKitNext project root when a local native build fails

Clone this wiki locally