音視頻學(xué)習(xí) (十三) Android 中通過 FFmpeg 命令對音視頻編輯處理...
視音頻編輯器
前言
有時候我們想對音視頻進(jìn)行加工處理,比如視頻編輯、添加字幕、裁剪等功能處理,雖然 Github 上開源了一些比較不錯的項(xiàng)目,但是如果我們想在此項(xiàng)目上進(jìn)行二次開發(fā),比如我想拿到該項(xiàng)目的動態(tài)庫基于 OpenH264 來進(jìn)行對 YUV 編碼,這個時候有可能該動態(tài)庫沒有集成 OpenH64 庫,所以為了擴(kuò)展性,我就自己弄了一套萬能的庫,基本上包含了所有常用的音視頻處理庫,你不用再去進(jìn)行編譯。
編譯完成的頭文件和動態(tài)庫可以在該項(xiàng)目的 core/cpp 目錄自行獲取(「已完全開源」)。
?ps:這里再推薦一下我的另一個音視頻處理庫 AVEditor ----> 功能正在完善中,可以先關(guān)注 ?? 。
AVEditor 是一款短視頻編輯 SDK,仿 DouYin 音視頻處理。功能包含有美顏、濾鏡、貼紙、特效、錄制、分段錄制、速率錄制、變聲、配樂、rtmp 直播推流、圖片轉(zhuǎn)視頻、剪輯,mp4/flv 格式封裝等功能。
?
介紹
「視音頻編輯器」 主要移植??FFmpeg v4.4-dev + libx264 + freetype + fontconfig + fribidi + openh264 +libfdk-aac + gnutls + speex + libwebp + lame +opus + opencore-amr + https 等庫編譯的適用于 Android 平臺的音視頻編輯、視頻剪輯的快速處理框架,目前內(nèi)置了音視頻剪輯、編輯、多個視頻文件合并、字幕、水印、倒放等功能,也可以傳入 「FFmpeg」 命令來進(jìn)行處理。
「我們先來看一下內(nèi)置功能的效果:」
音視頻剪輯:

音視頻合成:
音視頻編輯:
>?更多效果點(diǎn)擊閱讀原文進(jìn)行查看
如何使用
1. 添加依賴
implementation?'com.devyk.ffmpeglib:AVFFmpegCore:1.0.1'
2. 功能 API 介紹
「回調(diào)處理」
public?interface?ExecuteCallback?{
??/**
??*開始處理
??*/
????void?onStart(Long?executionId);
????/**
?????*?如果外部傳遞了當(dāng)前操作視頻的時長,那么返回的是百分比進(jìn)度,反之返回的是操作視頻對應(yīng)的微妙時長
?????*
?????*?@param?v
?????*/
????void?onProgress(float?v);
??/**
??*處理成功
??*/
????void?onSuccess(long?executionId);
??/**
??*處理失敗
??*/
????void?onFailure(long?executionId,?String?error);
??/**
??*取消處理
??*/
????void?onCancel(long?executionId);
??/**
??*?ffmpeg?執(zhí)行的?log
??*/
????void?onFFmpegExecutionMessage(LogMessage?logMessage);
}
「AVEditor」
剪輯
AVVideo:
//start:開始的時間?單位秒
//duration:?剪輯多少秒
fun?clip(start:?Float,?duration:?Float)
AVEditor:
fun?exec(
??epVideo:?AVVideo,?
??outputOption:?OutputOption,?
??executeCallback:?ExecuteCallback)旋轉(zhuǎn)
AVVideo:
//rotation:旋轉(zhuǎn)角度(僅支持90,180,270度旋轉(zhuǎn))
//isFlip:是否鏡像
fun?rotation(rotation:?Int,?isFlip:?Boolean)
AVEditor:
fun?exec(
??epVideo:?AVVideo,?
??outputOption:?OutputOption,?
??executeCallback:?ExecuteCallback)裁剪
AVVideo:
//width:?裁剪的寬
//height:?裁剪的高
//x:?從?x?點(diǎn)開始
//y:?從?y?點(diǎn)開始
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)視頻轉(zhuǎn)圖片
AVEditor:
fun?video2pic(
??videoin:?String,?//視頻輸入文件
??out:?String,??//圖片輸出路徑-目錄
??w:?Int,?h:?Int,?//輸出圖片的寬高
??rate:?Float,?//每秒視頻生成圖片數(shù)
??executeCallback:?ExecuteCallback)視頻轉(zhuǎn) 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 編譯小技巧
有時候我們發(fā)現(xiàn) Github 上一些基于 FFmpeg 開發(fā)的比較好的項(xiàng)目,比如 ijkplayer ,RxFFmpeg 等,我們想基于它做二次開發(fā),由于我們不知道怎么編譯,也不知道編譯 FFmpeg 到底需要開啟哪些節(jié)點(diǎn),這個時候我就想拿某些項(xiàng)目的編譯腳本,基于它來進(jìn)行二次編譯。一般來說有些項(xiàng)目不會開源編譯 FFmpeg 的腳本。這個時候我們可以通過拿到開源項(xiàng)目的靜態(tài)或者動態(tài)庫,這里我就以 RxFFmpeg ?來舉例,可以看看我是如果拿到它的編譯腳本.
1、先 clone ?RxFFmpeg
git?clone?https://github.com/microshow/RxFFmpeg.git
2、關(guān)聯(lián) librxffmpeg-core.so
通過該 so ?我們知道它應(yīng)該就是 FFmpeg 編譯之后的動態(tài)庫,現(xiàn)在我們通過 cmake 的方式關(guān)聯(lián)到該 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 函數(shù),拿到編譯腳本
//
//?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 指針指向內(nèi)存中的信息如下:
嗯,拿到了它的編譯信息,然后我們就可以基于它來完善我們項(xiàng)目的編譯,我們可以編譯出比它的功能更加豐富,就如開頭介紹一般,我添加了市面上常用的一些 C++ 庫,基本達(dá)到了萬能了吧。
總結(jié)
項(xiàng)目地址:AVFFmpegLib
這里就不在介紹如何編譯了,感興趣的可以看 mobile-ffmpeg 項(xiàng)目,我這里也是基于它進(jìn)行二次封裝開發(fā)。
參考
- EpMedia
- FFmpeg 常用命令
- mobile-ffmpeg
- Android 音視頻編輯經(jīng)驗(yàn)總結(jié)及開源工程分享
