在《如何快速實現移動端短視訊功能?》中,我們主要介紹了當前短視訊的大熱趨勢以及開發一個短視訊應用所涉及到的功能和業務。在本篇文章中,我們主要談一談短視訊在Android端上的具體實現技術。
推薦閱讀
短視訊業務主要包含:“視訊錄製”以及 “視訊編輯”這兩個核心功能。
其中視訊錄製又包括:視訊採集、實時美顏、自定義位元速率、攝像頭切換、變焦、對焦、曝光度調節以及濾鏡等功能。
視訊編輯包括:視訊裁剪、視訊拼接、混音、視訊動畫效果、動態貼圖等功能。
Android端短視訊錄製的技術方案
我們先來說說視訊錄製:
視訊錄製的大致實現流程就如上圖所示,先由Camera、AudioRecord進行最原始的相機畫面以及聲音的採集,然後將採集的資料進行濾鏡、降噪等前處理,處理完成後由MediaCodec進行硬體編碼,最後採用MediaMuxer生成最終的MP4檔案。
這個方案的優點在於,由於全程採用了GPU以及硬體編碼,基本上不涉及CPU上的操作,因此可實現在高幀率(30fps)、高解析度(720P)以及高位元速率的情況下CPU暫用率也非常低,即使在效能較差的手機上也能很好的執行。但同時這個方案的難點也在於此。
做過音視訊的同學都知道,通常情況下我們所說的對音視訊的處理,主要是對視訊的 YUV、H264 音訊的PCM、AAC這類資料格式進行操作,這類操作都有相關的RFC技術也比較成熟,實現起來比較容易,出了問題也更容易定位,通常情況下在PC等裝置上也都是這麼處理的。
但這樣的方案在對於手機端情況就不同了,雖然手機這幾年的效能大大加強了,很多旗艦手機基本都是8核的CPU了,但要操作如此大量的圖片資料並進行浮點運算對CPU的消耗還是很大的。CPU暫用率高就會引起手機發燙,手機發燙就會導致Camera採集的掉幀,甚至在一些小米等廠商下,手機發燙還會引起CPU降頻,CPU一降頻那APP所暫用的CPU比例就更高了,同時CPU暫用率高電量消耗就快。
因此上面的方案是目前Android上比較適合短視訊錄製的方案。
Android端短視訊錄製的具體實現
既然確定了技術方案,我們就來看看具體的實現。這裡首先需要知道幾個概念:
SurfaceTexture
我們知道在一些簡單的自定義相機應用中,要實現一個相機,只需要將一個SurfaceHolder設定給Camera,Android系統就會自動的幫我們把Camera採集的資料繪製到螢幕上。但由於在短視訊中我們需要對相機採集的資料進行前處理加工比如濾鏡等,而且還要做到可見即所得的效果,因此必須要求我們將相機採集的資料先快取起來,前處理完後自己再繪製到螢幕上,這時候就需要用到SurfaceTexture了。按照Android官方文件的介紹,SurfaceTexture就是這樣一塊用於接收Camera採集的資料,同時又不可見的畫布。這塊畫布是存在於GPU記憶體中的。
TextureID
紋理ID,主要用來標識每一塊紋理在GPU記憶體中的記憶體地址,類似於C語言中的記憶體指標。每一塊GPU的紋理(可以理解為一塊用於顯示圖片的畫布)都有對應的一個TextureID進行標識。上述的SurfaceTexture在建立也同樣需要繫結一個紋理ID進行唯一標識。
知道了這兩個概念,我們就知道了Camera採集的資料具體存在於GPU的哪個位置了。接下來就可以對原始的資料進行前處理編碼了。
這裡有一個需要注意的地方,Android的camera採集到SurfaceTexture上的紋理是GL_TEXTURE_EXTERNAL_OES 型別的紋理,而目前市面的很多濾鏡演算法,如開源的GPUImage中很多的濾鏡都是基於GL_TEXTURE_2D型別的紋理進行影像處理的。
因此在進行我們在基於開源濾鏡演算法或自研演算法時需要先將GL_TEXTURE_EXTERNAL_OES型別的紋理轉化為GL_TEXTURE_2D的紋理,或者在GPU Shader中加入 "#extension GL_OES_EGL_image_external: require" 來表明該紋理是OES紋理,同時編寫基於OES紋理的影像處理演算法。
目前網易這邊是先將OES轉化為TEXTURE_2D在進行前處理,這樣便於與iOS端演算法統一以及更好的接入一些開源的濾鏡演算法。
解決了SurfaceTexture的問題,接下來的MediaCodec以及MediaMuxer就比較容易了。Android中的MediaCodec天生支援將GPU中的紋理繪製到MediaCodec的Surface中,然後對Surface中的影像直接進行硬體編碼,影像資料始終是在GPU空間中進行流轉,而沒有涉及到CPU。
這裡需要注意的是MediaCodec以及MediaMuxer需要在API 18及以上才能使用。同時需要注意MediaCodec在不同裝置上的相容性。
Android端視訊編輯功能
最後對於視訊編輯的功能,目前Android上沒有很好的系統API即硬體處理方式,主要還是利用ffmpeg進行相應的疊加、裁剪混音等後期處理。可以優化的一個點是,先將原始的MP4視訊進行解碼,然後將解碼後的YUV資料對映到GPU的紋理上進行亮度、飽和度等引數的調節,做到檔案編輯的所見即所得,然後將調好的引數配置為ffmpeg進行編輯處理。
想要獲取更多產品乾貨、技術乾貨,記得關注網易雲信部落格。