Jsmpeg.JS + Ffmpeg + Websocket + Node实现在网页上播放rtsp视频流

一,简言

rtsp是一种RTSP(实时流协议)是一种网络协议,专门用于控制基于IP的网络上的多媒体流。RTSP主要用于设置和控制流媒体服务器上的媒体会话
一般电视直播或者摄像头(使用RTSP流来传输实时视频和音频)
RTSP流的URL通常包含协议类型、服务器地址、端口号和媒体资源路径,下面是一种格式

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

首先将rtsp形式的视频流在网页上播放有很多种方法。

方法1 rtsp 转 hls/m3u8

可以使用FFmpeg这个工具。FFmpeg可以读取RTSP流并将其转换为HLS流,然后生成m3u8文件但是转hls流出来延迟很大。

方法2 使用rtsp2web

是一个提供在web页面直接播放 rtsp 视频流的包。使用起来简单快捷高效
rtsp2web官网有具体
的使用方法。

方法3 Jsmpeg.JS + ffmpeg + websocket + node实现在网页上播放。

我实现这种功能用的就是方法 下面会对方法进行详细的说明,据网上搜索目前海k和大h也是使用的这种方法来实现的

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

首先这种方法的原理就是
1.RTSP流获取:使用FFmpeg从RTSP源获取视频流。
2.转码与推流:FFmpeg将视频流转码为MPEG-TS格式并通过WebSocket(全双工通信)推送到Node.js服务器。
3.WebSocket转发:Node.js服务器通过WebSocket将接收到的MPEG-TS流转发给网页客户端。
4.网页播放:网页客户端使用jsmpeg.js库从WebSocket接收MPEG-TS流并进行播放。

ffmpeg

简单来说就是一种能获取并且转换RTSP的一种工具,并且还是跨平台的

websocket

WebSocket 是一种全双工通信协议,允许服务器和客户端之间的实时数据传输
相比于传统的HTTP请求-响应模型,WebSocket提供了更低的延迟。这对于实时视频流传输非常重要,因为它能够减少视频播放的延迟
其在这里的作用是
**FFmpeg 通过 WebSocket 推送视频流到 Node.js 服务器,然后WebSocket 服务器监听连接请求,并通过WebSocket 服务器转发视频流所有已连接的客户端。

node

这里Node.js 服务器使用 ws 库创建一个 WebSocket 服务器,处理客户端的 WebSocket 连接请求,并且转发给所以连接的客户端,Node.js 服务器同时充当一个简单的 HTTP 服务器,使页面中的 JavaScript 代码与服务器建立 WebSocket 连接。

jsmpeg.Js

jsmpeg.js 是一个用 JavaScript 编写的轻量级视频播放器库,它能够在网页中通过 HTML5 <canvas> 元素播放视频。jsmpeg.js 特别适用于播放通过 WebSocket 接收到的实时视频流。它最常用于将视频流从服务器传输到浏览器客户端并进行播放。
而且使用canvas进行渲染非常的高性能,也能支持大多数浏览器.

作用就是从服务器接收视频流数据,然后解析 MPEG-TS 流中的视频帧,并进行视频解码,解码后的视频帧渲染到canvas中进行视频播放

三,实现步骤

一,拿到rtsp流

首先拿到后端给你的一个rtsp流你要先去进行这个rtsp视频流的*验证,确保这个视频流谁没问题的然后再去进行以下的工作
使用一款叫VLC media player的软件去进行测试
VLC media player下载地址
他是一个能播放所有类型的一个软件
打开之后去将rtsp地址

image.png

在这个位置打开,能正常播放说明给你的流没有问题.然后可以进行下一步的操作

第一步 布置环境变量

我用的是vue2版本进行开发的
vue2创建的命令是
安装npm install -g @vue/cli
创建项目 vue create myproject

第二步

  • 1 在vue项目中安装webSocet模块
    npm install ws
    image.png
  • 2 将之前下载的jsmpeg文件放在跟src目录下同级的位置,并新开一个终端去运行node websocket-relay.js supersecret 8081 8082命令.这个命令是用来启动一个 WebSocket 转发服务的,也就是监听这个8081端口(8082可以多端),然后一旦启动这个8081端口websocket就会监听到并将数据给到这个端口
    8082端口是jsmpeg经过处理过的可以让网页播放mpeg1的视频,可以实现浏览器中播放MPEG1视频和MP2音频流

node websocket-relay.js supersecret 8081 8082 这条命令用于启动一个 WebSocket 中继服务器,具体来说:
node: 是运行 JavaScript 的 Node.js 环境的命令。
websocket-relay.js: 是一个 JavaScript 脚本文件的名称,通常用于创建 WebSocket 服务器。
supersecret: 是一个参数,可能是用于标识 WebSocket 服务器的一部分信息或密码。
8081: 是 WebSocket 服务器的监听端口,即客户端将连接到的端口。
8082: 是 WebSocket 服务器的中继端口,即接收来自源服务器的流数据的端口。
这条命令的目的是启动一个 WebSocket 服务器,用于接收来自某个源的视频流数据,并通过 WebSocket 中继端口 (8082) 将该视频流数据转发到 WebSocket 客户端。

  • 3 然后再用cmd开一个服务(此操作在用户下打开终端就可以)执行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 协议推送到 http://127.0.0.1:8081/supersecret 这个地址

这条命令的目的是从一个 RTSP 源(rtsp://192.168.19.47/ch1)获取视频流,并通过 ffmpeg 进行处理和转码,然后将转码后的视频流以 MPEG-TS 格式发送到指定的 HTTP 地址(http://127.0.0.1:8081/supersecret)。
-rtsp_transport tcp: 指定使用 TCP 作为 RTSP 传输协议,确保稳定的数据传输。
-i rtsp://192.168.99.27/ch1: 指定输入源为 RTSP 地址 rtsp://192.168.19.27/ch1,从这个地址获取视频流。
-vf "delogo=x=10:y=10:w=400:h=80": 使用视频滤镜,去除视频中指定位置的水印(delogo)。
x=10: 水印左上角的 x 坐标。
y=10: 水印左上角的 y 坐标。
w=400: 水印的宽度。
h=80: 水印的高度。
-q:v 15: 视频质量参数,指定视频编码的质量,值越小质量越高。
-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: 指定视频缓冲区的大小为 4000 kbps。
-timeout 10000000: 指定超时时间为 10000000 微秒(10 秒),在此时间内没有数据传输将会中断连接。
-trellis 2: 激活 trellis 量化算法,提高视频编码的效率。
-qmax 30: 视频质量参数,最大量化参数,控制视频编码的最大量化值。
最后的 http://127.0.0.1:8081/supersecret 是输出的目标地址,指定将转码后的视频流以 MPEG-TS 格式发送到此 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>视频监控</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');
    
    // 创建 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 这样的地址来请求视频流数据。在这个例子中,brightness=1&saturation=0 
      //就是传递给服务器的参数)
      
      //这里只是部署到我自己的服务器了
      //1.WebSocket 地址ws://127.0.0.1:8082/brightness=1&saturation=0
      //2.node websocket-relay.js supersecret 8081 8082
      //8081 端口通常用于客户端向服务器发送视频流数据,8082 端口用于从服务器向客户端发送处理后的视频流数据。
      //前者定义了客户端请求视频流的地址和参数,后者提供了一个服务器端程序,用于处理客户端的请求并传输视频流数据
    };
  },
};
</script>

<style scoped>

</style>

四,补充

视频水印的去除

两种思路
1.在 HTML页面进行处理,就是在canvas上面进行每一帧对应位置的一个覆盖,但是这样对于一些复杂的水印可能处理不了,并且性能也不是很好
2 使用FFmpeg 提供了一个 delogo 滤镜,可以用来移除特定位置的水印.在运行ffmpeg上添加参数"delogo=x=10:y=10:w=200:h=80"

对于canvas的一些设置

可以参考github中的这个网址进行一些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() 时,第一个参数是接口地址拼接上 rtsp 地址,我们还可以使用 url 传参的方式传递更多的高阶参数。
这里可以利用jsmpeg去设置在页面播放视频的参数.如亮度,对比度等等

相关的报错

  • 1

    image.png

    这里出现的问题意思我大概理解是处理视频时有一些帧会丢失被剪切掉,到达了一个临界的值
    解决方法: 把-q这个参数的值调大一点就好了
    搜索了一下 -q 是视频质量(范围0(质量最高)-24),我之前设置的是0,可能是这个原因出现了上面的提示。

  • 2

    image.png

    这里的报错是进行视频处理时发生了网络相关的问题,通常是网络连接中断或连接被强制关闭所致。
    然后这里可以增加一个参数,一个增加连接超时参数:在 FFmpeg 命令中增加 -timeout 参数,以延长连接超时时间,-timeout 5000000
    然后看了10分钟目前没有出现断掉的情况,还需要去找真正的原因,看看是网络的问题导致的还是什么。

五,关于报错 不能长时间进行播放的

4b61da416cd861dfae739fca3ed09751.png

这个我查询了很多资料 其中影响的因素有很多
FFMPEG详解(完整版)-音视频开发中文网
这个网站有一些关于ffnpeg的一些说明

其中我分析影响掉线的几个点
1.网络问题
2.掉包问题导致不能转码
3.传输的协议 TCP(稳定但可能有延迟) UDP(忽略掉包 延迟小)
4.缓冲区和超时时间
5.视频质量的设置
6.设置-flags +global_header: ,这里是为了在每个关键帧前添加全局头信息,确保解码器正确解码。
7.编码格式RTSP通常用于控制和传输实时流媒体,而H.265则可以作为一种编码标准被用于压缩这些实时流媒体的视频数据
8.编解码器的参数(如码率、帧率、分辨率等)

所以我根据以上这些点进行综合调节.下面两条命令是一个UDP,一个TCP不同协议的命令
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标签来进行播放

如果你的监控系统使用的是 MPEG-TS(MPEG Transport Stream)格式,JSMpeg 是一个非常合适的选择。它可以通过 WebSocket 来接收和播放实时视频流。

假设你有一个 H.265 编码的视频源,想要通过 HLS 协议传输并播放它。以下是一个使用 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:质量控制参数,值越小质量越好但文件越大。
-c:a aac -b:a 128k:音频编码设置。
-f hls:输出格式为 HLS。
-hls_time 10:每个片段的持续时间为 10 秒。
-hls_playlist_type vod:HLS 播放列表类型为点播(VOD)。
-hls_segment_filename "segment_%03d.ts":设置输出片段文件的名称格式。
output.m3u8:输出的 HLS 播放列表文件。
通过这种方式,你可以将 H.265 编码的视频转换为 HLS 流,在前端播放器中实现播放

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容