這幾天在調研直播的技術。雖然如今有不少「開源」的SDK,或者各個廠家的SDK。可是仍是想本身去調研一下整個的直播流程/技術,而且經過代碼去實現一套這樣的功能。bash
看網上的文章介紹,基本上的流程是這樣的:採集,編碼,發送,轉發,解碼。我此次主要研究一下采集,編碼,發送這三個客戶端採集的步驟。服務器
採集設備:Android手機攝像頭採集視頻,麥克風採集音頻。 編碼格式:音頻:aac,視頻:h264。 發送協議:rtmp協議。
攝像頭採集視頻的方法有兩種:Camera的onPreviewFrame的回調方法,和MediaRecorder的outPut方法。通過對比,發現各有各的優缺點:網絡
Camera的onPreviewFrame方法:socket
優勢: 能夠獲取到視頻的原始YUV數據。 使用簡單:直接設置一個回調方法就可以獲取到預覽時的視頻數據。 缺點: 須要本身將YUV數據編碼爲h264格式,對編碼須要必定的瞭解。
MediaRecorder的outPut方法:編碼
優勢: 能夠直接獲取到編碼後的h264格式的視頻幀數據。 缺點: 獲取部分的代碼比較麻煩:須要在程序內部架設socket服務來獲取h264視頻數據。
在各有優缺點的狀況下,經過對比其餘現有的直播SDK的功能,最終採用了Camera的onPreviewFrame的方法。衆所周知,美顏功能已是目前直播的主要功能點之一。獲取到最原始的YUV數據,對於後期加美顏效果是有極大的幫助的。
麥克風採集音頻,也有兩種方式:AudioRecorder的read,和MediaRecorder的outPut方法。優缺點基本和視頻類似。故仍是選擇AudioRecorder來採集音頻,這樣就能獲取到最原始的PCM數據(也就是去掉wav頭信息的原始數據)。spa
視頻的編碼格式採用h264,主要從數據的體積大小上考慮。原始的視頻幀YUV數據,是沒有通過壓縮的,相對來講體積較大。數據越大,在網絡上傳輸出錯的可能性越大,而且對網絡的帶寬消耗也越大。而h264則對數據進行了壓縮和編碼,有了關鍵幀和非關鍵幀的概念。而非關鍵幀相對於關鍵幀,視頻數據小了不少。這樣帶來的好處就是直播須要在網絡上傳輸的數據就變少,對服務器的帶寬消耗也相對變小。code
音頻的編碼格式採用aac,主要仍是因爲體積問題。同時,aac在壓縮編碼以後,聲音的變化基本聽不出來,聲音質量高。視頻
目前大多數直播協議都是基於Rtmp協議的。因此我也準備採用這個協議。直播
有了具體的想法以後,就在於代碼的實現。而代碼實現每每是最難的部分。畢竟空想誰都會,實現起來,就會遇到各類問題。io
看到網上不少是基於ffmpeg去實現直播的採集。可是分析了採集的需求以後,其實發現咱們只須要三個地方作好,基本上採集就OK了。分別是:h264 的編碼實現。aac的編碼實現。rtmp的編碼實現。而通過查閱資料,發現ffmpeg也是集成了這三個功能,從而實現的直播功能。
爲了簡單,我決定就從這三個方面入手編寫代碼。編寫代碼不表明就是要從新造輪子。畢竟一我的徹底從0開始寫直播是不太符合目前的情況的:沒那個精力。因而,選擇庫,成了重要的一個步驟。
h264的編碼庫也很多,最終選擇了x264。 aac的編碼庫,選擇了fdkaac。 rtmp的庫,選擇了rtmpdump。
以上這三種庫都是馳騁沙場的老將,應該沒有問題。
接下來就是各個擊破,一步一步的去完成實現採集所需的功能。