Java 监控直播流rtsp协议转rtmp、hls、httpflv协议返回浏览器
目录
需求背景:
在做之前的项目的时候有一个对接摄像头实时播放的需求,由于我们摄像头的购买量不是很多,海康威视不给我们提供流媒体云服务器,所以需要我们自己去 一个去满足我们能在浏览器看到监控画面。项目源代码在以前公司没有拷贝就不能复习,最近又在准备面试,所以写了这个博客来复盘和扩展一下,由于我现在没有Liunx,我就用Windows来演示,生产环境还是要使用Liunx,下面这些操作在Liunx也是一样的流程,大家自行百度。
一:了解音视频流协议:
媒体流协议对比 协议HttpFlvRTMPHLSDash全称FLASH VIDEO over HTTPReal Time Message ProtocolHTTP Living Streaming传输方式HTTP长连接TCP长连接HTTP短连接HTTP短连接视频封装格式FLV FLV TAG
TS文件 Mp4
3gp
webm
原理 同RTMP,使用HTTP协议(80端口)
每个时刻的数据收到后立刻转发
集合一段时间的数据,生成TS切片文件(三片),并更新m3u8索引
延时 低
1~3秒
低
1~3秒
高
5~20秒(依切片情况)
高数据分段连续流连续流切片文件切片文件Html5播放 可通过HTML5解封包播放
(flv.js)
不支持 可通过HTML5解封包播放
(hls.js)
如果dash文件列表是MP4,
webm文件,可直接播放
其它 需要Flash技术支持,不支持多音频流、多视频流,不便于seek(即拖进度条)
跨平台支持较差,需要Flash技术支持
播放时需要多次请求,对于网络质量要求高
二:方案一 rtsp 转rtmp
1、下载nginx + nginx-rtmp-module
nginx:下载地址:http://nginx-win.ecsds.eu/download/
nginx-rtmp-module:nginx 的扩展,安装后支持rtmp协议,下载地址:https://github.com/arut/nginx-rtmp-module
解压nginx-rtmp-module到nginx根目录下,并修改其文件夹名为nginx-rtmp-module(原名为nginx-rtmp-module-master)
2、nginx配置文件
到nginx根目录下的conf目录下复制一份nginx-win.conf 重命名 nginx-win-rtmp.conf

nginx-win-rtmp.conf:3、cmd 到nginx根目录启动nginx
- nginx.exe -c conf\nginx-win-rtmp.conf
复制代码 测试:浏览器输入 http://localhost:5080/stat,看到

代表安装成功
4、下载ffmpeg安装
ffmpeg:一个处理音视频强大的库,我们需要用它来转协议,下载地址:https://www.gyan.dev/ffmpeg/builds/ ,这里可以下载essential和full版本,essential就是简版,只包含ffmpeg.exe、ffplay.exe、
ffprobe.exe, 而full版本就包含了动态库和相关头文件,方便我们在开发中调用。
5、配置ffmpeg环境变量
将ffmpeg解压后里面的bin路径复制到Path里面去
6、测试ffmpeg
cmd ffmpeg -version 命令看到代表成功

7、下载VLC播放器
下载地址:https://www.videolan.org/vlc/

8、查摄像头的rtsp协议格式
我这里截图是海康威视的


现在没有测试的流,我找了个点播的rtsp
rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4,用这个代替是一样的
9、执行ffmpeg命令
ffmpeg强大,命令也是复杂,我们cmd 执行- ffmpeg -re -rtsp_transport tcp -stimeout 20000000 -i "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4" -buffer_size 1024000 -max_delay 500000 -codec:v libx264 -r 25 -rtbufsize 10M -s 1280x720 -map:v 0 -an -f flv rtmp://127.0.0.1:1935/live/test
复制代码 rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4,是输入源头
rtmp://127.0.0.1:1935/live/test 是输出地址
如果没有报错的话,到现在rtsp就已经转换好了
ffmpeg命令学习:https://www.jianshu.com/p/df3216a52e59 、https://blog.csdn.net/fuhanghang/article/details/123565920
10、测试rtmp是否转换成功
我们打开VLC,媒体->打开网络串流->输入 rtmp://127.0.0.1:1935/live/test-> 播放

11、测试是否成功
等待几秒钟看到有视频播放就是成功了

12、为什么放弃了用rtmp
rtmp的优点是延迟低,效率高,但是在浏览器需要安装flash才能放,也就老版本的浏览器在用,rtmp可能会在别的地方支持,所以还是把他方式方法贴出来了。
三:方案二 rtsp转hls
1、nginx配置:
在前面已经贴出来了,其中这几个是针对hls的


2、执行ffmepg命令
- ffmpeg -i "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4" -vcodec libx264 -acodec aac -f flv rtmp://127.0.0.1:1935/hls/test
复制代码 3、查看nginx根目录 -> hls -> test.m3u8 是否生成
生成了代表一切正常

4、m3u8在网页上播放
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <title>前端播放m3u8格式视频</title>
-
- <link href="https://cdn.bootcss.com/video.js/7.6.5/alt/video-js-cdn.min.css" rel="stylesheet">
-
-
-
- </head>
- <body>
- <video id="myVideo" controls preload="auto" width="1080" height="708" data-setup='{}'>
- <source id="source" src="http://127.0.0.1:5080/hls/test.m3u8" type="application/x-mpegURL">
- </video>
- </body>
- </html>
复制代码 source标签的src属性:http://你的nginx ip:nginx http端口/hls/test.m3u8

rtsp转HLS成功!
5、认识一下m3u8格式
m3u8文件里面存储了一个索引,以文本格式打开是这样的- #EXTM3U
- #EXT-X-VERSION:3
- #EXT-X-MEDIA-SEQUENCE:56
- #EXT-X-TARGETDURATION:13
- #EXTINF:10.381,
- test-56.ts
- #EXTINF:10.422,
- test-57.ts
- #EXTINF:13.453,
- test-58.ts
复制代码 m3u8文件它不是视频源,源头是ts后缀文件

6、为什么放弃了用HLS
转HLS协议及网页加载过程:
ffmepg收到rtsp的流时候,会等一个切片的时间,一个切片时间到了,切片ts会放到服务器中,同时m3u8文件中加一个索引,对应着新进入的切片。网页在加载m3u8的时候,就是读取m3u8中的的索引去加载ts文件,所以在不断的请求ts,对ts进行解析,不断的和TCP握手,这就是为什么HLS延迟高和对网速的要求高的原因,我们监控肯定是要延迟低的,HLS兼容性好,适合点播。
四:方案三rtsp 转httpflv(采用)
1、安装nginx-flv-module
这个插件需要编译,教程:https://blog.csdn.net/KayChanGEEK/article/details/105095844
我这里已经编译好了,直接下载启动:
https://gitee.com/isyuesen/nginx-flv-file
2、nginx配置
看我git里面的https://gitee.com/isyuesen/nginx-flv-file/blob/master/conf/nginx.conf,和默认的config差别主要是添加了这几个- rtmp {
- server {
- listen 1935;
- # 流复用的最大块大小
- chunk_size 4000;
- application liveapp {
- live on;
- # 推流开始
- on_publish http://localhost:8081/auth;
- # 推流关闭
- on_publish_done http://localhost:8081/auth;
- # 客户端开始播放
- on_play http://localhost:8081/auth;
- # 客户端结束播放
- on_play_done http://localhost:8081/auth;
- }
- }
- }
复制代码- location /live {
- flv_live on;
- chunked_transfer_encoding on;
- add_header 'Access-Control-Allow-Credentials' 'true'; #add additional HTTP header
- add_header 'Access-Control-Allow-Origin' '*'; #add additional HTTP header
- add_header Access-Control-Allow-Headers X-Requested-With;
- add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
- add_header 'Cache-Control' 'no-cache';
- }
复制代码 3、做java权限认证
nginx rtmp配置中有配置on_publish钩子接口 http://localhost:8081/auth,这个回调HttpResponse stausCode如果不等于200会拒绝I/O,更多回调钩子看:https://github.com/arut/nginx-rtmp-module/wiki/Directives#on_connect- @PostMapping("/auth")
- public void getVideo(String token, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
- if (token.equals("tokenValue")) {
- httpServletResponse.setStatus(200);
- } else {
- // 拒绝服务
- httpServletResponse.setStatus(500);
- }
- }
复制代码 4、执行ffmepg命令:
- ffmpeg -re -rtsp_transport tcp -i "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4" -f flv -vcodec h264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -s 640*360 -q 10 "rtmp://127.0.0.1:1935/liveapp/test"
复制代码 4.1 采用java代码去执行ffmepg命令
依赖 javaCV- <dependency>
- <groupId>org.bytedeco</groupId>
- <artifactId>javacv-platform</artifactId>
- <version>1.5.2</version>
- </dependency>
复制代码- public class App {
- public static void main( String[] args ) throws IOException, InterruptedException {
- String name = "test";
- // rtsp地址
- String rtspDir = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4";
- // rtmp地址
- String rtmpDir = "rtmp://192.168.0.140:1935/liveapp/" + name + "?token=tokenValue";
- String ffmpeg = Loader.load(org.bytedeco.ffmpeg.ffmpeg.class);
- ProcessBuilder pb = new ProcessBuilder(ffmpeg,
- "-re",
- "-rtsp_transport",
- "tcp",
- "-i",
- rtspDir,
- "-f",
- "flv",
- "-vcodec",
- "h264",
- "-vprofile",
- "baseline",
- "-acodec",
- "aac",
- "-ar",
- "44100",
- "-strict",
- "-2",
- "-ac",
- "1",
- "-f",
- "flv",
- "-s",
- "640*360",
- "-q",
- "10",
- rtmpDir
- );
- pb.inheritIO().start().waitFor();
- }
- }
复制代码 5、测试http-flv链接
如果你跟着我做的,那链接就是 http://127.0.0.1:18080/live?port=1935&app=liveapp&stream=test&token=tokenValue,在VLC播放器中点击媒体 -> 打开网络串流 -> 输入http://127.0.0.1:18080/live?port=1935&app=liveapp&stream=test&token=tokenValue -> 播放
有视频证明你离成功就差最后一步
6、前端使用flv.js播放:
- <!doctype html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport"
- content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <title>播放http-flv</title>
- </head>
- <body>
- <video id="videoElement"></video>
- </body>
- </html>
复制代码 7、大功告成

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |