Android 音視頻涉及到的技術總結
共 2936字,需瀏覽 6分鐘
·
2022-02-09 17:34
前言
現(xiàn)在市面上的圖像,音視頻軟件越來越多,最近兩年也是直播,短視頻的紅利期。而圖像、音視頻一直是互聯(lián)網(wǎng)視覺的入口,掌握并熟練運用音視頻、圖像技術已經(jīng)是當前互聯(lián)網(wǎng)時代不可或缺的技能,而且這個技能是具有沉淀性質的。
目前市面上的學習資料參差不齊,我覺得想要開啟音視頻的學習之路,先得了解整體流程上會涉及的技術點,再一個個擊破。我也是音視頻方面的小白,最近公司要做一個視頻換臉的應用,目前處于技術調研期。趁此空檔,我準備開始我的音視頻學習之路。
音視頻 app
圖像類:
音頻類:
視頻類:
整體流程
以手機直播為例,其整體流程如下:
數(shù)據(jù)采集
1. 音頻采集
音頻采集涉及到以下幾點:
- 檢測麥克風是否可以使用;
- 需要檢測手機對某個音頻采樣率的支持;
- 在一些情況下需要對音頻進行回聲消除處理;
- 音頻采集時設置正確的緩沖區(qū)大小。
在 Android 系統(tǒng)中,一般使用 AudioRecord 或者 MediaRecord 來采集音頻。AudioRecord 是一個比較偏底層的 API,它可以獲取到一幀幀 PCM 數(shù)據(jù),之后可以對這些數(shù)據(jù)進行處理。而 MediaRecorder 是基于 AudioRecorder 的 API (最終還是會創(chuàng)建AudioRecord 用來與 AudioFlinger 進行交互) ,它可以直接將采集到的音頻數(shù)據(jù)轉化為執(zhí)行的編碼格式,并保存。
2. 視頻采集
視頻采集涉及到以下幾點:
- 檢測攝像頭是否可以使用;
- 攝像頭采集到的圖像是橫向的,需要對采集到的圖像進行一定的旋轉后再進行顯示;
- 攝像頭采集時有一系列的圖像大小可以選擇,當采集的圖像大小和手機屏幕大小比例不一致時,需要進行特殊處理;
- Android 手機攝像頭有一系列的狀態(tài),需要在正確的狀態(tài)下才能對攝像頭進行相應的操作。
- Android 手機攝像頭的很多參數(shù)存在兼容性問題,需要較好地處理這些兼容性的問題。
在 Android 系統(tǒng)下有兩套 API 可以進行視頻采集,它們是 Camera 和 Camera2 。Camera是以前老的 API ,從 Android 5.0(21) 之后就已經(jīng)放棄了。和音頻一樣,也有高層和低層的 API,高層就是 Camera 和 MediaRecorder,可以快速實現(xiàn)編碼,低層就是直接使用 Camera,然后將采集的數(shù)據(jù)進行濾鏡、降噪等前處理,處理完成后由 MediaCodec 進行硬件編碼,最后采用 MediaMuxer 生成最終的視頻文件。
數(shù)據(jù)處理
1. 音頻處理
可以對音頻的原始流做處理,如降噪、回音、以及各種 filter 效果。
2. 視頻處理
現(xiàn)在抖音、美圖秀秀等,在拍攝,視頻處理方面,都提供了很多視頻濾鏡,而且還有各種貼紙、場景、人臉識別、特效、添加水印等。
其實對視頻進行美顏和添加特效都是通過 OpenGL 進行處理的。Android 中有 GLSurfaceView,這個類似于 SurfaceView,不過可以利用 Renderer 對其進行渲染。通過 OpenGL 可以生成紋理,通過紋理的 Id 可以生成 SurfaceTexture,而 SurfaceTexture 可以交給 Camera,最后通過紋理就將攝像頭預覽畫面和 OpenGL 建立了聯(lián)系,從而可以通過 OpenGL 進行一系列的操作。
美顏的整個過程無非是根據(jù) Camera 預覽的紋理通過 OpenGL 中 FBO 技術生成一個新的紋理,然后在 Renderer 中的onDrawFrame() 使用新的紋理進行繪制。添加水印也就是先將一張圖片轉換為紋理,然后利用 OpenGL 進行繪制。添加動態(tài)掛件特效則比較復雜,先要根據(jù)當前的預覽圖片進行算法分析識別人臉部相應部位,然后在各個相應部位上繪制相應的圖像,整個過程的實現(xiàn)有一定的難度,人臉識別技術目前有 OpenCV、Dlib、MTCNN 等。
數(shù)據(jù)編碼
1. 音頻編碼
Android 中利用 AudioRecord 可以錄制聲音,錄制出來的聲音是 PCM 聲音,使用三個參數(shù)來表示聲音,它們是:聲道數(shù)、采樣位數(shù)和采樣頻率。如果音頻全部用 PCM 的格式進行傳輸,則占用帶寬比較大,因此在傳輸之前需要對音頻進行編碼。
現(xiàn)在已經(jīng)有一些廣泛使用的聲音格式,如:WAV、MIDI、MP3、WMA、AAC、Ogg 等等。相比于 PCM 格式而言,這些格式對聲音數(shù)據(jù)進行了壓縮處理,可以降低傳輸帶寬。對音頻進行編碼也可以分為軟編和硬編兩種。軟編則下載相應的編碼庫,寫好相應的 JNI,然后傳入數(shù)據(jù)進行編碼。硬編則是使用 Android 自身提供的 MediaCodec。
硬編碼和軟編碼的區(qū)別是:軟編碼可以在運行時確定、修改;而硬編碼是不能夠改變的。
2. 視頻編碼
在 Android 平臺上實現(xiàn)視頻的編碼有兩種實現(xiàn)方式:一種是軟編,一種是硬編。軟編的話,往往是依托于 cpu,利用 cpu 的計算能力去進行編碼。比如我們可以下載 x264 編碼庫,寫好相關的 JNI 接口,然后傳入相應的圖像數(shù)據(jù)。經(jīng)過 x264 庫的處理以后就將原始的圖像轉換成為 h264 格式的視頻。
硬編則是采用 Android 自身提供的 MediaCodec,使用 MediaCodec 需要傳入相應的數(shù)據(jù),這些數(shù)據(jù)可以是 YUV 的圖像信息,也可以是一個 Surface,一般推薦使用 Surface,這樣的話效率更高。Surface 直接使用本地視頻數(shù)據(jù)緩存,而沒有映射或復制它們到 ByteBuffers;因此,這種方式會更加高效。在使用 Surface 的時候,通常不能直接訪問原始視頻數(shù)據(jù),但是可以使用ImageReader 類來訪問不可靠的解碼后 (或原始) 的視頻幀。這可能仍然比使用 ByteBuffers 更加高效,因為一些本地緩存可以被映射到 direct ByteBuffers。當使用 ByteBuffer 模式,可以利用 Image 類和 getInput/OutputImage(int) 方法來訪問到原始視頻數(shù)據(jù)幀。
音視頻混合
下面我盜了一張圖,畫圖實在太費時間:
以合成 MP4 視頻為例:
- 整體來看,合成的 MP4 文件,視頻部分為 H.264 編碼格式的數(shù)據(jù),音頻部分為 AAC 編碼格式的數(shù)據(jù)。
- 通過 MediaMuxer 提供的接口-writeSampleData(),將 H.264 和 AAC 數(shù)據(jù)分別同時寫入到 MP4 文件。
數(shù)據(jù)傳輸
- 目前比較主流的視頻推流協(xié)議有 RTMP 協(xié)議、RTSP 協(xié)議。
涉及的技術
涉及到如下技術,我將從圖像、音頻、視頻的順序來羅列:
- Camera、Camera2。
- SurfaceView、TextureView、SurfaceTexture、GLSurfaceView。
- OpenGL ES。
- OpenCV、DLIB。
- YUV、PCM、H.264、H.265、ACC。
- AudioRecord、AudioTrack。
- MediaRecorder。
- MediaCodec。
- MediaExtractor、MediaMuxer。
- ffmpeg、ijkplayer。
- RTMP、RTSP。
后面我將針對這些技術,總結下音視頻相關的技術,有需要的可以點贊關注下。
