Jsmpeg.JS + Ffmpeg + Websocket + Node實現(xiàn)在網(wǎng)頁上播放rtsp視頻流

一,簡言

rtsp是一種RTSP(實時流協(xié)議)是一種網(wǎng)絡協(xié)議,專門用于控制基于IP的網(wǎng)絡上的多媒體流。RTSP主要用于設置和控制流媒體服務器上的媒體會話
一般電視直播或者攝像頭(使用RTSP流來傳輸實時視頻和音頻)
RTSP流的URL通常包含協(xié)議類型、服務器地址、端口號和媒體資源路徑,下面是一種格式

rtsp://username:password@hostname:port/path

首先將rtsp形式的視頻流在網(wǎng)頁上播放有很多種方法。

方法1 rtsp 轉 hls/m3u8

可以使用FFmpeg這個工具。FFmpeg可以讀取RTSP流并將其轉換為HLS流,然后生成m3u8文件但是轉hls流出來延遲很大。

方法2 使用rtsp2web

是一個提供在web頁面直接播放 rtsp 視頻流的包。使用起來簡單快捷高效
rtsp2web官網(wǎng)有具體
的使用方法。

方法3 Jsmpeg.JS + ffmpeg + websocket + node實現(xiàn)在網(wǎng)頁上播放。

我實現(xiàn)這種功能用的就是方法 下面會對方法進行詳細的說明,據(jù)網(wǎng)上搜索目前海k和大h也是使用的這種方法來實現(xiàn)的

二, ffmpeg + websocket + node+Jsmpeg.JS 的原理

首先這種方法的原理就是
1.RTSP流獲?。菏褂?strong>FFmpeg從RTSP源獲取視頻流。
2.轉碼與推流:FFmpeg將視頻流轉碼為MPEG-TS格式并通過WebSocket(全雙工通信)推送到Node.js服務器。
3.WebSocket轉發(fā):Node.js服務器通過WebSocket將接收到的MPEG-TS流轉發(fā)給網(wǎng)頁客戶端。
4.網(wǎng)頁播放:網(wǎng)頁客戶端使用jsmpeg.js庫從WebSocket接收MPEG-TS流并進行播放。

ffmpeg

簡單來說就是一種能獲取并且轉換RTSP的一種工具,并且還是跨平臺的

websocket

WebSocket 是一種全雙工通信協(xié)議,允許服務器和客戶端之間的實時數(shù)據(jù)傳輸
相比于傳統(tǒng)的HTTP請求-響應模型,WebSocket提供了更低的延遲。這對于實時視頻流傳輸非常重要,因為它能夠減少視頻播放的延遲
其在這里的作用是
**FFmpeg 通過 WebSocket 推送視頻流到 Node.js 服務器,然后WebSocket 服務器監(jiān)聽連接請求,并通過WebSocket 服務器轉發(fā)視頻流所有已連接的客戶端。

node

這里Node.js 服務器使用 ws 庫創(chuàng)建一個 WebSocket 服務器,處理客戶端的 WebSocket 連接請求,并且轉發(fā)給所以連接的客戶端,Node.js 服務器同時充當一個簡單的 HTTP 服務器,使頁面中的 JavaScript 代碼與服務器建立 WebSocket 連接。

jsmpeg.Js

jsmpeg.js 是一個用 JavaScript 編寫的輕量級視頻播放器庫,它能夠在網(wǎng)頁中通過 HTML5 <canvas> 元素播放視頻。jsmpeg.js 特別適用于播放通過 WebSocket 接收到的實時視頻流。它最常用于將視頻流從服務器傳輸?shù)綖g覽器客戶端并進行播放。
而且使用canvas進行渲染非常的高性能,也能支持大多數(shù)瀏覽器.

作用就是從服務器接收視頻流數(shù)據(jù),然后解析 MPEG-TS 流中的視頻幀,并進行視頻解碼,解碼后的視頻幀渲染到canvas中進行視頻播放

三,實現(xiàn)步驟

一,拿到rtsp流

首先拿到后端給你的一個rtsp流你要先去進行這個rtsp視頻流的*驗證,確保這個視頻流誰沒問題的然后再去進行以下的工作
使用一款叫VLC media player的軟件去進行測試
VLC media player下載地址
他是一個能播放所有類型的一個軟件
打開之后去將rtsp地址

image.png

在這個位置打開,能正常播放說明給你的流沒有問題.然后可以進行下一步的操作

第一步 布置環(huán)境變量

我用的是vue2版本進行開發(fā)的
vue2創(chuàng)建的命令是
安裝npm install -g @vue/cli
創(chuàng)建項目 vue create myproject

第二步

  • 1 在vue項目中安裝webSocet模塊
    npm install ws
    image.png
  • 2 將之前下載的jsmpeg文件放在跟src目錄下同級的位置,并新開一個終端去運行node websocket-relay.js supersecret 8081 8082命令.這個命令是用來啟動一個 WebSocket 轉發(fā)服務的,也就是監(jiān)聽這個8081端口(8082可以多端),然后一旦啟動這個8081端口websocket就會監(jiān)聽到并將數(shù)據(jù)給到這個端口
    8082端口是jsmpeg經(jīng)過處理過的可以讓網(wǎng)頁播放mpeg1的視頻,可以實現(xiàn)瀏覽器中播放MPEG1視頻和MP2音頻流

node websocket-relay.js supersecret 8081 8082 這條命令用于啟動一個 WebSocket 中繼服務器,具體來說:
node: 是運行 JavaScript 的 Node.js 環(huán)境的命令。
websocket-relay.js: 是一個 JavaScript 腳本文件的名稱,通常用于創(chuàng)建 WebSocket 服務器。
supersecret: 是一個參數(shù),可能是用于標識 WebSocket 服務器的一部分信息或密碼。
8081: 是 WebSocket 服務器的監(jiān)聽端口,即客戶端將連接到的端口。
8082: 是 WebSocket 服務器的中繼端口,即接收來自源服務器的流數(shù)據(jù)的端口。
這條命令的目的是啟動一個 WebSocket 服務器,用于接收來自某個源的視頻流數(shù)據(jù),并通過 WebSocket 中繼端口 (8082) 將該視頻流數(shù)據(jù)轉發(fā)到 WebSocket 客戶端。

  • 3 然后再用cmd開一個服務(此操作在用戶下打開終端就可以)執(zhí)行ffmpeg -i rtsp://192.168.2.0 -vf "delogo=x=10:y=10:w=400:h=80" -q 5 -f mpegts -codec:v mpeg1video -s 800x600 -timeout 5000000 http://127.0.0.1:8081/supersecret
    此命令作用是用ffmpeg的轉碼操作將從 rtsp://192.168.2.0 這個 RTSP 源獲取的視頻流,視頻流轉碼為 MPEG-TS 格式,并通過 HTTP 協(xié)議推送到 http://127.0.0.1:8081/supersecret 這個地址

這條命令的目的是從一個 RTSP 源(rtsp://192.168.19.47/ch1)獲取視頻流,并通過 ffmpeg 進行處理和轉碼,然后將轉碼后的視頻流以 MPEG-TS 格式發(fā)送到指定的 HTTP 地址(http://127.0.0.1:8081/supersecret)。
-rtsp_transport tcp: 指定使用 TCP 作為 RTSP 傳輸協(xié)議,確保穩(wěn)定的數(shù)據(jù)傳輸。
-i rtsp://192.168.99.27/ch1: 指定輸入源為 RTSP 地址 rtsp://192.168.19.27/ch1,從這個地址獲取視頻流。
-vf "delogo=x=10:y=10:w=400:h=80": 使用視頻濾鏡,去除視頻中指定位置的水?。╠elogo)。
x=10: 水印左上角的 x 坐標。
y=10: 水印左上角的 y 坐標。
w=400: 水印的寬度。
h=80: 水印的高度。
-q:v 15: 視頻質量參數(shù),指定視頻編碼的質量,值越小質量越高。
-f mpegts: 指定輸出格式為 MPEG-TS(MPEG Transport Stream)。
-codec:v mpeg1video: 指定視頻編碼器為 MPEG-1 Video。
-s 800x600: 指定輸出視頻的分辨率為 800x600 像素。
-b:v 2000k: 指定視頻的目標比特率為 2000 kbps。
-maxrate 2000k: 指定視頻的最大比特率為 2000 kbps。
-bufsize 4000k: 指定視頻緩沖區(qū)的大小為 4000 kbps。
-timeout 10000000: 指定超時時間為 10000000 微秒(10 秒),在此時間內沒有數(shù)據(jù)傳輸將會中斷連接。
-trellis 2: 激活 trellis 量化算法,提高視頻編碼的效率。
-qmax 30: 視頻質量參數(shù),最大量化參數(shù),控制視頻編碼的最大量化值。
最后的 http://127.0.0.1:8081/supersecret 是輸出的目標地址,指定將轉碼后的視頻流以 MPEG-TS 格式發(fā)送到此 HTTP 地址。

第三步 在vue頁面展示

  • 1 在vue項目的main.js文件中引入jsmpeg.min這個文件


    image.png

將jsmpeg.min文件的第一行改成window.JSMpeg(作用是將 JSMpeg 庫暴露到全局作用域中,使得在其他代碼中可以直接訪問和使用 JSMpeg 對象)

展示的vue文件

<template>
  <div class="right_one_box">
    <div class="title"><span></span>視頻監(jiān)控</div>
    <div class="box_con">
      <div class="con">
        <canvas id="video-canvas" style="height: 640px; width: 664px;"></canvas>
      </div>
    </div>
  </div>
</template>

<script>
import '../../jsmpeg-master/jsmpeg.min';// 引入 JSMpeg

export default {
  mounted() {
    // 獲取 canvas 元素
    const canvas = document.getElementById('video-canvas');
    
    // 創(chuàng)建 JSMpeg Player 實例,并傳入 WebSocket 地址和 canvas
    new JSMpeg.Player(this.path, {
      canvas: canvas,
      autoplay: true,
      loop: true,
    });
  },
  data() {
    return {
      path: 'ws://127.0.0.1:8082/brightness=1&saturation=0', // 視頻源地址(假設有一個 WebSocket 服務器運行在 127.0.0.1 的 8082 端口上,
      //客戶端可以通過 ws://127.0.0.1:8082/brightness=1&saturation=0 這樣的地址來請求視頻流數(shù)據(jù)。在這個例子中,brightness=1&saturation=0 
      //就是傳遞給服務器的參數(shù))
      
      //這里只是部署到我自己的服務器了
      //1.WebSocket 地址ws://127.0.0.1:8082/brightness=1&saturation=0
      //2.node websocket-relay.js supersecret 8081 8082
      //8081 端口通常用于客戶端向服務器發(fā)送視頻流數(shù)據(jù),8082 端口用于從服務器向客戶端發(fā)送處理后的視頻流數(shù)據(jù)。
      //前者定義了客戶端請求視頻流的地址和參數(shù),后者提供了一個服務器端程序,用于處理客戶端的請求并傳輸視頻流數(shù)據(jù)
    };
  },
};
</script>

<style scoped>

</style>

四,補充

視頻水印的去除

兩種思路
1.在 HTML頁面進行處理,就是在canvas上面進行每一幀對應位置的一個覆蓋,但是這樣對于一些復雜的水印可能處理不了,并且性能也不是很好
2 使用FFmpeg 提供了一個 delogo 濾鏡,可以用來移除特定位置的水印.在運行ffmpeg上添加參數(shù)"delogo=x=10:y=10:w=200:h=80"

對于canvas的一些設置

可以參考github中的這個網(wǎng)址進行一些canvas的操作https://github.com/Neveryu/rtsp2web/blob/master/example/index.html
比如說

 <!-- JSMpeg -->
    <!-- 方式一: 只給定寬度或者高度,另外一個值將會自適應;整體比例與原視頻一致 -->
    <canvas id="canvas-1" style="width: 400px"></canvas>

    <!-- 方式二: 可以自定義視頻播放窗口的寬度和高度,會鋪滿,比例可能與原視頻不一致了-->
    <canvas id="canvas-2" style="width: 400px; height: 400px"></canvas>

    <!-- 方式三:雖然設置了固定的寬高,但是視頻還是會選擇安寬度來自適應,比例與原視頻保持一致 -->
    <!-- 使用div + class="jsmpeg" + data-url的方式 -->

在調用 new JSMpeg.Player() 時,第一個參數(shù)是接口地址拼接上 rtsp 地址,我們還可以使用 url 傳參的方式傳遞更多的高階參數(shù)。
這里可以利用jsmpeg去設置在頁面播放視頻的參數(shù).如亮度,對比度等等

相關的報錯

  • 1

    image.png

    這里出現(xiàn)的問題意思我大概理解是處理視頻時有一些幀會丟失被剪切掉,到達了一個臨界的值
    解決方法: 把-q這個參數(shù)的值調大一點就好了
    搜索了一下 -q 是視頻質量(范圍0(質量最高)-24),我之前設置的是0,可能是這個原因出現(xiàn)了上面的提示。

  • 2

    image.png

    這里的報錯是進行視頻處理時發(fā)生了網(wǎng)絡相關的問題,通常是網(wǎng)絡連接中斷或連接被強制關閉所致。
    然后這里可以增加一個參數(shù),一個增加連接超時參數(shù):在 FFmpeg 命令中增加 -timeout 參數(shù),以延長連接超時時間,-timeout 5000000
    然后看了10分鐘目前沒有出現(xiàn)斷掉的情況,還需要去找真正的原因,看看是網(wǎng)絡的問題導致的還是什么。

五,關于報錯 不能長時間進行播放的

4b61da416cd861dfae739fca3ed09751.png

這個我查詢了很多資料 其中影響的因素有很多
FFMPEG詳解(完整版)-音視頻開發(fā)中文網(wǎng)
這個網(wǎng)站有一些關于ffnpeg的一些說明

其中我分析影響掉線的幾個點
1.網(wǎng)絡問題
2.掉包問題導致不能轉碼
3.傳輸?shù)膮f(xié)議 TCP(穩(wěn)定但可能有延遲) UDP(忽略掉包 延遲小)
4.緩沖區(qū)和超時時間
5.視頻質量的設置
6.設置-flags +global_header: ,這里是為了在每個關鍵幀前添加全局頭信息,確保解碼器正確解碼。
7.編碼格式RTSP通常用于控制和傳輸實時流媒體,而H.265則可以作為一種編碼標準被用于壓縮這些實時流媒體的視頻數(shù)據(jù)
8.編解碼器的參數(shù)(如碼率、幀率、分辨率等)

所以我根據(jù)以上這些點進行綜合調節(jié).下面兩條命令是一個UDP,一個TCP不同協(xié)議的命令
tcp:ffmpeg -report -rtsp_transport tcp -i rtsp://192.168.1.2/ch -vf "delogo=x=10:y=10:w=400:h=80" -q:v 20 -f mpegts -vcodec mpeg1video -s 800x600 -b:v 2000k -maxrate 2000k -bufsize 4000k -timeout 30000000 -trellis 2 -qmax 30 -flags +global_header [http://127.0.0.1:8081/supersecret](http://127.0.0.1:8081/supersecret)

udp:'ffmpeg -i rtsp://192.168.19.27/c -vf "delogo=x=10:y=10:w=400:h=80" -q:v 15 -f mpegts -codec:v mpeg1video -s 800x600 -b:v 2000k -maxrate 2000k -bufsize 4000k -timeout 10000000 -trellis 2 -qmax 30 http://127.0.0.1:8081/supersecret
'

前端可以播放MPEG-TS流和h265的格式流,但需要借助第三方進行處理
Video.js: 一個強大的HTML5視頻播放器,可以通過插件支持MPEG-TS。
hls.js: 一個支持HTTP Live Streaming(HLS)的JavaScript庫,可以將MPEG-TS流轉換為HLS格式進行播放。
Fluent-ffmpeg: 用于在服務器端處理視頻流,然后通過上述播放器庫在前端播放。

轉碼的HLS流可以借助video標簽來進行播放

如果你的監(jiān)控系統(tǒng)使用的是 MPEG-TS(MPEG Transport Stream)格式,JSMpeg 是一個非常合適的選擇。它可以通過 WebSocket 來接收和播放實時視頻流。

假設你有一個 H.265 編碼的視頻源,想要通過 HLS 協(xié)議傳輸并播放它。以下是一個使用 FFmpeg 將 H.265 編碼的視頻轉換為 HLS 流的示例:
sh
復制代碼
ffmpeg -i input_video.mp4 -c:v libx265 -preset fast -crf 28 -c:a aac -b:a 128k -f hls -hls_time 10 -hls_playlist_type vod -hls_segment_filename "segment_%03d.ts" output.m3u8
-i input_video.mp4:輸入視頻文件。
-c:v libx265:使用 H.265 編碼器。
-preset fast:編碼速度設置。
-crf 28:質量控制參數(shù),值越小質量越好但文件越大。
-c:a aac -b:a 128k:音頻編碼設置。
-f hls:輸出格式為 HLS。
-hls_time 10:每個片段的持續(xù)時間為 10 秒。
-hls_playlist_type vod:HLS 播放列表類型為點播(VOD)。
-hls_segment_filename "segment_%03d.ts":設置輸出片段文件的名稱格式。
output.m3u8:輸出的 HLS 播放列表文件。
通過這種方式,你可以將 H.265 編碼的視頻轉換為 HLS 流,在前端播放器中實現(xiàn)播放

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
禁止轉載,如需轉載請通過簡信或評論聯(lián)系作者。

相關閱讀更多精彩內容

友情鏈接更多精彩內容