Merge remote-tracking branch 'origin/master'

# Conflicts:
#	src/main/resources/application.yml
pull/1587/head
cntianxin@outlook.com 2024-07-24 13:45:59 +08:00
commit 2eb2a3e6c2
20 changed files with 181 additions and 77 deletions

View File

@ -2,12 +2,8 @@
# 编译 # 编译
WVP-PRO不只是实现了国标28181的协议本身也是一个完整的视频平台。所以对于新手来说你可能需要一些耐心来完成。遇到问题不要焦躁你可以 WVP-PRO不只是实现了国标28181的协议本身也是一个完整的视频平台。所以对于新手来说你可能需要一些耐心来完成。遇到问题不要焦躁你可以
1. 百度 1. 百度
2. 如果身边有熟悉java的朋友可以咨询下朋友 2. 加入星球体提问;[知识星球](https://t.zsxq.com/0d8VAD3Dm)
3. 来群里901799015咨询群友 3. 向作者发送邮件648540858@qq.com,寻求技术支持(有偿);
4. 向作者发送邮件648540858@qq.com
5. 作者远程支持(有偿)。
如果这些仍不能解决你的问题,那么你可能需要与作者我一起合作完成这个项目,解决你遇到的问题。
WVP-PRO使用Spring boot开发maven管理依赖。对于熟悉spring开发的朋友是很容易进行编译部署以及运行的。 WVP-PRO使用Spring boot开发maven管理依赖。对于熟悉spring开发的朋友是很容易进行编译部署以及运行的。
下面将提供一种通用方法方便大家运行项目。 下面将提供一种通用方法方便大家运行项目。

View File

@ -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") @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; private int originType;
@Schema(description = "转码后的视频流")
private StreamInfo transcodeStream;
public void setFlv(StreamURL flv) { public void setFlv(StreamURL flv) {
this.flv = flv; this.flv = flv;
} }
@ -533,6 +536,14 @@ public class StreamInfo implements Serializable, Cloneable{
this.transactionInfo = transactionInfo; this.transactionInfo = transactionInfo;
} }
public StreamInfo getTranscodeStream() {
return transcodeStream;
}
public void setTranscodeStream(StreamInfo transcodeStream) {
this.transcodeStream = transcodeStream;
}
@Override @Override
public StreamInfo clone() { public StreamInfo clone() {
StreamInfo instance = null; StreamInfo instance = null;

View File

@ -21,7 +21,7 @@ public class UserSetting {
private Boolean seniorSdp = Boolean.FALSE; private Boolean seniorSdp = Boolean.FALSE;
private Integer playTimeout = 18000; private Integer playTimeout = 10000;
private int platformPlayTimeout = 20000; private int platformPlayTimeout = 20000;

View File

@ -82,7 +82,9 @@ public class SipLayer implements CommandLineRunner {
monitorIps.add(sipConfig.getIp()); monitorIps.add(sipConfig.getIp());
} }
} }
sipConfig.setShowIp(String.join(",", monitorIps)); if (ObjectUtils.isEmpty(sipConfig.getShowIp())){
sipConfig.setShowIp(String.join(",", monitorIps));
}
SipFactory.getInstance().setPathName("gov.nist"); SipFactory.getInstance().setPathName("gov.nist");
if (monitorIps.size() > 0) { if (monitorIps.size() > 0) {
for (String monitorIp : monitorIps) { for (String monitorIp : monitorIps) {

View File

@ -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.service.IMediaServerService;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; 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.StreamPushItem;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.IPlayService;
import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.service.IStreamProxyService;
import com.genersoft.iot.vmp.service.IStreamPushService; import com.genersoft.iot.vmp.service.IStreamPushService;
@ -593,12 +594,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
sendRtpItem.setPlayType(InviteStreamType.PUSH); sendRtpItem.setPlayType(InviteStreamType.PUSH);
if (streamPushItem != null) { if (streamPushItem != null) {
// 从redis查询是否正在接收这个推流 // 从redis查询是否正在接收这个推流
StreamPushItem pushListItem = redisCatchStorage.getPushListItem(gbStream.getApp(), gbStream.getStream()); OnStreamChangedHookParam pushListItem = redisCatchStorage.getPushListItem(gbStream.getApp(), gbStream.getStream());
if (pushListItem != null) { if (pushListItem != null) {
sendRtpItem.setServerId(pushListItem.getServerId()); sendRtpItem.setServerId(pushListItem.getSeverId());
sendRtpItem.setMediaServerId(pushListItem.getMediaServerId()); sendRtpItem.setMediaServerId(pushListItem.getMediaServerId());
pushListItem.setSelf(userSetting.getServerId().equals(pushListItem.getServerId()));
redisCatchStorage.updateSendRTPSever(sendRtpItem); redisCatchStorage.updateSendRTPSever(sendRtpItem);
// 开始推流 // 开始推流
sendPushStream(sendRtpItem, mediaServerItem, platform, request); sendPushStream(sendRtpItem, mediaServerItem, platform, request);
@ -618,12 +618,14 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
} }
} else if ("proxy".equals(gbStream.getStreamType())) { } else if ("proxy".equals(gbStream.getStreamType())) {
if (null != proxyByAppAndStream) { if (null != proxyByAppAndStream) {
sendRtpItem.setServerId(userSetting.getServerId());
if (sendRtpItem.getSsrc() == null) { if (sendRtpItem.getSsrc() == null) {
// 上级平台点播时不使用上级平台指定的ssrc使用自定义的ssrc参考国标文档-点播外域设备媒体流SSRC处理方式 // 上级平台点播时不使用上级平台指定的ssrc使用自定义的ssrc参考国标文档-点播外域设备媒体流SSRC处理方式
String ssrc = "Play".equalsIgnoreCase(sessionName) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId()); String ssrc = "Play".equalsIgnoreCase(sessionName) ? ssrcFactory.getPlaySsrc(mediaServerItem.getId()) : ssrcFactory.getPlayBackSsrc(mediaServerItem.getId());
sendRtpItem.setSsrc(ssrc); sendRtpItem.setSsrc(ssrc);
} }
if (proxyByAppAndStream.isStatus()) { MediaInfo mediaInfo = redisCatchStorage.getProxyStream(gbStream.getApp(), gbStream.getStream());
if (mediaInfo != null) {
sendProxyStream(sendRtpItem, mediaServerItem, platform, request); sendProxyStream(sendRtpItem, mediaServerItem, platform, request);
} else { } else {
//开启代理拉流 //开启代理拉流

View File

@ -315,8 +315,8 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
} }
} }
@Scheduled(fixedRate = 10000) //每1秒执行一次 // @Scheduled(fixedRate = 10000) //每1秒执行一次
public void execute(){ // public void execute(){
logger.info("[待处理Notify-目录订阅消息数量]: {}", taskQueue.size()); // logger.info("[待处理Notify-目录订阅消息数量]: {}", taskQueue.size());
} // }
} }

View File

@ -188,8 +188,8 @@ public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessor
} }
taskQueue.clear(); taskQueue.clear();
} }
@Scheduled(fixedRate = 10000) // @Scheduled(fixedRate = 10000)
public void execute(){ // public void execute(){
logger.info("[待处理Notify-移动位置订阅消息数量]: {}", taskQueue.size()); // logger.debug("[待处理Notify-移动位置订阅消息数量]: {}", taskQueue.size());
} // }
} }

View File

@ -114,6 +114,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
device.setIp(remoteAddressInfo.getIp()); device.setIp(remoteAddressInfo.getIp());
device.setPort(remoteAddressInfo.getPort()); device.setPort(remoteAddressInfo.getPort());
device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort()))); device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));
device.setLocalIp(request.getLocalAddress().getHostAddress()); device.setLocalIp(request.getLocalAddress().getHostAddress());
Response registerOkResponse = getRegisterOkResponse(request); Response registerOkResponse = getRegisterOkResponse(request);
// 判断TCP还是UDP // 判断TCP还是UDP

View File

@ -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.MediaInfo;
import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; 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.setStream(hookParam.getStream());
mediaArrivalEvent.setMediaServer(mediaServer); mediaArrivalEvent.setMediaServer(mediaServer);
mediaArrivalEvent.setSchema(hookParam.getSchema()); mediaArrivalEvent.setSchema(hookParam.getSchema());
mediaArrivalEvent.setCallId(hookParam.getCallId()); mediaArrivalEvent.setSchema(hookParam.getSchema());
mediaArrivalEvent.setHookParam(hookParam);
return mediaArrivalEvent; return mediaArrivalEvent;
} }
@ -27,6 +29,10 @@ public class MediaArrivalEvent extends MediaEvent {
private String callId; private String callId;
private OnStreamChangedHookParam hookParam;
private StreamContent streamInfo;
public MediaInfo getMediaInfo() { public MediaInfo getMediaInfo() {
return mediaInfo; return mediaInfo;
} }
@ -43,4 +49,20 @@ public class MediaArrivalEvent extends MediaEvent {
public void setCallId(String callId) { public void setCallId(String callId) {
this.callId = 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;
}
} }

View File

@ -763,7 +763,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
calld = streamAuthorityInfo.getCallId(); calld = streamAuthorityInfo.getCallId();
} }
List<StreamInfo> streamInfoList = getMediaList(mediaInfo, app, stream, calld); List<StreamInfo> streamInfoList = getMediaList(mediaInfo, app, stream, calld);
if (streamInfoList.isEmpty()) { if (streamInfoList == null || streamInfoList.isEmpty()) {
return null; return null;
}else { }else {
return streamInfoList.get(0); 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.setRtc(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam, isPlay);
streamInfoResult.setMediaInfo(mediaInfo); 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; return streamInfoResult;
} }

View File

@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.common.InviteInfo;
import com.genersoft.iot.vmp.common.InviteSessionStatus; import com.genersoft.iot.vmp.common.InviteSessionStatus;
import com.genersoft.iot.vmp.common.InviteSessionType; import com.genersoft.iot.vmp.common.InviteSessionType;
import com.genersoft.iot.vmp.common.VideoManagerConstants; 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.MediaArrivalEvent;
import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent; import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent;
import com.genersoft.iot.vmp.service.IInviteStreamService; import com.genersoft.iot.vmp.service.IInviteStreamService;
@ -40,6 +41,9 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
@Autowired @Autowired
private IVideoManagerStorage storage; private IVideoManagerStorage storage;
@Autowired
private UserSetting userSetting;
/** /**
* *
*/ */
@ -67,7 +71,11 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
} }
@Override @Override
public void updateInviteInfo(InviteInfo inviteInfo) { 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 @Override
@ -148,7 +156,12 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
if (inviteInfoInDb.getSsrcInfo() != null) { if (inviteInfoInDb.getSsrcInfo() != null) {
inviteInfoInDb.getSsrcInfo().setStream(stream); 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; return inviteInfoInDb;
} }

View File

@ -459,9 +459,11 @@ public class PlayServiceImpl implements IPlayService {
ErrorCallback<Object> callback) { ErrorCallback<Object> callback) {
if (mediaServerItem == null || ssrcInfo == null) { if (mediaServerItem == null || ssrcInfo == null) {
callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), if (callback != null) {
InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(), callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(),
null); InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(),
null);
}
return; return;
} }
logger.info("[点播开始] deviceId: {}, channelId: {},码流类型:{}, 收流端口: {}, 码流:{}, 收流模式:{}, SSRC: {}, SSRC校验{}", logger.info("[点播开始] deviceId: {}, channelId: {},码流类型:{}, 收流端口: {}, 码流:{}, 收流模式:{}, SSRC: {}, SSRC校验{}",
@ -473,8 +475,9 @@ public class PlayServiceImpl implements IPlayService {
// 释放ssrc // 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
if (callback != null) {
callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null); callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null);
}
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null, inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null); InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), "点播端口分配异常", null);
return; return;
@ -494,8 +497,9 @@ public class PlayServiceImpl implements IPlayService {
logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},码流:{},端口:{}, SSRC: {}", logger.info("[点播超时] 收流超时 deviceId: {}, channelId: {},码流:{},端口:{}, SSRC: {}",
device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification(), device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification(),
ssrcInfo.getPort(), ssrcInfo.getSsrc()); ssrcInfo.getPort(), ssrcInfo.getSsrc());
if (callback != null) {
callback.run(InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), 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, inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null); InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getMsg(), null);
inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId()); inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId());
@ -531,14 +535,19 @@ public class PlayServiceImpl implements IPlayService {
// hook响应 // hook响应
StreamInfo streamInfo = onPublishHandlerForPlay(hookData.getMediaServer(), hookData.getMediaInfo(), device.getDeviceId(), channel.getChannelId()); StreamInfo streamInfo = onPublishHandlerForPlay(hookData.getMediaServer(), hookData.getMediaInfo(), device.getDeviceId(), channel.getChannelId());
if (streamInfo == null){ if (streamInfo == null){
callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), if (callback != null) {
InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), 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, inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
return; 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, inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getCode(),
InviteErrorCode.SUCCESS.getMsg(), InviteErrorCode.SUCCESS.getMsg(),
@ -558,8 +567,9 @@ public class PlayServiceImpl implements IPlayService {
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
if (callback != null) {
callback.run(event.statusCode, event.msg, null); callback.run(event.statusCode, event.msg, null);
}
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null, inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(),
String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg), null); String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg), null);
@ -575,9 +585,10 @@ public class PlayServiceImpl implements IPlayService {
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream());
if (callback != null) {
callback.run(InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), callback.run(InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(),
InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null);
}
inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null, inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null,
InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(), InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getCode(),
InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null); InviteErrorCode.ERROR_FOR_SIP_SENDING_FAILED.getMsg(), null);
@ -746,7 +757,7 @@ public class PlayServiceImpl implements IPlayService {
} }
MediaServer newMediaServerItem = getNewMediaServerItem(device); 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); logger.warn("[录像回放] 单端口收流时不支持TCP主动方式收流 deviceId: {},channelId:{}", deviceId, channelId);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "单端口收流时不支持TCP主动方式收流"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "单端口收流时不支持TCP主动方式收流");
} }
@ -1076,12 +1087,6 @@ public class PlayServiceImpl implements IPlayService {
logger.warn("[获取下载进度] 查询录像信息时发现节点不存在"); logger.warn("[获取下载进度] 查询录像信息时发现节点不存在");
return null; return null;
} }
SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, null, stream);
if (ssrcTransaction == null) {
logger.warn("[获取下载进度] 下载已结束");
return null;
}
String app = "rtp"; String app = "rtp";
Long duration = mediaServerService.updateDownloadProcess(mediaServerItem, app, stream); Long duration = mediaServerService.updateDownloadProcess(mediaServerItem, app, stream);
if (duration == null || duration == 0) { if (duration == null || duration == 0) {

View File

@ -26,6 +26,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.*; import com.genersoft.iot.vmp.storager.dao.*;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo; 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.PageHelper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -126,18 +127,13 @@ public class StreamPushServiceImpl implements IStreamPushService {
streamPushMapper.update(transform); streamPushMapper.update(transform);
gbStreamMapper.updateMediaServer(event.getApp(), event.getStream(), event.getMediaServer().getId()); 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消息 // 发送流变化redis消息
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();

View File

@ -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.bean.MediaServer;
import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; 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.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.GPSMsgInfo;
import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; 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 getStreamInfo(String app, String streamId, String mediaServerId);
MediaInfo getProxyStream(String app, String streamId);
void addCpuInfo(double cpuInfo); void addCpuInfo(double cpuInfo);
void addMemInfo(double memInfo); void addMemInfo(double memInfo);
@ -214,7 +216,7 @@ public interface IRedisCatchStorage {
void addPushListItem(String app, String stream, MediaArrivalEvent param); 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); void removePushListItem(String app, String stream, String mediaServerId);

View File

@ -53,7 +53,7 @@ public interface CloudRecordServiceMapper {
" <if test= 'ids != null ' > and id in " + " <if test= 'ids != null ' > and id in " +
" <foreach collection='ids' item='item' open='(' separator=',' close=')' > #{item}</foreach>" + " <foreach collection='ids' item='item' open='(' separator=',' close=')' > #{item}</foreach>" +
" </if>" + " </if>" +
" order by start_time DESC" + " order by start_time ASC" +
" </script>") " </script>")
List<CloudRecordItem> getList(@Param("query") String query, @Param("app") String app, @Param("stream") String stream, List<CloudRecordItem> getList(@Param("query") String query, @Param("app") String app, @Param("stream") String stream,
@Param("startTimeStamp")Long startTimeStamp, @Param("endTimeStamp")Long endTimeStamp, @Param("startTimeStamp")Long startTimeStamp, @Param("endTimeStamp")Long endTimeStamp,

View File

@ -5,16 +5,13 @@ import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.common.SystemAllInfo; import com.genersoft.iot.vmp.common.SystemAllInfo;
import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.AlarmChannelMessage; import com.genersoft.iot.vmp.gb28181.bean.*;
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.media.bean.MediaInfo; import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; 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.StreamAuthorityInfo;
import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; 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.GPSMsgInfo;
import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@ -496,6 +493,20 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
return result; 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<Object> 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 @Override
public void addCpuInfo(double cpuInfo) { public void addCpuInfo(double cpuInfo) {
String key = VideoManagerConstants.SYSTEM_INFO_CPU_PREFIX + userSetting.getServerId(); String key = VideoManagerConstants.SYSTEM_INFO_CPU_PREFIX + userSetting.getServerId();
@ -684,14 +695,13 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
@Override @Override
public void addPushListItem(String app, String stream, MediaArrivalEvent event) { public void addPushListItem(String app, String stream, MediaArrivalEvent event) {
String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream; String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream;
StreamPushItem streamPushItem = StreamPushItem.getInstance(event, userSetting.getServerId()); redisTemplate.opsForValue().set(key, event.getHookParam());
redisTemplate.opsForValue().set(key, streamPushItem);
} }
@Override @Override
public StreamPushItem getPushListItem(String app, String stream) { public OnStreamChangedHookParam getPushListItem(String app, String stream) {
String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream; String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream;
return (StreamPushItem)redisTemplate.opsForValue().get(key); return (OnStreamChangedHookParam)redisTemplate.opsForValue().get(key);
} }
@Override @Override

View File

@ -98,6 +98,9 @@ public class StreamContent {
@Schema(description = "文件下载地址(录像下载使用)") @Schema(description = "文件下载地址(录像下载使用)")
private DownloadFileInfo downLoadFilePath; private DownloadFileInfo downLoadFilePath;
@Schema(description = "转码后的视频流")
private StreamContent transcodeStream;
private double progress; private double progress;
public StreamContent(StreamInfo streamInfo) { public StreamContent(StreamInfo streamInfo) {
@ -179,6 +182,17 @@ public class StreamContent {
if (streamInfo.getDownLoadFilePath() != null) { if (streamInfo.getDownLoadFilePath() != null) {
this.downLoadFilePath = streamInfo.getDownLoadFilePath(); 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() { public String getApp() {

View File

@ -126,13 +126,32 @@ public class ApiStreamController {
resultJjson.put("ChannelID", code); resultJjson.put("ChannelID", code);
resultJjson.put("ChannelName", deviceChannel.getName()); resultJjson.put("ChannelName", deviceChannel.getName());
resultJjson.put("ChannelCustomName", ""); resultJjson.put("ChannelCustomName", "");
resultJjson.put("FLV", streamInfo.getFlv().getUrl()); if (streamInfo.getTranscodeStream() != null) {
if(streamInfo.getHttps_flv() != null) { resultJjson.put("FLV", streamInfo.getTranscodeStream().getFlv().getUrl());
resultJjson.put("HTTPS_FLV", streamInfo.getHttps_flv().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) { 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()); resultJjson.put("RTMP", streamInfo.getRtmp().getUrl());
if (streamInfo.getRtmps() != null) { if (streamInfo.getRtmps() != null) {

View File

@ -2,4 +2,4 @@ spring:
application: application:
name: wvp name: wvp
profiles: profiles:
active: base active: local272

View File

@ -473,10 +473,14 @@ export default {
}, },
getUrlByStreamInfo() { getUrlByStreamInfo() {
console.log(this.streamInfo) console.log(this.streamInfo)
let streamInfo = this.streamInfo
if (this.streamInfo.transcodeStream) {
streamInfo = this.streamInfo.transcodeStream;
}
if (location.protocol === "https:") { if (location.protocol === "https:") {
this.videoUrl = this.streamInfo[this.player[this.activePlayer][1]] this.videoUrl = streamInfo[this.player[this.activePlayer][1]]
} else { } else {
this.videoUrl = this.streamInfo[this.player[this.activePlayer][0]] this.videoUrl = streamInfo[this.player[this.activePlayer][0]]
} }
return this.videoUrl; return this.videoUrl;