位元組跳動開源了一個視訊動畫特效SDK(AlphaPlayer),可以通過製作Alpha通道分離的視訊素材,再在客戶端上通過OpenGL ES重新實現Alpha通道和RGB通道的混合,從而實現在端上播放帶透明通道的視訊。
AlphaPlayer已經在Github上標星650,累計分支 277個
抖音、抖音火山版、西瓜小視訊、今日頭條已經接入。
這套方案對設計師而言明顯降低了特效的製作成本,對於客戶端而言有著更可靠的效能和穩定性,且相比cocos2d引擎有著更低的入門門檻和維護成本,為複雜動畫的實現提供了一種全新的方式,新的複雜動畫開發將會變得更加簡單高效。
效果
AlphaPlayer
AlphaPlayer是直播中臺使用的一個視訊動畫特效SDK,可以通過製作Alpha通道分離的視訊素材,再在客戶端上通過OpenGL ES重新實現Alpha通道和RGB通道的混合,從而實現在端上播放帶透明通道的視訊。
這套方案對設計師而言明顯降低了特效的製作成本,對於客戶端而言有著更可靠的效能和穩定性,且相比cocos2d引擎有著更低的入門門檻和維護成本,為複雜動畫的實現提供了一種全新的方式,新的複雜動畫開發將會變得更加簡單高效。
背景
在直播專案的原有禮物動畫實現效果是通過cocos引擎實現的,大部分動畫都是通過一系列的旋轉平移縮放組合而成,能實現的動畫效果較簡單且開發成本較高。為了豐富動畫的表現形式,降低開發成本,我們引入了AlphaPlayer的動畫實現方案。
方案對比
目前較常見的動畫實現方案有原生動畫、幀動畫、gif/webp、lottie/SVGA、cocos引擎,對於複雜動畫特效的實現做個簡單對比
在複雜動畫特效高效實現的場景中,我們的備選方案會更少一些,可以將討論集中在Cocos2d、Lottie、Webp和本文的AlphaPlayer上。
Lottie
Lottie是非常優選的多平臺動畫效果解決方案,其簡單原理是將AE動畫匯出的json檔案解析成每個layer層級物件,再繪製成對應的Drawable,最後顯示在View上。在不涉及mask和mattes等特性時效能非常優選,主要耗時基本集中在Canvas#draw()上而已,json解析時通過流讀取的方式避免一次性載入全部json資料帶來的OOM問題。
但是也存在部分不足:
- 如果動畫涉及到mask或mattes等特性時,需要生成2~3個臨時bitmap實現動畫效果,容易引起記憶體抖動,且涉及的canvas#saveLayer()和canvas#drawBitmap()會帶來額外的耗時;
- 如果動畫中還直接使用了圖片,在ImageAssetManager首次對圖片解碼是在主執行緒進行的(據瞭解在iOS的版本上,使用圖片導致記憶體和CPU的效能消耗會更大);
- 主要耗時還是在draw()上,繪製區域越大耗時越長;
- 目前支援的AE特性還有待完善,此外有一些特性在低版本上可能還會沒有效果,設計資源時需要規避。(Supported After Effect Features)
實際使用過程中,最常見的首啟全屏引導動畫基本都會包含上面提到的前三點不足,這種情況下效能其實是大幅退化的。因此對於直播場景的複雜特效動畫而言,Lottie就不是一個很合適的實現方案了。
Cocos2d-x
Cocos2d-x支援非常多的遊戲功能,諸如精靈、動作、動畫、粒子特效、骨骼動畫等等,可以供開發者自由實現各種姿勢的動畫效果,再加上自身具備跨平臺能力和輕量級,同時支援Lua作為開發語言,可以說是非常適合植入移動端作為動畫效果實現方案的遊戲引擎。
但實際使用維護中會面臨很多問題:
- 體積大,即使經過裁剪也還有2M左右的大小,如果不是核心場景需要基本很難允許接入;
- 對開發者的技術棧有較高要求;
- 無法滿足快速迭代;
- 維護難度大,尤其是在Android機型相容的問題上。
Webp
Webp相比PNG和JPEG格式體積可以減少25%,在移動端的平臺支援上也很全面,支援24位RGB色;缺點是資源體積比較大,而且使用的軟解效率低下,低端機上有明顯示卡頓問題。
AlphaPlayer
相比於上面提到的幾個方案,AlphaPlayer的接入體積極小(只有40KB左右),而且對動畫資源的還原程度極高,資源製作時不用考慮特效是否支援的問題,對開發者和設計師都非常友好。通過接入ExoPlayer或者自研播放器可以解決系統播放器在部分機型上可能存在的相容性問題,且能帶來更好的解碼效能。
基本原理
AlphaPlayer主要有兩個核心部分,一個是MediaPlayer,負責視訊每一幀的解碼,支援接入方自行實現;另一個是VideoRenderer,負責將解析出來的每一幀畫面進行alpha通道混合,再輸出到Surface上。View使用的是GLSurfaceView,效能相對TextureView更優,但層級限制在最頂層。
AlphaPlayer內部是通過Render渲染紋理畫面的,設計師匯出的視訊資源會包含兩部分內容——透明遮罩畫面和原視訊畫面兩部分,然後通過shader進行alpha值的混合,詳細可以看 frag.sh和vertex.sh。