## 音视频学习 (十三) Android 中通过 FFmpeg 命令对音视频编辑处理(已开源)
## 视音频编辑器
## 前言
有时候我们想对音视频进行加工处理,比如视频编辑、添加字幕、裁剪等功能处理,虽然 Github 上开源了一些比较不错的项目,但是如果我们想在此项目上进行二次开发,比如我想拿到该项目的动态库基于 OpenH264 来进行对 YUV 编码,这个时候有可能该动态库没有集成 OpenH64 库,所以为了扩展性,我就自己弄了一套万能的库,基本上包含了所有常用的音视频处理库,你不用再去进行编译。
编译完成的头文件和动态库可以在该项目的 core/cpp 目录自行获取(**「已完全开源」**)。
> ❝
>
> ps:这里再推荐一下我的另一个音视频处理库[AVEditor](https://github.com/yangkun19921001/AVEditor)\----> 功能正在完善中,可以先关注 😜 。
>
> AVEditor 是一款短视频编辑 SDK,仿 DouYin 音视频处理。功能包含有美颜、滤镜、贴纸、特效、录制、分段录制、速率录制、变声、配乐、rtmp 直播推流、图片转视频、剪辑,mp4/flv 格式封装等功能。
>
> ❞
## 介绍
**「视音频编辑器」**主要移植`FFmpeg v4.4-dev + libx264 + freetype + fontconfig + fribidi + openh264 +libfdk-aac + gnutls + speex + libwebp + lame +opus + opencore-amr + https`等库编译的适用于 Android 平台的音视频编辑、视频剪辑的快速处理框架,目前内置了音视频剪辑、编辑、多个视频文件合并、字幕、水印、倒放等功能,也可以传入**「FFmpeg」**命令来进行处理。
**「我们先来看一下内置功能的效果:」**
**「视频剪辑:」**
![](data:image/svg+xml;utf8,)
**「视频合并:」**
![](data:image/svg+xml;utf8,)
**「视频编辑:」**
![](data:image/svg+xml;utf8,)
## 如何使用
### 1\. 添加依赖
~~~
implementation 'com.devyk.ffmpeglib:AVFFmpegCore:1.0.1'
复制代码
~~~
### 2\. 功能 API 介绍
**「回调处理」**
~~~
public interface ExecuteCallback {
/**
*开始处理
*/
void onStart(Long executionId);
/**
* 如果外部传递了当前操作视频的时长,那么返回的是百分比进度,反之返回的是操作视频对应的微妙时长
*
* @param v
*/
void onProgress(float v);
/**
*处理成功
*/
void onSuccess(long executionId);
/**
*处理失败
*/
void onFailure(long executionId, String error);
/**
*取消处理
*/
void onCancel(long executionId);
/**
* ffmpeg 执行的 log
*/
void onFFmpegExecutionMessage(LogMessage logMessage);
}
复制代码
~~~
**「AVEditor」**
* 剪辑
~~~
AVVideo:
//start:开始的时间 单位秒
//duration: 剪辑多少秒
fun clip(start: Float, duration: Float)
AVEditor:
fun exec(
epVideo: AVVideo,
outputOption: OutputOption,
executeCallback: ExecuteCallback)
复制代码
~~~
* 旋转
~~~
AVVideo:
//rotation:旋转角度(仅支持90,180,270度旋转)
//isFlip:是否镜像
fun rotation(rotation: Int, isFlip: Boolean)
AVEditor:
fun exec(
epVideo: AVVideo,
outputOption: OutputOption,
executeCallback: ExecuteCallback)
复制代码
~~~
* 裁剪
~~~
AVVideo:
//width: 裁剪的宽
//height: 裁剪的高
//x: 从 x 点开始
//y: 从 y 点开始
fun crop(
width: Float,
height: Float,
x: Float, y: Float)
AVEditor:
fun exec(
epVideo: AVVideo,
outputOption: OutputOption,
executeCallback: ExecuteCallback)
复制代码
~~~
* 添加文字水印
~~~
AVVideo:
fun addText(avText: AVText)
AVEditor:
fun exec(
epVideo: AVVideo,
outputOption: OutputOption,
executeCallback: ExecuteCallback)
复制代码
~~~
* 添加图片水印
~~~
AVVideo:
fun addDraw(epDraw: AVDraw)
AVEditor:
fun exec(
epVideo: AVVideo,
outputOption: OutputOption,
executeCallback: ExecuteCallback)
复制代码
~~~
* 视频合并
~~~
AVEditor:
fun merge(
epVideos: List<AVVideo>,
outputOption: OutputOption,
executeCallback: ExecuteCallback)
复制代码
~~~
* 添加背景音乐
~~~
AVEditor:
music(
videoin: String,
audioin: String,
output: String,
videoVolume: Float,
audioVolume: Float,
executeCallback: ExecuteCallback
)
复制代码
~~~
* 音视频分离
~~~
AVEditor:
fun demuxer(
inSource: String, outSource: String,
format: Format,
executeCallback: ExecuteCallback)
复制代码
~~~
* 视频倒放
~~~
AVEditor:
fun reverse(
videoin: String, out: String,
vr: Boolean,//视频是否倒放
ar: Boolean, //音频是否倒放
executeCallback: ExecuteCallback)
复制代码
~~~
* 视频转图片
~~~
AVEditor:
fun video2pic(
videoin: String, //视频输入文件
out: String, //图片输出路径-目录
w: Int, h: Int, //输出图片的宽高
rate: Float, //每秒视频生成图片数
executeCallback: ExecuteCallback)
复制代码
~~~
* 视频转 Gif
~~~
AVEditor:
fun video2Gif(
videoin: String,
gifOut: String,
startDuration: Int,
stopDuration: Int,
executeCallback: ExecuteCallback
)
复制代码
~~~
* 自定义命令
~~~
AVEditor:
//cmd:FFmpeg 命令
//duration: 处理视频的时长,可以通过 VideoUitls.getDuration(videoPath) 来获取
fun execCmd(cmd: String, duration: Long, executeCallback: ExecuteCallback)
复制代码
~~~
## FFmpeg 编译小技巧
有时候我们发现 Github 上一些基于 FFmpeg 开发的比较好的项目,比如[ijkplayer](https://github.com/bilibili/ijkplayer),[RxFFmpeg](https://github.com/microshow/RxFFmpeg)等,我们想基于它做二次开发,由于我们不知道怎么编译,也不知道编译 FFmpeg 到底需要开启哪些节点,这个时候我就想拿某些项目的编译脚本,基于它来进行二次编译。一般来说有些项目不会开源编译 FFmpeg 的脚本。这个时候我们可以通过拿到开源项目的静态或者动态库,这里我就以[RxFFmpeg](https://github.com/microshow/RxFFmpeg)来举例,可以看看我是如果拿到它的编译脚本.
1、先 clone[RxFFmpeg](https://github.com/microshow/RxFFmpeg)
~~~
git clone https://github.com/microshow/RxFFmpeg.git
复制代码
~~~
2、关联 librxffmpeg-core.so
通过该 so 我们知道它应该就是 FFmpeg 编译之后的动态库,现在我们通过 cmake 的方式关联到该 so
~~~
cmake_minimum_required(VERSION 3.4.1)
#JNI 路径
set(FFMpeg_include_PATH ${CMAKE_SOURCE_DIR})
include_directories(${FFMpeg_include_PATH}/include/)
add_library(RxFFmpeg SHARED IMPORTED)
set_target_properties(RxFFmpeg PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/../../../libs/${CMAKE_ANDROID_ARCH_ABI}/librxffmpeg-core.so)
find_library(
log-lib
log)
FILE(GLOB JNI_ALL_C ${JNI_PATH}/*.cpp)
add_library(
ffmpeg-tools
SHARED
${JNI_ALL_C}
)
target_link_libraries(
ffmpeg-tools
RxFFmpeg
${log-lib}
)
复制代码
~~~
3、编写 JNI 函数,拿到编译脚本
~~~
//
// Created by DevYK on 2020-10-02.
//
#include <android/log.h>
extern "C"
{
#include "libavutil/avutil.h"
}
#include <jni.h>
#define AV_TAG "AVLOG"
#define LOGE(format, ...) __android_log_print(ANDROID_LOG_ERROR, AV_TAG, format, ##__VA_ARGS__)
int JNI_OnLoad(JavaVM *javaVM, void *pVoid) {
const char *config = avutil_configuration();
LOGE("FFMPEG VERSION%s \n", av_version_info());
LOGE("FFMPEG configuration %s \n", avutil_configuration());
return JNI_VERSION_1_6;
}
复制代码
~~~
通过 debug 查看 config 指针指向内存中的信息如下:![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/022e89c6e28c45dba19011539c7bf12f~tplv-k3u1fbpfcp-zoom-1.image)
嗯,拿到了它的编译信息,然后我们就可以基于它来完善我们项目的编译,我们可以编译出比它的功能更加丰富,就如开头介绍一般,我添加了市面上常用的一些 C++ 库,基本达到了万能了吧。
## 总结
项目地址:[AVFFmpegLib](https://github.com/yangkun19921001/AVFFmpegLib)
这里就不在介绍如何编译了,感兴趣的可以看[mobile-ffmpeg](https://github.com/tanersener/mobile-ffmpeg)项目,我这里也是基于它进行二次封装开发。
## 参考
* [EpMedia](https://github.com/yangjie10930/EpMedia)
* [FFmpeg 常用命令](https://blog.csdn.net/kingvon_liwei/article/details/79271361)
* [mobile-ffmpeg](https://github.com/tanersener/mobile-ffmpeg)
* [Android 音视频编辑经验总结及开源工程分享](https://blog.csdn.net/u011495684/article/details/78437060)
- 前言
- JNI基础知识
- C语言知识点总结
- ①基本语法
- ②数据类型
- 枚举类型
- 自定义类型(类型定义)
- ③格式化输入输出
- printf函数
- scanf函数
- 编程规范
- ④变量和常量
- 局部变量和外部变量
- ⑤类型转换
- ⑥运算符
- ⑦结构语句
- 1、分支结构(选择语句)
- 2、循环结构
- 退出循环
- break语句
- continue语句
- goto语句
- ⑧函数
- 函数的定义和调用
- 参数
- 函数的返回值
- 递归函数
- 零起点学通C语言摘要
- 内部函数和外部函数
- 变量存储类别
- ⑨数组
- 指针
- 结构体
- 联合体(共用体)
- 预处理器
- 预处理器的工作原理
- 预处理指令
- 宏定义
- 简单的宏
- 带参数的宏
- 预定义宏
- 文件包含
- 条件编译
- 内存中的数据
- C语言读文件和写文件
- JNI知识点总结
- 前情回顾
- JNI规范
- jni开发
- jni开发中常见的错误
- JNI实战演练
- C++(CPP)在Android开发中的应用
- 掘金网友总结的音视频开发知识
- 音视频学习一、C 语言入门
- 1.程序结构
- 2. 基本语法
- 3. 数据类型
- 4. 变量
- 5. 常量
- 6. 存储类型关键字
- 7. 运算符
- 8. 判断
- 9. 循环
- 10. 函数
- 11. 作用域规则
- 12. 数组
- 13. 枚举
- 14. 指针
- 15. 函数指针与回调函数
- 16. 字符串
- 17. 结构体
- 18. 共用体
- 19. typedef
- 20. 输入 & 输出
- 21.文件读写
- 22. 预处理器
- 23.头文件
- 24. 强制类型转换
- 25. 错误处理
- 26. 递归
- 27. 可变参数
- 28. 内存管理
- 29. 命令行参数
- 总结
- 音视频学习二 、C++ 语言入门
- 1. 基本语法
- 2. C++ 关键字
- 3. 数据类型
- 4. 变量类型
- 5. 变量作用域
- 6. 常量
- 7. 修饰符类型
- 8. 存储类
- 9. 运算符
- 10. 循环
- 11. 判断
- 12. 函数
- 13. 数学运算
- 14. 数组
- 15. 字符串
- 16. 指针
- 17. 引用
- 18. 日期 & 时间
- 19. 输入输出
- 20. 数据结构
- 21. 类 & 对象
- 22. 继承
- 23. 重载运算符和重载函数
- 24. 多态
- 25. 数据封装
- 26. 接口(抽象类)
- 27. 文件和流
- 28. 异常处理
- 29. 动态内存
- 30. 命名空间
- 31. 预处理器
- 32. 多线程
- 总结
- 音视频学习 (三) JNI 从入门到掌握
- 音视频学习 (四) 交叉编译动态库、静态库的入门学习
- 音视频学习 (五) Shell 脚本入门
- 音视频学习 (六) 一键编译 32/64 位 FFmpeg 4.2.2
- 音视频学习 (七) 掌握音频基础知识并使用 AudioTrack、OpenSL ES 渲染 PCM 数据
- 音视频学习 (八) 掌握视频基础知识并使用 OpenGL ES 2.0 渲染 YUV 数据
- 音视频学习 (九) 从 0 ~ 1 开发一款 Android 端播放器(支持多协议网络拉流/本地文件)
- 音视频学习 (十) 基于 Nginx 搭建(rtmp、http)直播服务器
- 音视频学习 (十一) Android 端实现 rtmp 推流
- 音视频学习 (十二) 基于 FFmpeg + OpenSLES 实现音频万能播放器
- 音视频学习 (十三) Android 中通过 FFmpeg 命令对音视频编辑处理(已开源)