web無插件播放視頻之rtsp


前言:

作為一個從未接觸過實時流(直播流)的人,我之前對實時視頻一直沒有概念,而最近參與的項目剛好有視頻監控的需求,因此我對webs無插件實時流的展示進行了學習及研究,以下案例均經過實踐(不足之處望指教)。

概念:

視頻有一個流的概念,所以稱流媒體。實時視頻的流很好理解,因為視頻是實時的,需要有一個地方不停地輸出視頻出來,所以整個視頻可以用流來稱呼。可惜視頻並不能直接輸出至web,如果可以的話,也就沒有我這篇文章了。現在攝像頭的實時視頻流普遍采用的是 RTSP 協議(普奧視,海康,大華),而web並不能直接播放 RTSP 的視頻流

1.RTSP知識:

RTSP是 TCP/UDP 協議體系中的一個應用層協議,跟 HTTP 處在同一層。RTSP 在體系結構上位於 RTP 和RTCP 之上,它使用 TCP 或者 RTP 完成數據傳輸。RTSP 實時效果非常好,適合視頻聊天、視頻監控等方向。所以我們就需要一層中間層,來將 RTSP 流轉成前端可以支持的協議,這也引申出了目前實時流技術的幾種方向:

 RTSP -> RTMP

RTMP是屬於 Adobe 的一套視頻協議,這套方案需要專門的 RTMP 流媒體,並且如果想要在瀏覽器上播放,只能使用 Flash 播放器,無法直接使用 HTML5 的 video 標簽。它的實時性在幾種方案中是最好的,但是由於只能使用 Flash 的方案,所以在移動端和PC端就直接 GG 了(因為瀏覽器不在支持插件是大勢所趨)。 這里就大概展示一下 RTSP 流如何轉換成 RTMP ,我們使用 ffmpeg+Nginx+nginx-rtmp-module :

// 在 http 同一層配置 rtmp 協議的相關字段
rtmp {
    server {
            //端口
        listen 1935;
             //路徑
        application test {
            //開啟實時流模式
            live on;
            record off;
        }
    }
}
//bash 上執行 ffmpeg 把 rtsp 轉成 rtmp,並推到 1935 這個端口上
ffmpeg -i "rtsp://xxx.xxx.xxx:xxx/1" -vcodec copy -acodec copy -f flv "rtmp://127.0.0.1:1935/live/"

這樣就得到了一個 RTMP 的流,我們可以直接用 VLC 或者 IINA 來播放這個流

 RTSP -> HLS

HLS是蘋果公司提出的基於 HTTP 協議的的流媒體網絡傳輸協議,它的工作原理是把整個流分成一個個小的基於 HTTP 的文件來下載,每次只下載一些。HLS支持 iOS/Android/瀏覽器,通用性強。但是它的實時性差:蘋果官方建議是請求到3個片之后才開始播放。所以一般很少用 HLS 做為互聯網直播的傳輸協議。假設列表里面的包含5個 ts 文件,每個 TS 文件包含5秒的視頻內容,那么整體的延遲就是25秒。蘋果官方推薦的小文件時長是 10s,所以這樣就會有30s(n x 10)的延遲,所以此方案就先不嘗試了

RTSP -> RTMP -> HTTP-FLV

 HTTP-FLV 它集合了 HLS 的通用性和 RTMP 的實時性,可以做到在瀏覽器上用 HTML5 的 video 標簽,以較低的延時播放實時流。HTTP-FLV 依靠 MIME 的特性,根據協議中的 Content-Type 來選擇相應的程序去處理相應的內容,使得流媒體可以通過 HTTP 傳輸。除此之外,它可以通過 HTTP 302 跳轉靈活調度,支持使用 HTTPS 加密傳輸,也能夠兼容支持 Android,iOS 等移動端。HTTP-FLV 本質上是將流轉成 HTTP 協議下的 flv 文件,在 Nginx 上我們可以使用 nginx-http-flv-module 來將 RTMP 流轉成 HTTP 流。其實 flv 格式還是 Adobe 家的格式,原生 Video 標簽無法直接播放,不過我們有 bilibili 家的 flv.js,它可以將 FLV 文件流轉碼復用成 ISO BMFF(MP4 碎片)片段,然后通過 Media Source Extensions 將 MP4 片段喂進瀏覽器。 在支持瀏覽器的協議里,延遲排序是這樣的:RTMP = HTTP-FLV = WebSocket-FLV < HLS 而性能排序是這樣的:RTMP > HTTP-FLV = WebSocket-FLV > HLS,展示:

1.首先需要一個nginx 插件:nginx-http-flv-module

2.在 nginx.conf 中進行一些新的配置:

// rtmp server
application myvideo {
      live on;
      gop_cache: on; #減少首屏等待時間
}

// http server
location /live {
      flv_live on;
}

3.使用ffmpeg 來推流,就是上面 RTMP 的命令

4.web使用 import flv.js 來播放

//web使用 flv.js,開啟實時模式,然后訪問這個 nginx 地址下的路徑即可
import flvJs from 'flv.js';

export function playVideo(elementId, src) {
  const videoElement = document.getElementById(elementId);
  const flvPlayer = flvJs.createPlayer({
    isLive: true,
    type: 'flv',
    url: src,
  });
  flvPlayer.attachMediaElement(videoElement);
  flvPlayer.load();
}

playVideo('#video', 'http://localhost:8080/live?port=1985&app=myvideo&stream=streamname')
如果如果對延遲有更高的要求,可以嘗試下面的操作:
1.可以可以配置 flv.js 的 enableStashBuffer 字段,它是 flv.js 用於控制緩存 buffer 的開關,關閉了之后可以做到最小延遲,但由於沒有緩存,可能會看到網絡抖動帶來的視頻卡頓。
2.可以嘗試關閉 nginx 的 http 配置里的 gop_cachegop_cache 又稱關鍵幀緩存,其意義是控制視頻的關鍵幀之間的緩存是否開啟。

 

 

新的方案:服務器用OpenCV解碼,讀取每一幀轉為jpg,通過ws發到web端,web端通過改變img的src(h5的二進制),流暢播放視頻


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM