在安卓中使用 FFmpegKit 剪切视频并添加文字水印

在安卓中用到的三方库:https://github.com/arthenica/ffmpeg-kit

这个库很强大,支持很多平台,每个平台都有各自的分支代码,用了一段时间,稳定性挺好的,

找到安卓下的分支:FFmpegKit for Android FFmpegKit Android 版

引入项目:

java 复制代码
repositories {
    mavenCentral()
}

dependencies {
    implementation 'com.arthenica:ffmpeg-kit-full:6.0-2'
}

每个平台下,又分为多个库,每个库包含不同的功能,因为功能越丰富,导入到项目中编译的包体积越大,尽量选择适合自己功能的库进行使用。


📦 FFmpeg 编译配置选项(库依赖分类)

配置项 说明 包含的库
min 最小化构建 -
min-gpl 最小化构建并启用 GPL 库 vid.stab, x264, x265, xvidcore
https 启用 HTTPS 支持(使用非-GPL 依赖) gmp, gnutls
https-gpl 启用 HTTPS 支持(使用 GPL 兼容依赖) gmp, gnutls, vid.stab, x264, x265, xvidcore
audio 启用音频相关编码器/解码器 lame, libilbc, libvorbis, opencore-amr, opus, shine, soxr, speex, twolame, vo-amrwbenc
video 启用视频相关编码器/解码器 dav1d, fontconfig, freetype, fribidi, kvazaar, libass, libiconv, libtheora, libvpx, libwebp, snappy, zimg
full 启用所有非 GPL 第三方库 dav1d, fontconfig, freetype, fribidi, gmp, gnutls, kvazaar, libass, libiconv, libilbc, libtheora, libvorbis, libvpx, libwebp, libxml2, opencore-amr, opus, shine, snappy, soxr, speex, twolame, vo-amrwbenc, zimg
full-gpl 启用所有库(包括 GPL) dav1d, fontconfig, freetype, fribidi, gmp, gnutls, kvazaar, lame, libass, libiconv, libilbc, libtheora, libvorbis, libvpx, libwebp, libxml2, opencore-amr, opus, shine, snappy, soxr, speex, twolame, vid.stab, vo-amrwbenc, x264, x265, xvidcore, zimg

比如你如果只需要保存 rtsp 视频流 和 推流的话,只需要导入 min-gpl即可:

java 复制代码
 implementation 'com.arthenica:ffmpeg-kit-min-gpl:6.0-2'

如果你想要更多,比如添加水印,就涉及到 FFmpeg 滤镜相关功能,就需要引入full-gpl

java 复制代码
 implementation 'com.arthenica:ffmpeg-kit-full-gpl:6.0-2'

具体需要什么功能,可以进去看说明,说明没有涉及到的,并且你不想用全功能库,你也可以一个一个试试,也许就能满足你。

正文开始


由说明可知,使用方式为:

java 复制代码
import com.arthenica.ffmpegkit.FFmpegKit;

FFmpegSession session = FFmpegKit.execute("-i file1.mp4 -c:v mpeg4 file2.mp4");
if (ReturnCode.isSuccess(session.getReturnCode())) {

    // SUCCESS

} else if (ReturnCode.isCancel(session.getReturnCode())) {

    // CANCEL

} else {

    // FAILURE
    Log.d(TAG, String.format("Command failed with state %s and rc %s.%s", session.getState(), session.getReturnCode(), session.getFailStackTrace()));

}

或者异步调用:

java 复制代码
FFmpegKit.executeAsync("-i file1.mp4 -c:v mpeg4 file2.mp4", new FFmpegSessionCompleteCallback() {

    @Override
    public void apply(FFmpegSession session) {
        SessionState state = session.getState();
        ReturnCode returnCode = session.getReturnCode();

        // CALLED WHEN SESSION IS EXECUTED

        Log.d(TAG, String.format("FFmpeg process exited with state %s and rc %s.%s", state, returnCode, session.getFailStackTrace()));
    }
}, new LogCallback() {

    @Override
    public void apply(com.arthenica.ffmpegkit.Log log) {

        // CALLED WHEN SESSION PRINTS LOGS

    }
}, new StatisticsCallback() {

    @Override
    public void apply(Statistics statistics) {

        // CALLED WHEN SESSION GENERATES STATISTICS

    }
});

与正常 ffmpeg 命令不同的是,在传入命令时,前面不需要加 "ffmpeg" 关键字,只需传入后面的具体命令即可,加上会报错哦!

关键代码:

搞了好久才凑齐的正确代码,这东西真不能听 AI 的一面之辞,不然就被 AI 一条路领到黑,

java 复制代码
    private static String buildWatermarkCommand(VideoFile file, VideoTimeRange timeRange, String outputPath, String fontPath) {
        FFmpegKitConfig.setFontconfigConfigurationPath(fontPath);
      
        String drawtextFilter = String.format(
                "drawtext=text='%s':fontfile=%s:fontcolor=white:fontsize=20:x=0:y=30",
                DEFAULT_WATERMARK, fontPath
        );

        List<String> commandList = new ArrayList<>();
        commandList.add("-ss");                              // 指定输入文件的开始时间,格式:HH:MM:SS
        commandList.add(timeRange.startTime);
        commandList.add("-i");                               // 输入文件路径
        commandList.add(file.filePath);
        commandList.add("-t");                               // 指定持续时间,格式:HH:MM:SS
        commandList.add(timeRange.durationStr);
        commandList.add("-vf");                              // 视频滤镜,用于添加水印文字
        commandList.add(drawtextFilter);
        commandList.add("-c:v");                             // 视频编码器设置
        commandList.add(VIDEO_CODEC);                        // 使用H.264软件编码器
        commandList.add("-preset");                          // 编码速度预设
        commandList.add(VIDEO_PRESET);                       // ultrafast:最快编码速度,文件稍大
        commandList.add("-crf");                             // 恒定质量因子(0-51,越小质量越好)
        commandList.add(String.valueOf(VIDEO_CRF));          // 23:平衡质量和文件大小的推荐值
        commandList.add("-c:a");                             // 音频编码器设置
        commandList.add("copy");                             // 直接复制音频流,不重新编码
        commandList.add("-r");
        commandList.add("20");                               // 每秒20帧
        commandList.add("-avoid_negative_ts");               // 避免负时间戳问题
        commandList.add("make_zero");                        // 将负时间戳调整为0
        commandList.add(outputPath);                         // 输出文件路径

        return String.join(" ", commandList);
    }

简单介绍下命令作用:对一段现有的视频文件进行剪辑,-ss指定开始时间,比如要剪切的原视频时长为两分钟,所以开始时间到结束时间就是:00:00:00 - 00:02:00 , 假设要剪辑中间一分钟的视频,那么 -ss指定的开始时间为:00:00:30 , -t持续时间就是:00:01:00 , 截取的时间段为:00:00:30 - 00:01:30 ,-c:v设置编码器,一般 H.264 就够了,如果设置其他的编码器,要看你的设备支持不支持了,-r设置帧率,如果你想要剪切的视频大小小一点,一方面就可以通过降低帧率,另一方面就可以降低码率来实现(上述命令码率未指定默认按原视频码率)。

如果你指定的时间范围,超过原视频时长会报错,这很正常,只是报错内容可能看不懂,这是一个问题点!

设置 FFmpegKitConfig.setFontconfigConfigurationPath的作用是 https://github.com/arthenica/ffmpeg-kit/wiki/Tips 参考第四条:ffmpeg 需要有效的 fontconfig 配置才能在使用 drawtext filter 时渲染文本。

这里指定一个存在的字体路径即可 比如:/system/fonts/NotoSansCJK-Regular.ttc

注意:有的字体不支持中文,写入中文水印的时候会乱码!


视频处理性能测试(A133,Android 10)

测试环境

  • 设备平台:A133
  • 操作系统:Android 10
  • 测试内容:视频加水印 vs 无水印处理
  • 加水印帧率:15fps
  • 视频格式:H.264 (宽高:720x576)(位率:512Kbps)

性能对比数据

视频时长 处理方式 耗时(ms) 耗时(秒) 输出文件大小
30s 加水印 5214 5.21 1.5M
30s 加水印(15帧) 3813 3.81 1.5M
30s 不加水印 168 0.17 0.9M
60s 加水印 12013 12.01 2.5M
60s 加水印(15帧) 7392 7.39 2.5M
60s 不加水印 208 0.21 1.5M
120s 加水印 22006 22.01 5.03M
120s 加水印(15帧) 18404 18.40 5.03M
120s 不加水印 277 0.28 2.8M
240s 加水印 50547 50.55 10.57M
240s 加水印(15帧) 37857 37.86 10.57M
240s 不加水印 448 0.45 5.24M

在 A133 平台上,加水印操作是性能瓶颈,视频重编码操作对cpu要求比较高。

相关推荐
9527华安6 分钟前
FPGA实现Aurora 64B66B图像视频传输,基于GTY高速收发器,提供2套工程源码和技术支持
fpga开发·音视频·aurora·高速收发器·gty·aurora 64b66b
小强开学前2 小时前
WebView 静态页面秒加载方案要点
android·webview
纽马约2 小时前
Android Room的使用详解
android
Jons伯恩特2 小时前
音频中的噪音门
音视频·音频·噪音门·噪声门
我希望的一路生花3 小时前
Boris FX Samplitude Suite 2025.0.0 音频录制/编辑和母带处理
大数据·3d·oracle·sqlite·音视频·数据库开发
游戏开发爱好者83 小时前
基于uni-app的iOS应用上架,从打包到分发的全流程
android·ios·小程序·https·uni-app·iphone·webview
深盾科技3 小时前
Android Keystore签名文件详解与安全防护
android·安全·gitee
安卓开发者3 小时前
Android Glide插件化开发实战:模块化加载与自定义扩展
android·glide
大数据AI人工智能培训专家培训讲师叶梓7 小时前
腾讯混元开源视频拟音模型,破解 AI 视频 “无声” 难题
人工智能·音视频·多模态·大模型微调·人工智能讲师·人工智能培训·微调大模型