您當(dāng)前的位置是:  首頁(yè) > 資訊 > 文章精選 >
 首頁(yè) > 資訊 > 文章精選 >

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

--RingCentral Tech

2022-01-17 14:08:05   作者:文 | 阮景雄(Bear)   來(lái)源:CTI論壇   評(píng)論:0  點(diǎn)擊:


  隨著移動(dòng)互聯(lián)網(wǎng)時(shí)代的到來(lái),短視頻成為了最流行的內(nèi)容載體,而內(nèi)容的產(chǎn)生離不開視頻剪輯與特效創(chuàng)作工具。在LiveVideoStackCon 2021音視頻技術(shù)大會(huì)北京站上,RingCentral Video 移動(dòng)端架構(gòu)師——阮景雄(Bear),向大家分享了AVFoundation視頻剪輯框架,以及VideoLab框架的設(shè)計(jì)與實(shí)現(xiàn)。
  大家好,我是來(lái)自RingCentral鈴盛的阮景雄(Bear)。
  今天分享的主題是《高性能且靈活的iOS視頻剪輯與特效開源框架VideoLab》。
  今天的分享主要包含以上六個(gè)方面,首先會(huì)對(duì)個(gè)人及公司做個(gè)簡(jiǎn)介,其次會(huì)介紹VideoLab是什么,第三點(diǎn)會(huì)介紹VideoLab的技術(shù)選型,第四點(diǎn)介紹AVFoundation框架,接著會(huì)介紹VideoLab的設(shè)計(jì)與實(shí)現(xiàn),最后會(huì)介紹VideoLab后續(xù)的計(jì)劃。
  1. 個(gè)人及公司簡(jiǎn)介
  首先,先介紹下個(gè)人及公司。
  我2020年7月份入職了RingCentral,職位是移動(dòng)端架構(gòu)師。之前的任職工作期間,在視頻處理、視頻采集、視頻播放、直播、社區(qū)等幾個(gè)領(lǐng)域都有涉獵。在RingCentral,負(fù)責(zé)的業(yè)務(wù)主要是移動(dòng)端的架構(gòu)和iOS平臺(tái)模塊化的演進(jìn)。
  接著簡(jiǎn)單介紹下RingCentral鈴盛,從右邊的圖可以看出我們公司主要包含 Message/Video/Phone三塊業(yè)務(wù)。Message是最右下角的IM聊天,Video是視頻會(huì)議,Phone是最早的打電話功能。我們公司連續(xù)七年獲得統(tǒng)一通信及服務(wù)的領(lǐng)導(dǎo)者,總部位于美國(guó)硅谷,鈴盛中國(guó)成立于 2011,目前在杭州,廈門,香港均有辦公室。
  2. VideoLab 是什么?
  接著讓我們來(lái)聊下VideoLab是什么?
  首先,來(lái)看一些關(guān)鍵字:高性能,靈活,視頻剪輯,特效,開源框架,iOS,Swift,Metal,AVFoundation。這些關(guān)鍵字組合成一塊就解釋了VideoLab是什么。
  讓我們來(lái)看下當(dāng)前已有的一些Feature,當(dāng)前已經(jīng)支持了高性能實(shí)時(shí)剪輯與導(dǎo)出,高自由度組合視頻、圖片、音頻,支持音頻音高設(shè)置、音量調(diào)節(jié),支持CALayer矢量動(dòng)畫及復(fù)雜的文字動(dòng)畫,支持關(guān)鍵幀動(dòng)畫,支持類似于After Effect的預(yù)合成,支持轉(zhuǎn)場(chǎng),支持自定義各類特效。
  讓我們來(lái)看下一些Gif的示例,第一張圖片是多圖層的一個(gè)示例,組合了三個(gè)視頻,一張圖片。第二張是一個(gè)拆字的文字動(dòng)畫。第三張是漸隱漸顯加Transform的關(guān)鍵幀動(dòng)畫。第四張是類似AE里預(yù)合成的動(dòng)畫。第五張是zoom blur轉(zhuǎn)場(chǎng)的示例。
  3. 框架技術(shù)選型
  接著讓我們來(lái)談?wù)効蚣艿募夹g(shù)選型。
  說(shuō)到框架選型,難免提到一些友商。Videoleap是業(yè)界的標(biāo)桿了,它是國(guó)外的一家公司,它的母公司出了非常多剪輯和圖片處理的APP。剪映是頭條出品,目前在國(guó)內(nèi)做的也是非常好。VN 也是國(guó)內(nèi)的,整體體驗(yàn)還不錯(cuò)。
  在體驗(yàn)完競(jìng)品之后,對(duì)它們做了個(gè)逆向,Videoleap使用的是AVFoundation + OpenGL,剪映主要是AVFoundation + GPUImage,VN 是AVFoundation + CoreImage。再看我之前工作的美拍,它最早是用的AVFoundation + GPUImage,因?yàn)槟菚?huì)時(shí)間比較早,所以都是直接用AVAssetReader + AVAssetWriter,后面轉(zhuǎn)成了FFmpeg + OpenGL。
  在有了這些備選方案之后,我在想要做一個(gè)沉淀,要寫一個(gè)框架,能不能有一些其他選擇?然后我就選了AVFoundation + Metal,Metal是蘋果自家的渲染引擎,也是蘋果這幾年力推的主力之一,每年的WWDC都可以看到蘋果關(guān)于Metal的topic。
  4. AVFoundation框架
  接著我們來(lái)介紹下AVFoundation視頻剪輯的框架。
  首先來(lái)看下AVFoundation視頻剪輯的整體工作流程
  • 第一步,創(chuàng)建一個(gè)或多個(gè)AVAsset。AVAsset是有時(shí)間的,模擬音視頻實(shí)體的對(duì)象。
  • 第二步,創(chuàng)建AVComposition、AVVideoComposition以及 AVAudioMix。其中AVComposition指定了音視頻軌道的時(shí)間對(duì)齊,AVVideoComposition 指定了視頻軌道在任何給定時(shí)間點(diǎn)的幾何變換與混合,AVAudioMix管理音頻軌道的混合參數(shù)。這三個(gè)對(duì)象是視頻剪輯最主要的三個(gè)類,可以把第一個(gè)類的作用理解為擺放音視頻軌道,第二個(gè)類處理視頻混合,第三個(gè)類處理音頻混合。
  • 第三步,我們可以使用這三個(gè)對(duì)象來(lái)創(chuàng)建AVPlayerItem,并從中創(chuàng)建一個(gè)AVPlayer來(lái)播放編輯效果。
  • 此外,我們也可以使用這三個(gè)對(duì)象來(lái)創(chuàng)建AVAssetExportSession,用來(lái)將編輯結(jié)果寫入文件。
  接下來(lái),讓我們看下AVComposition,AVComposition是一個(gè)或多個(gè)AVCompositionTrack音視頻軌道的集合。其中AVCompositionTrack 又可以包含來(lái)自多個(gè) AVAsset 的AVAssetTrack。右圖的例子,將兩個(gè)AVAsset中的音視頻 AVAssetTrack 組合到AVComposition的音視頻AVCompositionTrack中。
 
  設(shè)想圖中所示的場(chǎng)景,AVComposition包含兩個(gè) AVCompositionTrack。我們?cè)赥1 時(shí)間點(diǎn)需要混合兩個(gè) AVCompositionTrack的圖像。為了達(dá)到這個(gè)目的,我們需要使用 AVVideoComposition。
 
  AVVideoComposition可以用來(lái)指定渲染大小、渲染縮放以及幀率。圖中紫色的部分包含了一組指令,這些指令存儲(chǔ)了混合的參數(shù)。有了這些混合的參數(shù)之后,可以通過(guò)自定義的 Compositor 來(lái)混合對(duì)應(yīng)的圖像幀。
  整體工作流如圖所示,接受指令,把原視頻幀通過(guò)合成器,生成合成后的幀,輸出給播放器或者導(dǎo)出器。讓我們聚焦到合成器,我們有多個(gè)原始幀,需要處理并輸出新的一幀。
  流程可分解為:
  • AVAsynchronousVideoCompositionRequest綁定了當(dāng)前時(shí)間的一系列原始幀,以及當(dāng)前時(shí)間所在的 Instruction。
  • 收到startVideoCompositionRequest: 回調(diào),并接收到這個(gè) Request。
  • 根據(jù)原始幀及Instruction 相關(guān)混合參數(shù),渲染得到合成的幀。
  • 調(diào)用finishWithComposedVideoFrame,交付渲染后的幀。
  AVAudioMix在AVComposition的音頻軌道上處理音頻。包含一組AVAudioMixInputParameters,每個(gè)Parameters對(duì)應(yīng)一個(gè)音頻的 AVCompositionTrack。右邊的圖片是一個(gè)示例,可以看到AVCompositionTrack和AVAudioMixInputParameters是一一對(duì)應(yīng)的。
  5. VideoLab 設(shè)計(jì)與實(shí)現(xiàn)
  前面我們介紹了AVFoundation視頻剪輯流程,接下來(lái)我們介紹下VideoLab框架的設(shè)計(jì)與實(shí)現(xiàn)。
  
  先簡(jiǎn)要介紹下AE(Adobe After Effect),AE是特效設(shè)計(jì)師常用的動(dòng)態(tài)圖形和視覺效果軟件。AE 通過(guò)“層”控制視頻、音頻及靜態(tài)圖片的合成,每個(gè)媒體(視頻、音頻及靜態(tài)圖片)對(duì)象都有自己獨(dú)立的軌道。
 
    圖片是在 AE 中合成兩個(gè)視頻的示例。在左上角Project區(qū)域內(nèi),有名為Comp1類型為Composition 的一個(gè)合成。在 AE 中合成可以認(rèn)為是一個(gè)作品,可以播放導(dǎo)出,也可以設(shè)置寬高值、幀率、背景色等參數(shù)。在下面Timeline Control 區(qū)域內(nèi),包含了兩個(gè)圖層,源分別為video1.MOV與video2.MOV。我們可以自由的設(shè)置圖層參數(shù),如Transform,Audio,也可以在右邊區(qū)域自由的移動(dòng)圖層,達(dá)到靈活的組合效果。針對(duì)每個(gè)圖層,AE里還可以添加一組特效。
  讓我們提取一些關(guān)鍵字:Composition合成,Layer圖層,Transform變換,Audio音頻和Source來(lái)源。
  
  基于前面對(duì) AE 的分析,我們可以設(shè)計(jì)相似的描述方式:
  • RenderComposition,對(duì)應(yīng)AE中的合成。包含一組RenderLayer。此外,RenderComposition還包含BackgroundColor、FrameDuration、RenderSize,分別對(duì)應(yīng)背景色、幀率及渲染大小等剪輯相關(guān)參數(shù)。
  • RenderLayer,對(duì)應(yīng)AE中的層。包含了Source、TimeRange、Transform、AudioConfiguration、Operations,分別對(duì)應(yīng)素材來(lái)源、在時(shí)間軸的時(shí)間區(qū)間、變換(位置、旋轉(zhuǎn)、縮放)、音頻配置及特效操作組。
  • RenderLayerGroup,對(duì)應(yīng) AE 的預(yù)合成。這個(gè)Group繼承自RenderLayer,包含一組RenderLayer。可以理解成先把一組視頻或圖片處理完,再去做合成。
  KeyframeAnimation,對(duì)應(yīng) AE 的關(guān)鍵幀動(dòng)畫。包含了KeyPath、Values、KeyTimes、緩動(dòng)函數(shù)數(shù)組。
  從上面的圖示可以看到,我們可以靈活自由的放置這些區(qū)域。
  前面介紹了RenderComposition、RenderLayer、RenderLayerGroup 以及KeyframeAnimation。從前面的AVFoundation 介紹可知,我們需要生成AVPlayerItem與AVAssetExportSession 用于播放與導(dǎo)出。因此,我們需要有一個(gè)對(duì)象可以解析這幾個(gè)描述對(duì)象,并用AVFoundation 的方法生成AVPlayerItem 與AVAssetExportSession?蚣軐⑦@個(gè)對(duì)象命名為VideoLab,可以理解成這是一個(gè)實(shí)驗(yàn)室。
  可以看到新的流程,把AVComposition/AVVideoComposition/AVAudioMix都封裝在了VideoLab內(nèi)。這樣做極大的簡(jiǎn)化了開發(fā)對(duì)AVFoundation的認(rèn)知,現(xiàn)在和AE比較相似,可以非常方便的組合這些圖層。流程就轉(zhuǎn)變?yōu)椋?/div>
  • 創(chuàng)建一個(gè)或多個(gè)RenderLayer。
  • 創(chuàng)建RenderComposition,設(shè)置其BackgroundColor、FrameDuration、RenderSize,以及RenderLayer 數(shù)組。
  • 使用創(chuàng)建的RenderComposition創(chuàng)建 VideoLab。
  • 使用創(chuàng)建的VideoLab生成AVPlayerItem或AVAssetExportSession。
  最新的流程極大的簡(jiǎn)化了用戶的使用成本。
  
  那VideoLab是如何把這些描述對(duì)象轉(zhuǎn)換為AVFoundation的三大對(duì)象的呢?
  先來(lái)看下AVComposition,我們需要給AVComposition分別添加視頻軌道與音頻軌道。如圖所示,這個(gè)RenderComposition包含6個(gè)RenderLayer,其中一個(gè)是RenderLayerGroup。
  第一步是將RenderLayer轉(zhuǎn)換VideoRenderLayer,VideoRenderLayer 是框架內(nèi)部對(duì)象,包含一個(gè)RenderLayer,主要負(fù)責(zé)將RenderLayer的視頻軌道添加到AVComposition中?赊D(zhuǎn)換為VideoRenderLayer的 RenderLayer包含以下幾類:1. Source包含視頻軌道;2. Source為圖片類型;3. 特效操作組不為空(Operations)。
  轉(zhuǎn)化為VideoRenderLayer后的第二步是將VideoRenderLayer視頻軌道添加到AVComposition中。從上圖中的例子可以看到,我們有3個(gè)視頻軌道,還有一個(gè)Blank Video Track。 這里的空視頻是指視頻軌道是黑幀且不包含音頻軌道的視頻,為image或只有Operation的VideoRenderLayer服務(wù)。
  從圖中能看到VideoRenderLayer1和VideoRenderLayer5共用的一個(gè)視頻軌道,這是因?yàn)樘O果對(duì)視頻軌道有限制,我們需要盡量的重用,每條視頻軌道對(duì)應(yīng)一個(gè)解碼器,當(dāng)解碼器數(shù)量超出系統(tǒng)限制時(shí),會(huì)出現(xiàn)無(wú)法解碼的錯(cuò)誤?蚣芤曨l軌道重用的原則是,如果要放入的 VideoRenderLayer 與之前視頻軌道的VideoRenderLayer在時(shí)間上沒有交集,則可以重用這個(gè)視頻軌道,所有視頻軌道都重用不了則新增一個(gè)視頻軌道。當(dāng)然這些其實(shí)都不重要,因?yàn)槎挤庋b在了VideoLab里面。
  讓我們接著聊下添加音頻軌道,添加音頻軌道第一步是將RenderLayer 轉(zhuǎn)換為AudioRenderLayer,AudioRenderLayer是框架內(nèi)部對(duì)象,包含一個(gè)RenderLayer,主要負(fù)責(zé)將RenderLayer的音頻軌道添到AVComposition中。可轉(zhuǎn)換為AudioRenderLayer的RenderLayer只需滿足一個(gè)條件:Source包含音頻軌道。轉(zhuǎn)換AudioRenderLayer之后如右圖所示。
  添加音頻軌道的第二步,將AudioRenderLayer視頻軌道添加到AVComposition中,對(duì)于RenderLayer的Source包含音頻軌道的AudioRenderLayer,從Source中獲取音頻AVAssetTrack,添加到AVComposition。
  如右圖所示,不同于視頻軌道的重用,音頻的每個(gè)AudioRenderLayer都對(duì)應(yīng)一個(gè)音頻軌道。這是由于一個(gè)AVAudioMixInputParameters與一個(gè)音頻的軌道一一對(duì)應(yīng),而其音高設(shè)置(audioTimePitchAlgorithm)作用于整個(gè)音頻軌道。如果重用的話,會(huì)存在一個(gè)音頻軌道有多個(gè)AudioRenderLayer的情況,這樣會(huì)導(dǎo)致所有的AudioRenderLayer都要配置同樣的音高,這顯然是不合理的。
  接下來(lái)介紹一下關(guān)于渲染的實(shí)現(xiàn)。從前面的AVFoundation介紹可知,AVVideoComposition可以用來(lái)指定渲染大小和渲染縮放,以及幀率。此外,還有一組存儲(chǔ)了混合參數(shù)的指令。有了這些指令后,AVVideoComposition可以通過(guò)自定義混合器來(lái)混合對(duì)應(yīng)的圖像幀。
  第一步是創(chuàng)建指令,我們會(huì)在時(shí)間軸上標(biāo)記每個(gè)VideoRenderLayer的起始時(shí)間點(diǎn)與結(jié)束時(shí)間點(diǎn)。然后為每個(gè)時(shí)間間隔創(chuàng)建一個(gè)Instruction,與時(shí)間間隔有交集的VideoRenderLayer,都作為Instruction的混合參數(shù)。
  然后我們對(duì)前面的Compositor工作流程做一個(gè)更新,將混合參數(shù)更新為與Instruction有交集的VideoRenderLayer組。對(duì)于混合規(guī)則的話,是按層級(jí)渲染,從下往上。如當(dāng)前層級(jí)有紋理則先處理自己的紋理,再混合進(jìn)前面的紋理。
  從前面的AVFoundation介紹可知,AVAudioMix用于處理音頻。包含一組的AVAudioMixInputParameters,可以設(shè)置實(shí)時(shí)處理音頻,指定音高算法。音頻混合比較簡(jiǎn)單,只要為每個(gè)AudioRenderLayer創(chuàng)建了一個(gè)AVAudioMixInputParameters即可。
  6. VideoLab后續(xù)計(jì)劃
  前面介紹了VideoLab的設(shè)計(jì)與實(shí)現(xiàn)。當(dāng)然要做一個(gè)好的開源框架還需要不斷的完善,接下來(lái)介紹一些VideoLab后續(xù)的計(jì)劃。
 
  首先是支持OpenGL,GL還是目前大多數(shù)公司選擇渲染引擎的首選,VideoLab 的規(guī)劃是能同時(shí)支持Metal + OpenGL,使用方?jīng)Q定渲染引擎使用Metal或Open GL。其次會(huì)持續(xù)完善特性,如變速、更便捷的轉(zhuǎn)場(chǎng)使用方式。接下來(lái)會(huì)開始寫有UI交互的Demo,這樣可能會(huì)更直接一些。最后,當(dāng)然期望VideoLab是可以跨平臺(tái),期望是上層能有統(tǒng)一的C++封裝API,統(tǒng)一設(shè)計(jì)思路,底下用各自的平臺(tái)優(yōu)勢(shì),比如iOS用AVFoundation 做編解碼,Android用 FFmpeg;iOS用Metal/GL,Android用Vulkan/GL。
  最后也是期望能有更多的人參與維護(hù),畢竟一個(gè)人的能力比較有限,大家一起維護(hù)能有更多的未來(lái)暢想。
  這里附帶上Github地址:https://github.com/ruanjx/VideoLab
  以上是我的全部分享,謝謝大家。
【免責(zé)聲明】本文僅代表作者本人觀點(diǎn),與CTI論壇無(wú)關(guān)。CTI論壇對(duì)文中陳述、觀點(diǎn)判斷保持中立,不對(duì)所包含內(nèi)容的準(zhǔn)確性、可靠性或完整性提供任何明示或暗示的保證。請(qǐng)讀者僅作參考,并請(qǐng)自行承擔(dān)全部責(zé)任。

專題

CTI論壇會(huì)員企業(yè)