海康rtsp视频流媒体服务器搭建(去除flash插件):rtsp > nginx-rtmp > http-flv > flv.js

一:简介

海康有直接开放rtsp链接视频流地址
由于HTML客户端不能直接对rtsp视频流进行播放,于是我在后台服务器做了一层转换rtsp > nginx-rtmp > http-flv > flv.js客户端播放流媒体服务。

二:流媒体服务器搭建

  1. 获取到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码流)

  2. 下载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>
    

以上就是整个流媒体服务的搭建和部署,仅供参考,如有疑问,欢迎大家一起沟通交流

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值