Android FFmpeg 视频压缩实战:从原理到性能优化
·
移动端视频处理的现实挑战
最近在开发社交类App时,用户上传的1080P视频平均大小达到200MB,导致三个显著问题:
- 用户等待上传时间超过5分钟,40%会中途取消
- 云端存储成本每月增加300%
- 低端手机编辑时频繁OOM崩溃

FFmpeg vs MediaCodec 技术选型
通过实测华为P30设备得到对比数据:
| 指标 | FFmpeg软编码 | MediaCodec硬编码 | |---------------|-------------|------------------| | 压缩1分钟视频 | 38秒 | 12秒 | | CPU占用峰值 | 85% | 30% | | PSNR值 | 42.5dB | 39.8dB |
关键结论: - 硬编码首选实时场景,节省60%+电量 - 软编码适合后期处理,画质更优
FFmpeg NDK集成实战
1. ABI适配方案
在CMakeLists.txt中配置关键指令:
set(FFMPEG_DIR ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI})
add_library( ffmpeg SHARED IMPORTED )
set_target_properties( ffmpeg PROPERTIES IMPORTED_LOCATION
${FFMPEG_DIR}/libffmpeg.so)
2. 核心压缩参数设置
Kotlin调用示例:
fun compress(input: String, output: String) {
val cmd = arrayOf(
"-y",
"-i", input,
"-vcodec", "libx264", // H.264编码
"-crf", "28", // 质量系数(18-28最佳)
"-preset", "faster", // 编码速度/质量平衡
"-s", "720x1280", // 分辨率降级
output
)
FFmpeg.execute(cmd) { progress ->
runOnUiThread { updateProgress(progress) }
}
}
性能优化三板斧
1. 内存池设计
static AVFrame* alloc_frame() {
static std::queue<AVFrame*> pool;
if (!pool.empty()) {
auto frame = pool.front();
pool.pop();
return frame;
}
return av_frame_alloc();
}
2. 多线程管道

3. 实测数据
| 优化项 | 压缩时间 | 内存峰值 | |--------------|---------|---------| | 原始方案 | 78s | 1.2GB | | 优化后 | 25s | 400MB |
避坑实录
-
指令集兼容:
ndk { abiFilters 'armeabi-v7a', 'arm64-v8a' } -
解码器异常处理:
try { decoder.configure(format, null, null, 0) } catch (e: Exception) { fallbackToSoftwareDecoder() }
拓展方向
建议尝试: - HEVC编码(节省50%体积) - 动态码率调整(VBR) - 智能场景识别压缩
通过这套方案,我们成功将用户上传取消率降低到8%,核心代码已开源在GitHub示例项目中。
更多推荐


所有评论(0)