几种浏览器播放RTSP视频流的方案 | 灼热光芒_介绍Waline

时间:2021年04月12日 01:57:15

上周又做了一次在浏览器中播放视频流的项目,不过以前做的是手机,这次做的是桌面。停车场出入口的摄像头作为源头提供RTSP协议的视频流,而浏览器不能直接播放,只有通过插件或者转码来实现这个需求。

要实现这个目的,可以采用的方案非常得多,有商业的也有开源的,这里主要列举一些开源的方案。

方案

这里的方案都是我尝试过了的,有些成功,有些没成功。但是因为每个项目情况不同,这次没成的方法,换个项目也许就能成,所以方案全部列在这里,失败的我也会说明原因。读者若走投无路,不妨也试试我失败了的方案。

由于项目原因,这里的浏览器主要考虑 Windows 平台。

顺序

由于方案很多,我们先归归类、排排序,从简单的到复杂的来。

1.通过浏览器插件直接播放RTSP

首先我们介绍没有中介的方案,也就是不预先进行转码,而在浏览器中直接解码RTSP流。

1.1 VLC插件

优点:

可以直接播放RTSP,无需任何中介服务器的帮助

缺点:

需要手动安装插件;基于NPAPI,不被最新的 Chrome 和 Firefox 支持

方法:安装 VLC 播放器时,可以选择安装浏览器插件,然后进入浏览器激活它们,最后在页面中嵌入一个简单的视频标签,完成。

1234

如果你项目的其他功能都能兼容客户电脑上的 IE 浏览器,这个方案就是首选。我们的项目就没有这个幸运,我们只支持了现代浏览器,而现代浏览器抛弃了 NPAPI 。

参考链接:

VLC wiki插件安装方法1.2 Flash

优点:

可以直接播放RTSP,但通常需要中介服务器支持几乎所有桌面浏览器

缺点:

需要手动安装插件(但大多数情况下已经安装了)

方法:

Flash 被不少用户痛恨,漏洞之王,耗电也厉害,但它确实能把事给办了。

不少视频网站包括直播网站都在用 Flash ,有不少基于 Flash 的在线视频播放器,我这次尝试的是 locomote ,一个结合 JavaScript 和 Flash 的开源解决方案。

把 dist 目录下的 .js 和 .swf 文件放到自己的项目里,然后通过 JavaScript 来调用 Flash 播放器播放 RTSP 视频。

123456789101112131415161718192021222324252627$(document).ready(function() {/* Load SWF and instantiate Locomote */var locomote = new Locomote('player', 'Player.swf');/* Set up a listener for when the API is ready to be used */locomote.on('apiReady', function() {console.log('API is ready. `play` can now be called');/* Tell Locomote to play the specified media */locomote.play('rtsp://192.168.10.51:554');});/* Start listening for streamStarted event */locomote.on('streamStarted', function() {console.log('stream has started');});/* If any error occurs, we should take action */locomote.on('error', function(err) {console.log(err);});});

如果你足够幸运,到此就完成了,不过大多数情况下并没有。

出于安全考虑,从 Flash 10 开始,需要一个 Socket Policy Server 来“授权”,才能允许 Flash 读取其他服务器上的内容,而且你读的视频流在哪个IP地址,Socket Policy Server 也必须在那个服务器上(默认843端口),而摄像头显然没有条件让你在上面跑另外一个服务。

这时候就需要一个中介服务器,我用 Nginx 的 stream 功能做了一个二进制流的反向代理来解决这个问题

stream {server {listen 9051;proxy_pass 192.168.10.51:554;}}

这样,就把摄像头的 554 端口代理到了这个服务器的 9051 端口,Flash 那边的 locomote.play 里的地址要改成运行 Nginx 的服务器的 9051 端口。然后在同一台服务器上运行一个服务,监听 843 端口,并返回授权信息。

下面的参考链接里可以下载到 flashpolicyd_v0.6.zip 这个压缩包,解压后找到并运行(需要 python 环境)

./flashpolicyd.py --file=../policyfile.xml --port=843

plicyfile.xml 是政策文件,你可以先把里面的 domain 和 to-ports 改成 * 放开限制,把功能调通,确定功能正常了,再把设置改成实际的地址和端口增加安全性。

正确开启这个服务后,就可以在浏览器中看到视频了。

非常不幸,我栽在了就要抵达胜利的时候。

类似这个问题 issues 117

摄像头发过来的协议头不标准,返回的 Content-Base 中没有协议

摄像头只返回了 Content-Base 192.168.10.51,按照标准中的例子,应该是 Content-Base rtsp://192.168.10.51,当然,这个视频在VLC里是可以播放的,也可以说是播放器的兼容性不好,不管怎样,我失败了,希望你够幸运。

参考链接:

locomote@githubSetting up a socket policy file server2.转码方案

优点:

可以转换成各种编码来适应客户端的要求

缺点:

服务器需要较大的性能开销需要维护额外的转码进程

转码方案我也尝试了两类,一类是需要专门的视频流服务器的,另一类是基于 http 的

两种方案都用到了 FFmpeg 这个开源软件,FFmpeg 在编解码领域是标杆性的,大量的播放器和其他涉及视频编解码的软件都用采用了它。

在 FFmpeg3 中,内置了 ffserver 视频流服务软件,可惜在 2017 年初的 FFmpeg4 中已经被移除了,但是相当多的 Linux 发型版仍然使用 FFmpeg3 并包含 ffserver 。

2.1 ffserver

优点:

方便

缺点:

ffserver 已经过时了

请注意,ffserver 已经过时了,项目组已经停止开发。

如果你的环境允许,使用 ffserver 会比直接使用 ffmpeg 免去很多进程管理上的工作,其配置文件大概是这个形式

HTTPPort 9999HTTPBindAddress 0.0.0.0MaxHTTPConnections 2000MaxClients 1000MaxBandwidth 1000000CustomLog -Format statusACL allow 127.0.0.1ACL allow 192.168.0.0 192.168.255.255File /tmp/feed51.ffmFileMaxSize 200MLaunch ffmpeg -i rtsp://192.168.10.51:554Format webmFeed feed51.ffmVideoCodec libvpxVideoFrameRate 30VideoBitRate 800VideoSize 720x576AVOptionVideo crf 23AVOptionVideo me_range 16AVOptionVideo qdiff 4AVOptionVideo qmin 10AVOptionVideo qmax 51AVOptionVideo flags +global_headerNoAudio

其中可以提供一个页面,让你通过浏览器查看整个 ffserver 的运行状况

是视频来源的入口,通过设置 Launch ffmpeg 可以调用 ffmpeg 将参数中的视频源转成 ffserver 的内部格式,这个是 ffserver 的一大优点,你不用另外管理这些转码的进程,ffserver 会调用和执行它们

是视频供外部消费的出口,我选择 webm 这个格式,因为主流浏览器可以直接在 video 标签中播放这个格式,而不需要 JavaScript 插件。Stream 里有一行配置是 Feed feed51.ffm ,用来指明视频的来源,当你有多路视频的时候,根据这个来把各路 Feed 和 Stream 对应起来,后面的参数则是调整视频流的帧率、尺寸、声音等具体表现的参数。

这个方法成功了,不过不知道是服务器不给力还是 FFmpeg3 的性能不如 FFmpeg4 ,用这个方法转码的时候容易断掉,导致播放体验不好。

后来专门用 FFmpeg3 和 FFmpeg4 在同一台服务器里运行了一下,FFmpeg3 挂掉次数明显比 FFmpeg4 多,即使没挂掉的时候,命令行里提示的 Warning 也要多很多。

参考资料:

ffserver wiki2.2 FFmpeg4 和 RTMP

既然 FFmpeg4 转码成功率更高,只好选择它,但是 FFmpeg4 没有对应的 ffserver 可以使用,必须另外找一个视频流服务软件作为代替,然后 Nginx 又登场了。

Linux 上需要安装一个组件 nginx-mod-rtmp,当然,不同发行版可能名称略有不同,Windows 上可以找第三方编译好的版本,官方下载的没有带这个组件。

在 Nginx 的配置文件中加入这些

rtmp {server {listen 1935;chunk_size 4096application live {live on;record off;}}}

然后使用 ffmpeg 转码视频流,并将转码结果推到这个端口

ffmpeg -i rtsp://192.168.10.51:554 -f flv rtmp://127.0.0.1:1935

RTMP 可以用前面提到的 Flash 播放器来播放,而且不需要另外配置 Socket Policy Server。

但在实际使用中,这个转码过的流在 VLC 中能够播放,在 Flash 中却失败了。证明转码是以及服务器的配置都是成功的,但此时已是周五下午,我实在没时间再进一步了,另一方面我拿 Flash 也没辙,它不提供任何错误信息,我就束手无策。

参考资料:

在 Nginx 中启用 RTMP 服务Youtube 上的视频演示2.3 FFmpeg4 和 HLS

这下只能回到以前成功过的方法了,想想还是有点凄惨,虽然花了两天时间学到不少东西,但终究走回了老路。

HLS 大体上是一种把视频切分成多个片段存在硬盘上,然后由一个 .m3u8 文件做索引的体系。RTSP 转 HLS 的过程,就是把 RTSP 流一段一段录像的过程,然后客户端再按照 .m3u8 文件中的指示,到服务器上把一段一段的录像下载过去再连起来播放,服务器上不停录下新的片段,客户端不停去下载新片段来播放,就实现了“直播”。与一般的基于视频流服务器的方式相比有以下特点:

优点:

基于 HTTP 协议,无需专门的视频流服务器中间产物可见,方便调试移动端的原生支持

缺点:

因为传输的最小单位是一段文件,而且需要先缓冲几段来保证视频顺畅,所以延迟较高

另外原先还有个缺点是需要自己管理已经播放过的视频片段,但做到最后发现 FFmpeg 已经实现自我管理,能把过时的文件清除掉了。

转码也只需要一条命令:

ffmpeg -i rtsp://192.168.10.51:554 -c:v h264 -flags +cgop -g 30 -hls_time 1 -hls_flags delete_segments 51/live.m3u8-c:v 后面跟的是编码方式-flags +cgop 和 -g 30 说实话我还没弄清楚,只是官方的列子都有这个参数我就照抄了-hls_time 1 是视频片段的长度,单位是秒,可以适当长一点-hls_flags delete_segments 是让 ffmpeg 自动删除已经不在 .m3u8 中的旧文件51/live.m3u8 是索引文件的名称,视频片段会和索引文件放在同一个目录下。

我有四路视频,所以需要开 4 个转码进程,这样管理起来会比较麻烦,加上视频源可能意外中断,导致解码进程退出,所以必须有一个工具来管理他们。最后写了一个简单的 node.js 脚本来做这件事。

123456789101112131415161718192021222324var respawn = require('respawn');[51,52,56,57].forEach((v) => {var monitor = respawn(['ffmpeg.exe','-rtsp_transport', 'tcp',`-i`, `rtsp://192.168.10.${v}`,'-c:v', 'h264','-flags', '+cgop','-g', '30','-hls_flags', 'delete_segments','-hls_time', '10',`${v}/live.m3u8`], {name: `live${v}`,// set monitor namecwd: '.',// set cwdmaxRestarts:-1,// how many restarts are allowed within 60s// or -1 for infinite restartssleep:1000,// time to sleep between restarts,kill:30000,// wait 30s before force killing after stopping});monitor.start();});

[51,52,56,57] 这个数组里面是四个摄像头 IP 的尾部,然后利用 respawn 在一个循环里将它们都开起来。respawn 最重要的工作,是根据你设定的参数在进程意外退出时将他们重新开启,免除了手工维护。

转化开启后,需要配置 web 服务器,将生成文件所在的目录放到可以通过 http 协议访问到的地方,具体过程不再赘述。

最后,考虑到不是所有浏览器都支持 HLS,我们需要使用 hls.js 来播放视频流。

123456789101112131415161718var video = document.getElementById('video');if(Hls.isSupported()) {var hls = new Hls();hls.loadSource('http://192.168.20.45:5444/51/live.m3u8');hls.attachMedia(video);hls.on(Hls.Events.MANIFEST_PARSED,function() {video.play();}); } else if (video.canPlayType('application/vnd.apple.mpegurl')) {video.src = 'http://192.168.20.45:5444/51/live.m3u8';video.addEventListener('loadedmetadata',function() {video.play();});}

过程非常简单,放上一个 video 标签,引入 hls.js,然后用 hls.js 来加载刚才生成的视频流,完成。

参考资料

respawn@githubffmpeg hlshls.js杂项

这里是我在尝试的过程中遇到的问题,与一些相关的技术,如果你在上面的方法中仍然没有找到解决方案,可以试试下面的关键字。

在使用 ffmepg 转码的时候可能会遇到 UDP timeout, retrying with TCP 的提示,但是它并不会自己去换成 TCP,你需要在命令中加入 -rtsp_transport tcp 这个参数如果你的客户可以接受弹出一个播放器的方式,你也可以考虑安装类似 Open in VLC media player 这样的浏览器插件将视频弹到播放器中进行播放。WebRTC 也是一种可以实现视频流的方式,但是我没找到一个直观的开源的服务器端解决方案,但是有看到正在讨论直接支持 RTSP 的动向,也许若干年以后,就可以直接用 WebRTC 技术来播放 RTSP 了。还有一个叫 Simple STMP Server 的独立的开源流媒体服务器软件,可以代替上面说的 Nginx 插件。VLC 既是播放器,也可以作为流媒体格式转换工具(与视频流服务器),虽然支持的输出格式没有 FFmpeg 广泛,但是有图形界面(也支持命令行调用),视频路数不多的时候,也是一个可以考虑的方案。最后,不差钱的话,可以考虑类似 wowza 这样的商业解决方案,前后配套,方便可靠,支持多种设备和格式,还可以搭在内网。

这是近年来写过最长的单篇了,感谢阅读。

HexoNext主题使用Waline评论系统Clay的技术博客

2021-4-8 · 本文主要介绍 Hexo Next 主题使用 Waline 评论系统。Clay 的技术博客 用进废退 首页 归档 标签 搜索 0% Hexo Next 主题使用 Waline 评论系统 发表于 2021-04-08 本文字数: 443 阅读时长 ≈ 1 分钟…https://www.techgrow.cn/posts/ae18fb85.html

静态博客如何高性能插入评论

2020-12-28 · 并且 Waline 提供了丰富的钩子功能 [3],支持在评论发布的时候触发自第一方法。我的博客部署在 Vercel 上,它提供了 Deploy Hooks [4] 功能,通过 URL 即可触发重新构建。也就是说我只要在 Waline 评论发布的钩子中调用 Vercel 的钩子 URL 触发重新构建即可https://blog.csdn.net/qiwoo_weekly/article/details/111877991

大大的小蜗牛

2021-1-13 · 启用 Waline 发布于 2020-12-19 15:38:00 2 分钟阅读 前言 经过一段时间的测试,现在本博客决定启用 Waline 评论系统。 在开始写这篇博文之前,我列了很多大纲,我以为我会写一篇长篇大论,实际开始写之后,我发现没什么好写的。人与人之间的感受 ...https://eallion.com

WindowsMacOSApp

2021-4-1 · Waline Valine 程序小黑 文武科技社是一个致力于黑苹果安装、资源分享、软件测试教学的个人博客 文章 76 标签 154 分类 18 Follow Me 公告 感謝訪問本站,若喜歡請收藏 ...https://chengxuxiaohei.cn/gzh/win/win-ssr-wsxk.html

通过Docker快速部署FileBrowser20随遇而安

2019-2-2 · 发表于 2019-02-02 分类于 应用部署 Waline : 阅读次数: 本文字数: 1.9k 阅读时长 ≈ 3 分钟 File Browser 作为一款远端文件浏览器,可以把你的服务器轻松地变为私人网盘。今天我就来简单介绍一下,如何通过 Docker 轻松部署 File Browser 2.0 ...https://www.iszy.cc/2019/02/02/filebrowser2-setup-docker

月亮女神

2017-10-23 · 月亮女神,月亮女神是蔷薇科、蔷薇属月季栽培品种。 义项指多义词的不同概念,如李娜的义项:网球运动员、歌手等;非诚勿扰的义项:冯小刚执导电影、江苏卫视交友节目等。 查看详细规范>>https://baike.so.com/doc/5331031-24992631.html

静态博客如何高性能插入评论

2006-1-2 · 前言我们知道,静态博客由于不带有动态功能,所以针对评论这种动态需求比较大众的做法就是使用第三方评论系统。第三方评论的本质其实就是使用 JS 去调取第三方服务接口获取评论后动态渲染到页面中。虽然它很好的解…https://zhuanlan.zhihu.com/p/339960819

几种浏览器播放RTSP视频流的方案灼热光芒

2019-1-20 · 上周又做了一次在浏览器中播放视频流的项目,不过以前做的是手机,这次做的是桌面。停车场出入口的摄像头作为源头提供RTSP协议的视频流,而浏览器不能直接播放,只有通过插件或者转码来实现这个需求。 要实现这个目的,可以采用的方案非常得多,有商业的也有开源的,这里主要列举一些 ...https://bnlt.org/2019/几种浏览器播放RTSP视频流...

着色器之书00

2020-8-27 · 这本书是 Patricio 的 the Book of Shaders 的中文翻译。我们希望借此将 Shader 这个有趣有益的工具介绍给更多国人。能力所限,不免有误,如有翻译不当,也请多多指出。感谢 Patricio 对我们的翻译的信任和支持。目录 关于这本书 开始 什么是片段着色器https://www.aigisss.com/blog/posts/353ae8a2.html