diff --git a/doc/_content/introduction/compile.md b/doc/_content/introduction/compile.md index b5dbef050..15f2a9e68 100644 --- a/doc/_content/introduction/compile.md +++ b/doc/_content/introduction/compile.md @@ -2,12 +2,8 @@ # 编译 WVP-PRO不只是实现了国标28181的协议,本身也是一个完整的视频平台。所以对于新手来说,你可能需要一些耐心来完成。遇到问题不要焦躁,你可以 1. 百度 -2. 如果身边有熟悉java的朋友,可以咨询下朋友; -3. 来群里(901799015)咨询群友; -4. 向作者发送邮件648540858@qq.com; -5. 作者远程支持(有偿)。 - 如果这些仍不能解决你的问题,那么你可能需要与作者我一起合作完成这个项目,解决你遇到的问题。 - +2. 加入星球体提问;[知识星球](https://t.zsxq.com/0d8VAD3Dm) +3. 向作者发送邮件648540858@qq.com,寻求技术支持(有偿); WVP-PRO使用Spring boot开发,maven管理依赖。对于熟悉spring开发的朋友是很容易进行编译部署以及运行的。 下面将提供一种通用方法方便大家运行项目。 diff --git a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java index f4774393f..96a987c94 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java @@ -87,6 +87,9 @@ public class StreamInfo implements Serializable, Cloneable{ @Schema(description = "产生源类型,包括 unknown = 0,rtmp_push=1,rtsp_push=2,rtp_push=3,pull=4,ffmpeg_pull=5,mp4_vod=6,device_chn=7") private int originType; + @Schema(description = "转码后的视频流") + private StreamInfo transcodeStream; + public void setFlv(StreamURL flv) { this.flv = flv; } @@ -533,6 +536,14 @@ public class StreamInfo implements Serializable, Cloneable{ this.transactionInfo = transactionInfo; } + public StreamInfo getTranscodeStream() { + return transcodeStream; + } + + public void setTranscodeStream(StreamInfo transcodeStream) { + this.transcodeStream = transcodeStream; + } + @Override public StreamInfo clone() { StreamInfo instance = null; diff --git a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java index 007c72a32..18114c5a4 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java @@ -21,7 +21,7 @@ public class UserSetting { private Boolean seniorSdp = Boolean.FALSE; - private Integer playTimeout = 18000; + private Integer playTimeout = 10000; private int platformPlayTimeout = 20000; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java index d52fbc519..afdbb494b 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -82,7 +82,9 @@ public class SipLayer implements CommandLineRunner { monitorIps.add(sipConfig.getIp()); } } - sipConfig.setShowIp(String.join(",", monitorIps)); + if (ObjectUtils.isEmpty(sipConfig.getShowIp())){ + sipConfig.setShowIp(String.join(",", monitorIps)); + } SipFactory.getInstance().setPathName("gov.nist"); if (monitorIps.size() > 0) { for (String monitorIp : monitorIps) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java index de1a92907..411c40fd2 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java @@ -27,6 +27,7 @@ import com.genersoft.iot.vmp.media.event.hook.HookType; import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.service.IStreamPushService; @@ -593,12 +594,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements sendRtpItem.setPlayType(InviteStreamType.PUSH); if (streamPushItem != null) { // 从redis查询是否正在接收这个推流 - StreamPushItem pushListItem = redisCatchStorage.getPushListItem(gbStream.getApp(), gbStream.getStream()); + OnStreamChangedHookParam pushListItem = redisCatchStorage.getPushListItem(gbStream.getApp(), gbStream.getStream()); if (pushListItem != null) { - sendRtpItem.setServerId(pushListItem.getServerId()); + sendRtpItem.setServerId(pushListItem.getSeverId()); sendRtpItem.setMediaServerId(pushListItem.getMediaServerId()); - pushListItem.setSelf(userSetting.getServerId().equals(pushListItem.getServerId())); redisCatchStorage.updateSendRTPSever(sendRtpItem); // 开始推流 sendPushStream(sendRtpItem, mediaServerItem, platform, request); @@ -618,12 +618,14 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements } } else if ("proxy".equals(gbStream.getStreamType())) { if (null != proxyByAppAndStream) { + sendRtpItem.setServerId(userSetting.getServerId()); if (sendRtpItem.getSsrc() == null) { // 上级平台点播时不使用上级平台指定的ssrc,使用自定义的ssrc,参考国标文档-点播外域设备媒体流SSRC处理方式 String ssrc = "Play".equalsIgnoreCase(sessionName) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId()); sendRtpItem.setSsrc(ssrc); } - if (proxyByAppAndStream.isStatus()) { + MediaInfo mediaInfo = redisCatchStorage.getProxyStream(gbStream.getApp(), gbStream.getStream()); + if (mediaInfo != null) { sendProxyStream(sendRtpItem, mediaServerItem, platform, request); } else { //开启代理拉流 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java index 6185cda4a..155d5f73d 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java @@ -315,8 +315,8 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent } } - @Scheduled(fixedRate = 10000) //每1秒执行一次 - public void execute(){ - logger.info("[待处理Notify-目录订阅消息数量]: {}", taskQueue.size()); - } +// @Scheduled(fixedRate = 10000) //每1秒执行一次 +// public void execute(){ +// logger.info("[待处理Notify-目录订阅消息数量]: {}", taskQueue.size()); +// } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java index 52fc7a3fc..9c414a855 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java @@ -188,8 +188,8 @@ public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessor } taskQueue.clear(); } - @Scheduled(fixedRate = 10000) - public void execute(){ - logger.info("[待处理Notify-移动位置订阅消息数量]: {}", taskQueue.size()); - } +// @Scheduled(fixedRate = 10000) +// public void execute(){ +// logger.debug("[待处理Notify-移动位置订阅消息数量]: {}", taskQueue.size()); +// } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java index 69dc45514..1f0ba5393 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java @@ -114,6 +114,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen device.setIp(remoteAddressInfo.getIp()); device.setPort(remoteAddressInfo.getPort()); device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort()))); + device.setLocalIp(request.getLocalAddress().getHostAddress()); Response registerOkResponse = getRegisterOkResponse(request); // 判断TCP还是UDP diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaArrivalEvent.java b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaArrivalEvent.java index 2379321a4..2f51a3e21 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaArrivalEvent.java +++ b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaArrivalEvent.java @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.media.event.media; import com.genersoft.iot.vmp.media.bean.MediaInfo; import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; +import com.genersoft.iot.vmp.vmanager.bean.StreamContent; /** * 流到来事件 @@ -19,7 +20,8 @@ public class MediaArrivalEvent extends MediaEvent { mediaArrivalEvent.setStream(hookParam.getStream()); mediaArrivalEvent.setMediaServer(mediaServer); mediaArrivalEvent.setSchema(hookParam.getSchema()); - mediaArrivalEvent.setCallId(hookParam.getCallId()); + mediaArrivalEvent.setSchema(hookParam.getSchema()); + mediaArrivalEvent.setHookParam(hookParam); return mediaArrivalEvent; } @@ -27,6 +29,10 @@ public class MediaArrivalEvent extends MediaEvent { private String callId; + private OnStreamChangedHookParam hookParam; + + private StreamContent streamInfo; + public MediaInfo getMediaInfo() { return mediaInfo; } @@ -43,4 +49,20 @@ public class MediaArrivalEvent extends MediaEvent { public void setCallId(String callId) { this.callId = callId; } + + public OnStreamChangedHookParam getHookParam() { + return hookParam; + } + + public void setHookParam(OnStreamChangedHookParam hookParam) { + this.hookParam = hookParam; + } + + public StreamContent getStreamInfo() { + return streamInfo; + } + + public void setStreamInfo(StreamContent streamInfo) { + this.streamInfo = streamInfo; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java index a0b334137..ae3d7c39b 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java @@ -763,7 +763,7 @@ public class MediaServerServiceImpl implements IMediaServerService { calld = streamAuthorityInfo.getCallId(); } List streamInfoList = getMediaList(mediaInfo, app, stream, calld); - if (streamInfoList.isEmpty()) { + if (streamInfoList == null || streamInfoList.isEmpty()) { return null; }else { return streamInfoList.get(0); @@ -809,6 +809,13 @@ public class MediaServerServiceImpl implements IMediaServerService { streamInfoResult.setRtc(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam, isPlay); streamInfoResult.setMediaInfo(mediaInfo); + + if (!"broadcast".equalsIgnoreCase(app) && !ObjectUtils.isEmpty(mediaServer.getTranscodeSuffix()) && !"null".equalsIgnoreCase(mediaServer.getTranscodeSuffix())) { + String newStream = stream + "_" + mediaServer.getTranscodeSuffix(); + mediaServer.setTranscodeSuffix(null); + StreamInfo transcodeStreamInfo = getStreamInfoByAppAndStream(mediaServer, app, newStream, null, addr, callId, isPlay); + streamInfoResult.setTranscodeStream(transcodeStreamInfo); + } return streamInfoResult; } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java index e5847f69a..b34a1b797 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.common.InviteInfo; import com.genersoft.iot.vmp.common.InviteSessionStatus; import com.genersoft.iot.vmp.common.InviteSessionType; import com.genersoft.iot.vmp.common.VideoManagerConstants; +import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent; import com.genersoft.iot.vmp.service.IInviteStreamService; @@ -40,6 +41,9 @@ public class InviteStreamServiceImpl implements IInviteStreamService { @Autowired private IVideoManagerStorage storage; + @Autowired + private UserSetting userSetting; + /** * 流到来的处理 */ @@ -67,7 +71,11 @@ public class InviteStreamServiceImpl implements IInviteStreamService { } @Override public void updateInviteInfo(InviteInfo inviteInfo) { - updateInviteInfo(inviteInfo, null); + if (InviteSessionStatus.ready == inviteInfo.getStatus()) { + updateInviteInfo(inviteInfo, Long.valueOf(userSetting.getPlayTimeout()) * 2); + }else { + updateInviteInfo(inviteInfo, null); + } } @Override @@ -148,7 +156,12 @@ public class InviteStreamServiceImpl implements IInviteStreamService { if (inviteInfoInDb.getSsrcInfo() != null) { inviteInfoInDb.getSsrcInfo().setStream(stream); } - redisTemplate.opsForValue().set(key, inviteInfoInDb); + if (InviteSessionStatus.ready == inviteInfo.getStatus()) { + redisTemplate.opsForValue().set(key, inviteInfoInDb, userSetting.getPlayTimeout() * 2, TimeUnit.SECONDS); + }else { + redisTemplate.opsForValue().set(key, inviteInfoInDb); + } + return inviteInfoInDb; } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java index 39c67c264..43816faca 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -459,9 +459,11 @@ public class PlayServiceImpl implements IPlayService { ErrorCallback callback) { if (mediaServerItem == null || ssrcInfo == null) { - callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), - InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(), - null); + if (callback != null) { + callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), + InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(), + null); + } return; } logger.info("[点播开始] deviceId: {}, channelId: {},码流类型:{}, 收流端口: {}, 码流:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", @@ -473,8 +475,9 @@ public class PlayServiceImpl implements IPlayService { // 释放ssrc mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream()); - - callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null); + if (callback != null) { + callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null); + } inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null, InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null); return; @@ -494,8 +497,9 @@ public class PlayServiceImpl implements IPlayService { logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},码流:{},端口:{}, SSRC: {}", device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification(), ssrcInfo.getPort(), ssrcInfo.getSsrc()); - - callback.run(InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); + if (callback != null) { + callback.run(InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); + } inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null, InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId()); @@ -531,14 +535,19 @@ public class PlayServiceImpl implements IPlayService { // hook响应 StreamInfo streamInfo = onPublishHandlerForPlay(hookData.getMediaServer(), hookData.getMediaInfo(), device.getDeviceId(), channel.getChannelId()); if (streamInfo == null){ - callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), - InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); + if (callback != null) { + callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); + } + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null, InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); return; } - callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); + if (callback != null) { + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); + } inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null, InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), @@ -558,8 +567,9 @@ public class PlayServiceImpl implements IPlayService { mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream()); - - callback.run(event.statusCode, event.msg, null); + if (callback != null) { + callback.run(event.statusCode, event.msg, null); + } inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null, InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg), null); @@ -575,9 +585,10 @@ public class PlayServiceImpl implements IPlayService { mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream()); - - callback.run(InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), - InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); + if (callback != null) { + callback.run(InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), + InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); + } inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null, InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); @@ -746,7 +757,7 @@ public class PlayServiceImpl implements IPlayService { } MediaServer newMediaServerItem = getNewMediaServerItem(device); - if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE") && ! newMediaServerItem.isRtpEnable()) { + if ("TCP-ACTIVE".equalsIgnoreCase(device.getStreamMode()) && ! newMediaServerItem.isRtpEnable()) { logger.warn("[录像回放] 单端口收流时不支持TCP主动方式收流 deviceId: {},channelId:{}", deviceId, channelId); throw new ControllerException(ErrorCode.ERROR100.getCode(), "单端口收流时不支持TCP主动方式收流"); } @@ -1076,12 +1087,6 @@ public class PlayServiceImpl implements IPlayService { logger.warn("[获取下载进度] 查询录像信息时发现节点不存在"); return null; } - SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, null, stream); - - if (ssrcTransaction == null) { - logger.warn("[获取下载进度] 下载已结束"); - return null; - } String app = "rtp"; Long duration = mediaServerService.updateDownloadProcess(mediaServerItem, app, stream); if (duration == null || duration == 0) { diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java index 3213eb982..18de78a03 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java @@ -26,6 +26,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.dao.*; import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo; +import com.genersoft.iot.vmp.vmanager.bean.StreamContent; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import org.slf4j.Logger; @@ -126,18 +127,13 @@ public class StreamPushServiceImpl implements IStreamPushService { streamPushMapper.update(transform); gbStreamMapper.updateMediaServer(event.getApp(), event.getStream(), event.getMediaServer().getId()); } - // TODO 相关的事件自行管理,不需要写入ZLMMediaListManager -// ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(transform.getApp(), transform.getStream()); -// if ( channelOnlineEventLister != null) { -// try { -// channelOnlineEventLister.run(transform.getApp(), transform.getStream(), transform.getServerId());; -// } catch (ParseException e) { -// logger.error("addPush: ", e); -// } -// removedChannelOnlineEventLister(transform.getApp(), transform.getStream()); -// } // 冗余数据,自己系统中自用 - redisCatchStorage.addPushListItem(event.getApp(), event.getStream(), event); + if (!"broadcast".equals(event.getApp()) && !"talk".equals(event.getApp())) { + StreamInfo streamInfo = mediaServerService.getStreamInfoByAppAndStream( + event.getMediaServer(), event.getApp(), event.getStream(), event.getMediaInfo(), event.getCallId()); + event.getHookParam().setStreamInfo(new StreamContent(streamInfo)); + redisCatchStorage.addPushListItem(event.getApp(), event.getStream(), event); + } // 发送流变化redis消息 JSONObject jsonObject = new JSONObject(); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java index 2347f5025..869d39bf9 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java @@ -7,7 +7,7 @@ import com.genersoft.iot.vmp.media.bean.MediaInfo; import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; -import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; @@ -135,6 +135,8 @@ public interface IRedisCatchStorage { MediaInfo getStreamInfo(String app, String streamId, String mediaServerId); + MediaInfo getProxyStream(String app, String streamId); + void addCpuInfo(double cpuInfo); void addMemInfo(double memInfo); @@ -214,7 +216,7 @@ public interface IRedisCatchStorage { void addPushListItem(String app, String stream, MediaArrivalEvent param); - StreamPushItem getPushListItem(String app, String stream); + OnStreamChangedHookParam getPushListItem(String app, String stream); void removePushListItem(String app, String stream, String mediaServerId); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java index a654ea06b..af1b42426 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java @@ -53,7 +53,7 @@ public interface CloudRecordServiceMapper { " and id in " + " #{item}" + " " + - " order by start_time DESC" + + " order by start_time ASC" + " ") List getList(@Param("query") String query, @Param("app") String app, @Param("stream") String stream, @Param("startTimeStamp")Long startTimeStamp, @Param("endTimeStamp")Long endTimeStamp, diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java index b743cfc62..e70e195c7 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java @@ -5,16 +5,13 @@ import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.common.SystemAllInfo; import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.UserSetting; -import com.genersoft.iot.vmp.gb28181.bean.AlarmChannelMessage; -import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; -import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.media.bean.MediaInfo; import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; -import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; @@ -496,6 +493,20 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { return result; } + @Override + public MediaInfo getProxyStream(String app, String streamId) { + String scanKey = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetting.getServerId() + "_PULL_" + app + "_" + streamId + "_*"; + + MediaInfo result = null; + List keys = RedisUtil.scan(redisTemplate, scanKey); + if (keys.size() > 0) { + String key = (String) keys.get(0); + result = JsonUtil.redisJsonToObject(redisTemplate, key, MediaInfo.class); + } + + return result; + } + @Override public void addCpuInfo(double cpuInfo) { String key = VideoManagerConstants.SYSTEM_INFO_CPU_PREFIX + userSetting.getServerId(); @@ -684,14 +695,13 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @Override public void addPushListItem(String app, String stream, MediaArrivalEvent event) { String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream; - StreamPushItem streamPushItem = StreamPushItem.getInstance(event, userSetting.getServerId()); - redisTemplate.opsForValue().set(key, streamPushItem); + redisTemplate.opsForValue().set(key, event.getHookParam()); } @Override - public StreamPushItem getPushListItem(String app, String stream) { + public OnStreamChangedHookParam getPushListItem(String app, String stream) { String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream; - return (StreamPushItem)redisTemplate.opsForValue().get(key); + return (OnStreamChangedHookParam)redisTemplate.opsForValue().get(key); } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java index 193c95d4a..ce7425127 100755 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java @@ -98,6 +98,9 @@ public class StreamContent { @Schema(description = "文件下载地址(录像下载使用)") private DownloadFileInfo downLoadFilePath; + @Schema(description = "转码后的视频流") + private StreamContent transcodeStream; + private double progress; public StreamContent(StreamInfo streamInfo) { @@ -179,6 +182,17 @@ public class StreamContent { if (streamInfo.getDownLoadFilePath() != null) { this.downLoadFilePath = streamInfo.getDownLoadFilePath(); } + if (streamInfo.getTranscodeStream() != null) { + this.transcodeStream = new StreamContent(streamInfo.getTranscodeStream()); + } + } + + public StreamContent getTranscodeStream() { + return transcodeStream; + } + + public void setTranscodeStream(StreamContent transcodeStream) { + this.transcodeStream = transcodeStream; } public String getApp() { diff --git a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java index be740c193..8937fd86e 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java @@ -126,13 +126,32 @@ public class ApiStreamController { resultJjson.put("ChannelID", code); resultJjson.put("ChannelName", deviceChannel.getName()); resultJjson.put("ChannelCustomName", ""); - resultJjson.put("FLV", streamInfo.getFlv().getUrl()); - if(streamInfo.getHttps_flv() != null) { - resultJjson.put("HTTPS_FLV", streamInfo.getHttps_flv().getUrl()); + if (streamInfo.getTranscodeStream() != null) { + resultJjson.put("FLV", streamInfo.getTranscodeStream().getFlv().getUrl()); + }else { + resultJjson.put("FLV", streamInfo.getFlv().getUrl()); + } - resultJjson.put("WS_FLV", streamInfo.getWs_flv().getUrl()); + if(streamInfo.getHttps_flv() != null) { + if (streamInfo.getTranscodeStream() != null) { + resultJjson.put("HTTPS_FLV", streamInfo.getTranscodeStream().getHttps_flv().getUrl()); + }else { + resultJjson.put("HTTPS_FLV", streamInfo.getHttps_flv().getUrl()); + } + } + + if (streamInfo.getTranscodeStream() != null) { + resultJjson.put("WS_FLV", streamInfo.getTranscodeStream().getWs_flv().getUrl()); + }else { + resultJjson.put("WS_FLV", streamInfo.getWs_flv().getUrl()); + } + if(streamInfo.getWss_flv() != null) { - resultJjson.put("WSS_FLV", streamInfo.getWss_flv().getUrl()); + if (streamInfo.getTranscodeStream() != null) { + resultJjson.put("WSS_FLV", streamInfo.getTranscodeStream().getWss_flv().getUrl()); + }else { + resultJjson.put("WSS_FLV", streamInfo.getWss_flv().getUrl()); + } } resultJjson.put("RTMP", streamInfo.getRtmp().getUrl()); if (streamInfo.getRtmps() != null) { diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 35abaffa5..023c055c8 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -2,4 +2,4 @@ spring: application: name: wvp profiles: - active: base \ No newline at end of file + active: local272 \ No newline at end of file diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue index 1c9705bc5..e0a1d01da 100755 --- a/web_src/src/components/dialog/devicePlayer.vue +++ b/web_src/src/components/dialog/devicePlayer.vue @@ -473,10 +473,14 @@ export default { }, getUrlByStreamInfo() { console.log(this.streamInfo) + let streamInfo = this.streamInfo + if (this.streamInfo.transcodeStream) { + streamInfo = this.streamInfo.transcodeStream; + } if (location.protocol === "https:") { - this.videoUrl = this.streamInfo[this.player[this.activePlayer][1]] + this.videoUrl = streamInfo[this.player[this.activePlayer][1]] } else { - this.videoUrl = this.streamInfo[this.player[this.activePlayer][0]] + this.videoUrl = streamInfo[this.player[this.activePlayer][0]] } return this.videoUrl;