work-demand neginx+ffmpeg实现摄像头在网页上播放
参考博客
https://hasaik.com/posts/358f95d9.html
https://segmentfault.com/a/1190000015025340
https://segmentfault.com/a/1190000015025340
https://blog.csdn.net/u011877155/article/details/83750651
https://codechina.csdn.net/mirrors/eguid/ffmpegcommandhandler4java/-/tree/master
https://www.cnblogs.com/xiaozhi_5638/p/8664841.html
https://blog.csdn.net/yuxielea/article/details/103146362
1.概述
客户提了一个demand,需要将现场的摄像头能再自己的网站上实现播放。。。当时接到这个需求wdnmd一脸懵逼,不过通过查阅一些文档还是做起来了。参考的博客,列在了上面了,通过参考这几篇文章是完全可以实现这个功能的,也就没有必要往下看了,下文是个人的一些记录。
2. 简单理解
直接参考博客的最后一篇,内容非常全面
简单一句话,借助一个流媒体中间件,能将摄像头的数据实时显示在网页。举个例子,生牛肉一般人不吃,借助一个烤箱撒点黑胡椒,我们就能吃的滋滋有味。这里的流媒体服务器就好比烤箱,生肉就是原始的数据(实时流采集终端的数据【比如摄像头录的数据】),而我们就是网页。原始的数据是rtsp格式的,而网页不能实现直接播放rtsp格式的流数据,借助这个流媒体中间件,将这个rtsp格式的数据转成了rtmp格式,我们就能播放了。
3.具体实现
3.1流程图
- 1.通过用户提供的摄像头rtsp地址,通过ffmpeg这个转流的工具,运行转流的命令将rtsp流转成rtmp流
- 2.疑问:那是不是我只要这个ffmpeg就行了?不行,简单来讲ffmpeg这个工具就是简单的转化了流的格式。而用户是通过请求访问这个rtmp流的,如何获得这个rtmp的流就是一个问题。而这边的nginx rtmp模块就可以实现这个功能,相当于一个中转站用来中转数据,类似vpn的原理,实现一个流媒体转发的作用,淦我感觉我没讲清楚 :)
- 3.借助nginx中的rtmp模块,用户可以通过特定的url访问rtmp流。
- 4.用户获得实时rtmp流,页面上通过flv.js播放这个数据。
3.2具体步骤
- 1.安装流媒体服务器 置顶的博客链接里里面有教程
- 2.配置流媒体服务器中nginx的配置文件
- 3.编写java代码,如果说项目部署在linux上,需要通过java代码调用系统的命令完成ffmpeg转流的操作
- 4.编写前台页面
- 5.注意:
前台页面和java代码都有对应的api,都在置顶的博客中都有
,操作来直接用就行了。
3.3踩过的坑
- 1.用了api,部署项目的时候发现通过java在linux执行转流的命令没有成功???
原因:复制过来的代码中执行系统的命令是适用windows的,不适用linux.靠当时排查了好长时间,下面是针对api中的代码做的修改,兼容windows和Linux
Runtime runtime = Runtime.getRuntime();
Process process = null;
// 执行命令获取主进程
if(System.getProperty("os.name").toLowerCase().contains("windows")){
//windows上执行命令的指令
process = runtime.exec(cmd);
} else{
// linux下执行命令
process = runtime.exec(new String[]{"sh","-c",cmd});
}
-
2.带宽问题,以及如何关闭转流的操作
-
带宽的问题:开启一个转流的操作,至少占用到10~20m的带宽,如果说服务器是100m的话,建议同时开启的转流的操作3个就差不多了。还有就是同一个实时流终端转出来的流可以供多人访问也可以提高效率,没有深入了解这一块的内容。
-
关闭转流的操作:
在网页上播放的时候,如果出现用户不正常的关闭的操作,比如说直接关掉标签页、或者说直接关闭掉浏览器,会导致服务器上转流的操作一直在运行,会出现问题。
**解决方法:**个人推荐在前台写一个类似心跳的功能,隔个几秒向后台发一下请求,然后后台写一个全局的map(用于放哪些开启转流命令的标志和前台发请求的时间),每次前台发请求就更新一下时间。如果说有一段时间没有发请求的话,就关闭的掉对应的转流的操作。当然后台对应的要写一个定时任务,隔一段时间检查下map中的时间,我也是这么做的(能想到的最简单的笨方法了)。
-