## 音視頻學習 (十三) 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」**命令來進行處理。
**「我們先來看一下內置功能的效果:」**
**「視頻剪輯:」**

**「視頻合并:」**

**「視頻編輯:」**

## 如何使用
### 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 指針指向內存中的信息如下:
嗯,拿到了它的編譯信息,然后我們就可以基于它來完善我們項目的編譯,我們可以編譯出比它的功能更加豐富,就如開頭介紹一般,我添加了市面上常用的一些 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 命令對音視頻編輯處理(已開源)