一:简介
海康有直接开放rtsp链接视频流地址。
由于HTML客户端不能直接对rtsp视频流进行播放,于是我在后台服务器做了一层转换rtsp > nginx-rtmp > http-flv > flv.js客户端播放流媒体服务。
二:流媒体服务器搭建
-
获取到rtsp视频流地址:
(海康地址:rtsp://admin:123456@192.168.1.200:554/Streaming/Channels/102
)
(大华地址:rtsp://admin:123456@192.168.1.200:554/cam/realmonitor?channel=1&subtype=01
)
说明:admin:用户名
123456:密码
192.168.1.200:ip地址
554:端口号
102:1-通道号、0-固定值、2-码流类型(1-主码流、2-子码流、3-第三码流、4-第4码流) -
下载nginx-rtmp-module hls流媒体传输代理文件
2.1:配置修改conf文件
worker_processes 1; events { worker_connections 1024; } # 添加RTMP服务 rtmp { server { listen 1935; #设置监听端口 application live { #设置访问路径(rtmp://127.0.0.1/live/自定名称) live on; #开启rtmp直播功能 hls on; #开启hls功能 hls_path G://nginx-rtmp/temp/hls; #设置hls视频文件存放路径 hls_fragment 60s; #设置分片时长(秒) } } } # HTTP服务 http { include mime.types; default_type application/octet-stream; server { listen 5050; server_name localhost; location /live { flv_live on; chunked_transfer_encoding on; #open 'Transfer-Encoding: chunked' response 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'; } } }
2.2:搭建nginx-rtmp系统服务
a:下载Windows Service Wrapper(winsw.exe)文件 b:将.exe文件复制到nginx.exe同级目录,名称可自行自定义(nginx-rtmp.exe) c:创建.xml文件,名称需和.exe文件一致(nginx-rtmp.xml) d:编写xml文件信息 <service> <id>nginx</id> <name>nginx-rtmp</name> #服务名称 <description>High Performance Nginx-rtmp Service</description> #服务描述 <executable>G:\nginx-rtmp\nginx.exe</executable> <logpath>G:\nginx-rtmp\server-logs\</logpath> #服务日志 <logmode>roll</logmode> <depend></depend> <startargument>-p G:\nginx-rtmp</startargument> <stopargument>-p G:\nginx-rtmp -s stop</stopargument> </service> e:进入cmd命令 f:创建服务:nginx-rtmp.exe install 删除服务:nginx-rtmp.exe uninstall 启动服务:nginx-rtmp.exe start 停止服务:nginx-rtmp.exe stop
2.3:java后台服务rtsp转换rtmp并推送到nginx代理服务
<!--javacv-platform--> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv</artifactId> <version>1.4.3</version> </dependency> <dependency> <groupId>org.bytedeco.javacpp-presets</groupId> <artifactId>ffmpeg-platform</artifactId> <version>4.0.2-1.4.3</version> </dependency>
public static void main(String[] args) { final int captureWidth = 500; //宽度 final int captureHeight = 300; //高度 final double framerate; try { //rtsp取流 final FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("rtsp://admin:123456@192.168.1.200:554/Streaming/Channels/102"); grabber.setImageWidth(captureWidth); grabber.setImageHeight(captureHeight); // rtsp格式一般添加TCP配置,否则丢帧会比较严重 // Brick在测试过程发现,该参数改成udp可以解决部分电脑出现的下列报警,但是丢帧比较严重 // av_interleaved_write_frame() error -22 while writing interleaved video packet. grabber.setOption("rtsp_transport", "tcp"); if (grabber.getFrameRate() > 0 && grabber.getFrameRate() < 100) { framerate = grabber.getFrameRate(); } else { framerate = 15.0; } grabber.start(); //代理名称 // 最后一个参数是AudioChannels,建议通过grabber获取 final FFmpegFrameRecorder recorder = new FFmpegFrameRecorder("rtmp://192.168.1.200:1935/live/test", captureWidth, captureHeight, 1); recorder.setInterleaved(true); // 降低编码延时 recorder.setVideoOption("tune", "zerolatency"); // 提升编码速度 // 权衡quality(视频质量)和encode speed(编码速度) values(值): // ultrafast(终极快),superfast(超级快), veryfast(非常快), faster(很快), fast(快), // medium(中等), slow(慢), slower(很慢), veryslow(非常慢) // ultrafast(终极快)提供最少的压缩(低编码器CPU)和最大的视频流大小;而veryslow(非常慢)提供最佳的压缩(高编码器CPU)的同时降低视频流的大小 recorder.setVideoOption("preset", "veryslow"); // 视频质量参数(详见 https://trac.ffmpeg.org/wiki/Encode/H.264) 0~51;18~28是一个合理范围 recorder.setVideoOption("crf", "28"); // 分辨率 recorder.setVideoBitrate(2000000); // 视频编码格式/解码器 recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // 视频格式 recorder.setFormat("flv"); // 视频帧率 recorder.setFrameRate(framerate); recorder.setGopSize((int) framerate * 4); recorder.setAudioOption("crf", "0"); recorder.setAudioQuality(0); recorder.setSampleRate(44100); if (grabber.getVideoBitrate() > 0) { recorder.setAudioBitrate(grabber.getVideoBitrate()); } // 从grabber获取AudioChannels recorder.setAudioChannels(grabber.getAudioChannels()); recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC); recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); recorder.start(); // 解决音视频同步导致的延时问题 Field field = recorder.getClass().getDeclaredField("oc"); field.setAccessible(true); avformat.AVFormatContext oc = (avformat.AVFormatContext) field.get(recorder); oc.max_interleave_delta(100); // 有些时候,程序执行回报下列错误,添加一行代码解决此问题 grabber.flush(); Frame capturedFrame = null; while ((capturedFrame = grabber.grab())) { recorder.setTimestamp(capturedFrame.timestamp); recorder.record(capturedFrame); } //关闭推流 if(recorder != null){ recorder.close(); } if(grabber != null){ grabber.close(); } } catch (Exception e) { e.printStackTrace(); } }
2.4:使用flv播放器工具测试是否执行正常
http://192.168.1.200:5050/live?app=live&stream=test
说明:192.168.1.200:ip地址
5050:端口
test:自定义转换名称2.5:HTML访问视频(需要下载flv.js文件)
<!DOCTYPE html> <html> <head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> <title>flv.js demo</title> <style> .mainContainer { display: block; width: 1024px; margin-left: auto; margin-right: auto; } .urlInput { display: block; width: 100%; margin-left: auto; margin-right: auto; margin-top: 8px; margin-bottom: 8px; } .centeredVideo { display: block; width: 100%; height: 576px; margin-left: auto; margin-right: auto; margin-bottom: auto; } .controls { display: block; width: 100%; text-align: left; margin-left: auto; margin-right: auto; } </style> </head> <body> <div class="mainContainer"> <video id="videoElement" class="centeredVideo" controls autoplay width="1024" height="576">Your browser is too old which doesn't support HTML5 video.</video> </div> <br> <div class="controls"> <!--<button οnclick="flv_load()">加载</button>--> <button onclick="flv_start()">开始</button> <button onclick="flv_pause()">暂停</button> <button onclick="flv_destroy()">停止</button> <input style="width:100px" type="text" name="seekpoint" /> <button onclick="flv_seekto()">跳转</button> </div> <script src="flv.js"></script> <script> var player = document.getElementById('videoElement'); if (flvjs.isSupported()) { var flvPlayer = flvjs.createPlayer({ type: 'flv', url: 'http://192.168.1.200:5050/live?app=live&stream=test' }); flvPlayer.attachMediaElement(videoElement); flvPlayer.load(); //加载 } function flv_start() { player.play(); } function flv_pause() { player.pause(); } function flv_destroy() { player.pause(); player.unload(); player.detachMediaElement(); player.destroy(); player = null; } function flv_seekto() { player.currentTime = parseFloat(document.getElementsByName('seekpoint')[0].value); } </script> </body> </html>
以上就是整个流媒体服务的搭建和部署,仅供参考,如有疑问,欢迎大家一起沟通交流