FFmpeg for Android, iOS and tvOS. Not maintained anymore. Superseded by FFmpegKit.
FFmpeg for Android, iOS and tvOS. Not maintained anymore. Superseded by FFmpegKit.
FFmpeg
and FFprobe
v3.4.x
, v4.0.x
, v4.1
, v4.2
, v4.3
and v4.4-dev
releasesGithub
/Maven Central
/CocoaPods
or build your own version with external libraries you needIncludes cross-compile instructions for 47 open-source libraries
chromaprint
, expat
, ffmpeg
, fontconfig
, freetype
, fribidi
, giflib
, gmp
, gnutls
, kvazaar
, lame
, leptonica
, libaom
, libass
, libiconv
, libilbc
, libjpeg
, libjpeg-turbo
, libogg
, libpng
, libsamplerate
, libsndfile
, libtheora
, libuuid
, libvorbis
, libvpx
, libwebp
, libxml2
, nettle
, opencore-amr
, openh264
, opus
, rubberband
, sdl
, shine
, snappy
, soxr
, speex
, tesseract
, tiff
, twolame
, vid.stab
, vo-amrwbenc
, wavpack
, x264
, x265
, xvidcore
API Level 16+
on Androidarm-v7a
, arm-v7a-neon
, arm64-v8a
, x86
and x86_64
Android architectureszlib
and MediaCodec
Android system librariesiOS SDK 9.3
or laterarmv7
, armv7s
, arm64
, arm64e
, i386
, x86_64
and x86_64
(Mac Catalyst) iOS architecturesbzip2
, iconv
, libuuid
, zlib
iOS system libraries and AudioToolbox
, VideoToolbox
, AVFoundation
iOS system frameworkstvOS SDK 9.2
or laterarm64
and x86_64
tvOS architecturesbzip2
, iconv
, libuuid
, zlib
tvOS system libraries and AudioToolbox
, VideoToolbox
tvOS system frameworksARC
enabled iOS libraryBinaries are available at Github, Maven Central and CocoaPods.
There are eight different prebuilt packages. Below you can see which external libraries are enabled in each of them.
Please remember that some parts of FFmpeg
are licensed under the GPL
and only GPL
licensed mobile-ffmpeg
packages include them.
min | min-gpl | https | https-gpl | audio | video | full | full-gpl |
---|---|---|---|---|---|---|---|
- | vid.stab x264 x265 xvidcore |
gmp gnutls |
gmp gnutls vid.stab x264 x265 xvidcore |
lame libilbc libvorbis opencore-amr opus shine soxr speex twolame vo-amrwbenc wavpack |
fontconfig freetype fribidi kvazaar libaom libass libiconv libtheora libvpx libwebp snappy |
fontconfig freetype fribidi gmp gnutls kvazaar lame libaom libass libiconv libilbc libtheora libvorbis libvpx libwebp libxml2 opencore-amr opus shine snappy soxr speex twolame vo-amrwbenc wavpack |
fontconfig freetype fribidi gmp gnutls kvazaar lame libaom libass libiconv libilbc libtheora libvorbis libvpx libwebp libxml2 opencore-amr opus shine snappy soxr speex twolame vid.stab vo-amrwbenc wavpack x264 x265 xvidcore |
libilbc
, opus
, snappy
, x264
and xvidcore
are supported since v1.1
libaom
and soxr
are supported since v2.0
chromaprint
, vid.stab
and x265
are supported since v2.1
sdl
, tesseract
, twolame
external libraries; zlib
, MediaCodec
Android system libraries; bzip2
, zlib
iOS system libraries and AudioToolbox
, VideoToolbox
, AVFoundation
iOS system frameworks are supported since v3.0
Since v4.2
, chromaprint
, sdl
and tesseract
libraries are not included in binary releases. You can still build them and include in your releases
AVFoundation
is not available on tvOS
, VideoToolbox
is not available on tvOS
LTS releases
Since v4.3.1
, iOS
and tvOS
releases started to use iconv
system library instead of iconv
external library
vo-amrwbenc
is supported since v4.4
4.4
and 4.4.LTS
, add mavenCentral()
to your build.gradle
and make sure that it is listed
before jcenter()
4.3.2
and older releases, add jcenter()
repositories {
mavenCentral()
}
build.gradle
in mobile-ffmpeg-<package name>
pattern.
dependencies {
implementation 'com.arthenica:mobile-ffmpeg-full:4.4'
}
import com.arthenica.mobileffmpeg.Config;
import com.arthenica.mobileffmpeg.FFmpeg;
int rc = FFmpeg.execute("-i file1.mp4 -c:v mpeg4 file2.mp4");
if (rc == RETURN_CODE_SUCCESS) {
Log.i(Config.TAG, "Command execution completed successfully.");
} else if (rc == RETURN_CODE_CANCEL) {
Log.i(Config.TAG, "Command execution cancelled by user.");
} else {
Log.i(Config.TAG, String.format("Command execution failed with rc=%d and the output below.", rc));
Config.printLastCommandOutput(Log.INFO);
}
import com.arthenica.mobileffmpeg.Config;
import com.arthenica.mobileffmpeg.FFmpeg;
long executionId = FFmpeg.executeAsync("-i file1.mp4 -c:v mpeg4 file2.mp4", new ExecuteCallback() {
@Override
public void apply(final long executionId, final int returnCode) {
if (rc == RETURN_CODE_SUCCESS) {
Log.i(Config.TAG, "Async command execution completed successfully.");
} else if (rc == RETURN_CODE_CANCEL) {
Log.i(Config.TAG, "Async command execution cancelled by user.");
} else {
Log.i(Config.TAG, String.format("Async command execution failed with rc=%d.", rc));
}
}
});
import com.arthenica.mobileffmpeg.Config;
import com.arthenica.mobileffmpeg.FFprobe;
int rc = FFprobe.execute("-i file1.mp4");
if (rc == RETURN_CODE_SUCCESS) {
Log.i(Config.TAG, "Command execution completed successfully.");
} else {
Log.i(Config.TAG, String.format("Command execution failed with rc=%d and the output below.", rc));
Config.printLastCommandOutput(Log.INFO);
}
int rc = Config.getLastReturnCode();
if (rc == RETURN_CODE_SUCCESS) {
Log.i(Config.TAG, "Command execution completed successfully.");
} else if (rc == RETURN_CODE_CANCEL) {
Log.i(Config.TAG, "Command execution cancelled by user.");
} else {
Log.i(Config.TAG, String.format("Command execution failed with rc=%d and the output below.", rc));
Config.printLastCommandOutput(Log.INFO);
}
FFmpeg.cancel();
FFmpeg.cancel(executionId);
MediaInformation info = FFprobe.getMediaInformation("<file path or uri>");
FFmpeg.execute("-f android_camera -i 0:0 -r 30 -pixel_format bgr0 -t 00:00:05 <record file path>");
Config.enableLogCallback(new LogCallback() {
public void apply(LogMessage message) {
Log.d(Config.TAG, message.getText());
}
});
Config.enableStatisticsCallback(new StatisticsCallback() {
public void apply(Statistics newStatistics) {
Log.d(Config.TAG, String.format("frame: %d, time: %d", newStatistics.getVideoFrameNumber(), newStatistics.getTime()));
}
});
Config.ignoreSignal(Signal.SIGXCPU);
final List<FFmpegExecution> ffmpegExecutions = FFmpeg.listExecutions();
for (int i = 0; i < ffmpegExecutions.size(); i++) {
FFmpegExecution execution = ffmpegExecutions.get(i);
Log.d(TAG, String.format("Execution %d = id:%d, startTime:%s, command:%s.", i, execution.getExecutionId(), execution.getStartTime(), execution.getCommand()));
}
Config.setLogLevel(Level.AV_LOG_FATAL);
Config.setFontDirectory(this, "<folder with fonts>", Collections.EMPTY_MAP);
Add MobileFFmpeg dependency to your Podfile
in mobile-ffmpeg-<package name>
pattern.
pod 'mobile-ffmpeg-full', '~> 4.4'
pod 'mobile-ffmpeg-tvos-full', '~> 4.4'
#import <mobileffmpeg/MobileFFmpegConfig.h>
#import <mobileffmpeg/MobileFFmpeg.h>
int rc = [MobileFFmpeg execute: @"-i file1.mp4 -c:v mpeg4 file2.mp4"];
if (rc == RETURN_CODE_SUCCESS) {
NSLog(@"Command execution completed successfully.\n");
} else if (rc == RETURN_CODE_CANCEL) {
NSLog(@"Command execution cancelled by user.\n");
} else {
NSLog(@"Command execution failed with rc=%d and output=%@.\n", rc, [MobileFFmpegConfig getLastCommandOutput]);
}
#import <mobileffmpeg/MobileFFmpegConfig.h>
#import <mobileffmpeg/MobileFFmpeg.h>
long executionId = [MobileFFmpeg executeAsync:@"-i file1.mp4 -c:v mpeg4 file2.mp4" withCallback:self];
- (void)executeCallback:(long)executionId :(int)returnCode {
if (rc == RETURN_CODE_SUCCESS) {
NSLog(@"Async command execution completed successfully.\n");
} else if (rc == RETURN_CODE_CANCEL) {
NSLog(@"Async command execution cancelled by user.\n");
} else {
NSLog(@"Async command execution failed with rc=%d.\n", rc);
}
}
#import <mobileffmpeg/MobileFFmpegConfig.h>
#import <mobileffmpeg/MobileFFprobe.h>
int rc = [MobileFFprobe execute: @"-i file1.mp4"];
if (rc == RETURN_CODE_SUCCESS) {
NSLog(@"Command execution completed successfully.\n");
} else if (rc == RETURN_CODE_CANCEL) {
NSLog(@"Command execution cancelled by user.\n");
} else {
NSLog(@"Command execution failed with rc=%d and output=%@.\n", rc, [MobileFFmpegConfig getLastCommandOutput]);
}
int rc = [MobileFFmpegConfig getLastReturnCode];
NSString *output = [MobileFFmpegConfig getLastCommandOutput];
if (rc == RETURN_CODE_SUCCESS) {
NSLog(@"Command execution completed successfully.\n");
} else if (rc == RETURN_CODE_CANCEL) {
NSLog(@"Command execution cancelled by user.\n");
} else {
NSLog(@"Command execution failed with rc=%d and output=%@.\n", rc, output);
}
[MobileFFmpeg cancel];
[MobileFFmpeg cancel:executionId];
MediaInformation *mediaInformation = [MobileFFprobe getMediaInformation:@"<file path or uri>"];
Record video and audio using iOS camera. This operation is not supported on tvOS
since AVFoundation
is not available on tvOS
.
[MobileFFmpeg execute: @"-f avfoundation -r 30 -video_size 1280x720 -pixel_format bgr0 -i 0:0 -vcodec h264_videotoolbox -vsync 2 -f h264 -t 00:00:05 %@", recordFilePath];
[MobileFFmpegConfig setLogDelegate:self];
- (void)logCallback:(long)executionId :(int)level :(NSString*)message {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"%@", message);
});
}
[MobileFFmpegConfig setStatisticsDelegate:self];
- (void)statisticsCallback:(Statistics *)newStatistics {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"frame: %d, time: %d\n", newStatistics.getVideoFrameNumber, newStatistics.getTime);
});
}
[MobileFFmpegConfig ignoreSignal:SIGXCPU];
NSArray* ffmpegExecutions = [MobileFFmpeg listExecutions];
for (int i = 0; i < [ffmpegExecutions count]; i++) {
FFmpegExecution* execution = [ffmpegExecutions objectAtIndex:i];
NSLog(@"Execution %d = id: %ld, startTime: %@, command: %@.\n", i, [execution getExecutionId], [execution getStartTime], [execution getCommand]);
}
[MobileFFmpegConfig setLogLevel:AV_LOG_FATAL];
[MobileFFmpegConfig setFontDirectory:@"<folder with fonts>" with:nil];
MobileFFmpeg
version number is aligned with FFmpeg
since version 4.2
.
In previous versions, MobileFFmpeg
version of a release and FFmpeg
version included in that release was different.
The following table lists FFmpeg
versions used in MobileFFmpeg
releases.
dev
part in FFmpeg
version number indicates that FFmpeg
source is pulled from the FFmpeg
master
branch.
Exact version number is obtained using git describe --tags
.MobileFFmpeg Version | FFmpeg Version | Release Date |
---|---|---|
4.4 | 4.4-dev-416 | Jul 25, 2020 |
4.4.LTS | 4.4-dev-416 | Jul 24, 2020 |
4.3.2 | 4.3-dev-2955 | Apr 15, 2020 |
4.3.1 | 4.3-dev-1944 | Jan 13, 2020 |
4.3.1.LTS | 4.3-dev-1944 | Jan 13, 2020 |
4.3 | 4.3-dev-1181 | Oct 27, 2019 |
4.2.2 | 4.2-dev-1824 | July 3, 2019 |
4.2.2.LTS | 4.2-dev-1824 | July 3, 2019 |
4.2.1 | 4.2-dev-1156 | Apr 2, 2019 |
4.2 | 4.2-dev-480 | Jan 3, 2019 |
4.2.LTS | 4.2-dev-480 | Jan 3, 2019 |
3.1 | 4.1-10 | Dec 11, 2018 |
3.0 | 4.1-dev-1517 | Oct 25, 2018 |
2.2 | 4.0.3 | Nov 10, 2018 |
2.1.1 | 4.0.2 | Sep 19, 2018 |
2.1 | 4.0.2 | Sep 5, 2018 |
2.0 | 4.0.1 | Jun 30, 2018 |
1.2 | 3.4.4 | Aug 30, 2018 |
1.1 | 3.4.2 | Jun 18, 2018 |
1.0 | 3.4.2 | Jun 6, 2018 |
Starting from v4.2
, MobileFFmpeg
binaries are published in two different variants: Main Release
and LTS Release
.
Main releases include complete functionality of the library and support the latest SDK/API features.
LTS releases are customized to support a wider range of devices. They are built using older API/SDK versions, so some features are not available on them.
This table shows the differences between two variants.
Main Release | LTS Release | |
---|---|---|
Android API Level | 24 | 16 |
Android Camera Access | Yes | - |
Android Architectures | arm-v7a-neon arm64-v8a x86 x86-64 |
arm-v7a arm-v7a-neon arm64-v8a x86 x86-64 |
Xcode Support | 10.1 | 7.3.1 |
iOS SDK | 12.1 | 9.3 |
iOS AVFoundation | Yes | - |
iOS Architectures | arm64 arm64e1 x86-64 x86-64-mac-catalyst2 |
armv7 arm64 i386 x86-64 |
tvOS SDK | 10.2 | 9.2 |
tvOS Architectures | arm64 x86-64 |
arm64 x86-64 |
1 - Included until v4.3.2
2 - Included since v4.3.2
Use your package manager (apt, yum, dnf, brew, etc.) to install the following packages.
autoconf automake libtool pkg-config curl cmake gcc gperf texinfo yasm nasm bison autogen patch git
Use android.sh
, ios.sh
and tvos.sh
to build MobileFFmpeg for each platform.
After a successful build, compiled FFmpeg and MobileFFmpeg libraries can be found under prebuilt
directory.
export ANDROID_HOME=<Android SDK Path>
export ANDROID_NDK_ROOT=<Android NDK Path>
./android.sh
./ios.sh
./tvos.sh
It is possible to enable GPL licensed libraries x264
, xvidcore
since v1.1
; vid.stab
, x265
since v2.1
and
rubberband
since v4.3.2
from the top level build scripts. Their source code is not included in the repository and
downloaded when enabled.
build
directory includes build scripts of all external libraries. Two scripts exist for each external library,
one for Android
and one for iOS / tvOS
. Each of these two scripts contains options/flags used to cross-compile the
library on the specified mobile platform.
A more detailed documentation is available at Wiki.
MobileFFmpeg
is licensed under the LGPL v3.0. However, if source code is built using the optional --enable-gpl
flag
or prebuilt binaries with -gpl
postfix are used, then MobileFFmpeg is subject to the GPL v3.0 license.
The source code of all external libraries included is in compliance with their individual licenses.
openh264
source code included in this repository is licensed under the 2-clause BSD License but this license does
not cover the MPEG LA
licensing fees. If you build mobile-ffmpeg
with openh264
and distribute that library, then
you are subject to pay MPEG LA
licensing fees. Refer to OpenH264 FAQ page for
the details. Please note that mobile-ffmpeg
does not publish a binary with openh264
inside.
strip-frameworks.sh
script included and distributed (until v4.x) is published under the
Apache License version 2.0.
In test applications; embedded fonts are licensed under the SIL Open Font License, other digital assets are published in the public domain.
Please visit License page for the details.
It is not clearly explained in their documentation but it is believed that FFmpeg
, kvazaar
, x264
and x265
include algorithms which are subject to software patents. If you live in a country where software algorithms are
patentable then you’ll probably need to pay royalty fees to patent holders. We are not lawyers though, so we recommend
that you seek legal advice first. See FFmpeg Patent Mini-FAQ.
openh264
clearly states that it uses patented algorithms. Therefore, if you build mobile-ffmpeg with openh264 and
distribute that library, then you are subject to pay MPEG LA licensing fees. Refer to
OpenH264 FAQ page for the details.