關於ffmpeg必須知道的

1、ffmpeg.exe只是一個外圍程序,其核心邏輯在libavcodec.dll和libavformat.dll,libavdevice.dll等

之所以是外圍,相當於一個GUI,也就是說基於這些dll,你可以寫自己的外圍程序,比如做成特別的功能齊全的錄屏軟件或windows GUI的轉碼軟件

2、libavcodec超過30mb,要想變小必須自己編譯ffmpeg,放棄大量對你無用的encoder和decoder,這樣可以降到2MB以內

3、ffmpeg錄屏

如果使用gdigrab只能支持錄製20fps以內的,以上將導致cpu佔比超過30%,而且如果同時錄音的話,則會產生巨大的幀延遲

ffmpeg.exe -y -rtbufsize 100M -f gdigrab -framerate 15 -offset_x 0 -offset_y 0 -video_size 1920x1080 -draw_mouse 1 -i desktop -f dshow -i audio="麥克風 (Realtek High Definition Au" -c:v libx264 -r 15 -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p -c:a libmp3lame -qscale:a 4 "output-grab15.mp4"

 

 

如果使用creen-capture-recorder雖然可以達到30fps,但是cpu佔比高達50%以上

 

4、ffmpeg -h encoder=libx264可以查看支持什麼pixformat

我嘗試過通過c++程序直接把rgba數據格式AV_PIX_FMT_BGRA(ARGB)直接avcodec_encode_video2到x264格式的mp4文件,會提示[libx264 @ 004b1e60] Specified pixel format bgra is invalid or not supported,通過上述命令可以查到:

Encoder libx264 [libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10]:

    General capabilities: delay threads

    Threading capabilities: auto

    Supported pixel formats: yuv420p yuvj420p yuv422p yuvj422p yuv444p yuvj444p nv12 nv16 nv21

可以說mp4只支持yuv系列的數據格式,這些格式中以yuv420p爲主,是ffmpeg的默認編碼輸入的格式。

 

5、關於yuv420p格式:

yuv420p格式,如果不經過準確處理,會導致嚴重的失真,原因是yuv格式並不是無損格式,只是損失比較小,但是其大小確實比rgb24格式節省了一半的存儲空間。

 

如rgb經過變換yuv格式,再變換回rgb格式後,絕對值的和(absSum(r,g,b))要比原來有2-30的誤差,導致顏色有一些細微變化。

在我的轉換中,雖然清晰度很高,但是某些細微的地方總是出現顏色變化,特別是亮度明顯比原來變暗。

但是swscale內部的變換代碼卻能比較好的處理這種格式,覺察不出有顏色變化,如果有人能從ffmpeg裏面提取一個rgb2yuv420p的函數,請告知一下。

而yuv420p2rgb的函數在https://github.com/FFmpeg/FFmpeg/blob/master/libswscale/yuv2rgb.c或http://www.fourcc.org/fccyvrgb.php 找到,或者使用swscale內部的函數:

 SwsContext   *img_convert_ctx= sws_getContext(w,h,AV_PIX_FMT_BGRA, w,h,AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);  

int op=sws_scale(img_convert_ctx, (const unsigned char* const*)srcFrame->data, (const int*)srcFrame->linesize, 0,h, dstFrame->data, dstFrame->linesize);  

 

記得linesize都是一個二維數組,必須對srcFrame進行初始化才能成功,或則會提示數據沒有對齊的錯誤

 

對於rgba數據,必須這樣初始化:

AVFrame *srcFrame = av_frame_alloc(); 

srcFrame ->data[0]=in_frame_data;//rgba的數據

srcFrame ->linesize[0]=in_linesize;//像素個數x4

這樣轉換的yuv420p數據就會轉換到srcFrame->data裏面

 

6、其他關於錄屏的方案

1、先錄製yuv420p的文件、pts時間文件和音頻文件再後期通過ffmpeg轉成mp4

這個方案可以支持的fps應該是最高的,25fps的錄製,cpu佔有率不會高於20%

風險:視頻和音頻對不上,而且所需的磁盤文件極爲極大,1920x1080的25fps視頻60分鐘需要超過1T的存儲空間。

正方意見:專業電影錄製的時候也是音頻和視頻分開錄製的

反方意見:錄個屏幕,你有多少時間和精力做後期的處理?又有多少個高速硬盤可以用來錄屏?

所以,該方案對於非專業級的需求,是很不經濟的。

 

2、用ffmpeg.exe命令行錄製音頻和視頻,對於一般要求,這個基本可以解決問題,但是可控度不高

比如不能暫停,出錯不能及時得到通知,不能分文件保存。有點就是無需任何開發工作。這點優勢也是高到天花板上去了。

 

3、就是利用libavxxx.dll這些共享dll,開發自己的程序,以實現暫停、及時反饋、分文件

這個就需要開發了,雖然開發工作不算多,但是爲了穩定運行,對ffmpeg的api要有比較詳細的認知。否則性能和穩定性還不如ffmpeg本身。

 

以上僅爲備忘。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章