高性能且靈活的 iOS 視頻剪輯與特效開源框架 – VideoLab

點擊上方“LiveVideoStack”關注我們

隨着移動互聯網時代的到來,短視頻成爲了最流行的內容載體,而內容的產生離不開視頻剪輯與特效創作工具。本次LiveVideoStackCon 2021 音視頻技術大會 北京站,我們邀請到了RingCentral Video 移動端架構師——阮景雄,他向我們分享了AVFoundation視頻剪輯框架,以及VideoLab框架的設計與實現。


 | 阮景雄

整理 | LiveVideoStack

大家好,我是 來自RingCentral的阮景雄,今天分享的主題是,高性能且靈活的iOS視頻剪輯與特效開源框架VideoLab。


今天的分享主要包含以上六個方面,首先會對個人及公司做個簡介,其次會介紹VideoLab是什麼,第三點會介紹VideoLab的技術選型,第四點介紹AVFoundation框架,接着會介紹VideoLab的設計與實現,最後會介紹VideoLab後續的計劃。

 

1. 個人及公司簡介

首先,先介紹下個人及公司。



我是2013年畢業入職美圖,在2015年開始擔任美圖美拍iOS的負責人,在去年7月份入職了RingCentral,職位是移動端架構師。在美圖 7 年期間,在視頻處理、視頻採集、視頻播放、直播、社區等幾個領域都有涉獵。在RingCentral,負責的業務主要是移動端的架構和iOS平臺模塊化的演進。


接着簡單介紹下RingCentral,從右邊的圖可以看出我們公司主要包含 Message/Video/Phone三塊業務。Message是最右下角的IM聊天,Video是視頻會議,Phone是最早的打電話功能。我們公司連續七年獲得統一通信及服務的領導者,總部位於美國硅谷,鈴勝中國成立於 2011,目前在杭州,廈門,香港均有辦公室。

 

2. VideoLab 是什麼?

接着讓我們來聊下VideoLab是什麼?



首先,來看一些關鍵字:高性能,靈活,視頻剪輯,特效,開源框架,iOS,Swift,Metal,AVFoundation。這些關鍵字組合成一塊就解釋了VideoLab是什麼。


讓我們來看下當前已有的一些Feature,當前已經支持了高性能實時剪輯與導出,高自由度組合視頻、圖片、音頻,支持音頻音高設置、音量調節,支持CALayer矢量動畫及複雜的文字動畫,支持關鍵幀動畫,支持類似於After Effect的預合成,支持轉場,支持自定義各類特效。



讓我們來看下一些Gif的示例,第一張圖片是多圖層的一個示例,組合了三個視頻,一張圖片。第二張是一個拆字的文字動畫。第三張是漸隱漸顯加Transform的關鍵幀動畫。第四張是類似AE裏預合成的動畫。第五張是zoom blur轉場的示例。

 

3. 框架技術選型

接着讓我們來談談框架的技術選型。



說到框架選型,難免提到一些友商。Videoleap是業界的標杆了,它是國外的一家公司,它的母公司出了非常多剪輯和圖片處理的APP。剪映是頭條出品,目前在國內做的也是非常好。VN 也是國內的,整體體驗還不錯。


在體驗完競品之後,對它們做了個逆向,Videoleap使用的是AVFoundation + OpenGL,剪映主要是AVFoundation + GPUImage,VN 是AVFoundation + CoreImage。再看我之前工作的美拍,它最早是用的AVFoundation + GPUImage,因爲那會時間比較早,所以都是直接用AVAssetReader + AVAssetWriter,後面轉成了FFmpeg + OpenGL。


在有了這些備選方案之後,我在想要做一個沉澱,要寫一個框架,能不能有一些其他選擇?然後我就選了AVFoundation + Metal,Metal是蘋果自家的渲染引擎,也是蘋果這幾年力推的主力之一,每年的WWDC都可以看到蘋果關於Metal的topic。

 

4. AVFoundation框架

接着我們來介紹下AVFoundation視頻剪輯的框架。



首先來看下AVFoundation視頻剪輯的整體工作流程:


第一步,創建一個或多個AVAsset。AVAsset是有時間的,模擬音視頻實體的對象。


第二步,創AVComposition、AVVideoComposition以及 AVAudioMix。其中AVComposition指定了音視頻軌道的時間對齊,AVVideoComposition 指定了視頻軌道在任何給定時間點的幾何變換與混合,AVAudioMix管理音頻軌道的混合參數。這三個對象是視頻剪輯最主要的三個類,可以把第一個類的作用理解爲擺放音視頻軌道,第二個類處理視頻混合,第三個類處理音頻混合。


第三步,我們可以使用這三個對象來創建AVPlayerItem,並從中創建一個AVPlayer來播放編輯效果。


此外,我們也可以使用這三個對象來創建AVAssetExportSession,用來將編輯結果寫入文件。



接下來,讓我們看下AVComposition,AVComposition是一個或多個AVCompositionTrack音視頻軌道的集合。其中AVCompositionTrack 又可以包含來自多個 AVAsset 的AVAssetTrack。右圖的例子,將兩個AVAsset中的音視頻 AVAssetTrack 組合到AVComposition的音視頻AVCompositionTrack中。



設想圖中所示的場景,AVComposition包含兩個 AVCompositionTrack。我們在T1 時間點需要混合兩個 AVCompositionTrack的圖像。爲了達到這個目的,我們需要使用 AVVideoComposition。



AVVideoComposition可以用來指定渲染大小、渲染縮放以及幀率。圖中紫色的部分包含了一組指令,這些指令存儲了混合的參數。有了這些混合的參數之後,可以通過自定義的 Compositor 來混合對應的圖像幀。


整體工作流如圖所示,接受指令,把原視頻幀通過合成器,生成合成後的幀,輸出給播放器或者導出器。讓我們聚焦到合成器,我們有多個原始幀,需要處理並輸出新的一幀。


流程可分解爲:


  • AVAsynchronousVideoCompositionRequest綁定了當前時間的一系列原始幀,以及當前時間所在的 Instruction。
  • 收到startVideoCompositionRequest: 回調,並接收到這個 Request。
  • 根據原始幀及Instruction 相關混合參數,渲染得到合成的幀。
  • 調用finishWithComposedVideoFrame,交付渲染後的幀。



AVAudioMix在AVComposition的音頻軌道上處理音頻。包含一組AVAudioMixInputParameters,每個Parameters對應一個音頻的 AVCompositionTrack。右邊的圖片是一個示例,可以看到AVCompositionTrack和AVAudioMixInputParameters是一一對應的。

 

5. VideoLab 設計與實現

前面我們介紹了AVFoundation視頻剪輯流程,接下來我們介紹下VideoLab框架的設計與實現。

 


先簡要介紹下AE(Adobe After Effect),AE是特效設計師常用的動態圖形和視覺效果軟件。AE 通過“層”控制視頻、音頻及靜態圖片的合成,每個媒體(視頻、音頻及靜態圖片)對象都有自己獨立的軌道。


圖片是在 AE 中合成兩個視頻的示例。在左上角Project區域內,有名爲Comp1類型爲Composition 的一個合成。在 AE 中合成可以認爲是一個作品,可以播放導出,也可以設置寬高值、幀率、背景色等參數。在下面Timeline Control 區域內,包含了兩個圖層,源分別爲video1.MOV與video2.MOV。我們可以自由的設置圖層參數,如Transform,Audio,也可以在右邊區域自由的移動圖層,達到靈活的組合效果。針對每個圖層,AE裏還可以添加一組特效。


讓我們提取一些關鍵字:Composition合成,Layer圖層,Transform變換,Audio音頻和Source來源。



基於前面對 AE 的分析,我們可以設計相似的描述方式:


RenderComposition,對應AE中的合成。包含一組RenderLayer。此外,RenderComposition還包含BackgroundColor、FrameDuration、RenderSize,分別對應背景色、幀率及渲染大小等剪輯相關參數。


RenderLayer,對應AE中的層。包含了Source、TimeRange、Transform、AudioConfiguration、Operations,分別對應素材來源、在時間軸的時間區間、變換(位置、旋轉、縮放)、音頻配置及特效操作組。


RenderLayerGroup,對應 AE 的預合成。這個Group繼承自RenderLayer,包含一組RenderLayer。可以理解成先把一組視頻或圖片處理完,再去做合成。


KeyframeAnimation,對應 AE 的關鍵幀動畫。包含了KeyPath、Values、KeyTimes、緩動函數數組。


從上面的圖示可以看到,我們可以靈活自由的放置這些區域。



前面介紹了RenderComposition、RenderLayer、RenderLayerGroup 以及KeyframeAnimation。從前面的AVFoundation 介紹可知,我們需要生成AVPlayerItem與AVAssetExportSession 用於播放與導出。因此,我們需要有一個對象可以解析這幾個描述對象,並用AVFoundation 的方法生成AVPlayerItem 與AVAssetExportSession。框架將這個對象命名爲VideoLab,可以理解成這是一個實驗室。


可以看到新的流程,把AVComposition/AVVideoComposition/AVAudioMix都封裝在了VideoLab內。這樣做極大的簡化了開發對AVFoundation的認知,現在和AE比較相似,可以非常方便的組合這些圖層。流程就轉變爲:


  • 創建一個或多個RenderLayer。
  • 創建RenderComposition,設置其BackgroundColor、FrameDuration、RenderSize,以及RenderLayer 數組。
  • 使用創建的RenderComposition創建 VideoLab。
  • 使用創建的VideoLab生成AVPlayerItem或AVAssetExportSession。
  • 新的流程極大的簡化了用戶的使用成本。



那VideoLab是如何把這些描述對象轉換爲AVFoundation的三大對象的呢?


先來看下AVComposition,我們需要給AVComposition分別添加視頻軌道與音頻軌道。如圖所示,這個RenderComposition包含6個RenderLayer,其中一個是RenderLayerGroup。


第一步是將RenderLayer轉換VideoRenderLayer,VideoRenderLayer 是框架內部對象,包含一個RenderLayer,主要負責將RenderLayer的視頻軌道添加到AVComposition中。可轉換爲VideoRenderLayer的 RenderLayer包含以下幾類:1. Source包含視頻軌道;2. Source爲圖片類型;3. 特效操作組不爲空(Operations)。



轉化爲VideoRenderLayer後的第二步是將VideoRenderLayer視頻軌道添加到AVComposition中。從上圖中的例子可以看到,我們有3個視頻軌道,還有一個Blank Video Track。 這裏的空視頻是指視頻軌道是黑幀且不包含音頻軌道的視頻,爲image或只有Operation的VideoRenderLayer服務。

從圖中能看到VideoRenderLayer1和VideoRenderLayer5共用的一個視頻軌道,這是因爲蘋果對視頻軌道有限制,我們需要儘量的重用,每條視頻軌道對應一個解碼器,當解碼器數量超出系統限制時,會出現無法解碼的錯誤。框架視頻軌道重用的原則是,如果要放入的 VideoRenderLayer 與之前視頻軌道的VideoRenderLayer在時間上沒有交集,則可以重用這個視頻軌道,所有視頻軌道都重用不了則新增一個視頻軌道。當然這些其實都不重要,因爲都封裝在了VideoLab裏面。



讓我們接着聊下添加音頻軌道,添加音頻軌道第一步是將RenderLayer 轉換爲AudioRenderLayer,AudioRenderLayer是框架內部對象,包含一個RenderLayer,主要負責將RenderLayer的音頻軌道添到AVComposition中。可轉換爲AudioRenderLayer的RenderLayer只需滿足一個條件:Source包含音頻軌道。轉換AudioRenderLayer之後如右圖所示。



添加音頻軌道的第二步,將AudioRenderLayer視頻軌道添加到AVComposition中,對於RenderLayer的Source包含音頻軌道的AudioRenderLayer,從Source中獲取音頻AVAssetTrack,添加到AVComposition。


如右圖所示,不同於視頻軌道的重用,音頻的每個AudioRenderLayer都對應一個音頻軌道。這是由於一個AVAudioMixInputParameters與一個音頻的軌道一一對應,而其音高設置(audioTimePitchAlgorithm)作用於整個音頻軌道。如果重用的話,會存在一個音頻軌道有多個AudioRenderLayer的情況,這樣會導致所有的AudioRenderLayer都要配置同樣的音高,這顯然是不合理的。

 


接下來介紹一下關於渲染的實現。從前面的AVFoundation介紹可知,AVVideoComposition可以用來指定渲染大小和渲染縮放,以及幀率。此外,還有一組存儲了混合參數的指令。有了這些指令後,AVVideoComposition可以通過自定義混合器來混合對應的圖像幀。


第一步是創建指令,我們會在時間軸上標記每個VideoRenderLayer的起始時間點與結束時間點。然後爲每個時間間隔創建一個Instruction,與時間間隔有交集的VideoRenderLayer,都作爲Instruction的混合參數。


然後我們對前面的Compositor工作流程做一個更新,將混合參數更新爲與Instruction有交集的VideoRenderLayer組。對於混合規則的話,是按層級渲染,從下往上。如當前層級有紋理則先處理自己的紋理,再混合進前面的紋理。



從前面的AVFoundation介紹可知,AVAudioMix用於處理音頻。包含一組的AVAudioMixInputParameters,可以設置實時處理音頻,指定音高算法。音頻混合比較簡單,只要爲每個AudioRenderLayer創建了一個AVAudioMixInputParameters即可。

 

6. VideoLab後續計劃

前面介紹了VideoLab的設計與實現。當然要做一個好的開源框架還需要不斷的完善,接下來介紹一些VideoLab後續的計劃。



首先是支持OpenGL,GL還是目前大多數公司選擇渲染引擎的首選,VideoLab 的規劃是能同時支持Metal + OpenGL,使用方決定渲染引擎使用Metal或Open GL。其次會持續完善特性,如變速、更便捷的轉場使用方式。接下來會開始寫有UI交互的Demo,這樣可能會更直接一些。最後,當然期望VideoLab是可以跨平臺,期望是上層能有統一的C++封裝API,統一設計思路,底下用各自的平臺優勢,比如iOS用AVFoundation 做編解碼,Android用 FFmpeg;iOS用Metal/GL,Android用Vulkan/GL。


最後也是期望能有更多的人蔘與維護,畢竟一個人的能力比較有限,大家一起維護能有更多的未來暢想。


這裏附帶上Github地址:https://github.com/ruanjx/VideoLab


以上是我的全部分享,謝謝大家。





講師招募

LiveVideoStackCon 2022 音視頻技術大會 上海站,正在面向社會公開招募講師,無論你所處的公司大小,title高低,老鳥還是菜鳥,只要你的內容對技術人有幫助,其他都是次要的。歡迎通過 [email protected] 提交個人資料及議題描述,我們將會在24小時內給予反饋。

喜歡我們的內容就點個“在看”吧!

本文分享自微信公衆號 - LiveVideoStack(livevideostack)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

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