本演講主要講解如何通過FFmpeg作爲一個主要的接口,將OpenGL、OpenCV以及諸如Tensorflow等AI框架以第三方庫的形式,作爲FFmpeg的一個模塊進行快速的業務開發,從而簡化音視頻圖像處理的開發流程,爲聽衆打開一個新思路。
文 / 劉歧
整理 / LiveVideoStack
審校/ 趙軍
感謝大家關注FFmpeg在OnVideo以及AI方面的一些工作,我是劉歧,是OnVideo聯合創始人的同時也擔任技術負責人,同時也是FFmpeg的官方顧問,FFmpeg GSoC 2019 Mentor,FFmpeg決策委員會的委員,以及騰訊雲TVP。我主要的興趣在嵌入式開發、圖形圖像及音視頻流媒體處理、分布式系統設計等領域。FFmpeg官方有我的聯系方式,大家有問題可以和我隨時交流。關于FFmpeg深度學習場景下的應用,目前看來,頗具價值且實用。
1. 契機
首先介紹一下我們的公司,OnVideo是一個音視頻在線編輯雲平台,上圖是制作人員的處理過程中效果預覽這個功能的一個展示。OnVideo雲平台可以支持很多的圖像處理相關功能,但實際上它並不限于視頻和圖片相關,它大量的使用了FFmpeg的一些內置功能以及AI相關的框架與算法,其具體功能大約如下圖所示:
另外一個需要附帶提及的事情是我在2019年Google Summer of Code期間指導學生做的一個深度學習相關FFmpeg Mentor Project,這是一個基于神經網絡實現對圖像進行去雨點、去霧的功能(本質上這兩個是類似的功能),最終實現並放入了FFmpeg。
在做FFmpeg GSOC項目期間,首先和有意願的學生事先溝通,然後在FFmpeg社區以及GSOC上申請立項,之後是與學生溝通要達到去雨點去霧的功能要點,做出實際的開發計劃任務,緊接著,我安排並引導學生去了解了FFmpeg的一些基本功能以及相關原理,隨後實現了去雨點去霧的功能,需要注明的是,FFmpeg目前的去雨點,去霧使用了基于AI的方式,目前FFmpeg同時支持兩類後端,其中一個是FFmpeg native的DNN後端,但性能較差,主要用作驗證,另一個是可以在實際場合中部署的TensorFlow後端。上圖展示了最終的一個結果,圖中上半部分爲原圖,下面是對應去雨點去霧的圖像,需要注意,雖然目前的實現基本上能解決大部分的問題了,例如天氣惡劣的環境采集的圖像後期處理,通過這種技術可以節省很多時間,但更廣泛的現實場景是有可能會存在一些瑕疵,這可能是目前AI算法普適性的一個通用問題。接下來重點分享一下onVideo中更細節的一些技術內容。
2. 初級處理
做音視頻的雲端處理,尤其是Web-base的場景,最忌諱的是前端Web部分預覽看到的內容與後端實際生成的結果不一致,會導致非常尴尬的用戶體驗,我們的第一步就需要將Codec格式統一化,此步會在雲端進行處理,對于輸出,在客戶要求的情況下,我們會給到高清版本,否則就給到低清版本,原因是高清版本流量消耗較大,會耗費很多帶寬;另外,實際使用中,常規的預覽並不真正需要高清,除非用戶有特別需求。另外,爲了後期在後端處理更快,會將所有內容變成I幀,這樣的好處是可以精確處理到幀;其次,我們也使用了FFmpeg提供的一些基礎的濾鏡,概述如下:
畫字體(FFmpeg的字體功能使用了FreeType等),爲了解決其中一些瑕疵(例如某些系統下的文字大小粗細不一致)嘗試過更改drawtext,但效果不理想;另外,如果字體找不到的話,那會變成一小方塊,此時只需要換一個字體庫即可。再就是subtitle,唱詞的時候用subtitle,例如電影中的字幕,可以切爲一段一段。
在平時我們做視頻切片處理的時候,會有一個問題,在生成一個視頻之後,所有視頻的start time全都會歸零,在切片時,需要將多軌道的時間都對上,所以setpts和asetpts、adelay、atempo這些功能強大的Filter,在處理音視頻的編輯中,例如多軌道疊加或者邊緣對齊等需求下,起了非常大的作用。我寫過一篇關于setpts的文章,大家有興趣可以去閱覽一下。
overlay多圖層:有時候我們並不只是要求單純的設x,y,也需要同時需要調整寬高,但overlay不直接支持寬高的調整,這可以通過一些簡單的開發,例如增加前景寬高處理用來做縮放效果,或者還有一些其他效果例如使用expr的辦法。另外,FFmpeg有內置方法,可以直接做一些想要的效果,例如跑馬燈效果,遊動效果等;甚至于導播台中,在直播的過程當中,推出去一個視頻流,可以通過利用zmq的方式動態的改一個logo,或者是加字幕。
chromakey:與colorkey類似,chromakey主要是以 YUV處理爲主,colorkey主要以RGB處理爲主,二者均只支持摳單色。例如扣綠幕背景時,將其中的代碼稍作修改(增加diff值的計算)即可改善摳圖的小瑕疵問題。如果是雜色背景,就需要多次摳圖或者利用AI的方式,再或者邊緣檢測等方式。
crop:剪切處理,國內經常看到的視頻是16:9/9:16/3:4/4:3的分辨率,但如果把視頻發到Twitter上,則看到大多數是以1:1的分辨率顯示的,就需要進行crop裁剪處理;除去上述這些Filter以外,我們還使用了boxblur、avgblur等。
3. 進一步圖像處理
一些基本的處理功能介紹完畢之後就需要考慮關于性能的問題。
3.1 如何解決FFmpeg某些濾鏡處理性能差的問題
以overlay爲例,早期用overlay等Filter是順序處理的,是一個簡單的單線程處理,我們知道,多數圖像都是decode之後的圖像,多數都是yuv格式,是一個點一個點打上去的圖像,在像素之間沒有關聯的情況下,可以考慮充分利用多核,進行多線程處理。這是FFmpeg Filter內部的一個優化點。
分布式處理:通過引入timeline的概念,不同的軌道對應各自的timeline,在進行多個軌道切片的時候,通過timeline進行對應匹配。此方法的性能使得可以在數秒至一分鍾之內快速處理完成一個1小時長度的視頻任務。
OpenGL優化:在用FFmpeg做圖像移動,放大效果動畫,縮小效果動畫,旋轉效果動畫等圖像動態效果時,圖像會有抖動感;可以在遇到圖像抖動情況通過此方式處理。
使用分布式+FFmpeg+OpenGL,是我本人處理這些問題的基本做法。
3.2 單獨使用FFmpeg的一些問題
單獨使用FFmpeg tools某些場景下可能會出現性能差、運動不平滑、計算量大、擴展不方便和升級開銷大的問題,因此團隊開始考慮如下的一些優化,嘗試把FFmpeg和OpenGL結合起來,解決性能問題。
3.3 利用FFmpeg+OpenGL方式處理
上圖所示,是利用FFmpeg API +OpenGL API方式處理的流程圖。但利用FFmpeg API+OpenGL API方式處理的特點是開發成本高、技能融合模糊,因爲開發人員全部都要精通(指同時知曉FFmpeg API的使用,OpenGL API的使用),很難短時間找到這樣的合適的開發人員,不太適合創業型小公司,所以團隊采用了下面的方式避過這個問題.
3.4 FFmpeg內置OpenGL
采用FFmpeg融合了OpenGL,但並不直接touch OpenGL的優化部分,這部分又精通OpenGL的開發人員之間使用GLSL優化,而FFmpeg開發者只關心怎麽把FFmpeg作爲一個通用的Filter放入進來,最終是將圖像算法處理和音視頻編解碼處理分開,開發層次會更加清晰,如上圖所示爲升級優化之後的處理流程。FFmpeg內置OpenGL的方法處理的優勢是可以一勞永逸、不同專業的人員做不同專業的事情。
專業的人員處理專業的事情之後,我們需要的就是將執行步驟抽象爲接口,再利用插件(Plugin)將內容按照接口進行處理。
3.5 FFmpeg與OpenCV的配合
由于OpenCV的特點,它在3.0版本之後全面擁抱C++,因此FFmpeg只能使用舊版本,但是我們還是需要用一些新版本的OpenCV的功能。面對這種情況,我們只能自己抽象需要的接口,再做成so,先完成導入後再進行處理。
4. AI融合
自2018年起,FFmpeg GSOC項目開始集成CUDNN以及TensorFlow框架,使得它調第三方程序即可實現超分辨率或者直接使用FFmpeg內置的CUDNN模塊。需要提及一下,如果直接用FFmpeg內置的DNN,性能很差,甚至會慢到0.001的倍速,它指使用了CPU資源,且沒做任何優化,基本上用作算法的驗證,不能作爲線上實際使用的後端。在FFmpeg的AI框架下,目前還支持了SDR轉HDR、去雨點去霧處理以及智能插幀(還在開發中)。
關于Native DNN的支持,主要處理以上幾個接口即可。
目前AI部分需要自己單獨進行模型(Model)訓練,在以前,FFmpeg使用這些Model的時候需要自己轉換Model爲PB文件,目前通過處理後直接提供Model文件即可。
5. 總結
一個創業團隊的初期會按照最簡單迅速的方式演進,因此我們團隊初期全部使用FFmpeg,在應用過程中,功能快速跑起來時發現了一系列問題,根據經驗和團隊成員各自擅長的部分進行針對處理,最後在考慮性能時加入了分布式的方法。