Build FFmpeg Shared Libraries for Android NDK
This guide provides a step-by-step walkthrough on how to compile
FFmpeg source code into shared libraries (.so files)
specifically for Android NDK integration. You will learn how to set up
the Android NDK environment, configure the FFmpeg build script for
modern CPU architectures (such as arm64-v8a and
armeabi-v7a), compile the binaries, and import them into an
Android Studio project.
Prerequisites
Before starting, ensure you have the following environment prepared:
- Operating System: Linux (Ubuntu recommended) or macOS. If you are on Windows, use Windows Subsystem for Linux (WSL).
- Android NDK: Download and extract the Android NDK (r21 or newer recommended) to a known directory.
- FFmpeg Source: Download and extract the latest stable FFmpeg source code from the official website.
- Build Tools: Ensure
make,gcc, andgitare installed on your host system.
Step 1: Set Up the Compilation Script
Modern Android NDK releases (r19 and newer) use the Clang compiler by default. You do not need to create a standalone toolchain; instead, you can point your compiler variables directly to the toolchain embedded inside the NDK directory.
Navigate to your extracted FFmpeg source directory and create a shell
script named build_android.sh:
cd /path/to/ffmpeg-source
touch build_android.sh
chmod +x build_android.shOpen build_android.sh in a text editor and add the
following script. This script targets the arm64-v8a
architecture, which is standard for modern 64-bit Android devices.
#!/bin/bash
# Set your NDK path here
NDK=/path/to/your/android-ndk
# Set the host system (linux-x86_64, darwin-x86_64, etc.)
HOST_PLATFORM=linux-x86_64
# Define target API and Architecture
API=21
ARCH=aarch64
CPU=armv8-a
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/$HOST_PLATFORM
OUTPUT_DIR=$(pwd)/android/$ARCH
# Compiler configurations
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
function build_ffmpeg {
./configure \
--prefix=$OUTPUT_DIR \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-symver \
--cross-prefix=$TOOLCHAIN/bin/aarch64-linux-android- \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--cc=$CC \
--cxx=$CXX \
--enable-cross-compile \
--sysroot=$TOOLCHAIN/sysroot \
--extra-cflags="-Os -fPIC" \
--extra-ldflags="" \
$ADDITIONAL_CONFIGURE_FLAGS
make clean
make -j$(nproc)
make install
}
build_ffmpegNote: Replace /path/to/your/android-ndk with the
absolute path to your downloaded NDK, and adjust
HOST_PLATFORM to darwin-x86_64 if you are on
macOS.
Step 2: Compile the Libraries
Execute the build script in your terminal:
./build_android.shOnce the compilation is complete, you will find a new directory named
android/aarch64 inside your FFmpeg source folder. This
folder contains: * include/: The header files
(.h) required for C/C++ compilation. * lib/:
The shared libraries (.so files, e.g.,
libavcodec.so, libavformat.so,
libavutil.so).
To target other architectures (like 32-bit armeabi-v7a),
duplicate the script and modify the ARCH, CPU,
CC, CXX, and --cross-prefix
variables to point to the respective 32-bit compilers (e.g.,
armv7a-linux-androideabi$API-clang).
Step 3: Integrate into Android Studio
Once you have generated the .so files, you must add them
to your Android project’s C++ configuration.
1. Copy Files to Your Android Project
Copy the generated .so files and header files into your
Android project’s directory structure:
- Place the
.sofiles in:app/src/main/jniLibs/arm64-v8a/ - Place the header folders (like
libavcodec/,libavformat/) in:app/src/main/cpp/include/
2. Configure CMakeLists.txt
Configure your app/src/main/cpp/CMakeLists.txt file to
locate and link the prebuilt FFmpeg shared libraries. Add the following
directives:
cmake_minimum_required(VERSION 3.10.2)
project("ffmpeg_android")
# Define path to prebuilt JNI libraries
set(JNI_LIBS_DIR ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
# Import FFmpeg avcodec as a shared library
add_library(avcodec SHARED IMPORTED)
set_target_properties(avcodec PROPERTIES
IMPORTED_LOCATION ${JNI_LIBS_DIR}/libavcodec.so)
# Import FFmpeg avformat as a shared library
add_library(avformat SHARED IMPORTED)
set_target_properties(avformat PROPERTIES
IMPORTED_LOCATION ${JNI_LIBS_DIR}/libavformat.so)
# Import FFmpeg avutil as a shared library
add_library(avutil SHARED IMPORTED)
set_target_properties(avutil PROPERTIES
IMPORTED_LOCATION ${JNI_LIBS_DIR}/libavutil.so)
# Add include directories for header files
include_directories(${CMAKE_SOURCE_DIR}/include)
# Create your native wrapper library
add_library(native-lib SHARED native-lib.cpp)
# Link your library with FFmpeg libraries
target_link_libraries(native-lib
avcodec
avformat
avutil
log)3. Load Libraries in Kotlin or Java
Before calling any native method using FFmpeg in your Android codebase, load the compiled libraries into memory in your activity or class file:
companion object {
init {
System.loadLibrary("avutil")
System.loadLibrary("avcodec")
System.loadLibrary("avformat")
System.loadLibrary("native-lib")
}
}