项目中有两种情况用到 FFmpeg :
- C++ 底层代码调用 FFmpeg 用于音视频解码
- Android 上层使用 FFmpeg 命令行工具用于音视频裁剪、分离、加水印等
一般用法是编译一份 FFmpeg 静态库或动态库(大小 4M+)用于底层依赖和调用,再编译一份 ffmpeg 可执行程序(大小 4M+),但这样实际上项目中有两份 ffmpeg 核心库,会增加安装包体积。因此优化如下:
- 编译一份 libffmepg.so (大小 4M+),底层代码依赖和可执行程序共同依赖该动态库;
- 将 ffmpeg.c 等代码依赖 libffmepg.so 编译 libffmpeg_tool.so 编译成可执行程序(大小几百K,安装包中 90K)
这样项目中减少一份 ffmpeg 核心库的大小(4M+),安装包能减小 1.5~1.7M
libffmpeg_tool.so 调用方式:
1、通过 adb shell 调用测试:
# 将 libffmpeg_tool.so 和 libffmpeg.so 放到 /data/local/tmp 目录
adb push libffmpeg_tool.so /data/local/tmp
adb push libffmpeg.so /data/local/tmp
# adb shell 并进入 /data/local/tmp 目录
adb shell
cd /data/local/tmp
# 给 libffmpeg_tool.so 赋予可执行权限
chmod +x libffmpeg_tool.so
# 增加链接库路径(因为 libffmpeg_tool.so 执行时需要依赖 libffmpeg.so)
export LD_LIBRARY_PATH=/data/local/tmp:$LD_LIBRARY_PATH
./libffmpeg_tool.so -i /sdcard/Alan/ffmpeg/test.mp4
2、在 Android 项目中执行
private Process exec(String cmd) throws IOException {
String filepath = getSoFilePath();
if (!TextUtils.isEmpty(filepath)) {
String nativeLibrariesPath = mContext.getApplicationContext().getApplicationInfo().nativeLibraryDir;
Log.e(TAG ," nativeLibrariesPath = " + nativeLibrariesPath);
ProcessBuilder processBuilder = new ProcessBuilder();
Map<String, String> envMap = processBuilder.environment();
envMap.put("LD_LIBRARY_PATH", nativeLibrariesPath);
String _cmd = String.format("%s %s", filepath, cmd);
Log.d(TAG, "_cmd:" + _cmd);
String[] commands = { "sh", "-c", _cmd };
processBuilder.command(commands);
return processBuilder.start();
}
return null;
}
完整测试 Demo 及编译脚本见我的 github