解決低延遲問題的核心思想:NO BUFFER
低延遲:顧名思義,就是讓播放端和推流端的時間差越小越好,那么如何做到低延遲呢,一個詞概括:no buffer
首先說明一下視頻流的流向:推流端--->CDN服務器--->拉流端
1. 推流端 nobuffer,也就是保證推流端緩存的buffer最小。這樣基本上保證在推流端出現網絡抖動或者突然變差的情況下,能夠舍棄已經緩存的buffer,繼續推新生成好的視頻幀。這樣保證了,在網絡端開始傳輸的時候的視頻內容是最新的。
2. CDN nobuffer,針對性的調整CDN的配置,讓CDN服務器緩存的GOP盡可能的少,這樣保證拉流端獲取到的是最新的內容。
3. 拉流端 nobuffer,既然推流和中轉的CDN都設置了nobuffer,那么拉流端設置nobuffer的意義,應該不需要做過多的解釋了吧。
記住一點:低延遲問題的解決不是一端的事情,三端的配置都會對延遲的效果產生影響。
拉流端(基於IjkPlayer)低延時直播的經驗:
在直播的過程中,有首開延時和內容延時。首開延時,基本可以控制在100ms左右;基於RTMP播放的內容延遲根據CDN的情況,基本上會在2~5秒左右。而因為RTMP是基於TCP協議的,所以在播放的過程中會受到網絡條件的影響,造成延遲增加的情況。通過了解直播流的推流和拉流相關的知識,可以知道,根據推流端(推流策略)與服務器(緩存策略)不同的控制的設定,我們很可能拿到幾秒之前的內容(甚至十幾秒),可以通過對比拉流端與推流端的內容即可得知。而這些內容,在拉流端會把CDN服務器緩存的數據拉取過來,這時buffer queue變大。那么,buffer queue越大,拉流端與推流端的延時越大。
拉流端影響延時的核心原因: buffer queue 變大,拉流端播放的內容和推流端相差時延增加。
解決辦法:
1. 控制max_buffer_size,合理設置max_buffer_size,使得拉流端不會緩存太長時間的內容(經過測試,發現不是很實用,因為內容延時只有追趕或者丟棄當前播放的內容,快速跳播到最新數據才能達到低延時播放)
2. 使用倍速播放,快速消耗Buffer Queue,在消耗到合理的區間后,進行正常播放(監聽並動態控制buffer queue,此方案要求設備的解碼性能能夠支撐)。
3. 使用丟包(丟幀)策略。策略說明:
- 有音頻流和視頻流,或者只有音頻流情況下,當audioq達到一定的duration,就丟掉前面一部分數據包,因為默認是AV_SYNC_AUDIO_MASTER,視頻會追上來。
- 只有視頻流情況,當videoq達到一定的duration,就丟掉前面一部分數據包。
下面是我在解決低延遲問題的時候,參考的丟包(丟幀)策略相關文章:ijkplayer丟幀的處理方案 、jkplay播放直播流延時控制小結。