本文由馬北劍西投稿。
馬北劍西的博客地址:
http://blog.csdn.net/mabeijianxi/
之前還推送給過一篇:仿微信視頻拍攝UI, 基于ffmpeg的視頻錄制編輯,可以一起學習~
1
概述
本庫暫時是在秒拍開源庫上做的二次開發,旨在開發簡單好用高效的視頻錄制庫。本篇文檔只涉及Java層次邏輯,正在業余修煉c語言與JNI相關的東西,如果有幸寫第二篇文章,那時將對其做更深入的剖析,如FFmpeg編譯、JNI相關代碼編寫。
效果圖:
[圖片上傳中。。。(1)]
功能描述:
利用FFmpeg錄制定制化的視頻,并可對其定制化的壓縮處理。如設置視頻尺寸、設置碼率、碼率模式、幀率、視頻質量等級、壓縮速度等等,當然這些只是暫時的,后期會繼續維護。
項目地址:
https://github.com/mabeijianxi/small-video-record.
2
使用方法
1:添加依賴
compile 'com.mabeijianxi:small-video-record:1.2.0'
2:在manifests里面添加
<activity android:name="mabeijianxi.camera.MediaRecorderActivity"/>
3:在Application里面初始化小視頻錄制:
4:跳轉錄制界面:
3
原理講解
基本過程就是調用系統camera與AudioRecord得到視頻和音頻的byte回調,然后出入配置好參數FFmpeg,結束后得到目標視頻。
(1)配置Camera參數:
首先我們錄制的視頻是豎著的,所以需要旋轉90°(默認是橫屏錄制):camera.setDisplayOrientation(90);
然后設置顯示控件:camera.setPreviewDisplay(mSurfaceHolder);
幀率設置:這個參數是可傳入的,但是每個攝像頭所支持的大小是不一樣的,所以你傳入maxFrameRate我會再校驗一遍,如果當前攝像頭支持此幀率那么就使用,如果不支持那么就選擇個最接近且小于它的,如果你值很小有可能還是找不到,這時就選擇最小的一個,具體算法如下:
攝像頭輸出尺寸設置:
通過系統API mParameters.getSupportedPreviewSizes()可以得到當前攝像頭所支持的尺寸,注意這里返回的Size里面其height對應的屏幕短邊,width對應的是屏幕長邊,也就是說我們也要校驗傳入的smallVideoWidth是否支持,當然smallVideoHeight不需要校驗,
因為是小視頻,我們到時候說不定還會剪切掉一部分,校驗完成即可得到傳入的smallVideoWidth所對應的且攝像頭所支持的對應高度,把這個寬高設置上即可。常見的smallVideoWidth 有480、720、1080等等。
具體如下:
設置采樣率:
常用格式有兩種:NV21 / YV12,mParameters.setPreviewFormat(ImageFormat.NV21)
(2)接收設備并傳入FFmpeg音(音頻具體可參考AudioRecorder類)視頻數據:
這里首先需要知道幾個FFmpeg命令:
-vf 可以添加濾鏡,特別強大,可以旋轉縮放剪切等等,我們需要用到旋轉和剪切(我一直考慮需不需要用縮放的方式,因為這樣可以在預覽界面設置高分辨率看著清晰一些)。
transpose,旋轉,對應的值有0、1、2、3,0:逆時針旋轉90°然后垂直翻轉1:順時針旋轉90°,2:逆時針旋轉90°,3:順時針旋轉90°然后水平翻轉。
剪切,關鍵字是crop,其有四個參數,分別是寬度、高度、其實剪切位置的X值與Y值,如ffmpeg -i a.mp4 -vf crop=480:360:0:0...;
-vcodec 指定視頻編解碼器;
-acodec 指定音頻編解碼器;
vbr 動態碼率;
cbr 靜態碼率;
-crf 視頻質量等級051,越大質量越差,建議1828即可,與cbr模式不兼容;
-preset 轉碼速度,快慢的優劣應該都懂的,可根據自己業務場景設置,具體有:ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、placebo;
-i 指定輸入;
-x264opts 配置其編解碼參數;
maxrate 最大碼率;
bitrate 固定碼率;
-f 輸出格式;
-s 設置幀大小。格式為 ‘wxh’;
-ss 指定開始時間;
-vframes 指定多少幀;
接著皆可在錄制前配置我們的錄制參數:
我們這里設置了旋轉濾鏡與剪切濾鏡,由于我們錄制豎屏視頻所以旋轉90°,然后剪切為我們制定的視頻尺寸。當然里面還有三個get函數,分別是視頻質量等級、轉碼速度、碼率模式。
視頻質量等級命令為-crf [size]:
轉碼速度命令為-preset [what]:
[圖片上傳中。。。(8)]
碼率模式: 碼率模式分為vbr與cbr,我在里面加了三個類AutoVBRMode、VBRMode、CBRMode,三者都可傳入轉碼速度。如果不想管那么多那么只需傳入無參的AutoVBRMode對象即可,只有AutoVBRMode模式下可以傳入視頻質量等級值,這個值將最大程度上控制視頻質量。VBRMode模式下可以指定最大碼率與額定碼率。、CBRMode模式下出入一個固定碼率即可。
[圖片上傳中。。。(9)]
配置好后即可開始錄制,在camera的數據回調里面把數據轉入底層。
[圖片上傳中。。。(10)]
(3)多段視頻合并
錄制過程中我們可以暫停錄制,這個可能生成n段短視頻,這個我們就需要合并視頻了,利用FFmpeg命令也可以輕松實現:
[圖片上傳中。。。(11)]
這里視頻和音頻的編解碼器使用原始數據的即可,命令為-vcodec copy -acodec copy這樣速度回比較快,-absf表示為匹配的流設置比特流過濾器,當然還有-vbsf,最新的指定方式是-bsf:v
(4)進一步轉碼壓縮
如果沒有設置 doH264Compress 參數那么將不執行以下邏輯
[圖片上傳中。。。(12)]
上面我們指定了視頻編解碼器為libx264,音頻編解碼器為libfdkaac,然后跟你個性化沖入的doH264Compress 參數進行壓縮,結束后我們就得到了壓縮好的視頻了。
(5)截取視頻中的一幀作為封面
[圖片上傳中。。。(13)]
總結
本庫的優點是簡單便捷,可控性強,后期將繼續維護。
缺點是FFmpeg優點老,后期會考慮自己編譯一份,那時利用FFmpeg玩轉Android視頻錄制與壓縮(二)也就出來了,優點開始期待了,有興趣的同學
注意:
編譯環境請滿足:targetSdkVersion<=22
出現 java.lang.UnsatisfiedLinkError錯誤可以嘗試在gradle.properties中添加:android.useDeprecatedNdk=true,然后在主module的build.gradle中配置ndk {abiFilters "armeabi", "armeabi-v7a"}
歡迎到我github上指教
https://github.com/mabeijianxi/small-video-record本文由馬北劍西投稿。
馬北劍西的博客地址:
http://blog.csdn.net/mabeijianxi/
之前還推送給過一篇:仿微信視頻拍攝UI, 基于ffmpeg的視頻錄制編輯,可以一起學習~
1
概述
本庫暫時是在秒拍開源庫上做的二次開發,旨在開發簡單好用高效的視頻錄制庫。本篇文檔只涉及Java層次邏輯,正在業余修煉c語言與JNI相關的東西,如果有幸寫第二篇文章,那時將對其做更深入的剖析,如FFmpeg編譯、JNI相關代碼編寫。
效果圖:
[圖片上傳中。。。(1)]
功能描述:
利用FFmpeg錄制定制化的視頻,并可對其定制化的壓縮處理。如設置視頻尺寸、設置碼率、碼率模式、幀率、視頻質量等級、壓縮速度等等,當然這些只是暫時的,后期會繼續維護。
項目地址:
https://github.com/mabeijianxi/small-video-record.
2
使用方法
1:添加依賴
compile 'com.mabeijianxi:small-video-record:1.2.0'
2:在manifests里面添加
<activity android:name="mabeijianxi.camera.MediaRecorderActivity"/>
3:在Application里面初始化小視頻錄制:
4:跳轉錄制界面:
3
原理講解
基本過程就是調用系統camera與AudioRecord得到視頻和音頻的byte回調,然后出入配置好參數FFmpeg,結束后得到目標視頻。
(1)配置Camera參數:
首先我們錄制的視頻是豎著的,所以需要旋轉90°(默認是橫屏錄制):camera.setDisplayOrientation(90);
然后設置顯示控件:camera.setPreviewDisplay(mSurfaceHolder);
幀率設置:這個參數是可傳入的,但是每個攝像頭所支持的大小是不一樣的,所以你傳入maxFrameRate我會再校驗一遍,如果當前攝像頭支持此幀率那么就使用,如果不支持那么就選擇個最接近且小于它的,如果你值很小有可能還是找不到,這時就選擇最小的一個,具體算法如下:
攝像頭輸出尺寸設置:
通過系統API mParameters.getSupportedPreviewSizes()可以得到當前攝像頭所支持的尺寸,注意這里返回的Size里面其height對應的屏幕短邊,width對應的是屏幕長邊,也就是說我們也要校驗傳入的smallVideoWidth是否支持,當然smallVideoHeight不需要校驗,
因為是小視頻,我們到時候說不定還會剪切掉一部分,校驗完成即可得到傳入的smallVideoWidth所對應的且攝像頭所支持的對應高度,把這個寬高設置上即可。常見的smallVideoWidth 有480、720、1080等等。
具體如下:
設置采樣率:
常用格式有兩種:NV21 / YV12,mParameters.setPreviewFormat(ImageFormat.NV21)
(2)接收設備并傳入FFmpeg音(音頻具體可參考AudioRecorder類)視頻數據:
這里首先需要知道幾個FFmpeg命令:
-vf 可以添加濾鏡,特別強大,可以旋轉縮放剪切等等,我們需要用到旋轉和剪切(我一直考慮需不需要用縮放的方式,因為這樣可以在預覽界面設置高分辨率看著清晰一些)。
transpose,旋轉,對應的值有0、1、2、3,0:逆時針旋轉90°然后垂直翻轉1:順時針旋轉90°,2:逆時針旋轉90°,3:順時針旋轉90°然后水平翻轉。
剪切,關鍵字是crop,其有四個參數,分別是寬度、高度、其實剪切位置的X值與Y值,如ffmpeg -i a.mp4 -vf crop=480:360:0:0...;
-vcodec 指定視頻編解碼器;
-acodec 指定音頻編解碼器;
vbr 動態碼率;
cbr 靜態碼率;
-crf 視頻質量等級051,越大質量越差,建議1828即可,與cbr模式不兼容;
-preset 轉碼速度,快慢的優劣應該都懂的,可根據自己業務場景設置,具體有:ultrafast、superfast、veryfast、faster、fast、medium、slow、slower、veryslow、placebo;
-i 指定輸入;
-x264opts 配置其編解碼參數;
maxrate 最大碼率;
bitrate 固定碼率;
-f 輸出格式;
-s 設置幀大小。格式為 ‘wxh’;
-ss 指定開始時間;
-vframes 指定多少幀;
接著皆可在錄制前配置我們的錄制參數:
我們這里設置了旋轉濾鏡與剪切濾鏡,由于我們錄制豎屏視頻所以旋轉90°,然后剪切為我們制定的視頻尺寸。當然里面還有三個get函數,分別是視頻質量等級、轉碼速度、碼率模式。
視頻質量等級命令為-crf [size]:
[圖片上傳中。。。(7)]
轉碼速度命令為-preset [what]:
[圖片上傳中。。。(8)]
碼率模式: 碼率模式分為vbr與cbr,我在里面加了三個類AutoVBRMode、VBRMode、CBRMode,三者都可傳入轉碼速度。如果不想管那么多那么只需傳入無參的AutoVBRMode對象即可,只有AutoVBRMode模式下可以傳入視頻質量等級值,這個值將最大程度上控制視頻質量。VBRMode模式下可以指定最大碼率與額定碼率。、CBRMode模式下出入一個固定碼率即可。
[圖片上傳中。。。(9)]
配置好后即可開始錄制,在camera的數據回調里面把數據轉入底層。
[圖片上傳中。。。(10)]
(3)多段視頻合并
錄制過程中我們可以暫停錄制,這個可能生成n段短視頻,這個我們就需要合并視頻了,利用FFmpeg命令也可以輕松實現:
[圖片上傳中。。。(11)]
這里視頻和音頻的編解碼器使用原始數據的即可,命令為-vcodec copy -acodec copy這樣速度回比較快,-absf表示為匹配的流設置比特流過濾器,當然還有-vbsf,最新的指定方式是-bsf:v
(4)進一步轉碼壓縮
如果沒有設置 doH264Compress 參數那么將不執行以下邏輯
[圖片上傳中。。。(12)]
上面我們指定了視頻編解碼器為libx264,音頻編解碼器為libfdkaac,然后跟你個性化沖入的doH264Compress 參數進行壓縮,結束后我們就得到了壓縮好的視頻了。
(5)截取視頻中的一幀作為封面
總結
本庫的優點是簡單便捷,可控性強,后期將繼續維護。
缺點是FFmpeg優點老,后期會考慮自己編譯一份,那時利用FFmpeg玩轉Android視頻錄制與壓縮(二)也就出來了,優點開始期待了,有興趣的同學
注意:
編譯環境請滿足:targetSdkVersion<=22
出現 java.lang.UnsatisfiedLinkError錯誤可以嘗試在gradle.properties中添加:android.useDeprecatedNdk=true,然后在主module的build.gradle中配置ndk {abiFilters "armeabi", "armeabi-v7a"}
歡迎到我github上指教
https://github.com/mabeijianxi/small-video-recordhttp://keeganlee.me/post/android/20150830