智慧小車開發篇 - 低時延直播測試

Bt4Girls發表於2024-06-14

智慧小車開發篇 - 低時延直播測試

本章節暫不考慮伺服器效能指標, 目前僅對核心開發板資源佔用、延時作為硬性考慮指標

前言

目前市面上常見的推拉流協議有:RTMP、HLS、HTTP-FLV、RTSP、WebRTC

協議名稱 延時 傳輸協議 優勢 劣勢 適用場景
RTMP 1~5s TCP 1. 協議成熟
2. 上手成本低
相容性問題,大部分主流瀏覽器已不支援 Flash PC 端延時不敏感直播
HLS >10s TCP 1. 點播場景非常適用
2. 平滑播放(像播放影片檔案一樣直播)
延遲非常高 點播場景
HTTP-FLV 1~5s TCP 1. 延時較低且可瀏覽器播放 瀏覽器上適用需要用到特定本播放器(flv.js) 對延時有一定要求並期望在瀏覽器上播放的場景
RTSP <1s TCP/UDP 1. 延時極低
屬於被動協議,需要客戶端主動去拉流,不會向外推流(GB28181 可以實現向外推流) 各大攝像頭廠商基本協議
WebRTC <500ms UDP 1.延時很低 上手難度大 低時延直播、會議室

上述的表格統計也僅為本人經驗總結,歡迎大佬們指正與指點迷津。😀😀

🚩 上述延時均為大概範圍,具體時間還得看不同的拉流手段、伺服器環境、網路環境等因素。

🔶🔶 題外話:

本人專案中也試過這樣的推拉流方案:

  • 推流端: RTSP
  • 拉流端: JSMpeg
  • 中轉端: FFmpeg

整個流程:RTSP -> FFmpeg -> JAVA 服務 -> WebSocket -> 客戶端

FFmpeg 拉取 RTSP 流,轉碼並轉成 TCP 流至 JAVA 服務,JAVA 服務將接收到的流透過 WebSocket 推送至瀏覽器客戶端;客戶端接收後利用 JSMpeg 來播放整個流

當初這樣處理主要是為了少搭建一個流媒體伺服器,一般情況下我還是會去選擇轉 RTMP 後適用 flv.js 播放

相關資源

本次實驗與測試物件如下

  • 核心開發板:樹莓派 4B Raspbarry 4B (4G 版本)
  • 攝像頭:樹莓派官方 CSI 介面攝像頭 1280x720
  • 作業系統: ubuntu server 22.04LTS
  • 相關軟體: GStreamer

伺服器相關資源

  • 容器: Docker
  • 流媒體伺服器: SRS5.0
  • 監控: Prometheus + Grafana

環境安裝與部署

相關環境安裝的教程建議參考官方文件(好的專案總是不斷更新迭代的,經常翻閱文件將會是一個不錯的習慣)

  • SRS V5 官方文件
  • GStreamer 官方文件
  • Prometheus 官方文件
  • Grafana 官方文件
  • 線上時間

測試方案

目前由於學習成本與時間關係:僅從以下幾種低成本的方式進行選擇性測試,後續再發文其他方式的相關文章。

由於對延時的要求較高,因此目前暫不考慮 HLS 這等高延時方案,RTSP 由於是一個被動拉取的協議,因此也暫時不考慮 RTSP 的方案,WebRTC 方案技術成本較高,放後續進行測試與整理文件。

  1. RTMP 推 - HTTP-FLV 拉
  2. RTMP 推 - WebRTC 拉
  3. 自定義格式 UDP 推流 - 自定義 UDP 拉流

基本資源佔用情況

基本資源佔用情況
如上圖所示,在未進行任何推流的情況下資源佔用

  • CPU:<= 1.5%
  • 記憶體:<= 9.6%
  • 網路:~= 0 kb/s

開發板中僅執行了:node_exporter 用於監控開發板資源

SRS 配置檔案

由於是內網環境,目前下屬檔案配置環境中的 candidate 設定的 ip 為我區域網 ip

# main config for srs.
# @see full.conf for detail config.

listen              1935;
max_connections     1000;
#srs_log_tank        file;
#srs_log_file        ./objs/srs.log;
daemon              on;
http_api {
    enabled         on;
    listen          1985;
}

http_server {
    enabled         on;
    listen          8080;
    dir             ./objs/nginx/html;
    #這裡開啟了跨域允許
    crossdomain on;
}

rtc_server {
    enabled on;
    listen 8000; # UDP port
    # @see https://ossrs.net/lts/zh-cn/docs/v4/doc/webrtc#config-candidate
    candidate 192.168.108.9;
}

vhost __defaultVhost__ {
    enabled on;
    tcp_nodelay on;
    min_latency on;

    hls {
        #暫不適用hls,不做開啟
        enabled     off;
    }

    http_remux {
        enabled     on;
        mount       [vhost]/[app]/[stream].flv;
    }

    rtc {
        enabled     on;
        nack on;
        rtmp_to_rtc on;
        twcc on;
    }

    play{
        gop_cache off;
        queue_length 10;
        mw_latency 350;
    }

    publish{
        mr on;
        mr_latency 350;
    }
}

方案一:RTMP 推流 + RTMP 拉流

GStreamer 推流

推流前系統資源佔用情況

此時裝置剛開機,CPU 佔用~=40%,檢視了一下程序,發現是自動更新了某些東西

因此等待更新完成後再做下列操作

推流前系統資源佔用情況

img

  • CPU:~= 1%
  • 記憶體:~= 10%
  • 網路:~= 0 kb/s

開始推流

推流指令

gst-launch-1.0 -v v4l2src device=/dev/video0 ! 'video/x-h264, width=1280, height=720, framerate=30/1' ! h264parse ! flvmux ! rtmpsink location='${ip}'

推流了大概 5 分鐘後延時圖
推流效果圖

推流資源佔用情況

img

時機 CPU 記憶體 網路
推流前 1% 10% 0 kb/s
推流後 2.5% 10.3% 60 kb/s ~ 7 Mb/s

推流直播延時

  • 實際時間: 10:14:15:069
  • 顯示時間: 10:14:13:600
  • 相差延時: 1.3s 左右

本次推流大概使用的資源如下

  • CPU:~= 1.5%
  • 記憶體:~= 3M 左右
  • 網路:60 kb/s ~ 7 Mb/s(具體看畫面變化)

小總結

總的看來,使用 GStreamer 推流時頻寬使用的較為大外,資源佔用情況還是比較低的

我們其實可以看到 Network Traffic Basic 這一欄的波動,前一段是一個平緩的數值,突然間上漲到一個高度,然後再後續下降下來,最後呈現出一個很低的平緩直線

一開始我還在好奇,怎麼流量上漲了這麼多?我好像也沒處理什麼,還以為有什麼其他程式增高了這個

但後想了以下,也沒開其他應用程式;

然後懷疑是 H.264 傳輸壓縮的問題, 測試了一下,當我將攝像頭擺在一個畫面豐富且動態變化的情況下,此時網路佔用非常高;當我將攝像頭蓋起來(基本上處於一個黑色不變的情況下),此時網路佔用幾近於無(~=60 kb/s)

做了這個實驗其實已經證實了我的想法, H.264 編碼裡面會使用 I幀P幀B幀 來組成畫面與減少資料體積;[1]

當我們畫面幾乎不變時 使用 P幀B幀 編碼是資料體積會很小,因此節省了很多的頻寬資源。

FFmpeg 推流

推流前系統資源佔用情況

推流前先用了 echo 3 > /proc/sys/vm/drop_caches 命令清空了 buff/cache

此時系統佔用情況

img

  • CPU:~= 1.3%
  • 記憶體:~= 9.5%
  • 網路:~= 0 kb/s

開始推流

推流指令

ffmpeg -f v4l2 -framerate 30 -video_size 1280x720 -i /dev/video0 \
       -c:v libx264 -preset veryfast -maxrate 1000k -bufsize 2000k -pix_fmt yuv420p \
       -c:a aac -b:a 128k -ar 44100 \
       -f flv ${ip}

推流了大概 5 分鐘後延時圖

img

系統資源佔用情況
img

時機 CPU 記憶體 網路
推流前 1.3% 9.5% 0 kb/s
推流後 58.2% 14.3% 600 kb/s

推流直播延時

  • 實際時間: 10:30:24:387
  • 顯示時間: 10:30:21:533
  • 相差延時: 3s 左右

本次推流大概使用的資源如下

  • CPU:~= 58%
  • 記憶體:~= 140M 左右
  • 網路:600 kb/s

小總結

這裡可以看到與 Gstreamer 推流相比,FFmpeg 推流下系統資源佔用,延時等明顯上升了一個臺階,但是頻寬穩定在 600 kb/s

這裡應該是對整個影片流進行了壓縮處理導致需要較多的 CPU 資源與 記憶體佔用(目前還沒熟悉 FFmpeg 的相關引數,後續對其學習後整理相關的文件在過來重新分析對此進行分析)

章節總結

推流方式 延時 CPU 佔用 記憶體佔用 頻寬佔用
GStreamer 1.3s 1.5% ~=3M 60 kb/s ~ 7 Mb/s(具體看畫面變化)
FFmpeg 3s 58% ~=140M 600 kb/s

上面的總結測試並不完整與科學;明顯能得出的是 FFmpeg 應該會去壓縮畫面從而減少頻寬,但與之相對應的是系統資源的佔用提升;目前由於我們第一要義是選擇資源佔用小的,延時低的,暫時先選擇用 GStreamer 來進行推流;(歡迎各位大佬來幫忙解答這部分)

方案二:RTMP 推流 + HTTP-FLV 拉流

由於推流在方案一里已經做了對比效果,因此本方案只使用 GStreamer 進行推流;然後只針對於 HTTP-FLV 拉流的方式進行檢視延時效果

拉流效果圖

img

  • 實際時間: 10:52:01:173
  • 顯示時間: 10:52:00:289
  • 相差延時: 1s 左右

總的來說效果還是出乎我的意料的;看上去延時不是特別高,而且最主要還能直接透過瀏覽器進行播放;

方案二:RTMP 推流 + WebRTC 拉流

由於推流在方案一里已經做了對比效果,因此本方案只使用 GStreamer 進行推流;然後只針對於 WebRTC 拉流的方式進行檢視延時效果

拉流效果圖

img

  • 實際時間: 10:55:03:620
  • 顯示時間: 10:55:03:452
  • 相差延時: 200ms 左右

這個區域網拉流的實際效果已經非常不錯了,基本上可以算是一個比較實時的反饋了。當然其實 WebRTC 還是一個比較龐大且複雜的東西,裡面還需要我更深入的去研究才能做出更好的選擇。

測試小結

推流方式 拉流方式 延時 備註
GStreamer - RTMP KMPlayer - RTMP 1.3s 資推流資源佔用較低,但拉流時間較高
FFmpeg - RTMP KMPlayer - RTMP 3s 資源佔用較高,
GStreamer - RTMP HTTP-FLV 1s 效果還行,普通的低延時場景夠用,如果做遠端控制則還是不太足夠
GStreamer - RTMP WebRTC 200ms 效果不錯,但挪到公網上還有待考究

最後的總結:

如果雙端都能做到走 WebRTC 的方案,延時會更小更穩定一些吧;
如果是普通場景,我覺得我去先擇 RTMP + HTTP-FLV 已經十分足夠了,但是目前需要做遠端控制,而且還需要做到外網控制的話, WebRTC 是一個不錯的選擇。
當然,本次實驗的過程其實可以說是漏洞百出,例如:

  1. 沒有對 KMPlayer 播放器是否會做其他操作來增高延時(例如SRS裡面說的不要用VLC觀看,VLC延時會很大[2]
  2. 也沒使用自定義協議來進行傳輸(理論上應該延時也比較低,但是穩定性就需要看怎麼去設計了)
  3. 而且很多細節沒有去深究為什麼,怎麼做到統一從而減少誤差。
    參考了很多文章,也學到了不少新的知識點,也算是稍微拓寬了我的知識面吧。

相關用到的部署命令


# Docker run Prometheus
docker run -itd -p 9090:9090 --name promethues prom/prometheus

# Docker run Grafana
docker run -d --name grafana -p 3000:3000 grafana/grafana-enterprise


參考文章

https://stackoverflow.com/questions/70655928/live-streaming-from-raspberry-pi-to-nodejs-server-hosted-on-google-app-engine/70675353#70675353
https://opensource.com/article/19/1/gstreamer
https://github.com/ossrs/srs/issues/2304
http://www.riqicha.com/beijingshijian.html


  1. https://www.cnblogs.com/Lxk0825/p/9925041.html ↩︎

  2. https://ossrs.net/lts/zh-cn/docs/v5/doc/sample-realtime ↩︎

相關文章