华为海康大华摄像头编译RTSP转RTMP和HTTPFLV

Posted ChuZJava

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了华为海康大华摄像头编译RTSP转RTMP和HTTPFLV相关的知识,希望对你有一定的参考价值。

项目需求要看摄像头实时画面谷歌浏览器不支持RTSP流直接展示

因为开发一般用的都是谷歌浏览器但是谷歌浏览器不支持rtsp流直接转化视频,就靠着网上的博文一直尝试 最终总结了一套流程 自学

方案一 通过Java+nginx+rtsp转rtmp流

直接进入主题,第一次尝试通过Javacv + nginx-moudle-temp (下边放地址) 直接转rtmp流
原文地址 原文地址

因为nginx+rtmpMoudles需要编译 我把地址放到云上下载解压 双击nginx.exe就能使用 配置无需修改

所需依赖

	<!-- javacv1.5.1 -->
		<dependency>
			<groupId>org.bytedeco</groupId>
			<artifactId>javacv</artifactId>
			<version>1.5.1</version>
		</dependency>
		<dependency>
			<groupId>org.bytedeco</groupId>
			<artifactId>ffmpeg-platform</artifactId>
			<version>4.1.3-1.5.1</version>
		</dependency>

Java代码如下:

	/**
     *
     * @param  rtmpPath 推流地址 rtmp://127.0.0.1:1935/live/(这个地方写不写都行自己琢磨吧)
     *         rtspPath rtsp流地址
     *         audioRecord 是否录制  0= 不录制 1=录制
     *         saveVideo  是否保存视频
     * @return
     */
 public static void test(String rtmpPath,String rtspPath,int audioRecord,boolean saveVideo ) throws Exception  {
        //FrameGrabber grabber = FrameGrabber.createDefault(0); // 本机摄像头 默认
        // 使用rtsp的时候需要使用 FFmpegFrameGrabber,不能再用 FrameGrabber
        int width = 640,height = 480;
        FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault(rtspPath);
        grabber.setOption("rtsp_transport", "tcp"); // 使用tcp的方式,不然会丢包很严重
        // 一直报错的原因!!!就是因为是 2560 * 1440的太大了。。
        grabber.setImageWidth(width);
        grabber.setImageHeight(height);
        System.out.println("grabber start");
        grabber.start();
        //FrameRecorder recorder = FrameRecorder.createDefault(rtmpPath, 640,480,0);
        // 流媒体输出地址,分辨率(长,高),是否录制音频(0:不录制/1:录制)
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(rtmpPath, width, height, audioRecord);
        recorder.setInterleaved(true);
        recorder.setVideoOption("crf","28");
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // 28
        recorder.setFormat("flv"); // rtmp的类型
        recorder.setFrameRate(25);
        recorder.setPixelFormat(0); // yuv420p
        System.out.println("recorder start");
        recorder.start();
        //
        OpenCVFrameConverter.ToIplImage conveter = new OpenCVFrameConverter.ToIplImage();
        System.out.println("all start!!");
        int count = 0;
        while(!exit){
            count++;
            Frame frame = grabber.grabImage();
            if(frame == null){
                continue;
            }
            if(count % 100 == 0){
                System.out.println("count="+count);
            }
            recorder.record(frame);
        }
        grabber.stop();
        grabber.release();
        recorder.stop();
        recorder.release();
    }

因为这个方案转出来的流是rtmp 这个流需要配合flash使用 在2020年年底
谷歌就停止了对flash的支持所以这个方案被pass
代码亲测可用 因为不是通过中间件转流是通过 Java封装的FFmpeg转的所以延迟测试在19秒左右

方案二 通过Java+ Nginx-http-flv-module + FFmpeg + Flv.js 实现rtsp转flv在vue项目中 (采用)

因为在第一个方案中rtmp流在谷歌浏览器中无法播放 所以改变方案

  1. 部署所需的软件 FFmpeg在官网上下载配置下环境变量就行了如下图就是配置成功
  2. 部署 Nginx-http-flv-module这是源码地址 自己编译一下就好了 启动之后配置下配置文件
    以我的为例:
    这个在http server下边 这个是flv的配置 获取到rtmp之后转为flv
 location /flv {
            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';
        }

        location /hls {      
		   add_header Access-Control-Allow-Origin *;
           types{    
             application/vnd.apple.mpegurl m3u8;    
             video/mp2t ts;    
           }    
        alias /test;    
        expires -1;    
        }
        
        location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }

        location /stat.xsl {
            root html/nginx-http-flv-module/;
        }

        location /control {
            rtmp_control all;
        }

        location /rtmp-publisher {
            root html/nginx-http-flv-module/test;
        }

这个在外边 因为是通过rtsp转rtmp


rtmp {  
    server {  
        listen 1935;  
        chunk_size 4000;  
        application hls { 
            live on;
            hls on;
            hls_path /test;
            hls_fragment 1s;
        }  
    }  
}

3.配置完成之后跟第一个方案一样 测试安装好没有 双击nginx.exe 看下后台进程 如果有nginx 呢就是正常启动 如果没有看下log里边的报错信息 我的没有出问题
4.通过Java拼接FFmpeg命令 将rtsp通过FFmpeg转为rtmp 推流到nginx 。FFmpeg命令自行百度
代码:

	/**
     * 推送到nginx的流地址按照自己配置的信息进行拼接不是固定的
     * @param  nginxRtmpUrl 推流地址 rtmp://127.0.0.1:1935/hls/rtmpStream
     *         rtspUrl rtsp流地址 
     * @return
     */
  public static Integer pushVideoAsRTSP(String rtspUrl, String nginxRtmpUrl) {
        int flag = -1;
        try {
            String command = "ffmpeg ";
            command += " -re -rtsp_transport tcp -i " + rtspUrl;
            command += " -f flv -vcodec libx264 -vprofile baseline -acodec aac -ar 44100 -strict -2 -ac 1 -f flv -s 800x600 -q 10 " + nginxRtmpUrl;
            System.out.println("ffmpeg推流命令:" + command);

            Process process = Runtime.getRuntime().exec(command);
            BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            String line = "";
            while ((line = br.readLine()) != null) {
                System.out.println("视频推流信息[" + line + "]");
            }
            flag = process.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

5.运行这个方法之后会出现可以通过vlc进行测试rtmp流地址 如果rtmp能显示画面 往下进行测试自行拼接flv地址 地址按照上边nginx配置文件进行配置

http://127.0.0.1:18080/flv?app=hls&stream=rtmpStream

6.web端通过vue实现
安装flv.js

npm install --save flv.js

全局引用的话放到main.js
我没有全局引用直接上vue全部代码

 <video id="videoElement" controls autoplay muted width="800px" height="400px"></video>
import flvjs from "flv.js"
  export default {
    data() {
      return {
        flvPlayer: null
      }
    },
    mounted() {
      if (flvjs.isSupported()) {
        var videoElement = document.getElementById('videoElement');
        this.flvPlayer = flvjs.createPlayer({
          type: 'flv',
          isLive: true,
          hasAudio: false,
          url: 'http://127.0.0.1:18080/flv?app=hls&stream=rtmpStream'
        });
        this.flvPlayer.attachMediaElement(videoElement);
        this.flvPlayer.load();
        this.flvPlayer.play();
      }
    }
   }

flv测试用的demo

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>播放页面</title>
    </head>
    <body>
        <script src="https://cdn.bootcdn.net/ajax/libs/flv.js/1.5.0/flv.min.js"></script>
        <video style="height: 400px;width: 600px;" id="videoElement" muted autoplay controls></video>
        <script>
            var flvPlayer = null;
            if (flvjs.isSupported()) {
                var videoElement = document.getElementById('videoElement');
                flvPlayer = flvjs.createPlayer({
                    type: 'flv',
                    // 8080 对应Nginx监听的端口
                    // rtmpLive 对应Nginx的路径
                    url: 'http://127.0.0.1:18080/flv?app=hls&stream=rtmpStream'
                });
                flvPlayer.attachMediaElement(videoElement);
                flvPlayer.load();
            }
        </script>
    </body>
</html>

延迟刷新之后七秒 但是web端不稳定 延迟会越来越大

推流时间一小时二十分钟 流还是很稳定 vlc 延迟一直稳定在十秒左右


上边有些代码是从网上找到 我也忘了出处在哪 侵删
这些方法延迟比较高 如果对延迟有比较严格的 我觉得可以研究下vlc在软硬件上边下手 可能会比较好点

以上是关于华为海康大华摄像头编译RTSP转RTMP和HTTPFLV的主要内容,如果未能解决你的问题,请参考以下文章

海康威视RTSP摄像头转RTMP推流前端方案(浏览器兼容及权限验证)

RTSP_ONVIF协议视频流媒体网页无插件直播服务器EasyNVR配置海康大华等安防摄像头通道地址的方法

RTSP安防摄像头/海康大华硬盘录像机/NVR网页低延时播放流媒体服务器EasyNVR调取接口报Unauthorized如何解决?

WEB页面实时播放海康大华等摄像头RTSP视频流完全方案

LiveNVR高性能稳定RTSPOnvif探测流媒体服务配置通道接入海康大华等摄像机进行全终端无插件直播

流媒体服务海康摄像头RTSP视频推流转码拉流直播综合应用:VLC+FFMPEG+Nginx实现RTSP到RTMP网页直播