禮物特效動畫
背景
在直播房間里面的虛擬禮物是主播和觀眾互動的重要道具,也能帶來比較多的收入。先前的實現方案是使用動態圖片格式,用GIF和webp,雖然使用起來還算方便,但是有許多不足:沒法播放音頻、幀速過低、制造復雜特效不方便、體積過大。新的多媒體格式的動畫特效恰恰可以解決這些缺陷,能夠實現流暢高幀率酷炫特效動畫,提高用戶付費率,增加營收。
相關知識
-
視頻解碼;動畫用的是h264編碼的,為了提高解碼效率,在移動平台都是使用各自系統提供的硬解碼VideoToolBox(iOS)和MediaCodec(Android)
-
音頻解碼;音頻使用的aac編碼,解碼不復雜,硬解和軟解都可以。
-
動畫的渲染;視頻在移動平台使用OpenGL ES比較方便,解碼后渲染到view。
-
音視頻同步; 根據pts,使視頻同步到音頻。
設計實現和測試
1.iOS實現
為了方便快捷,iOS上面的實現直接使用的是ijkplayer這個第三方庫,ijkplayer使用的是FFmpeg對動畫視頻進行解碼,使用SDL播放音頻,在渲染的時候有個問題:MP4格式h264編碼的多媒體格式,不支持alpha通道,而我們的動畫要求有些部分是透明的,所以我們在制作動畫視頻的時候,把一個視頻一分為二,左邊部分通過黑白度來表示透明度,右邊為動畫效果,在shader中編寫合成算法實現最終效果,首先通過shader把解碼后的yuv圖片轉換成rgb, 渲染到texture上面,然后再進入根據黑白度合成的shader,最后渲染到對應的view上面。音視頻同步的問題,ijkplayer使用的ffplay的源碼,已經很好的解決了,默認視頻跟音頻同步。
2.Android實現
安卓上使用NDK里面的MediaCodec接口,實現音視頻的解碼,通過Java傳入的surface接收解碼的數據,然后送入和iOS一樣的shader進行繪制。音頻播放使用OpenSL ES進行播放,使用事件驅動的方式實現播放。安卓的硬解使用Java層的MediaCodec比較多,使用NDK同時進行音視頻很少,網上基本找不到資料,這里面有個坑就是音視頻必須要有兩個不同的AMediaExtractor和FileDes分別作用於音視頻的track,否則就會在一些手機上出現一些播放異常。
3.實現效果
左邊的是原視頻,右邊是手機上渲染效果。


4.測試
通過上千次的循環播放動畫流暢,沒有內存泄漏,音視頻基本同步的,完成的預期目標。
總結和改進
在使用安卓的NDK中MediaCodec同時進行音視頻解碼坑還是挺多的,看了安卓官網的文檔,都只有單獨針對視頻,網上的也基本上用Java層的接口,通過多次試驗終於兼容5.0系統所有設備。在音視頻解碼和播放的多線程處理犯過幾個錯誤,及時改過來了。對安卓NDK開發還是需要再加深了解。安卓的OpenGL ES的渲染放在Java層,效率比NDK會差一些,后續可以用NDK的接口實現。iOS上面也可以不用ijkplayer直接使用原生接口實現,可以解決這個很重的依賴,減少包的體積。