rtsp之web无插件播放视频
前言:
作为一个从未接触过实时流(直播流)的人,我之前对实时视频一直没有概念,而最近参与的项目刚好有视频监控的需求,因此我对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_cache
。gop_cache
又称关键帧缓存,其意义是控制视频的关键帧之间的缓存是否开启。
新的方案:服务器用OpenCV解码,读取每一帧转为jpg,通过ws发到web端,web端通过改变img的src(h5的二进制),流畅播放视频
本文来自博客园,作者:封兴旺,转载请注明原文链接:https://www.cnblogs.com/fxw1/p/14923470.html