
时光飞逝,距离 《NDK 是什么 | FFmpeg 5.0 编译 so 库》 一文已经过去快三年了,曾经最新的 FFmpeg 5.0 ,如今也来到了 FFmpeg 7.1.1。本文就来通过 NDK 编译一下 Android 的 ffmpeg 动态链接库。关于 NDK 是什么可以详见上篇文章,这里不再赘述。
1. 准备编译环境
如果把 ffmpeg 源码编译动态链接库视为一道菜,那么:
厨房 : 我用的是 Windows 的 Linux 子系统
WSL2

厨具 : 用的 ndk 版本为
26.1.10909125

食材 : 在
https://www.ffmpeg.org/download.html
下载源码

2. 开始烹饪
首先将源码压缩包通过命令解压:
tar -xvf ffmpeg-7.1.1.tar.xz

然后进入 ffmpeg-7.1.1 目录,创建 build_android.sh 编译脚本。这里只编译了 arm64 的架构
cd ffmpeg-7.1.1
vim build_android.sh
bash
#!/bin/bash
# 配置路径
NDK_PATH=/home/toly/SDK/AndroidSdk/ndk/26.1.10909125
TOOLCHAIN=$NDK_PATH/toolchains/llvm/prebuilt/linux-x86_64 # 根据系统调整
# 配置编译器
API_LEVEL=24
TARGET=aarch64-linux-android
CC=$TOOLCHAIN/bin/${TARGET}${API_LEVEL}-clang
CXX=$TOOLCHAIN/bin/${TARGET}${API_LEVEL}-clang++
# 设置 arm64 编译参数
ARCH=arm64 # 可选:arm, arm64, x86, x86_64
OUTPUT_DIR=$(pwd)/android/$ARCH
CPU=armv8-a
# 执行 FFmpeg 配置
./configure \
--target-os=android \
--prefix=$OUTPUT_DIR \
--arch=aarch64 \
--cpu=$CPU \
--cc=$CC \
--cxx=$CXX \
--strip=$TOOLCHAIN/bin/llvm-strip \
--enable-cross-compile \
--sysroot=$TOOLCHAIN/sysroot \
--enable-shared \
--disable-static \
--disable-doc \
--disable-programs \
--disable-avdevice \
--disable-avfilter \
--disable-postproc \
--disable-symver \
--extra-cflags="-O3 -fPIC"
# 清理并编译
make clean
make -j$(nproc)
make install
最后,给 build_android.sh 脚本可执行权限,运行即可。完成后,在 android 文件夹下会有我们需要的头文件和 so 链接库文件:
bash
chmod +x build_android.sh
./build_android.sh

3. 盛菜上桌
接下来,创建一个 Native C++ 的 Android 项目,验证编译的结果是否正确。

把生面产出的文件,放下项目的对应位置。由于只打包了 arm64 , 可以在 app/build.gradle
中的 defaultConfig
里指定 ndk 支持的架构:

把默认的 hello 字符串改为 av_version_info
可以查看 FFmpeg 版本号; avcodec_configuration
可以查看编译时的配置信息:
c++
#include <jni.h>
#include <string>
extern "C"{
#include <libavcodec/avcodec.h>
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_toly1994_toly_1ffmpeg_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
// return env->NewStringUTF( av_version_info()); // 查看版本号
return env->NewStringUTF(avcodec_configuration()); // 查看编译配置信息
}
版本 | 编译信息 |
---|---|
![]() |
![]() |
另外,CMakeLists.txt
中的内容和上一篇一样; 《Android NDK 开发 | CMake 使用手册 - 初见篇》 一文介绍过 CMake 的使用,后续有空会继续补充。
cmake
cmake_minimum_required(VERSION 3.22.1)
project("toly_ffmpeg")
#引入头文件
include_directories(includes)
# 定义当前 so 库 - 在 java 代码中加载
add_library(toly_ffmpeg SHARED native-lib.cpp)
# 添加 ffmpeg 的 avcodec、swresample、avutil 模块 start======
set(ABI_DIR ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
add_library(avcodec SHARED IMPORTED)
set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION ${ABI_DIR}/libavcodec.so)
add_library(swresample SHARED IMPORTED)
set_target_properties(swresample PROPERTIES IMPORTED_LOCATION ${ABI_DIR}/libswresample.so)
add_library(avutil SHARED IMPORTED)
set_target_properties(avutil PROPERTIES IMPORTED_LOCATION ${ABI_DIR}/libavutil.so)
# 添加 ffmpeg 的 avcodec、swresample、avutil 模块 end======
find_library(log-lib log)
target_link_libraries(
toly_ffmpeg
avcodec
swresample
avutil
${log-lib})
整体来说,这道菜做的还是比较顺利的。
4. 编译脚本分析
编译脚本中最核心的是执行源码中的 configure
文件,这是 FFmpeg 的配置脚本。 前面的代码都是为了执行它而准备的参数:
NDK_PATH=/home/toly/SDK/AndroidSdk/ndk/26.1.10909125
指定本地 NDK 路径,根据 FFmpeg 交叉编译需要。NDK 可以通过 Android SDK 的管理工具下载:

TOOLCHAIN=$NDK_PATH/toolchains/llvm/prebuilt/linux-x86_64
TOOLCHAIN
: 指定 LLVM 工具链路径,根据系统编译环境系统架构选择 linux-x86_64
。我们可以进入 NDK 对应的文件夹中,看到它:

bash
API_LEVEL=24
TARGET=aarch64-linux-android
CC=$TOOLCHAIN/bin/${TARGET}${API_LEVEL}-clang
CXX=$TOOLCHAIN/bin/${TARGET}${API_LEVEL}-clang++
CC
与 CXX
: 分别为 C 和 C++ 编译器,后缀 ${API_LEVEL}-clang
是 LLVM 编译器要求的命名格式。这里对应的是这两个文件:

ini
ARCH=arm64 # 可选:arm, arm64, x86, x86_64
CPU=armv8-a
OUTPUT_DIR=$(pwd)/android/$ARCH
ARCH=arm64
: 编译架构,这里是arm64
,对应的目标是aarch64-linux-android
。CPU=armv8-a
: 目标 CPU 架构,这里编译armv8-a
OUTPUT_DIR
: 编译产物输出目录,当前路径下的android/arm64
然后是执行 configure
脚本:
bash
# 执行 FFmpeg 配置
./configure \
--target-os=android \
--prefix=$OUTPUT_DIR \
--arch=aarch64 \
--cpu=$CPU \
--cc=$CC \
--cxx=$CXX \
--strip=$TOOLCHAIN/bin/llvm-strip \
--enable-cross-compile \
--sysroot=$TOOLCHAIN/sysroot \
--enable-shared \
--disable-static \
--disable-doc \
--disable-programs \
--disable-avdevice \
--disable-avfilter \
--disable-postproc \
--disable-symver \
--extra-cflags="-O3 -fPIC"
--target-os=android
:目标平台为 Android--prefix
:安装路径(输出路径)--arch=aarch64
:设置目标架构--cpu=armv8-a
:设置目标 CPU 架构,arm64 架构常见选项--cc / --cxx
:使用 clang 交叉编译器--strip
:使用 LLVM 工具链提供的 strip 工具去除符号--enable-cross-compile
:开启交叉编译--sysroot
:NDK 的 sysroot,指定头文件与库路径--enable-shared
/--disable-static
:只生成.so
动态库--disable-doc / --disable-programs
:不构建文档与工具程序(如 ffmpeg 命令行工具)--disable-avdevice
--disable-avfilter
--disable-postproc
:裁剪不必要的功能模块,减小体积--disable-symver
:禁用 symbol versioning(可能为兼容 Android)--extra-cflags
:添加优化选项-O3
,开启-fPIC
(位置无关代码,构建动态库必须)
5. 尾声
到这里,我们就完成了 FFmpeg7.1.1 最新版本,编译为 Android 的动态链接库,完成了万里长征的第一步。后面有机会可能会研究一下 FFmpeg,希望下一篇不会是下一个三年,再编译一个 FFmpeg 9.0, 哈哈, 敬请期待 ~
更多文章和视频知识资讯,大家可以关注我的公众号、掘金和 B 站 。