關於使用ffmpeg的一些牢騷

 

1、囉嗦幾句python

好幾年不寫博客了,一是工做計算機都加密了無法編輯提交;二是各類語言混用,什麼都會就是什麼都不會,delphi、c#、vb、python、c++要說我精通啥,啥也不精,因此不敢亂寫。c++

最近作一個關於視頻處理的項目,用到ffmpeg,實在是憋不住,在此記錄一下摸索的過程。能夠絕不誇張的說,網上關於ffmpeg的使用,大部分用命令行方式,調用api方式的不多,並且盲目抄襲甚盛,斗膽妄言,罪過罪過。編程

 

2、感謝c#

我是經過學習雷神的博客逐漸掌握了ffmpeg的一些東西,好歹把項目作完了,效果很好,在此向雷神由衷的表示感謝。雷神由淺入深的介紹了ffmpeg的使用方法,有理論有實踐,能夠說網上的不少文章很難與雷神媲美,並且國內這方面的文章太少了,這麼多作視頻方面的,怎麼就沒有這方面的優質文章,在此是個疑點。惋惜的是雷神花費了大量時間開放本身的學習探索的心得,當逐步的到達核心地帶時,戛然而止,雷神去世了,天妒英才吶。在此沉痛緬懷並致以崇高的敬意!api

在本文中,沒有直接可運行的代碼,一是加密,沒法拷貝;二是提倡動手實踐,先把雷神的實例代碼挨個學習調試,自會有極大的提升;緩存

 

3、項目背景編程語言

核心一句話:接收高清視頻流(H264+mp3 TS流),每30分鐘存儲一個mp4文件,相鄰兩個文件的播放要順暢不能丟幀。爲啥說是高清呢,30分鐘文件就有5個G。學習

編程語言c++測試

 

4、踩過的坑加密

4.1進程方式

網上不少文章都是用命令行的,這種方式只能說測試還行,真正項目應用差點意思了,由於你要管理這個進程,他是個什麼狀態,你不知,但你又不能無論,關鍵作不到先後兩個視頻無縫銜接,咋整,雞肋啊,作個測試、驗證等能夠,作項目不行。用api吧,資料太少,項目組意見不一,最後舉個例子達成一致了,前面有個碉堡,咱們明知道用手榴彈不行,還堅持讓你們扔手榴彈,這是瞎耽誤工夫;拿zha yao確定行,可是有人得犧牲(扔手榴彈站在遠處扔就行,zha yao包得有人扛到跟前),要想完全解決就得用完全的辦法。因此不少時候咱們缺乏的就是沉下心的耐力和扛zha yao包的勇氣,潰癰雖痛勝於養毒,把雷神用api的例子所有從頭調試一遍,總結出流程,都須要哪些要素,時間基、採樣率、音視頻流是啥用來作啥,搞明白就完事了。

4.2 ffmpeg rtp

ffmpeg能夠直接接收RTP,也有提供轉換MP4的方法,要注意的是接收和處理放在一個線程中有問題,容易丟幀,由於UDP通訊必須設置緩存大小,可是一旦處理堵住了,數據絕對會丟失。程序在現場長時間不間斷運行,很難保證不出現丟幀的狀況,經簡單測試,直接拋棄該方式。

5、個人實現方法

一、使用UDP方式接收組播視頻流,並寫入文件中,文件按時間命名。

二、當檢測到夠30分鐘時,中止寫入當前文件,開始寫入另外一個文件。

三、通知視頻轉換線程,處理當前寫完的文件。

四、視頻轉換線程,讀取文件,

打開輸入文件流(avformat_open_input),

建立輸出上下文(avformat_alloc_output_context2),咱們要根據文件轉成mp4。

查找視頻信息(avformat_find_stream_info),查找輸入的碼流:視頻流、音頻流、字幕流。

根據輸入碼流建立輸出碼流,流的參數拷貝就行(avcodec_parameters_copy),特別要注意的是輸入輸出流的時間基(time_base)。

打開輸出流,寫入文件頭,設定一個文件結尾的閾值,當輸入流剩餘字節數小於該值時而且找到最後一個關鍵幀,則寫入到輸出流後,將剩餘輸入文件的結尾置換到下一個文件的開頭中,這樣先後兩個文件無縫銜接,第一個文件最後一個關鍵幀是第二個文件開頭的第一幀,因此無縫銜接了。

循環讀取輸入流(av_read_frame)根據流索引肯定是音頻仍是視頻流,若是是視頻流寫入文件的第一幀必須是關鍵幀。寫入時特別注意音頻和視頻的pkt的時間(pts、dts、duration)須要根據本身的時間基從新換算(av_rescale_q_rnd),並記錄第一幀的時間戳pts,換算後的pts和dts要減去第一幀的pts,這樣每一個文件播放就是從頭開始了。寫入輸出流用av_interleaved_write_frame。

讀取文件轉換成mp4,在現場機器(高速緩存設備)上總共須要不到15秒鐘。

6、最終效果

項目部署5個多月,內存(103M左右,峯值180M)、cpu(3%--8%),很是穩定,無異常崩潰退出,視頻無馬賽克、先後視頻銜接很棒。

 

7、總結

堅持實踐就是硬道理,不管什麼職位、角色都不能眼高手低。

抄別人代碼一千遍不如本身動手調一遍。

相關文章
相關標籤/搜索