拉流(播放):
根據協議類型(如RTMP、RTP、RTSP、HTTP等),與服務器建立連接并接收數據;
解析二進制數據,從中找到相關流信息;
根據不同的封裝格式(如FLV、TS)解復用(demux);
分別得到已編碼的H.264視頻數據和AAC音頻數據;
使用硬解碼(對應系統的API)或軟解碼(FFMpeg)來解壓音視頻數據;
經過解碼后得到原始的視頻數據(YUV)和音頻數據(AAC);
因為音頻和視頻解碼是分開的,所以我們得把它們同步起來,否則會出現音視頻不同步的現象,比如別人說話會跟口型對不上;
最后把同步的音頻數據送到耳機或外放,視頻數據送到屏幕上顯示。
了解了播放器的播放流程后,我們可以優化以下幾點:
首屏時間優化
從步驟2入手,通過預設解碼器類型,省去探測文件類型時間;
從步驟5入手,縮小視頻數據探測范圍,同時也意味著減少了需要下載的數據量,特別是在網絡不好的時候,減少下載的數據量能為啟動播放節省大量的時間,當檢測到I幀數據后就立馬返回并進入解碼環節。
推流:
經過輸出設備(AVCaptureVideoDataOutput)得到原始的采樣數據--視頻數據(YUV)和音頻數據(AAC);
使用硬編碼(對應系統的API)或軟編碼(FFMpeg)來編碼壓縮音視頻數據;
分別得到已編碼的H.264視頻數據和AAC音頻數據;
根據不同的封裝格式(如FLV、TS、MPEG-TS);
使用HLS協議的時候加上這一步(HLS分段生成策略及m3u8索引文件)
通過流上傳到服務器;
服務器進行相關協議的分發
推流步驟說明:很容易看出推流跟播放其實是逆向的,具體流程就不多說了。
- 優化一:適當的Qos(Quality of Service,服務質量)策略。
推流端會根據當前上行網絡情況控制音視頻數據發包和編碼,在網絡較差的情況下,音視頻數據發送不出去,造成數據滯留在本地,這時,會停掉編碼器防止發送數據進一步滯留,同時會根據網絡情況選擇合適的策略控制音視頻發送。
比如網絡很差的情況下,推流端會優先發送音頻數據,保證用戶能聽到聲音,并在一定間隔內發關鍵幀數據,保證用戶在一定時間間隔之后能看到一些畫面的變化。
- 優化二:合理的關鍵幀配置。
合理控制關鍵幀發送間隔(建議2秒或1秒一個),這樣可以減少后端處理過程,為后端的緩沖區設置更小創造條件。
軟硬編解選擇
網上有不少關于選擇軟解還是硬解的分析文章,這里也介紹一些經驗,但根本問題是,沒有一個通用方案能最優適配所有操作系統和機型。
推流編碼: 推薦Andorid4.3(API18)或以上使用硬編,以下版本使用軟編;iOS使用全硬編方案;
播放解碼:Andorid、iOS播放器都使用軟解碼方案,經過我們和大量客戶的測試以及總結,雖然犧牲了功耗,但是在部分細節方面表現會較優,且可控性強,兼容性也強,出錯情況少,推薦使用。
附軟硬編解碼優缺點對比:
采集
采集的步驟:
- 創建AVCaptureSession
- 輸入對象AVCaptureDeviceInput
- 輸出對象AVCaptureVideoDataOutput
- 輸出代理方法captureOutput(_:didOutputSampleBuffer:fromConnection:)
相關內容
- 采集數據:iOS平臺上采集音視頻數據,需要使用AVFoundation.Framework框架,從captureSession會話的回調中獲取音頻,視頻數據。
- 傳輸層協議:主要采用RTMP協議居多(默認端口1935,采用TCP協議),也有部分使用HLS協議
- 音/視頻編碼解碼:FFMpege編碼解碼
- 視頻編碼格式:H.265、H.264、MPEG-4等,封裝容器有TS、MKV、AVI、MP4等
- 音頻編碼格式:G.711μ、AAC、Opus等,封裝有MP3、OGG、AAC等
- 渲染工具:采用OpenGL渲染YUV數據,呈現視頻畫面。將PCM送入設備的硬件資源播放,產生聲音。iOS播放流式音頻,使用Audio Queue 的方式,即,利用AudioToolbox.Framework 框架。
參考技術文章
http://www.lxweimin.com/p/10b338e56800
快速集成iOS基于RTMP的視頻推流
雷霄驊(leixiaohua1020)的專欄
參考框架
RTMP推流
LiveVideoCoreSDK
FLVKit
PLMediaStreamingKit
直播播放器
ijkplayer
美顏
GPUImage