pom.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/genersoft/iot/vmp/utils/IdUtils.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/resources/application-dev.yml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main/resources/application.yml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
web_src/package-lock.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
pom.xml
@@ -95,6 +95,14 @@ </profiles> <dependencies> <!--视频处理--> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.5.7</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
@@ -117,7 +117,7 @@ .authorizeRequests() .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() .antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll() .antMatchers("/api/user/login", "/index/hook/**","/index/hook/abl/**", "/swagger-ui/**", "/doc.html#/**").permitAll() .antMatchers("/api/device/query/devices/**","/api/play/start/img/**", "/api/user/login", "/index/hook/**","/index/hook/abl/**", "/swagger-ui/**", "/doc.html#/**").permitAll() .anyRequest().authenticated() // 异常处理器 .and() src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java
@@ -460,7 +460,7 @@ logger.info("获取负载最低的节点时无在线节点"); return null; } logger.error("ddddddd"); // 获取分数最低的,及并发最低的 Set<Object> objects = redisTemplate.opsForZSet().range(key, 0, -1); ArrayList<Object> mediaServerObjectS = new ArrayList<>(objects); @@ -468,7 +468,9 @@ if (hasAssist == null) { String mediaServerId = (String)mediaServerObjectS.get(0); mediaServer = getOne(mediaServerId); logger.error("111"); }else if (hasAssist) { logger.error("222"); for (Object mediaServerObject : mediaServerObjectS) { String mediaServerId = (String)mediaServerObject; MediaServer serverItem = getOne(mediaServerId); @@ -478,6 +480,7 @@ } } }else if (!hasAssist) { logger.error("333"); for (Object mediaServerObject : mediaServerObjectS) { String mediaServerId = (String)mediaServerObject; MediaServer serverItem = getOne(mediaServerId); src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -726,13 +726,16 @@ @Override public MediaServer getNewMediaServerItem(Device device) { logger.error(device.getMediaServerId(), "wocnm"); if (device == null) { return null; } MediaServer mediaServerItem; if (ObjectUtils.isEmpty(device.getMediaServerId()) || "auto".equals(device.getMediaServerId())) { logger.error("进的这"); mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null); } else { logger.error("进的else"); mediaServerItem = mediaServerService.getOne(device.getMediaServerId()); } if (mediaServerItem == null) { src/main/java/com/genersoft/iot/vmp/utils/IdUtils.java
New file @@ -0,0 +1,56 @@ package com.genersoft.iot.vmp.utils; import java.text.SimpleDateFormat; import java.util.Date; import java.util.UUID; /** * ID生成器工具类 * * @author ruoyi */ public class IdUtils { private final static SimpleDateFormat FORMAT = new SimpleDateFormat("yyyyMMddHHmmss"); private final static SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("yyyyMMdd"); /** * 获取随机UUID * * @return 随机UUID */ public static String randomUUID() { return UUID.randomUUID().toString(); } /** * 简化的UUID,去掉了横线 * * @return 简化的UUID,去掉了横线 */ public static String simpleUUID() { return UUID.randomUUID().toString().replaceAll("_", "").replaceAll("-", ""); } /** * 获取当前时间+随机数的编号 * * @return 编号 */ public static String randomNO(Date now) { return DAY_FORMAT.format(now) + UUID.randomUUID().toString().replaceAll("-","").substring(0, 18); } /** * 获取当前时间+工单数的编号 * * @return 编号 */ public static String workOrderNO(Date now,String orderNumber) { return DAY_FORMAT.format(now) +"_"+ orderNumber; } } src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -2,6 +2,7 @@ import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.fasterxml.jackson.databind.ObjectMapper; import com.genersoft.iot.vmp.common.InviteSessionType; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.UserSetting; @@ -20,6 +21,7 @@ import com.genersoft.iot.vmp.service.bean.InviteErrorCode; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.IdUtils; import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.StreamContent; @@ -28,16 +30,25 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import org.bytedeco.javacv.FFmpegFrameGrabber; import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.FrameGrabber; import org.bytedeco.javacv.OpenCVFrameConverter; import org.bytedeco.opencv.global.opencv_imgcodecs; import org.bytedeco.opencv.opencv_core.Mat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; import javax.servlet.http.HttpServletRequest; import java.net.MalformedURLException; import java.net.URL; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.UUID; @@ -76,6 +87,8 @@ @Autowired private UserSetting userSetting; private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); @Operation(summary = "开始点播", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @@ -149,6 +162,76 @@ return result; } @Operation(summary = "开始点播并返回图片", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true) @GetMapping("/start/img/{deviceId}/{channelId}") public DeferredResult<WVPResult<String>> playReturnImg(HttpServletRequest request, @PathVariable String deviceId, @PathVariable String channelId) { DeferredResult<WVPResult<StreamContent>> play = this.play(request, deviceId, channelId); Object resultStr = play.getResult(); System.out.println("获取结果:" + resultStr); WVPResult wvpResult = (WVPResult) resultStr; WVPResult<String> result = new WVPResult<>(); result.setData(this.getImg(wvpResult)); result.setCode(wvpResult.getCode()); result.setMsg(wvpResult.getMsg()); DeferredResult<WVPResult<String>> r = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); r.setResult(result); return r; } private String getImg(WVPResult<StreamContent> wvpResult) { String imgUrl = null; if (wvpResult.getCode() == 0) { String rtspUrl = wvpResult.getData().getFmp4(); // 取mp4地址 if (StringUtils.hasText(rtspUrl)) { System.out.println("目标地址:" + rtspUrl); FFmpegFrameGrabber grabber = null; try { grabber = new FFmpegFrameGrabber(rtspUrl); // grabber.setOption("rtsp_transport", "tcp"); // 使用tcp的方式,不然会丢包很严重 // grabber.setVideoOption("probesize", "10000"); // 设置捕获分析的最大字节 grabber.start(); Frame frame = grabber.grabImage(); // 直接捕获一帧 if (frame != null) { System.out.println("成功捕获一帧"); // 将Frame转换为Mat OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat(); Mat mat = converter.convertToMat(frame); imgUrl = format.format(new Date()) + "_" + IdUtils.randomUUID() + ".png"; // 生成图片路径 String imgPath = "/home/zgyw/uploadPath/" + imgUrl; System.out.println("图片保存地址:" + imgPath); imgUrl = "/profile/" + imgUrl; // 保存图片 opencv_imgcodecs.imwrite(imgPath, mat); } else { System.out.println("未捕获到帧"); } } catch (FrameGrabber.Exception e) { e.printStackTrace(); } finally { if (grabber != null) { try { grabber.stop(); // 停止捕获 } catch (FrameGrabber.Exception e) { e.printStackTrace(); } } } } } else { System.out.println("请求失败,错误码:" + wvpResult.getCode() + "--" + wvpResult.getMsg()); } System.out.println("图片URL:" + imgUrl); return imgUrl; } @Operation(summary = "停止点播", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true) src/main/resources/application-dev.yml
@@ -32,9 +32,9 @@ master: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/wvp2?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true url: jdbc:mysql://51.92.65.72:3306/wvp2?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true username: root password: root123 password: zgyw@202488 hikari: connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数 initialSize: 50 # 连接池初始化连接数 @@ -44,7 +44,7 @@ max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位) #[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 server: port: 8080 port: 7788 # [可选] HTTPS配置, 默认不开启 ssl: # [可选] 是否开启HTTPS访问 @@ -76,21 +76,21 @@ media: id: zlmediakit-local # [必须修改] zlm服务器的内网IP ip: 172.19.128.50 ip: 51.92.65.72 # [可选] 有公网IP就配置公网IP, 不可用域名 wan_ip: # [必须修改] zlm服务器的http.port http-port: 9092 http-port: 800 # [可选] zlm服务器访问WVP所使用的IP, 默认使用127.0.0.1,zlm和wvp没有部署在同一台服务器时必须配置 hook-ip: 172.19.128.50 hook-ip: 51.92.65.72 # [必选选] zlm服务器的hook.admin_params=secret secret: TWSYFgYJOQWB4ftgeYut8DW4wbs7pQnj secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试 rtp: # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输 enable: true # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功 port-range: 50000,50300 # 端口范围 port-range: 30000,30300 # 端口范围 # [可选] 国标级联在此范围内选择端口发送媒体流, send-port-range: 50000,50300 # 端口范围 # [根据业务需求配置] src/main/resources/application.yml
@@ -2,4 +2,4 @@ application: name: wvp profiles: active: local272 active: dev web_src/package-lock.json
New file Diff too large