天天看點

android播放器錄制視訊,Android播放器的錄制實踐

播放錄制是在觀衆端錄制視訊内容存至本地。觀衆對觀看内容非常感興趣想要将該視訊内容留存至本地時便可使用該功能。

一. 可行的方案

在Android端實作播放錄制的方法大約有下面三種:

1. 錄屏

在Android 5.0 (API Level 21)及以上版本提供了錄屏功能,使用系統提供的類MediaProjection與VirtualDisplay可實作在Android端的錄制螢幕内容的功能,此處不再贅述。

但此方法亦會錄制應用的UI及可能的消息通知等與視訊無關的内容,對Android的版本有一定要求。

2. 重封裝(Remux)

播放器在播放視訊時可擷取原始音視訊資料,當觀衆希望錄制視訊的時候,将原數資料進行一次Remux即成。

但是Remux的資料需要保證第一個視訊幀是關鍵幀。是以播放器内部内部需要緩存已經解碼并播放過的音視訊資料直到新的關鍵幀(IDR幀)到來。

但此方案存在若幹問題:

額外的記憶體開銷。已經用于解碼的音視訊資料,其對應記憶體不可被釋放,以備觀衆錄制視訊内容、直到新的GOP資料到來,上一個GOP的資料方可被釋放。這樣就帶來了額外的記憶體開銷。

内容多餘。此方案必須從關鍵幀開始做Remux,并不一定是從使用者想要錄制的内容開始,特别是對于GOP較大的視訊,此問題尤為明顯。

3. 重編碼&封裝

此方法是将解碼之後的YUV和PCM資料送入編碼器,将編碼後的資料重新封裝為目标視訊。

此方案需要重新編碼,會占用相當的CPU資源。

我們最終采用了方案3作為初始方案,采用Android手機提供的硬編功能将音視訊資料編碼,将編碼後的資料封裝為MP4檔案。

二. 踩過的坑

在開發過程中踩過不少坑,下面和大家分享下:

2.1 MediaCodec

MediaCodec是Android提供的關于音視訊硬編/硬解功能的核心類,其接口及相應功能在此不在贅述。實作播放錄屏功能時使用MediaCodec編碼視訊,遇到的最坑的問題是:

顔色空間,一般情況下軟解視訊輸出YUV420Planar資料,而Android手機可能隻支援YUV420Planar或YUV420SemiPlanar,其差別如下圖所示。是以需要根據每個手機的實際情況做出适配。

android播放器錄制視訊,Android播放器的錄制實踐

2.2 MediaMuxer

MediaMuxer是Android于4.3版本引入的用于将編碼後的音視訊資料封裝為MP4的核心類。實作播放錄屏功能時最初是選用MediaMuxer将編碼之後的音視訊資料複用為MP4,然則因為Android系統的碎片化,各廠商根據各自的需求對ROM做了相應修改,導緻MediaMuxer的穩定性在各手機表現不太一緻,與預期相差較遠。

三. 最終的方案

最終的解決方案是使用MediaCodec+FFMpeg,MediaCodec将解碼後的音視訊資料編碼,FFMpeg将編碼之後的音視訊資料封裝為MP4檔案。其中視訊編碼預設使用H.264/AVC的Baseline,音頻編碼使用AAC-LC。其基本架構圖如下所示

播放器将解碼後的音視訊資料(YUV/PCM)交予錄制子產品,錄制子產品有兩個緩存隊列分别緩存解碼後的音視訊資料;

錄制子產品的音視訊各有一個編碼線程,每個線程持有一個MediaCodec的對象,分别從音視訊隊列取解碼後的資料,然後将編碼後的資料放入已編碼資料隊列。寫資料線程會不斷從已編碼資料隊列中拉取資料,然後調用封裝子產品的接口,将音視訊資料封裝為MP4;

封裝子產品調用了FFMpeg提供的接口,将音視訊資料寫入本地磁盤。其中需要先寫入音視訊的關鍵資訊例如: SPS/PPS、ADTS等。

四. 結語

按照以上步驟便可實作在Android端的播放錄制功能,但是依舊有改進的空間,例如使用MediaCodec做視訊編碼在少許低端機型依舊存在問題,後續會根據推出更加穩定的版本。

服務于大家,一直是金山雲多媒體SDK團隊的目标。團隊在很用心的開發短視訊SDK,歡迎試用!