-
Notifications
You must be signed in to change notification settings - Fork 25
Tips
FFmpegKit.execute(), FFmpegKit.executeAsync(), FFprobeKit.execute() and FFprobeKit.executeAsync() accept a single command string. FFmpegKitNext parses that string with FFmpegKitConfig.parseArguments(): spaces split arguments, and single or double quotes keep a value together.
This works when you quote paths or filter expressions correctly.
FFmpegKit.execute("-i '/storage/emulated/0/My Videos/input file.mp4' -c:v mpeg4 '/storage/emulated/0/My Videos/output file.mp4'");For generated commands, user-selected file names, filter graphs, JSON values or any value that may contain quotes or spaces, prefer the argument-array APIs. They avoid command-string quoting mistakes.
FFmpegKit.executeWithArguments(new String[] {
"-i", inputPath,
"-c:v", "mpeg4",
outputPath
});await FFmpegKit.executeWithArguments([
'-i', inputPath,
'-c:v', 'mpeg4',
outputPath,
]);Do not put shell syntax such as pipes, redirects, command substitution or environment assignments into an execute() command string. FFmpegKitNext passes arguments to FFmpeg/FFprobe; it does not run the command through a shell.
FFmpegKitNext does not publish ready-to-use packages to Maven Central, CocoaPods, pub.dev or npm. Build the native artifacts locally, then integrate the generated files from prebuilt.
For a native Android app, consume the local Maven repository produced by the Android build. Match the path to the API level you built.
repositories {
maven { url "<ffmpeg-kit-next>/prebuilt/bundle-android-aar-24-maven" }
// Resolves transitive dependencies declared by the local POM.
mavenCentral()
}
dependencies {
implementation "com.arthenica:ffmpeg-kit-next:<version>"
}For Apple platforms, use the generated frameworks, xcframeworks or local Swift package from prebuilt. There are no hosted CocoaPods packages to install.
ffmpeg_kit_next_flutter is not published to pub.dev. Use a local path dependency after building and copying the native binaries into the plugin.
dependencies:
ffmpeg_kit_next_flutter:
path: ../ffmpeg-kit-next/flutter/flutterFlutter Android also needs the plugin's local Maven repository in your Flutter app's project-level android/build.gradle.
allprojects {
repositories {
google()
mavenCentral()
def ffmpegKitProject = rootProject.findProject(":ffmpeg_kit_next_flutter")
if (ffmpegKitProject != null) {
maven {
url "${ffmpegKitProject.projectDir}/libs-maven"
}
}
}
}ffmpeg-kit-next-react-native is not published to npm. Use a local file dependency.
yarn add file:../ffmpeg-kit-next/react-nativeor:
npm install ../ffmpeg-kit-next/react-nativeReact Native Android also needs the plugin's local Maven repository in your app's android/build.gradle.
allprojects {
repositories {
def ffmpegKitProject = rootProject.findProject(":ffmpeg-kit-next-react-native")
if (ffmpegKitProject != null) {
maven {
url "${ffmpegKitProject.projectDir}/libs-maven"
}
}
}
}On iOS, iPadOS and macOS, Flutter and React Native use the local plugin podspecs and copied local frameworks. They do not need an extra Maven-style repository step.
Filters, encoders, decoders, protocols and external-library-backed formats are decided when FFmpegKitNext is built. Application code cannot enable a missing FFmpeg feature at runtime.
Use --enable-<library> options or --full while building. Use --enable-gpl when you intentionally enable GPL-licensed libraries.
Nix wrappers are the recommended entry points because they provide the build environment:
./nix-android.sh -p android-r27d --enable-libass --enable-freetype --enable-fontconfig
./nix-ios.sh -p xcode26 --enable-libass --enable-freetype --enable-fontconfigCalling the direct platform scripts is still supported when you provide the required SDK, toolchain and host tools yourself:
./scripts/start-android.sh --enable-libass --enable-freetype --enable-fontconfig
./scripts/start-ios.sh --enable-libass --enable-freetype --enable-fontconfigLinux built-in feature options use linux- names, for example:
./nix-linux.sh -p linux-x86_64-glibc-2_40 --enable-linux-libass --enable-linux-freetype --enable-linux-fontconfigAt runtime, check what your binary actually contains with Packages.getExternalLibraries() rather than assuming a package variant.
Log.d(TAG, Packages.getExternalLibraries().toString());final libraries = await Packages.getExternalLibraries();The subtitles filter depends on libass. Build with --enable-libass when you want to burn subtitle files into video. In the build scripts, enabling libass also enables the font-related dependencies it needs, including fontconfig, freetype, fribidi and harfbuzz.
Android does not provide a default fontconfig setup for applications. If fonts are not registered, subtitle rendering may fail or may complete without drawing the expected text. Register system fonts and any custom font directory before running the command.
FFmpegKitConfig.setFontDirectoryList(
context,
Arrays.asList("/system/fonts", customFontDirectory),
Collections.emptyMap()
);If a subtitle file requests a font family that is not present on the device, either include that font with your app or provide a font-name mapping in the third argument of setFontDirectory() or setFontDirectoryList().
If a command fails with:
No such filter: 'drawtext'
your FFmpeg binary was built without the libraries required by the drawtext filter. Rebuild with freetype and harfbuzz enabled.
./nix-android.sh -p android-r27d --enable-freetype --enable-harfbuzz
./scripts/start-android.sh --enable-freetype --enable-harfbuzzIf the filter exists but font family lookup fails with an error like:
Cannot find a valid font for the family Sans
Error initializing filter 'drawtext'
then enable fontconfig in the build and register a font directory with FFmpegKitConfig.setFontDirectory() or FFmpegKitConfig.setFontDirectoryList().
You can also use an explicit font file when that is simpler. This still requires freetype and harfbuzz, but it avoids font-family lookup.
-vf "drawtext=fontfile=/system/fonts/Roboto-Regular.ttf:text='Hello world':x=10:y=10"
On Android, system fonts are usually under:
/system/fonts
On Apple platforms, system fonts are commonly under:
/System/Library/Fonts
/System/Library/Fonts/Cache
On macOS, application sandboxing and file permissions may affect access to additional locations such as /Library/Fonts or ~/Library/Fonts. For bundled app fonts, register the directory inside your application bundle instead of relying on user font folders.
Examples:
[FFmpegKitConfig setFontDirectoryList:@[
@"/System/Library/Fonts",
@"/System/Library/Fonts/Cache"
] with:@{}];FFmpegKitConfig::setFontDirectoryList(
std::list<std::string>{"/usr/share/fonts"},
std::map<std::string, std::string>()
);The font directory helpers require a build with fontconfig support. They generate a temporary fonts.conf file, include a cachedir entry for Fontconfig cache files, and set FONTCONFIG_PATH for the native FFmpeg process.
Android document picker Uris are content:// Uris, not normal file paths. Convert them to ffkitsaf: URLs before passing them to FFmpegKit or FFprobeKit.
String safUrl = FFmpegKitConfig.getSafParameterForRead(context, uri, true);
FFmpegKit.executeAsync(String.format("-i %s -c:v mpeg4 file2.mp4", safUrl), session -> {
FFmpegKitConfig.unregisterSafProtocolUrl(safUrl);
});For output files created with ACTION_CREATE_DOCUMENT, use getSafParameterForWrite().
String safUrl = FFmpegKitConfig.getSafParameterForWrite(context, uri);
FFmpegKit.executeAsync(String.format("-i file1.mp4 -c:v mpeg4 %s", safUrl));By default, a generated SAF URL is single-use and is released automatically when the file is closed. Pass reusable=true only when you need to use the same URL in more than one command, and then release it manually with unregisterSafProtocolUrl().
Flutter and React Native expose the same SAF helpers, but they are Android-only. Calling them on other platforms fails.
FFmpegKitNext adds custom protocols on top of FFmpeg:
- Android:
ffkitsaf:,ffkitmem:andffkitstream: - Apple, Linux and Web:
ffkitmem:andffkitstream:
The build option --no-ffmpeg-kit-protocols disables these protocols. If a command fails with a protocol error for ffkitsaf, ffkitmem or ffkitstream, make sure your binary was not built with --no-ffmpeg-kit-protocols.
The Android AAR contains native libraries that may include libc++_shared.so. If another dependency also packages it, Gradle can fail with an error similar to:
More than one file was found with OS independent path 'lib/x86/libc++_shared.so'
With recent Android Gradle Plugin versions, use the packaging.jniLibs.pickFirsts DSL:
android {
packaging {
jniLibs {
pickFirsts += [
"lib/armeabi-v7a/libc++_shared.so",
"lib/arm64-v8a/libc++_shared.so",
"lib/x86/libc++_shared.so",
"lib/x86_64/libc++_shared.so"
]
}
}
}Older projects may still use:
android {
packagingOptions {
pickFirst "lib/armeabi-v7a/libc++_shared.so"
pickFirst "lib/arm64-v8a/libc++_shared.so"
pickFirst "lib/x86/libc++_shared.so"
pickFirst "lib/x86_64/libc++_shared.so"
}
}This resolves the packaging conflict only. It does not prove that all native dependencies were built against compatible C++ runtime expectations, so test every ABI you ship.
Current FFmpegKitNext Apple artifacts support these minimum deployment targets:
- iOS and iPadOS:
12.1 - macOS:
10.15 - tvOS:
11.0 - visionOS:
1.0
If an application target is lower than the local artifact or plugin podspec, CocoaPods, Swift Package Manager or Xcode can fail with a higher-minimum-deployment-target error. Raise the app target to at least the supported value.
For Flutter or CocoaPods-based iOS apps:
platform :ios, '12.1'For macOS CocoaPods targets:
platform :osx, '10.15'When building your own Apple artifacts, you can override deployment target values with script options such as --target and --mac-catalyst-target, but do not go below the supported platform floor.
./nix-ios.sh -p xcode26 --target=12.1 --mac-catalyst-target=12.1
./nix-macos.sh -p xcode26 --target=10.15
./nix-tvos.sh -p xcode26 --target=11.0
./nix-visionos.sh -p xcode26 --target=1.0Xcode can optimize PNG files that are included in an application bundle. In some cases, the optimized resource cannot be decoded by FFmpeg's libpng support and the command fails with:
Error while decoding stream #0:0: Generic error in an external library
If this happens for PNG files bundled with the app, open the app target's Build Settings in Xcode and disable these Packaging settings:
Compress PNG FilesRemove Text Metadata From PNG Files
These settings may be hidden until the target contains at least one .png file. This tip applies to resources processed by Xcode in the app bundle, not to arbitrary PNG files downloaded or created at runtime.
Mono-based frameworks such as Unity and Xamarin may need SIGXCPU handling disabled inside FFmpegKitNext.
Android:
FFmpegKitConfig.ignoreSignal(Signal.SIGXCPU);Apple:
[FFmpegKitConfig ignoreSignal:SIGXCPU];Flutter:
await FFmpegKitConfig.ignoreSignal(Signal.sigXCpu);React Native:
await FFmpegKitConfig.ignoreSignal(Signal.SIGXCPU);Current Android build scripts enable pthreads for FFmpeg. Therefore, this old message should not appear with a current Android binary built by the provided scripts:
'circular_buffer_size' option was set but it is not supported on this build (pthread support is required)
If you see it, you are likely running an old or custom FFmpeg binary built without pthread support. Rebuild from current FFmpegKitNext sources. For RTSP streams, you can also force TCP transport when UDP is unreliable or blocked by the network:
-rtsp_transport tcp
Log and statistics redirection is enabled by default. With redirection enabled, sessions collect logs/statistics and callbacks work.
FFmpegKitConfig.disableRedirection() has broader side effects: logs are printed to stderr, log/statistics callbacks are disabled, and FFprobe media information helpers do not work. Use it only when you intentionally want those behavior changes.
If you only want quieter output, keep redirection enabled and either lower FFmpeg's log level:
-loglevel error
or change the log redirection strategy. For example, on Android:
FFmpegKitConfig.setLogRedirectionStrategy(LogRedirectionStrategy.NEVER_PRINT_LOGS);The equivalent enum names are LogRedirectionStrategyNeverPrintLogs on Apple, LogRedirectionStrategy.neverPrintLogs on Flutter and LogRedirectionStrategy.NEVER_PRINT_LOGS on React Native.
The console often shows only the high-level failing step. The detailed configure, compiler, linker and pkg-config output is written to build.log in the project root. When an external library fails to build or FFmpeg says a library was not found, inspect build.log before changing build options.
Copyright (c) 2026 FFmpegKitNext
- Status
- Versions
- Changelog
- Project Layout
- Using
- Building
- External Libraries
- Patents
- License