海康威视摄像头ISUP(原EHOME协议) 摄像头实时预览springboot 版本java实现,并可以在浏览器vue前端播放(附带源码)

1.首先说了一下为什么要用ISUP协议来取流

ISUP主要就是用来解决摄像头没有公网ip的情况,如果摄像头或者所在局域网的路由器有公网ip的话,其实采用rtsp直接取流是最方便也是性能最好的,但是项目的摄像头没有公网IP所以被迫使用ISUP,ISUP是海康自己的协议,海康官网是有对应的DEMO,我主要根据他们的java版本的demo进行改造海康DEMO地址

2.具体实现

首先得设置摄像头编码格式H.264

音频编码要改成ACC

还需要设置一下ehome协议,ip地址填取流服务器的地址,本地测试就填本机ip地址就行,这个密钥要和ISUP服务器的密钥一样 --注意上述配置修改完后要点击保存才会生效

3.核心代码_取流并再推流到nginx-rtmp

代码(完整服务源码地址

   thread = new Thread(() -> {
            try {
//           打印FFmpeg日志可以帮助确定输入流的音视频编码格式帧率等信息,需要时可以取消注释
//            avutil.av_log_set_level(avutil.AV_LOG_INFO);
//            FFmpegLogCallback.set();
            grabber = new FFmpegFrameGrabber(inputStream, 0);
            grabber.setOption("rtsp_transport", "tcp"); // 设置RTSP传输协议为TCP
//            grabber.setVideoCodec(avcodec.AV_CODEC_ID_H264); // 设置视频编解码器为H.264
//            grabber.setAudioCodec(avcodec.AV_CODEC_ID_AAC); // 设置音频编解码器为ACC
            grabber.setFormat("mpeg"); // 设置格式为MPEG
            grabber.start();

                // 获取输入格式上下文
                AVFormatContext ifmt_ctx = grabber.getFormatContext();

                log.info("视频宽度:" + grabber.getImageWidth());
                log.info("视频高度:" + grabber.getImageHeight());
                log.info("音频通道:" + grabber.getAudioChannels());

                recorder = new FFmpegFrameRecorder(pushAddress, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());
                recorder.setInterleaved(true);  // 设置音视频交织方式
                recorder.setVideoOption("crf", "23"); //画质参数
                recorder.setFormat("flv");  // 设置推流格式为 FLV
//                recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);  // 设置音频编码器为 AAC
                recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);  // 设置视频编码器为 H.264

                recorder.setSampleRate(grabber.getSampleRate());  // 设置音频采样率
                recorder.setFrameRate(grabber.getFrameRate()); //设置视频帧率
                recorder.setVideoBitrate(3000000);  // 设置视频比特率为 3 Mbps(根据需要调整)
//                recorder.setVideoQuality(0);  // 设置视频质量参数(0为最高质量)
//                recorder.setAudioQuality(0);  // 设置音频质量参数(0为最高质量)
                recorder.setGopSize((int) (grabber.getFrameRate()*2));
                recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
                recorder.setVideoOption("tune", "zerolatency"); // 降低编码延迟
                recorder.setVideoOption("preset", "superfast"); // 提升编码速度

                recorder.start(ifmt_ctx);  // 启动推流器
                Frame frame;

                count=0;

                long t1 = System.currentTimeMillis();
                AVPacket packet;
                while (running &&(packet = grabber.grabPacket()) != null) {
                    count++;
                    recorder.recordPacket(packet);
//                    if ((System.currentTimeMillis() - t1) > RECORD_LENGTH) {
//                        break;
//                    }
                    if (count % 100 == 0) {
                        // 处理每帧
                        log.info("packet推流帧====>" + count);
                    }
                }
            } 

4.结语

 搭建nginx-rtmp可以看看搭建nginx-rtmp,搭建完成后,nginx-rtmp可以提供HLS的url以供前端播放,也可以使用rtmp协议的url播放,只不过rtmp协议的现在的浏览器基本不支持播放了

本地实测延迟大概在5秒内,一般3秒左右

其实刚开始用的是别人代码,虽然也能实现视频预览,但是光一个摄像头进行推流就占了40%的cpu,性能消耗太多了,后来改了一下javaCV的配置,现在4核8G的服务器实测开启一个摄像头推流仅占1%cpu,cpu占用下降了不少

有些问题,

1.如果你拉的流解析没有音频通道(为0)的话,nginx-rtmp是不会生成.m3u8和ts文件的,无法生成播放hls的文件那么就只能用rtmp协议的url播放了 或者 手动添加音频。。。

2.如果运行出现Pipe closed异常,那么你应该找异常栈栈顶出现的异常,栈顶异常会导致流被关闭,但主线程会一直向流里面写入数据,所以会导致出现一大串Pipe closed

3.源码中依赖的lib文件里面动态链接库最好不要修改相对位置。.dll是windows系统运行需要的,.so是linux系统需要的

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现接入海康威视摄像头预览画面到前端展示,可以按照以下步骤进行: 1. 在 Spring Boot 项目中引入海康威视 Java SDK 的依赖,例如: ``` <dependency> <groupId>com.hikvision.ivms</groupId> <artifactId>ivms-8700-sdk</artifactId> <version>1.0.0</version> </dependency> ``` 2. 在 Spring Boot 项目中编写代码,通过海康威视 SDK 获取摄像头预览流,并将其转换为 Base64 编码的字符串,例如: ``` // 获取海康威视 SDK 的实例 HCNetSDK hcNetSDK = HCNetSDK.INSTANCE; // 登录摄像头 NativeLong userId = new NativeLong(-1); HCNetSDK.NET_DVR_DEVICEINFO_V30 deviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V30(); userId = hcNetSDK.NET_DVR_Login_V30("10.0.0.1", (short) 8000, "admin", "password", deviceInfo); // 获取预览流 HCNetSDK.NET_DVR_PREVIEWINFO previewInfo = new HCNetSDK.NET_DVR_PREVIEWINFO(); previewInfo.lChannel = new NativeLong(1); previewInfo.dwStreamType = 1; previewInfo.dwLinkMode = 0; NativeLong lRealPlayHandle = hcNetSDK.NET_DVR_RealPlay_V40(userId, previewInfo, null); // 获取预览流数据 HCNetSDK.NET_DVR_PREVIEWINFO previewInfo = new HCNetSDK.NET_DVR_PREVIEWINFO(); previewInfo.lChannel = new NativeLong(1); previewInfo.dwStreamType = 1; previewInfo.dwLinkMode = 0; NativeLong lRealPlayHandle = hcNetSDK.NET_DVR_RealPlay_V40(userId, previewInfo, null); // 将预览流数据转换为 BufferedImage 对象 HCNetSDK.NET_DVR_GetRealPlayerIndex(lRealPlayHandle); HCNetSDK.NET_DVR_CLIENTINFO clientInfo = new HCNetSDK.NET_DVR_CLIENTINFO(); clientInfo.lChannel = new NativeLong(1); clientInfo.hPlayWnd = null; byte[] bJpegPicBuffer = new byte[1024 * 1024]; IntByReference dwPicSize = new IntByReference(); if (hcNetSDK.NET_DVR_GetRealPlayerIndex(lRealPlayHandle) >= 0 && hcNetSDK.NET_DVR_ClientGetVideoEffect(lRealPlayHandle, HCNetSDK.VIDEOEFFECT_GET, clientInfo)) { if (hcNetSDK.NET_DVR_GetPlayerBackShare(lRealPlayHandle, bJpegPicBuffer, 1024 * 1024, dwPicSize)) { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bJpegPicBuffer, 0, dwPicSize.getValue()); BufferedImage bufferedImage = ImageIO.read(byteArrayInputStream); // 将 BufferedImage 对象转换为 Base64 编码的字符串 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ImageIO.write(bufferedImage, "jpg", byteArrayOutputStream); byte[] bytes = byteArrayOutputStream.toByteArray(); String base64String = Base64.getEncoder().encodeToString(bytes); } } // 停止预览并注销登录 hcNetSDK.NET_DVR_StopRealPlay(lRealPlayHandle); hcNetSDK.NET_DVR_Logout_V30(userId); ``` 3. 将 Base64 编码的字符串返回到前端,并在前端页面中使用 JavaScript 将其解码并显示为图片,例如: ``` <img src="data:image/jpeg;base64,${base64String}" /> ``` 这样就可以将海康威视摄像头预览画面展示到前端页面中了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值