播放問題排查:
一旦我們遇到視頻播放不了,第一件事,就是要找幾個別的播放器也播放看看,做一下對比測試,或者對碼流做一些基礎分析,以便更好的定位問題的源頭,而各個平台比較常見的播放/分析工具有如下幾個:
2.1 命令行工具
ffplay,ffprobe,mediainfo,hls-analyzer 等
2.2 網頁端工具
2.3 App 應用
vlc,vplayer,mxplayer 等
2.4 Windows 工具
mp4info,FlvParse,FLVMeta,Elecard StreamEye Studio 等
ping 一下域名試試,看看是否可以 ping 通,如果 ping 不通,則可能要檢查下域名解析的配置了。
只有音頻沒有視頻,或者只有視頻沒有音頻:
基於 ffmpeg 的播放器的 `probesize` 設置太小,導致解析碼流信息不足
播放卡頓:
- 頻繁出現緩沖 - 播放不夠流暢,畫面一卡一卡的
其實是指播放器渲染的幀率太低
如何判斷主播網絡不好
(1)帶寬測試
用帶寬測試工具:
Speedtest by Ookla - The Global Broadband Speed Test
測試下主播的帶寬,如果主播的上行帶寬明顯小於推流的碼率,那么肯定會出現推流幀率不穩定。
(2)統計回調
一般的推流 SDK 都會統計主播推流的實時視頻幀率,如果預設的幀率是 20fps,但是實際的幀率低得很多,比如 5fps,排除手機性能低的原因的話,多半也是網絡帶寬不足引起的。
播放設備性能不足:
- 盡可能選擇使用硬解,充分利用 GPU 加速 - 如果有多種碼流,盡可能在低端機上選擇非高清碼流 - 增大緩沖區,有助於緩解解碼不穩定帶來的卡頓
可以修改 ffplay 源碼,把讀取到的每一幀音頻、視頻的時間戳打印出來看看,這里我給出對 ffplay 的修改 commit 記錄,大家可以參考一下:
為了有效降低 DNS 解析對首開的影響,我們可以提前完成播放域名->IP 地址的解析,並緩存起來,播放的時候,直接傳入帶 IP 地址的播放地址,從而省去了 DNS 解析的耗時。
如果要支持用 ip 地址播放,是需要修改底層 ffmpeg 源碼的,目前七牛的 PLDroidPlayer 就支持這樣的播放地址:
URL 格式:“protocol://ip/path?domain=xxxx.com”
所有基於 ffmpeg 的播放器,都會遇到 `avformat_find_stream_info` 這個函數耗時比較久,從而增大了首開時間,該函數主要作用是通過讀取一定字節的碼流數據,來分析碼流的基本信息,如編碼信息、時長、碼率、幀率等等,它由兩個參數來控制其讀取的數據量大小和時長,一個是 probesize,一個是 analyzeduration
減少 probesize 和 analyzeduration 可以有效地減少 `avformat_find_stream_info` 的函數耗時,從而加快首開,但是需要注意的是,設置地太小可能會導致讀取的數據量不足,從而無法解析出碼流信息,導致播放失敗,或者出現只有音頻沒有視頻,只有視頻沒有音頻的問題。
一般圖像處理、數據拷貝、編解碼帶來的延時,
都是 ms 級別的
,真正會產生比較大延時的地方,一個是互聯網上的網絡傳輸延時,另一個就是業務代碼中的緩沖區了。
推流端的數據是怎么 “積累” 起來的 ?
采集 -> 編碼 -> 數據發送 -> [服務器]
當網絡產生抖動的時候,“數據發送” 會因此減慢,產生一定的阻塞,從而導致這些數據會被 “積累” 在了推流端的發送緩沖區中。
[服務器]-> 數據接收 -> 解碼 -> 渲染
當網絡產生抖動的時候,服務器的數據無法 “及時” 地傳輸到播放端,而由於 TCP 協議的可靠性,所有的數據都會被服務端積累起來,在網絡恢復良好的時候,會快速傳輸到播放端,這些數據會被動地 “積累” 在接收緩沖區中。
怎么消除業務緩沖區的累積延時呢 ?
推流端的發送緩沖區,可以在網絡恢復良好的時候,快送發送出去,從而消除掉這個累積延時。
播放端的接收緩沖區,可以通過丟幀或者加速播放的方式快速消費掉緩沖區中的數據,從而消除累計延時。
想從本質上解決直播延時問題,還是要換成基於
udp
的私有協議來傳輸數據。
參考: