本文阐述下集成Android集成FFmpeg库的流程,如有不完善的地方,麻烦指出,万分感谢。
硬件环境:MacBook Air
软件环境:Android Studio Narwhal 3 Feature Drop | 2025.1.3+Java 11+
build.gradle.kts(8.13)+NDK 20.0.5594570+ffmpeg 8.0.1
步骤:
(1)下载ffmpeg项目代码
(2)CLANG编译FFmpeg
(3)新建Native C++项目
(4)配置ffmpeg动态库
(5)添加 FFmpeg so库的头文件
(6)native-lib.cpp实现获取 FFmpeg 基础信息
一.下载ffmpeg
官网: https://ffmpeg.org/download.html
git下载:
java
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
二.CLANG编译FFmpeg
1.ffmpeg代码修改配置ClANG
修改 configure 脚本

将configure文件拖动到Android studio,修改以下几点:
(1)添加cross_prefix_clang参数:
我们可以搜索 CMDLINE_SET ,可以找到以下代码,然后新增一个命令行选项cross_prefix_clang

(2)修改编译工具路径设置
我们可以搜索 ar_default="{cross_prefix}{ar_default}" , 找到以下代码:

将高亮两行修改为:

(3)新建编译脚本
在 ffmpeg根目录下新建 shell 脚本,命名为: build_android_clang.sh,脚本代码如下:
java
#!/bin/bash
set -x
# 目标Android版本
API=29
ARCH=arm64
CPU=armv8-a
TOOL_CPU_NAME=aarch64
#so库输出目录
OUTPUT=/Users/guoxiang/Downloads/ffmpeg/android/$CPU
# NDK的路径,根据自己的NDK位置进行设置
NDK=/Users/guoxiang/Library/Android/sdk/ndk/20.0.5594570
# 编译工具链路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
# 编译环境
SYSROOT=$TOOLCHAIN/sysroot
TOOL_PREFIX="$TOOLCHAIN/bin/$TOOL_CPU_NAME-linux-android"
CC="$TOOL_PREFIX$API-clang"
CXX="$TOOL_PREFIX$API-clang++"
OPTIMIZE_CFLAGS="-march=$CPU"
function build
{
./configure \
--prefix=$OUTPUT \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--disable-asm \
--enable-neon \
--enable-cross-compile \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffplay \
--disable-ffprobe \
--disable-symver \
--disable-ffmpeg \
--cc=$CC \
--cxx=$CXX \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \
make clean all
# 这里是定义用几个CPU编译
make -j8
make install
}
build
其中两个地方需要根据自己的配置修改
java
#so库输出目录
OUTPUT=/Users/guoxiang/Downloads/ffmpeg/android/$CPU
# NDK的路径,根据自己的NDK位置进行设置
NDK=/Users/guoxiang/Library/Android/sdk/ndk/20.0.5594570
修改脚本权限
java
chmod +x build_android_clang.sh
修改完后,终端执行命令:
java
./build_android_clang.sh
编译完成后,在android/armv8-a目录下会生成lib和include文件夹,这两者分别是so库和头文件所在位置

三.Android studio新建Native C++项目



四.配置ffmpeg动态库
将ffmpeg/android/armv8-a/lib中的so库导入到NativeDemo项目中,如下:

注意:图中高亮地方是依赖so库编译目录为jniLibs目录
五.添加 FFmpeg so库的头文件
将ffmpeg/android/armv8-a/include中的头文件导入到NativeDemo项目中,如下:

注意:图中高亮地方是依赖头文件编译目录
六.native-lib.cpp实现获取 FFmpeg 基础信息
(1)配置CMakeLists.txt如下
Kotlin
cmake_minimum_required(VERSION 3.22.1)
#project(nativedemo)
# 支持gnu++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
# 1. 定义so库和头文件所在目录,方面后面使用
set(ffmpeg_lib_dir ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR})
# 2. 添加头文件目录
include_directories(${ffmpeg_head_dir})
# 3. 添加ffmpeg相关的so库
add_library( avutil
SHARED
IMPORTED )
set_target_properties( avutil
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libavutil.so )
add_library( swresample
SHARED
IMPORTED )
set_target_properties( swresample
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libswresample.so )
add_library( avcodec
SHARED
IMPORTED )
set_target_properties( avcodec
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libavcodec.so )
add_library( avfilter
SHARED
IMPORTED)
set_target_properties( avfilter
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libavfilter.so )
add_library( swscale
SHARED
IMPORTED)
set_target_properties( swscale
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libswscale.so )
add_library( avformat
SHARED
IMPORTED)
set_target_properties( avformat
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libavformat.so )
add_library( avdevice
SHARED
IMPORTED)
set_target_properties( avdevice
PROPERTIES IMPORTED_LOCATION
${ffmpeg_lib_dir}/libavdevice.so )
# 查找代码中使用到的系统库
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# 配置目标so库编译信息
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp
)
# 指定编译目标库时,cmake要链接的库
target_link_libraries(
# 指定目标库,native-lib 是在上面 add_library 中配置的目标库
native-lib
# 4. 连接 FFmpeg 相关的库
avutil
swresample
avcodec
avfilter
swscale
avformat
avdevice
# Links the target library to the log library
# included in the NDK.
${log-lib} )
(2)build.gradle.kts中添加cmake和viewBinding
Kotlin
externalNativeBuild {
cmake {
path = file("src/main/cpp/CMakeLists.txt")
version = "3.22.1"
}
}
buildFeatures {
viewBinding = true
}
(3)在创建的MainActivity中实现如下代码:
Kotlin
package com.example.nativedemo
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import com.example.nativedemo.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val result = ffmpegInfo()
binding.sampleText.text = result
}
companion object {
//加载native-lib静态库
init {
System.loadLibrary("native-lib")
}
}
/**
* 获取ffmpeg的基本信息
*/
external fun ffmpegInfo(): String
}
(4)native-lib.cpp中实现如下方法:
Kotlin
extern "C" {
JNIEXPORT jstring JNICALL
Java_com_example_nativedemo_MainActivity_ffmpegInfo(
JNIEnv *env,
jobject mainActivty) {
char info[40000] = {0};
void *iter = NULL;
const AVCodec *c_temp = NULL;
while ((c_temp = av_codec_iterate(&iter)) != NULL) {
if (av_codec_is_decoder(c_temp)) {
printf("Decoder: %s\n", c_temp->name);
}
switch (c_temp->type) {
case AVMEDIA_TYPE_VIDEO:
sprintf(info, "%s(video):", info);
break;
case AVMEDIA_TYPE_AUDIO:
sprintf(info, "%s(audio):", info);
break;
default:
sprintf(info, "%s(other):", info);
break;
}
sprintf(info, "%s[%s]\n", info, c_temp->name);
}
return env->NewStringUTF(info);
}
}
(5)运行NativeDemo项目,MainActivity中的TextView会显示ffmpeg音视频编解码的基本信息,如下图示:

代码地址: