Merge remote-tracking branch 'github/wvp-28181-2.0' into wvp-28181-2.0
# Conflicts: # pom.xml # src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java # src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java # src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
This commit is contained in:
commit
01622884a9
BIN
libs/jdbc-x86/bcprov-jdk15on-1.70.jar
Normal file
BIN
libs/jdbc-x86/bcprov-jdk15on-1.70.jar
Normal file
Binary file not shown.
BIN
libs/jdbc-x86/kingbase8-8.6.0.jar
Normal file
BIN
libs/jdbc-x86/kingbase8-8.6.0.jar
Normal file
Binary file not shown.
BIN
libs/jdbc-x86/kingbase8-8.6.0.jre6.jar
Normal file
BIN
libs/jdbc-x86/kingbase8-8.6.0.jre6.jar
Normal file
Binary file not shown.
BIN
libs/jdbc-x86/kingbase8-8.6.0.jre7.jar
Normal file
BIN
libs/jdbc-x86/kingbase8-8.6.0.jre7.jar
Normal file
Binary file not shown.
BIN
libs/jdbc-x86/postgresql-42.2.9.jar
Normal file
BIN
libs/jdbc-x86/postgresql-42.2.9.jar
Normal file
Binary file not shown.
BIN
libs/jdbc-x86/postgresql-42.2.9.jre6.jar
Normal file
BIN
libs/jdbc-x86/postgresql-42.2.9.jre6.jar
Normal file
Binary file not shown.
BIN
libs/jdbc-x86/postgresql-42.2.9.jre7.jar
Normal file
BIN
libs/jdbc-x86/postgresql-42.2.9.jre7.jar
Normal file
Binary file not shown.
30
pom.xml
30
pom.xml
@ -11,7 +11,7 @@
|
||||
|
||||
<groupId>com.genersoft</groupId>
|
||||
<artifactId>wvp-pro</artifactId>
|
||||
<version>2.6.9</version>
|
||||
<version>2.7.0</version>
|
||||
<name>web video platform</name>
|
||||
<description>国标28181视频平台</description>
|
||||
<packaging>${project.packaging}</packaging>
|
||||
@ -50,15 +50,15 @@
|
||||
<maven.build.timestamp.format>MMddHHmm</maven.build.timestamp.format>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
|
||||
<!-- 依赖版本 -->
|
||||
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
|
||||
<asciidoctor.input.directory>${project.basedir}/docs/asciidoc</asciidoctor.input.directory>
|
||||
<generated.asciidoc.directory>${project.build.directory}/asciidoc</generated.asciidoc.directory>
|
||||
<asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory>
|
||||
<asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory>
|
||||
<!-- 依赖版本 -->
|
||||
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
|
||||
<asciidoctor.input.directory>${project.basedir}/docs/asciidoc</asciidoctor.input.directory>
|
||||
<generated.asciidoc.directory>${project.build.directory}/asciidoc</generated.asciidoc.directory>
|
||||
<asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory>
|
||||
<asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory>
|
||||
<org.mapstruct.version>1.5.3.Final</org.mapstruct.version>
|
||||
<springboot.version>2.7.2</springboot.version>
|
||||
</properties>
|
||||
</properties>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
@ -178,6 +178,20 @@
|
||||
<artifactId>springdoc-openapi-security</artifactId>
|
||||
<version>1.6.10</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.baomidou/dynamic-datasource-spring-boot-starter -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
|
||||
<version>3.6.1</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!--在线文档 -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-ui</artifactId>
|
||||
<version>1.6.10</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
|
@ -1,8 +0,0 @@
|
||||
alter table wvp_device_channel
|
||||
change stream_id stream_id varying(255)
|
||||
|
||||
alter table wvp_platform
|
||||
add auto_push_channel bool default false
|
||||
|
||||
alter table wvp_stream_proxy
|
||||
add stream_key character varying(255)
|
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.common;
|
||||
|
||||
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -76,6 +77,8 @@ public class StreamInfo implements Serializable, Cloneable{
|
||||
private String endTime;
|
||||
@Schema(description = "进度(录像下载使用)")
|
||||
private double progress;
|
||||
@Schema(description = "文件下载地址(录像下载使用)")
|
||||
private DownloadFileInfo downLoadFilePath;
|
||||
|
||||
@Schema(description = "是否暂停(录像回放使用)")
|
||||
private boolean pause;
|
||||
@ -605,5 +608,11 @@ public class StreamInfo implements Serializable, Cloneable{
|
||||
this.subStream = subStream;
|
||||
}
|
||||
|
||||
public DownloadFileInfo getDownLoadFilePath() {
|
||||
return downLoadFilePath;
|
||||
}
|
||||
|
||||
public void setDownLoadFilePath(DownloadFileInfo downLoadFilePath) {
|
||||
this.downLoadFilePath = downLoadFilePath;
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ public class VideoManagerConstants {
|
||||
|
||||
public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_MEDIA_TRANSACTION_";
|
||||
|
||||
public static final String MEDIA_STREAM_AUTHORITY = "MEDIA_STREAM_AUTHORITY_";
|
||||
public static final String MEDIA_STREAM_AUTHORITY = "VMP_MEDIA_STREAM_AUTHORITY_";
|
||||
|
||||
public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_";
|
||||
|
||||
@ -70,6 +70,7 @@ public class VideoManagerConstants {
|
||||
public static final String SYSTEM_INFO_DISK_PREFIX = "VMP_SYSTEM_INFO_DISK_";
|
||||
|
||||
public static final String REGISTER_EXPIRE_TASK_KEY_PREFIX = "VMP_device_register_expire_";
|
||||
public static final String PUSH_STREAM_LIST = "VMP_PUSH_STREAM_LIST_";
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,83 @@
|
||||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
|
||||
import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
|
||||
import com.genersoft.iot.vmp.vmanager.cloudRecord.CloudRecordController;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 录像文件定时删除
|
||||
*/
|
||||
@Component
|
||||
public class CloudRecordTimer {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(CloudRecordTimer.class);
|
||||
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@Autowired
|
||||
private CloudRecordServiceMapper cloudRecordServiceMapper;
|
||||
|
||||
@Autowired
|
||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||
|
||||
/**
|
||||
* 定时查询待删除的录像文件
|
||||
*/
|
||||
// @Scheduled(fixedRate = 10000) //每五秒执行一次,方便测试
|
||||
@Scheduled(cron = "0 0 0 * * ?") //每天的0点执行
|
||||
public void execute(){
|
||||
logger.info("[录像文件定时清理] 开始清理过期录像文件");
|
||||
// 获取配置了assist的流媒体节点
|
||||
List<MediaServerItem> mediaServerItemList = mediaServerService.getAllOnline();
|
||||
if (mediaServerItemList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
long result = 0;
|
||||
for (MediaServerItem mediaServerItem : mediaServerItemList) {
|
||||
|
||||
Calendar lastCalendar = Calendar.getInstance();
|
||||
if (mediaServerItem.getRecordDay() > 0) {
|
||||
lastCalendar.setTime(new Date());
|
||||
// 获取保存的最后截至日[期,因为每个节点都有一个日期,也就是支持每个节点设置不同的保存日期,
|
||||
lastCalendar.add(Calendar.DAY_OF_MONTH, -mediaServerItem.getRecordDay());
|
||||
Long lastDate = lastCalendar.getTimeInMillis();
|
||||
|
||||
// 获取到截至日期之前的录像文件列表,文件列表满足未被收藏和保持的。这两个字段目前共能一致,
|
||||
// 为我自己业务系统相关的代码,大家使用的时候直接使用收藏(collect)这一个类型即可
|
||||
List<CloudRecordItem> cloudRecordItemList = cloudRecordServiceMapper.queryRecordListForDelete(lastDate, mediaServerItem.getId());
|
||||
if (cloudRecordItemList.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
// TODO 后续可以删除空了的过期日期文件夹
|
||||
for (CloudRecordItem cloudRecordItem : cloudRecordItemList) {
|
||||
String date = new File(cloudRecordItem.getFilePath()).getParentFile().getName();
|
||||
JSONObject jsonObject = zlmresTfulUtils.deleteRecordDirectory(mediaServerItem, cloudRecordItem.getApp(),
|
||||
cloudRecordItem.getStream(), date, cloudRecordItem.getFileName());
|
||||
if (jsonObject.getInteger("code") != 0) {
|
||||
logger.warn("[录像文件定时清理] 删除磁盘文件错误: {}:{}", cloudRecordItem.getFilePath(), jsonObject);
|
||||
}
|
||||
}
|
||||
result += cloudRecordServiceMapper.deleteList(cloudRecordItemList);
|
||||
}
|
||||
}
|
||||
logger.info("[录像文件定时清理] 共清理{}个过期录像文件", result);
|
||||
}
|
||||
}
|
@ -86,6 +86,12 @@ public class MediaConfig{
|
||||
@Value("${media.record-assist-port:0}")
|
||||
private Integer recordAssistPort = 0;
|
||||
|
||||
@Value("${media.record-day:7}")
|
||||
private Integer recordDay;
|
||||
|
||||
@Value("${media.record-path:}")
|
||||
private String recordPath;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
@ -218,13 +224,32 @@ public class MediaConfig{
|
||||
mediaServerItem.setRecordAssistIp(recordAssistIp);
|
||||
mediaServerItem.setRecordAssistPort(recordAssistPort);
|
||||
mediaServerItem.setHookAliveInterval(30.00f);
|
||||
|
||||
mediaServerItem.setRecordDay(recordDay);
|
||||
if (recordPath != null) {
|
||||
mediaServerItem.setRecordPath(recordPath);
|
||||
}
|
||||
mediaServerItem.setCreateTime(DateUtil.getNow());
|
||||
mediaServerItem.setUpdateTime(DateUtil.getNow());
|
||||
|
||||
return mediaServerItem;
|
||||
}
|
||||
|
||||
public Integer getRecordDay() {
|
||||
return recordDay;
|
||||
}
|
||||
|
||||
public void setRecordDay(Integer recordDay) {
|
||||
this.recordDay = recordDay;
|
||||
}
|
||||
|
||||
public String getRecordPath() {
|
||||
return recordPath;
|
||||
}
|
||||
|
||||
public void setRecordPath(String recordPath) {
|
||||
this.recordPath = recordPath;
|
||||
}
|
||||
|
||||
public String getRtpSendPortRange() {
|
||||
return rtpSendPortRange;
|
||||
}
|
||||
|
@ -39,4 +39,6 @@ public class SystemInfoTimerTask {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public class UserSetting {
|
||||
|
||||
private Integer playTimeout = 18000;
|
||||
|
||||
private int platformPlayTimeout = 60000;
|
||||
private int platformPlayTimeout = 20000;
|
||||
|
||||
private Boolean interfaceAuthentication = Boolean.TRUE;
|
||||
|
||||
@ -61,8 +61,6 @@ public class UserSetting {
|
||||
|
||||
private String serverId = "000000";
|
||||
|
||||
private String recordPath = null;
|
||||
|
||||
private String thirdPartyGBIdReg = "[\\s\\S]*";
|
||||
|
||||
private String civilCodeFile = "classpath:civilCode.csv";
|
||||
@ -257,14 +255,6 @@ public class UserSetting {
|
||||
this.refuseChannelStatusChannelFormNotify = refuseChannelStatusChannelFormNotify;
|
||||
}
|
||||
|
||||
public String getRecordPath() {
|
||||
return recordPath;
|
||||
}
|
||||
|
||||
public void setRecordPath(String recordPath) {
|
||||
this.recordPath = recordPath;
|
||||
}
|
||||
|
||||
public int getMaxNotifyCountQueue() {
|
||||
return maxNotifyCountQueue;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public class RecordEndEventListener implements ApplicationListener<RecordEndEven
|
||||
event.getRecordInfo().getDeviceId(),
|
||||
event.getRecordInfo().getChannelId(), count,sumNum);
|
||||
logger.debug("handlerMap.size => {}", handlerMap.size());
|
||||
if (handlerMap.size() > 0) {
|
||||
if (!handlerMap.isEmpty()) {
|
||||
String key = deviceId + channelId + sn;
|
||||
logger.debug("handlerMap.keys => {}", handlerMap.keySet());
|
||||
RecordEndEventHandler handler = handlerMap.get(deviceId + channelId + sn);
|
||||
@ -63,6 +63,9 @@ public class RecordEndEventListener implements ApplicationListener<RecordEndEven
|
||||
scheduleMap.put(key,schedule);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
logger.info("录像查询完成事件触发, 但是订阅为空,取消发送,deviceId:{}, channelId: {}",
|
||||
event.getRecordInfo().getDeviceId(), event.getRecordInfo().getChannelId());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,13 +148,13 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
|
||||
if (event.getDeviceChannels() != null) {
|
||||
deviceChannelList.addAll(event.getDeviceChannels());
|
||||
}
|
||||
if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
|
||||
if (event.getGbStreams() != null && !event.getGbStreams().isEmpty()){
|
||||
for (GbStream gbStream : event.getGbStreams()) {
|
||||
deviceChannelList.add(
|
||||
gbStreamService.getDeviceChannelListByStreamWithStatus(gbStream, gbStream.getCatalogId(), parentPlatform));
|
||||
}
|
||||
}
|
||||
if (deviceChannelList.size() > 0) {
|
||||
if (!deviceChannelList.isEmpty()) {
|
||||
logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size());
|
||||
try {
|
||||
sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe, null);
|
||||
@ -163,10 +163,10 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
|
||||
logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}else if (parentPlatformMap.keySet().size() > 0) {
|
||||
}else if (!parentPlatformMap.keySet().isEmpty()) {
|
||||
for (String gbId : parentPlatformMap.keySet()) {
|
||||
List<ParentPlatform> parentPlatforms = parentPlatformMap.get(gbId);
|
||||
if (parentPlatforms != null && parentPlatforms.size() > 0) {
|
||||
if (parentPlatforms != null && !parentPlatforms.isEmpty()) {
|
||||
for (ParentPlatform platform : parentPlatforms) {
|
||||
SubscribeInfo subscribeInfo = subscribeHolder.getCatalogSubscribe(platform.getServerGBId());
|
||||
if (subscribeInfo == null) {
|
||||
|
@ -75,6 +75,33 @@ public class VideoStreamSessionManager {
|
||||
return (SsrcTransaction)redisTemplate.opsForValue().get(scanResult.get(0));
|
||||
}
|
||||
|
||||
public SsrcTransaction getSsrcTransactionByCallId(String callId){
|
||||
|
||||
if (ObjectUtils.isEmpty(callId)) {
|
||||
return null;
|
||||
}
|
||||
String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_*_*_" + callId+ "_*";
|
||||
List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
|
||||
if (!scanResult.isEmpty()) {
|
||||
return (SsrcTransaction)redisTemplate.opsForValue().get(scanResult.get(0));
|
||||
}else {
|
||||
key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_*_*_play_*";
|
||||
scanResult = RedisUtil.scan(redisTemplate, key);
|
||||
if (scanResult.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (Object keyObj : scanResult) {
|
||||
SsrcTransaction ssrcTransaction = (SsrcTransaction)redisTemplate.opsForValue().get(keyObj);
|
||||
if (ssrcTransaction.getSipTransactionInfo() != null &&
|
||||
ssrcTransaction.getSipTransactionInfo().getCallId().equals(callId)) {
|
||||
return ssrcTransaction;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<SsrcTransaction> getSsrcTransactionForAll(String deviceId, String channelId, String callId, String stream){
|
||||
if (ObjectUtils.isEmpty(deviceId)) {
|
||||
deviceId ="*";
|
||||
|
@ -129,4 +129,6 @@ public class SipRunner implements CommandLineRunner {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -66,17 +66,17 @@ public class SIPSender {
|
||||
// 添加错误订阅
|
||||
if (errorEvent != null) {
|
||||
sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {
|
||||
errorEvent.response(eventResult);
|
||||
sipSubscribe.removeErrorSubscribe(eventResult.callId);
|
||||
sipSubscribe.removeOkSubscribe(eventResult.callId);
|
||||
errorEvent.response(eventResult);
|
||||
}));
|
||||
}
|
||||
// 添加订阅
|
||||
if (okEvent != null) {
|
||||
sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> {
|
||||
okEvent.response(eventResult);
|
||||
sipSubscribe.removeOkSubscribe(eventResult.callId);
|
||||
sipSubscribe.removeErrorSubscribe(eventResult.callId);
|
||||
okEvent.response(eventResult);
|
||||
});
|
||||
}
|
||||
if ("TCP".equals(transport)) {
|
||||
|
@ -557,7 +557,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
|
||||
@Override
|
||||
public void sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) throws InvalidArgumentException, ParseException, NoSuchFieldException, SipException, IllegalAccessException {
|
||||
if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) {
|
||||
if (parentPlatform == null || deviceChannels == null || deviceChannels.isEmpty() || subscribeInfo == null) {
|
||||
return;
|
||||
}
|
||||
if (index == null) {
|
||||
@ -575,6 +575,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
Integer finalIndex = index;
|
||||
String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channels,
|
||||
deviceChannels.size(), type, subscribeInfo);
|
||||
logger.info("[发送NOTIFY通知]类型: {},发送数量: {}", type, channels.size());
|
||||
sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
|
||||
logger.error("发送NOTIFY通知消息失败。错误:{} {}", eventResult.statusCode, eventResult.msg);
|
||||
}, (eventResult -> {
|
||||
@ -598,7 +599,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
|
||||
SIPRequest notifyRequest = headerProviderPlatformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, subscribeInfo);
|
||||
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), notifyRequest);
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), notifyRequest, errorEvent, okEvent);
|
||||
}
|
||||
|
||||
private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, List<DeviceChannel> channels, int sumNum, String type, SubscribeInfo subscribeInfo) {
|
||||
@ -610,9 +611,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
.append("<CmdType>Catalog</CmdType>\r\n")
|
||||
.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n")
|
||||
.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n")
|
||||
.append("<SumNum>1</SumNum>\r\n")
|
||||
.append("<SumNum>"+ sumNum +"</SumNum>\r\n")
|
||||
.append("<DeviceList Num=\"" + channels.size() + "\">\r\n");
|
||||
if (channels.size() > 0) {
|
||||
if (!channels.isEmpty()) {
|
||||
for (DeviceChannel channel : channels) {
|
||||
if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
|
||||
channel.setParentId(parentPlatform.getDeviceGBId());
|
||||
@ -679,6 +680,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
}else {
|
||||
channels = deviceChannels.subList(index, deviceChannels.size());
|
||||
}
|
||||
logger.info("[发送NOTIFY通知]类型: {},发送数量: {}", type, channels.size());
|
||||
Integer finalIndex = index;
|
||||
String catalogXmlContent = getCatalogXmlContentForCatalogOther(parentPlatform, channels, type);
|
||||
sendNotify(parentPlatform, catalogXmlContent, subscribeInfo, eventResult -> {
|
||||
@ -725,13 +727,14 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
if ( parentPlatform ==null) {
|
||||
return ;
|
||||
}
|
||||
logger.info("[国标级联] 发送录像数据通道: {}", recordInfo.getChannelId());
|
||||
String characterSet = parentPlatform.getCharacterSet();
|
||||
StringBuffer recordXml = new StringBuffer(600);
|
||||
recordXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n")
|
||||
.append("<Response>\r\n")
|
||||
.append("<CmdType>RecordInfo</CmdType>\r\n")
|
||||
.append("<SN>" +recordInfo.getSn() + "</SN>\r\n")
|
||||
.append("<DeviceID>" + recordInfo.getChannelId() + "</DeviceID>\r\n")
|
||||
.append("<DeviceID>" + deviceChannel.getChannelId() + "</DeviceID>\r\n")
|
||||
.append("<SumNum>" + recordInfo.getSumNum() + "</SumNum>\r\n");
|
||||
if (recordInfo.getRecordList() == null ) {
|
||||
recordXml.append("<RecordList Num=\"0\">\r\n");
|
||||
@ -741,7 +744,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
for (RecordItem recordItem : recordInfo.getRecordList()) {
|
||||
recordXml.append("<Item>\r\n");
|
||||
if (deviceChannel != null) {
|
||||
recordXml.append("<DeviceID>" + recordItem.getDeviceId() + "</DeviceID>\r\n")
|
||||
recordXml.append("<DeviceID>" + deviceChannel.getChannelId() + "</DeviceID>\r\n")
|
||||
.append("<Name>" + recordItem.getName() + "</Name>\r\n")
|
||||
.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getStartTime()) + "</StartTime>\r\n")
|
||||
.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(recordItem.getEndTime()) + "</EndTime>\r\n")
|
||||
@ -761,12 +764,14 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
|
||||
|
||||
recordXml.append("</RecordList>\r\n")
|
||||
.append("</Response>\r\n");
|
||||
|
||||
logger.info("[国标级联] 发送录像数据通道:{}, 内容: {}", recordInfo.getChannelId(), recordXml);
|
||||
// callid
|
||||
CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
|
||||
|
||||
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request);
|
||||
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, null, eventResult -> {
|
||||
logger.info("[国标级联] 发送录像数据通道:{}, 发送成功", recordInfo.getChannelId());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ import javax.sip.header.CallIdHeader;
|
||||
import javax.sip.message.Response;
|
||||
import java.text.ParseException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -149,7 +150,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
|
||||
}else {
|
||||
|
||||
// 可能是设备发送的停止
|
||||
SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
|
||||
SsrcTransaction ssrcTransaction = streamSession.getSsrcTransactionByCallId(callIdHeader.getCallId());
|
||||
if (ssrcTransaction == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
String requesterId = SipUtils.getUserIdFromFromHeader(request);
|
||||
CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
|
||||
if (requesterId == null || channelId == null) {
|
||||
logger.info("无法从FromHeader的Address中获取到平台id,返回400");
|
||||
logger.info("无法从请求中获取到平台id,返回400");
|
||||
// 参数不全, 发400,请求错误
|
||||
try {
|
||||
responseAck(request, Response.BAD_REQUEST);
|
||||
@ -155,6 +155,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("[INVITE] requesterId: {}, callId: {}, 来自:{}:{}",
|
||||
requesterId, callIdHeader.getCallId(), request.getRemoteAddress(), request.getRemotePort());
|
||||
|
||||
// 查询请求是否来自上级平台\设备
|
||||
ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId);
|
||||
@ -415,7 +417,16 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
// 非严格模式端口不统一, 增加兼容性,修改为一个不为0的端口
|
||||
localPort = new Random().nextInt(65535) + 1;
|
||||
}
|
||||
content.append("m=video " + localPort + " RTP/AVP 96\r\n");
|
||||
if (sendRtpItem.isTcp()) {
|
||||
content.append("m=video " + localPort + " TCP/RTP/AVP 96\r\n");
|
||||
if (!sendRtpItem.isTcpActive()) {
|
||||
content.append("a=setup:active\r\n");
|
||||
} else {
|
||||
content.append("a=setup:passive\r\n");
|
||||
}
|
||||
}else {
|
||||
content.append("m=video " + localPort + " RTP/AVP 96\r\n");
|
||||
}
|
||||
content.append("a=sendonly\r\n");
|
||||
content.append("a=rtpmap:96 PS/90000\r\n");
|
||||
content.append("y=" + sendRtpItem.getSsrc() + "\r\n");
|
||||
@ -540,7 +551,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
sendRtpItem.setPlayType(InviteStreamType.PLAY);
|
||||
String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
|
||||
sendRtpItem.setStreamId(streamId);
|
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
||||
SSRCInfo ssrcInfo = playService.play(mediaServerItem, device.getDeviceId(), channelId, ssrc, ((code, msg, data) -> {
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()) {
|
||||
hookEvent.run(code, msg, data);
|
||||
@ -552,9 +566,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
errorEvent.run(code, msg, data);
|
||||
}
|
||||
}));
|
||||
sendRtpItem.setPlayType(InviteStreamType.PLAY);
|
||||
String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
|
||||
sendRtpItem.setStreamId(streamId);
|
||||
sendRtpItem.setSsrc(ssrcInfo.getSsrc());
|
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
||||
|
||||
@ -736,9 +747,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
zlmHttpHookSubscribe.removeSubscribe(hookSubscribe);
|
||||
dynamicTask.stop(callIdHeader.getCallId());
|
||||
}
|
||||
|
||||
|
||||
|
||||
} else if ("push".equals(gbStream.getStreamType())) {
|
||||
if (!platform.isStartOfflinePush()) {
|
||||
// 平台设置中关闭了拉起离线的推流则直接回复
|
||||
@ -761,13 +769,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
|
||||
logger.info("[ app={}, stream={} ] 等待设备开始推流超时", gbStream.getApp(), gbStream.getStream());
|
||||
try {
|
||||
redisPushStreamResponseListener.removeEvent(gbStream.getApp(), gbStream.getStream());
|
||||
mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
|
||||
responseAck(request, Response.REQUEST_TIMEOUT); // 超时
|
||||
} catch (SipException e) {
|
||||
logger.error("未处理的异常 ", e);
|
||||
} catch (InvalidArgumentException e) {
|
||||
logger.error("未处理的异常 ", e);
|
||||
} catch (ParseException e) {
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("未处理的异常 ", e);
|
||||
}
|
||||
}, userSetting.getPlatformPlayTimeout());
|
||||
@ -778,6 +783,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
|
||||
// 添加在本机上线的通知
|
||||
mediaListManager.addChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream(), (app, stream, serverId) -> {
|
||||
dynamicTask.stop(callIdHeader.getCallId());
|
||||
redisPushStreamResponseListener.removeEvent(gbStream.getApp(), gbStream.getStream());
|
||||
if (serverId.equals(userSetting.getServerId())) {
|
||||
SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId,
|
||||
app, stream, channelId, mediaTransmissionTCP, platform.isRtcp());
|
||||
|
@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||
import com.genersoft.iot.vmp.service.IDeviceChannelService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Element;
|
||||
import org.slf4j.Logger;
|
||||
@ -185,6 +186,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
|
||||
// 判断此通道是否存在
|
||||
DeviceChannel deviceChannel = deviceChannelService.getOne(deviceId, channel.getChannelId());
|
||||
if (deviceChannel != null) {
|
||||
logger.info("[增加通道] 已存在,不发送通知只更新,设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
|
||||
channel.setId(deviceChannel.getId());
|
||||
updateChannelMap.put(channel.getChannelId(), channel);
|
||||
if (updateChannelMap.keySet().size() > 300) {
|
||||
@ -222,6 +224,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
|
||||
DeviceChannel deviceChannelForUpdate = deviceChannelService.getOne(deviceId, channel.getChannelId());
|
||||
if (deviceChannelForUpdate != null) {
|
||||
channel.setId(deviceChannelForUpdate.getId());
|
||||
channel.setUpdateTime(DateUtil.getNow());
|
||||
updateChannelMap.put(channel.getChannelId(), channel);
|
||||
if (updateChannelMap.keySet().size() > 300) {
|
||||
executeSaveForUpdate();
|
||||
@ -244,11 +247,11 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
|
||||
// 转发变化信息
|
||||
eventPublisher.catalogEventPublish(null, channel, event);
|
||||
|
||||
if (updateChannelMap.keySet().size() > 0
|
||||
|| addChannelMap.keySet().size() > 0
|
||||
|| updateChannelOnlineList.size() > 0
|
||||
|| updateChannelOfflineList.size() > 0
|
||||
|| deleteChannelList.size() > 0) {
|
||||
if (!updateChannelMap.keySet().isEmpty()
|
||||
|| !addChannelMap.keySet().isEmpty()
|
||||
|| !updateChannelOnlineList.isEmpty()
|
||||
|| !updateChannelOfflineList.isEmpty()
|
||||
|| !deleteChannelList.isEmpty()) {
|
||||
|
||||
if (!dynamicTask.contains(talkKey)) {
|
||||
dynamicTask.startDelay(talkKey, this::executeSave, 1000);
|
||||
@ -262,16 +265,36 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
|
||||
}
|
||||
|
||||
private void executeSave(){
|
||||
executeSaveForAdd();
|
||||
executeSaveForUpdate();
|
||||
executeSaveForDelete();
|
||||
executeSaveForOnline();
|
||||
executeSaveForOffline();
|
||||
try {
|
||||
executeSaveForAdd();
|
||||
} catch (Exception e) {
|
||||
logger.error("[存储收到的增加通道] 异常: ", e );
|
||||
}
|
||||
try {
|
||||
executeSaveForUpdate();
|
||||
} catch (Exception e) {
|
||||
logger.error("[存储收到的更新通道] 异常: ", e );
|
||||
}
|
||||
try {
|
||||
executeSaveForDelete();
|
||||
} catch (Exception e) {
|
||||
logger.error("[存储收到的删除通道] 异常: ", e );
|
||||
}
|
||||
try {
|
||||
executeSaveForOnline();
|
||||
} catch (Exception e) {
|
||||
logger.error("[存储收到的通道上线] 异常: ", e );
|
||||
}
|
||||
try {
|
||||
executeSaveForOffline();
|
||||
} catch (Exception e) {
|
||||
logger.error("[存储收到的通道离线] 异常: ", e );
|
||||
}
|
||||
dynamicTask.stop(talkKey);
|
||||
}
|
||||
|
||||
private void executeSaveForUpdate(){
|
||||
if (updateChannelMap.values().size() > 0) {
|
||||
if (!updateChannelMap.values().isEmpty()) {
|
||||
ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(updateChannelMap.values());
|
||||
updateChannelMap.clear();
|
||||
deviceChannelService.batchUpdateChannel(deviceChannels);
|
||||
@ -280,7 +303,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
|
||||
}
|
||||
|
||||
private void executeSaveForAdd(){
|
||||
if (addChannelMap.values().size() > 0) {
|
||||
if (!addChannelMap.values().isEmpty()) {
|
||||
ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(addChannelMap.values());
|
||||
addChannelMap.clear();
|
||||
deviceChannelService.batchAddChannel(deviceChannels);
|
||||
@ -288,21 +311,21 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
|
||||
}
|
||||
|
||||
private void executeSaveForDelete(){
|
||||
if (deleteChannelList.size() > 0) {
|
||||
if (!deleteChannelList.isEmpty()) {
|
||||
deviceChannelService.deleteChannels(deleteChannelList);
|
||||
deleteChannelList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void executeSaveForOnline(){
|
||||
if (updateChannelOnlineList.size() > 0) {
|
||||
if (!updateChannelOnlineList.isEmpty()) {
|
||||
deviceChannelService.channelsOnline(updateChannelOnlineList);
|
||||
updateChannelOnlineList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void executeSaveForOffline(){
|
||||
if (updateChannelOfflineList.size() > 0) {
|
||||
if (!updateChannelOfflineList.isEmpty()) {
|
||||
deviceChannelService.channelsOffline(updateChannelOfflineList);
|
||||
updateChannelOfflineList.clear();
|
||||
}
|
||||
|
@ -103,23 +103,27 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
|
||||
String title = registerFlag ? "[注册请求]": "[注销请求]";
|
||||
logger.info(title + "设备:{}, 开始处理: {}", deviceId, requestAddress);
|
||||
if (device != null &&
|
||||
device.getSipTransactionInfo() != null &&
|
||||
request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) {
|
||||
device.getSipTransactionInfo() != null &&
|
||||
request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) {
|
||||
logger.info(title + "设备:{}, 注册续订: {}",device.getDeviceId(), device.getDeviceId());
|
||||
device.setExpires(request.getExpires().getExpires());
|
||||
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
|
||||
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
|
||||
String transport = reqViaHeader.getTransport();
|
||||
device.setTransport("TCP".equalsIgnoreCase(transport) ? "TCP" : "UDP");
|
||||
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), registerOkResponse);
|
||||
device.setRegisterTime(DateUtil.getNow());
|
||||
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)registerOkResponse);
|
||||
deviceService.online(device, sipTransactionInfo);
|
||||
if (registerFlag) {
|
||||
device.setExpires(request.getExpires().getExpires());
|
||||
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
|
||||
ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
|
||||
String transport = reqViaHeader.getTransport();
|
||||
device.setTransport("TCP".equalsIgnoreCase(transport) ? "TCP" : "UDP");
|
||||
sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), registerOkResponse);
|
||||
device.setRegisterTime(DateUtil.getNow());
|
||||
SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)registerOkResponse);
|
||||
deviceService.online(device, sipTransactionInfo);
|
||||
}else {
|
||||
deviceService.offline(deviceId, "主动注销");
|
||||
}
|
||||
return;
|
||||
}
|
||||
String password = (device != null && !ObjectUtils.isEmpty(device.getPassword()))? device.getPassword() : sipConfig.getPassword();
|
||||
|
@ -76,7 +76,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
|
||||
|
||||
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
|
||||
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) {
|
||||
logger.info("[心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
|
||||
logger.info("[收到心跳] 设备{}地址变化, 远程地址为: {}:{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort());
|
||||
device.setPort(remoteAddressInfo.getPort());
|
||||
device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));
|
||||
device.setIp(remoteAddressInfo.getIp());
|
||||
|
@ -2,19 +2,27 @@ package com.genersoft.iot.vmp.media.zlm;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import okhttp3.*;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
public class AssistRESTfulUtils {
|
||||
@ -22,21 +30,41 @@ public class AssistRESTfulUtils {
|
||||
private final static Logger logger = LoggerFactory.getLogger(AssistRESTfulUtils.class);
|
||||
|
||||
|
||||
private OkHttpClient client;
|
||||
|
||||
|
||||
public interface RequestCallback{
|
||||
void run(JSONObject response);
|
||||
}
|
||||
|
||||
private OkHttpClient getClient(){
|
||||
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
|
||||
if (logger.isDebugEnabled()) {
|
||||
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> {
|
||||
logger.debug("http请求参数:" + message);
|
||||
});
|
||||
logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
|
||||
// OkHttp進行添加攔截器loggingInterceptor
|
||||
httpClientBuilder.addInterceptor(logging);
|
||||
return getClient(null);
|
||||
}
|
||||
|
||||
private OkHttpClient getClient(Integer readTimeOut){
|
||||
if (client == null) {
|
||||
if (readTimeOut == null) {
|
||||
readTimeOut = 10;
|
||||
}
|
||||
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
|
||||
// 设置连接超时时间
|
||||
httpClientBuilder.connectTimeout(8, TimeUnit.SECONDS);
|
||||
// 设置读取超时时间
|
||||
httpClientBuilder.readTimeout(readTimeOut,TimeUnit.SECONDS);
|
||||
// 设置连接池
|
||||
httpClientBuilder.connectionPool(new ConnectionPool(16, 5, TimeUnit.MINUTES));
|
||||
if (logger.isDebugEnabled()) {
|
||||
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> {
|
||||
logger.debug("http请求参数:" + message);
|
||||
});
|
||||
logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
|
||||
// OkHttp進行添加攔截器loggingInterceptor
|
||||
httpClientBuilder.addInterceptor(logging);
|
||||
}
|
||||
client = httpClientBuilder.build();
|
||||
}
|
||||
return httpClientBuilder.build();
|
||||
return client;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -50,11 +78,11 @@ public class AssistRESTfulUtils {
|
||||
logger.warn("未启用Assist服务");
|
||||
return null;
|
||||
}
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
stringBuffer.append(String.format("http://%s:%s/%s", mediaServerItem.getIp(), mediaServerItem.getRecordAssistPort(), api));
|
||||
StringBuilder stringBuffer = new StringBuilder();
|
||||
stringBuffer.append(api);
|
||||
JSONObject responseJSON = null;
|
||||
|
||||
if (param != null && param.keySet().size() > 0) {
|
||||
if (param != null && !param.keySet().isEmpty()) {
|
||||
stringBuffer.append("?");
|
||||
int index = 1;
|
||||
for (String key : param.keySet()){
|
||||
@ -69,6 +97,7 @@ public class AssistRESTfulUtils {
|
||||
}
|
||||
|
||||
String url = stringBuffer.toString();
|
||||
logger.info("[访问assist]: {}", url);
|
||||
Request request = new Request.Builder()
|
||||
.get()
|
||||
.url(url)
|
||||
@ -124,13 +153,92 @@ public class AssistRESTfulUtils {
|
||||
return responseJSON;
|
||||
}
|
||||
|
||||
public JSONObject sendPost(MediaServerItem mediaServerItem, String url,
|
||||
JSONObject param, ZLMRESTfulUtils.RequestCallback callback,
|
||||
Integer readTimeOut) {
|
||||
OkHttpClient client = getClient(readTimeOut);
|
||||
|
||||
public JSONObject fileDuration(MediaServerItem mediaServerItem, String app, String stream, RequestCallback callback){
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("app",app);
|
||||
param.put("stream",stream);
|
||||
param.put("recordIng",true);
|
||||
return sendGet(mediaServerItem, "api/record/file/duration",param, callback);
|
||||
if (mediaServerItem == null) {
|
||||
return null;
|
||||
}
|
||||
JSONObject responseJSON = new JSONObject();
|
||||
//-2自定义流媒体 调用错误码
|
||||
responseJSON.put("code",-2);
|
||||
responseJSON.put("msg","ASSIST调用失败");
|
||||
|
||||
RequestBody requestBodyJson = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), param.toString());
|
||||
|
||||
Request request = new Request.Builder()
|
||||
.post(requestBodyJson)
|
||||
.url(url)
|
||||
.addHeader("Content-Type", "application/json")
|
||||
.build();
|
||||
if (callback == null) {
|
||||
try {
|
||||
Response response = client.newCall(request).execute();
|
||||
if (response.isSuccessful()) {
|
||||
ResponseBody responseBody = response.body();
|
||||
if (responseBody != null) {
|
||||
String responseStr = responseBody.string();
|
||||
responseJSON = JSON.parseObject(responseStr);
|
||||
}
|
||||
}else {
|
||||
response.close();
|
||||
Objects.requireNonNull(response.body()).close();
|
||||
}
|
||||
}catch (IOException e) {
|
||||
logger.error(String.format("[ %s ]ASSIST请求失败: %s", url, e.getMessage()));
|
||||
|
||||
if(e instanceof SocketTimeoutException){
|
||||
//读取超时超时异常
|
||||
logger.error(String.format("读取ASSIST数据失败: %s, %s", url, e.getMessage()));
|
||||
}
|
||||
if(e instanceof ConnectException){
|
||||
//判断连接异常,我这里是报Failed to connect to 10.7.5.144
|
||||
logger.error(String.format("连接ASSIST失败: %s, %s", url, e.getMessage()));
|
||||
}
|
||||
|
||||
}catch (Exception e){
|
||||
logger.error(String.format("访问ASSIST失败: %s, %s", url, e.getMessage()));
|
||||
}
|
||||
}else {
|
||||
client.newCall(request).enqueue(new Callback(){
|
||||
|
||||
@Override
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response){
|
||||
if (response.isSuccessful()) {
|
||||
try {
|
||||
String responseStr = Objects.requireNonNull(response.body()).string();
|
||||
callback.run(JSON.parseObject(responseStr));
|
||||
} catch (IOException e) {
|
||||
logger.error(String.format("[ %s ]请求失败: %s", url, e.getMessage()));
|
||||
}
|
||||
|
||||
}else {
|
||||
response.close();
|
||||
Objects.requireNonNull(response.body()).close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e) {
|
||||
logger.error(String.format("连接ZLM失败: %s, %s", call.request().toString(), e.getMessage()));
|
||||
|
||||
if(e instanceof SocketTimeoutException){
|
||||
//读取超时超时异常
|
||||
logger.error(String.format("读取ZLM数据失败: %s, %s", call.request().toString(), e.getMessage()));
|
||||
}
|
||||
if(e instanceof ConnectException){
|
||||
//判断连接异常,我这里是报Failed to connect to 10.7.5.144
|
||||
logger.error(String.format("连接ZLM失败: %s, %s", call.request().toString(), e.getMessage()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
return responseJSON;
|
||||
}
|
||||
|
||||
public JSONObject getInfo(MediaServerItem mediaServerItem, RequestCallback callback){
|
||||
@ -138,33 +246,43 @@ public class AssistRESTfulUtils {
|
||||
return sendGet(mediaServerItem, "api/record/info",param, callback);
|
||||
}
|
||||
|
||||
public JSONObject addStreamCallInfo(MediaServerItem mediaServerItem, String app, String stream, String callId, RequestCallback callback){
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("app",app);
|
||||
param.put("stream",stream);
|
||||
param.put("callId",callId);
|
||||
return sendGet(mediaServerItem, "api/record/addStreamCallInfo",param, callback);
|
||||
public JSONObject addTask(MediaServerItem mediaServerItem, String app, String stream, String startTime,
|
||||
String endTime, String callId, List<String> filePathList, String remoteHost) {
|
||||
|
||||
JSONObject videoTaskInfoJSON = new JSONObject();
|
||||
videoTaskInfoJSON.put("app", app);
|
||||
videoTaskInfoJSON.put("stream", stream);
|
||||
videoTaskInfoJSON.put("startTime", startTime);
|
||||
videoTaskInfoJSON.put("endTime", endTime);
|
||||
videoTaskInfoJSON.put("callId", callId);
|
||||
videoTaskInfoJSON.put("filePathList", filePathList);
|
||||
if (!ObjectUtils.isEmpty(remoteHost)) {
|
||||
videoTaskInfoJSON.put("remoteHost", remoteHost);
|
||||
}
|
||||
String urlStr = String.format("%s/api/record/file/download/task/add", remoteHost);;
|
||||
return sendPost(mediaServerItem, urlStr, videoTaskInfoJSON, null, 30);
|
||||
}
|
||||
|
||||
public JSONObject getDateList(MediaServerItem mediaServerItem, String app, String stream, int year, int month) {
|
||||
public JSONObject queryTaskList(MediaServerItem mediaServerItem, String app, String stream, String callId,
|
||||
String taskId, Boolean isEnd, String scheme) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("app", app);
|
||||
param.put("stream", stream);
|
||||
param.put("year", year);
|
||||
param.put("month", month);
|
||||
return sendGet(mediaServerItem, "api/record/date/list", param, null);
|
||||
if (!ObjectUtils.isEmpty(app)) {
|
||||
param.put("app", app);
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(stream)) {
|
||||
param.put("stream", stream);
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(callId)) {
|
||||
param.put("callId", callId);
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(taskId)) {
|
||||
param.put("taskId", taskId);
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(isEnd)) {
|
||||
param.put("isEnd", isEnd);
|
||||
}
|
||||
String urlStr = String.format("%s://%s:%s/api/record/file/download/task/list",
|
||||
scheme, mediaServerItem.getIp(), mediaServerItem.getRecordAssistPort());;
|
||||
return sendGet(mediaServerItem, urlStr, param, null);
|
||||
}
|
||||
|
||||
public JSONObject getFileList(MediaServerItem mediaServerItem, int page, int count, String app, String stream,
|
||||
String startTime, String endTime) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("app", app);
|
||||
param.put("stream", stream);
|
||||
param.put("page", page);
|
||||
param.put("count", count);
|
||||
param.put("startTime", startTime);
|
||||
param.put("endTime", endTime);
|
||||
return sendGet(mediaServerItem, "api/record/file/listWithDate", param, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -110,6 +110,9 @@ public class ZLMHttpHookListener {
|
||||
@Autowired
|
||||
private IUserService userService;
|
||||
|
||||
@Autowired
|
||||
private ICloudRecordService cloudRecordService;
|
||||
|
||||
@Autowired
|
||||
private VideoStreamSessionManager sessionManager;
|
||||
|
||||
@ -231,12 +234,6 @@ public class ZLMHttpHookListener {
|
||||
streamAuthorityInfo.setSign(sign);
|
||||
// 鉴权通过
|
||||
redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
|
||||
// 通知assist新的callId
|
||||
if (mediaInfo != null && mediaInfo.getRecordAssistPort() > 0) {
|
||||
taskExecutor.execute(() -> {
|
||||
assistRESTfulUtils.addStreamCallInfo(mediaInfo, param.getApp(), param.getStream(), callId, null);
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
zlmMediaListManager.sendStreamEvent(param.getApp(), param.getStream(), param.getMediaServerId());
|
||||
@ -262,7 +259,6 @@ public class ZLMHttpHookListener {
|
||||
} else {
|
||||
result.setEnable_mp4(userSetting.isRecordPushLive());
|
||||
}
|
||||
|
||||
// 国标流
|
||||
if ("rtp".equals(param.getApp()) ) {
|
||||
|
||||
@ -279,9 +275,17 @@ public class ZLMHttpHookListener {
|
||||
}
|
||||
|
||||
// 设置音频信息及录制信息
|
||||
List<SsrcTransaction> ssrcTransactionForAll = (inviteInfo == null ? null :
|
||||
sessionManager.getSsrcTransactionForAll(inviteInfo.getDeviceId(), inviteInfo.getChannelId(), null, null));
|
||||
List<SsrcTransaction> ssrcTransactionForAll = sessionManager.getSsrcTransactionForAll(null, null, null, param.getStream());
|
||||
if (ssrcTransactionForAll != null && ssrcTransactionForAll.size() == 1) {
|
||||
|
||||
// 为录制国标模拟一个鉴权信息, 方便后续写入录像文件时使用
|
||||
StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
|
||||
streamAuthorityInfo.setApp(param.getApp());
|
||||
streamAuthorityInfo.setStream(ssrcTransactionForAll.get(0).getStream());
|
||||
streamAuthorityInfo.setCallId(ssrcTransactionForAll.get(0).getSipTransactionInfo().getCallId());
|
||||
|
||||
redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), ssrcTransactionForAll.get(0).getStream(), streamAuthorityInfo);
|
||||
|
||||
String deviceId = ssrcTransactionForAll.get(0).getDeviceId();
|
||||
String channelId = ssrcTransactionForAll.get(0).getChannelId();
|
||||
DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
|
||||
@ -290,26 +294,16 @@ public class ZLMHttpHookListener {
|
||||
}
|
||||
// 如果是录像下载就设置视频间隔十秒
|
||||
if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.DOWNLOAD) {
|
||||
result.setMp4_max_second(10);
|
||||
result.setEnable_mp4(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mediaInfo.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) {
|
||||
logger.info("推流时发现尚未设置录像路径,从assist服务中读取");
|
||||
JSONObject info = assistRESTfulUtils.getInfo(mediaInfo, null);
|
||||
if (info != null && info.getInteger("code") != null && info.getInteger("code") == 0 ) {
|
||||
JSONObject dataJson = info.getJSONObject("data");
|
||||
if (dataJson != null) {
|
||||
String recordPath = dataJson.getString("record");
|
||||
userSetting.setRecordPath(recordPath);
|
||||
result.setMp4_save_path(recordPath);
|
||||
// 修改zlm中的录像路径
|
||||
if (mediaInfo.isAutoConfig()) {
|
||||
taskExecutor.execute(() -> {
|
||||
mediaServerService.setZLMConfig(mediaInfo, false);
|
||||
});
|
||||
// 获取录像的总时长,然后设置为这个视频的时长
|
||||
InviteInfo inviteInfoForDownload = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, param.getStream());
|
||||
if (inviteInfoForDownload != null && inviteInfoForDownload.getStreamInfo() != null) {
|
||||
String startTime = inviteInfoForDownload.getStreamInfo().getStartTime();
|
||||
String endTime = inviteInfoForDownload.getStreamInfo().getEndTime();
|
||||
long difference = DateUtil.getDifference(startTime, endTime) / 1000;
|
||||
result.setMp4_max_second((int) difference);
|
||||
result.setEnable_mp4(true);
|
||||
// 设置为2保证得到的mp4的时长是正常的
|
||||
result.setModify_stamp(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -357,13 +351,11 @@ public class ZLMHttpHookListener {
|
||||
|
||||
List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks();
|
||||
// TODO 重构此处逻辑
|
||||
boolean isPush = false;
|
||||
if (param.isRegist()) {
|
||||
// 处理流注册的鉴权信息
|
||||
// 处理流注册的鉴权信息, 流注销这里不再删除鉴权信息,下次来了新的鉴权信息会对就的进行覆盖
|
||||
if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal()
|
||||
|| param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
|
||||
|| param.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
|
||||
isPush = true;
|
||||
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
|
||||
if (streamAuthorityInfo == null) {
|
||||
streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
|
||||
@ -373,8 +365,6 @@ public class ZLMHttpHookListener {
|
||||
}
|
||||
redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
|
||||
}
|
||||
} else {
|
||||
redisCatchStorage.removeStreamAuthorityInfo(param.getApp(), param.getStream());
|
||||
}
|
||||
|
||||
if ("rtsp".equals(param.getSchema())) {
|
||||
@ -415,6 +405,9 @@ public class ZLMHttpHookListener {
|
||||
|| param.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
|
||||
param.setSeverId(userSetting.getServerId());
|
||||
zlmMediaListManager.addPush(param);
|
||||
|
||||
// 冗余数据,自己系统中自用
|
||||
redisCatchStorage.addPushListItem(param.getApp(), param.getStream(), param);
|
||||
}
|
||||
} else {
|
||||
// 兼容流注销时类型从redis记录获取
|
||||
@ -423,6 +416,10 @@ public class ZLMHttpHookListener {
|
||||
if (onStreamChangedHookParam != null) {
|
||||
type = OriginType.values()[onStreamChangedHookParam.getOriginType()].getType();
|
||||
redisCatchStorage.removeStream(mediaInfo.getId(), type, param.getApp(), param.getStream());
|
||||
if ("PUSH".equalsIgnoreCase(type)) {
|
||||
// 冗余数据,自己系统中自用
|
||||
redisCatchStorage.removePushListItem(param.getApp(), param.getStream(), param.getMediaServerId());
|
||||
}
|
||||
}
|
||||
GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream());
|
||||
if (gbStream != null) {
|
||||
@ -771,7 +768,7 @@ public class ZLMHttpHookListener {
|
||||
taskExecutor.execute(() -> {
|
||||
JSONObject json = (JSONObject) JSON.toJSON(param);
|
||||
List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_rtp_server_timeout);
|
||||
if (subscribes != null && subscribes.size() > 0) {
|
||||
if (subscribes != null && !subscribes.isEmpty()) {
|
||||
for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
|
||||
subscribe.response(null, param);
|
||||
}
|
||||
@ -781,6 +778,28 @@ public class ZLMHttpHookListener {
|
||||
return HookResult.SUCCESS();
|
||||
}
|
||||
|
||||
/**
|
||||
* 录像完成事件
|
||||
*/
|
||||
@ResponseBody
|
||||
@PostMapping(value = "/on_record_mp4", produces = "application/json;charset=UTF-8")
|
||||
public HookResult onRecordMp4(HttpServletRequest request, @RequestBody OnRecordMp4HookParam param) {
|
||||
logger.info("[ZLM HOOK] 录像完成事件:{}->{}", param.getMediaServerId(), param.getFile_path());
|
||||
|
||||
taskExecutor.execute(() -> {
|
||||
List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_record_mp4);
|
||||
if (subscribes != null && !subscribes.isEmpty()) {
|
||||
for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
|
||||
subscribe.response(null, param);
|
||||
}
|
||||
}
|
||||
cloudRecordService.addRecord(param);
|
||||
|
||||
});
|
||||
|
||||
return HookResult.SUCCESS();
|
||||
}
|
||||
|
||||
private Map<String, String> urlParamToMap(String params) {
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
if (ObjectUtils.isEmpty(params)) {
|
||||
|
@ -25,8 +25,6 @@ public class ZLMRESTfulUtils {
|
||||
|
||||
private OkHttpClient client;
|
||||
|
||||
|
||||
|
||||
public interface RequestCallback{
|
||||
void run(JSONObject response);
|
||||
}
|
||||
@ -398,4 +396,14 @@ public class ZLMRESTfulUtils {
|
||||
param.put("stream_id", streamId);
|
||||
return sendPost(mediaServerItem, "updateRtpServerSSRC",param, null);
|
||||
}
|
||||
|
||||
public JSONObject deleteRecordDirectory(MediaServerItem mediaServerItem, String app, String stream, String date, String fileName) {
|
||||
Map<String, Object> param = new HashMap<>(1);
|
||||
param.put("vhost", "__defaultVhost__");
|
||||
param.put("app", app);
|
||||
param.put("stream", stream);
|
||||
param.put("period", date);
|
||||
param.put("name", fileName);
|
||||
return sendPost(mediaServerItem, "deleteRecordDirectory",param, null);
|
||||
}
|
||||
}
|
||||
|
@ -41,4 +41,15 @@ public class HookSubscribeFactory {
|
||||
|
||||
return hookSubscribe;
|
||||
}
|
||||
|
||||
public static HookSubscribeForRecordMp4 on_record_mp4(String mediaServerId, String app, String stream) {
|
||||
HookSubscribeForRecordMp4 hookSubscribe = new HookSubscribeForRecordMp4();
|
||||
JSONObject subscribeKey = new com.alibaba.fastjson2.JSONObject();
|
||||
subscribeKey.put("app", app);
|
||||
subscribeKey.put("stream", stream);
|
||||
subscribeKey.put("mediaServerId", mediaServerId);
|
||||
hookSubscribe.setContent(subscribeKey);
|
||||
|
||||
return hookSubscribe;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
package com.genersoft.iot.vmp.media.zlm.dto;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.annotation.JSONField;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* hook订阅-录像完成
|
||||
* @author lin
|
||||
*/
|
||||
public class HookSubscribeForRecordMp4 implements IHookSubscribe{
|
||||
|
||||
private HookType hookType = HookType.on_record_mp4;
|
||||
|
||||
private JSONObject content;
|
||||
|
||||
@JSONField(format="yyyy-MM-dd HH:mm:ss")
|
||||
private Instant expires;
|
||||
|
||||
@Override
|
||||
public HookType getHookType() {
|
||||
return hookType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(JSONObject content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant getExpires() {
|
||||
return expires;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpires(Instant expires) {
|
||||
this.expires = expires;
|
||||
}
|
||||
}
|
@ -85,9 +85,11 @@ public class MediaServerItem{
|
||||
@Schema(description = "是否是默认ZLM")
|
||||
private boolean defaultServer;
|
||||
|
||||
@Schema(description = "当前使用到的端口")
|
||||
private int currentPort;
|
||||
@Schema(description = "录像存储时长")
|
||||
private int recordDay;
|
||||
|
||||
@Schema(description = "录像存储路径")
|
||||
private String recordPath;
|
||||
|
||||
public MediaServerItem() {
|
||||
}
|
||||
@ -274,14 +276,6 @@ public class MediaServerItem{
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
public int getCurrentPort() {
|
||||
return currentPort;
|
||||
}
|
||||
|
||||
public void setCurrentPort(int currentPort) {
|
||||
this.currentPort = currentPort;
|
||||
}
|
||||
|
||||
public boolean isStatus() {
|
||||
return status;
|
||||
}
|
||||
@ -313,4 +307,20 @@ public class MediaServerItem{
|
||||
public void setSendRtpPortRange(String sendRtpPortRange) {
|
||||
this.sendRtpPortRange = sendRtpPortRange;
|
||||
}
|
||||
|
||||
public int getRecordDay() {
|
||||
return recordDay;
|
||||
}
|
||||
|
||||
public void setRecordDay(int recordDay) {
|
||||
this.recordDay = recordDay;
|
||||
}
|
||||
|
||||
public String getRecordPath() {
|
||||
return recordPath;
|
||||
}
|
||||
|
||||
public void setRecordPath(String recordPath) {
|
||||
this.recordPath = recordPath;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ public class HookResultForOnPublish extends HookResult{
|
||||
private int mp4_max_second;
|
||||
private String mp4_save_path;
|
||||
private String stream_replace;
|
||||
private Integer modify_stamp;
|
||||
|
||||
public HookResultForOnPublish() {
|
||||
}
|
||||
@ -60,14 +61,23 @@ public class HookResultForOnPublish extends HookResult{
|
||||
this.stream_replace = stream_replace;
|
||||
}
|
||||
|
||||
public Integer getModify_stamp() {
|
||||
return modify_stamp;
|
||||
}
|
||||
|
||||
public void setModify_stamp(Integer modify_stamp) {
|
||||
this.modify_stamp = modify_stamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HookResultForOnPublish{" +
|
||||
"enable_audio=" + enable_audio +
|
||||
", enable_mp4=" + enable_mp4 +
|
||||
", mp4_max_second=" + mp4_max_second +
|
||||
", stream_replace=" + stream_replace +
|
||||
", mp4_save_path='" + mp4_save_path + '\'' +
|
||||
", stream_replace='" + stream_replace + '\'' +
|
||||
", modify_stamp='" + modify_stamp + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
114
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnRecordMp4HookParam.java
Executable file
114
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnRecordMp4HookParam.java
Executable file
@ -0,0 +1,114 @@
|
||||
package com.genersoft.iot.vmp.media.zlm.dto.hook;
|
||||
|
||||
/**
|
||||
* zlm hook事件中的on_rtp_server_timeout事件的参数
|
||||
* @author lin
|
||||
*/
|
||||
public class OnRecordMp4HookParam extends HookParam{
|
||||
private String app;
|
||||
private String stream;
|
||||
private String file_name;
|
||||
private String file_path;
|
||||
private long file_size;
|
||||
private String folder;
|
||||
private String url;
|
||||
private String vhost;
|
||||
private long start_time;
|
||||
private double time_len;
|
||||
|
||||
public String getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void setApp(String app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public String getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void setStream(String stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public String getFile_name() {
|
||||
return file_name;
|
||||
}
|
||||
|
||||
public void setFile_name(String file_name) {
|
||||
this.file_name = file_name;
|
||||
}
|
||||
|
||||
public String getFile_path() {
|
||||
return file_path;
|
||||
}
|
||||
|
||||
public void setFile_path(String file_path) {
|
||||
this.file_path = file_path;
|
||||
}
|
||||
|
||||
public long getFile_size() {
|
||||
return file_size;
|
||||
}
|
||||
|
||||
public void setFile_size(long file_size) {
|
||||
this.file_size = file_size;
|
||||
}
|
||||
|
||||
public String getFolder() {
|
||||
return folder;
|
||||
}
|
||||
|
||||
public void setFolder(String folder) {
|
||||
this.folder = folder;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getVhost() {
|
||||
return vhost;
|
||||
}
|
||||
|
||||
public void setVhost(String vhost) {
|
||||
this.vhost = vhost;
|
||||
}
|
||||
|
||||
public long getStart_time() {
|
||||
return start_time;
|
||||
}
|
||||
|
||||
public void setStart_time(long start_time) {
|
||||
this.start_time = start_time;
|
||||
}
|
||||
|
||||
public double getTime_len() {
|
||||
return time_len;
|
||||
}
|
||||
|
||||
public void setTime_len(double time_len) {
|
||||
this.time_len = time_len;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OnRecordMp4HookParam{" +
|
||||
"app='" + app + '\'' +
|
||||
", stream='" + stream + '\'' +
|
||||
", file_name='" + file_name + '\'' +
|
||||
", file_path='" + file_path + '\'' +
|
||||
", file_size='" + file_size + '\'' +
|
||||
", folder='" + folder + '\'' +
|
||||
", url='" + url + '\'' +
|
||||
", vhost='" + vhost + '\'' +
|
||||
", start_time=" + start_time +
|
||||
", time_len=" + time_len +
|
||||
'}';
|
||||
}
|
||||
}
|
59
src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java
Executable file
59
src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java
Executable file
@ -0,0 +1,59 @@
|
||||
package com.genersoft.iot.vmp.service;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
|
||||
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
|
||||
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 云端录像管理
|
||||
* @author lin
|
||||
*/
|
||||
public interface ICloudRecordService {
|
||||
|
||||
/**
|
||||
* 分页回去云端录像列表
|
||||
*/
|
||||
PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems);
|
||||
|
||||
/**
|
||||
* 根据hook消息增加一条记录
|
||||
*/
|
||||
void addRecord(OnRecordMp4HookParam param);
|
||||
|
||||
/**
|
||||
* 获取所有的日期
|
||||
*/
|
||||
List<String> getDateList(String app, String stream, int year, int month, List<MediaServerItem> mediaServerItems);
|
||||
|
||||
/**
|
||||
* 添加合并任务
|
||||
*/
|
||||
String addTask(String app, String stream, MediaServerItem mediaServerItem, String startTime,
|
||||
String endTime, String callId, String remoteHost, boolean filterMediaServer);
|
||||
|
||||
|
||||
/**
|
||||
* 查询合并任务列表
|
||||
*/
|
||||
JSONArray queryTask(String app, String stream, String callId, String taskId, String mediaServerId, Boolean isEnd, String scheme);
|
||||
|
||||
/**
|
||||
* 收藏视频,收藏的视频过期不会删除
|
||||
*/
|
||||
int changeCollect(boolean result, String app, String stream, String mediaServerId, String startTime, String endTime, String callId);
|
||||
|
||||
/**
|
||||
* 添加指定录像收藏
|
||||
*/
|
||||
int changeCollectById(Integer recordId, boolean result);
|
||||
|
||||
/**
|
||||
* 获取播放地址
|
||||
*/
|
||||
DownloadFileInfo getPlayUrlPath(Integer recordId);
|
||||
}
|
@ -87,21 +87,12 @@ public interface IMediaServerService {
|
||||
|
||||
void updateMediaServerKeepalive(String mediaServerId, ServerKeepaliveData data);
|
||||
|
||||
boolean checkRtpServer(MediaServerItem mediaServerItem, String rtp, String stream);
|
||||
|
||||
/**
|
||||
* 获取负载信息
|
||||
* @return
|
||||
*/
|
||||
MediaServerLoad getLoad(MediaServerItem mediaServerItem);
|
||||
|
||||
/**
|
||||
* 按时间查找录像文件
|
||||
*/
|
||||
List<RecordFile> getRecords(String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems);
|
||||
List<MediaServerItem> getAllWithAssistPort();
|
||||
|
||||
/**
|
||||
* 查找存在录像文件的时间
|
||||
*/
|
||||
List<String> getRecordDates(String app, String stream, int year, int month, List<MediaServerItem> mediaServerItems);
|
||||
}
|
||||
|
@ -22,11 +22,6 @@ public interface IPlayService {
|
||||
|
||||
MediaServerItem getNewMediaServerItem(Device device);
|
||||
|
||||
/**
|
||||
* 获取包含assist服务的节点
|
||||
*/
|
||||
MediaServerItem getNewMediaServerItemHasAssist(Device device);
|
||||
|
||||
void playBack(String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback);
|
||||
void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback);
|
||||
void zlmServerOffline(String mediaServerId);
|
||||
@ -44,5 +39,4 @@ public interface IPlayService {
|
||||
|
||||
void getSnap(String deviceId, String channelId, String fileName, ErrorCallback errorCallback);
|
||||
|
||||
|
||||
}
|
||||
|
@ -114,4 +114,5 @@ public interface IStreamPushService {
|
||||
* @return
|
||||
*/
|
||||
ResourceBaseInfo getOverview();
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,205 @@
|
||||
package com.genersoft.iot.vmp.service.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
|
||||
|
||||
/**
|
||||
* 云端录像数据
|
||||
*/
|
||||
public class CloudRecordItem {
|
||||
/**
|
||||
* 主键
|
||||
*/
|
||||
private int id;
|
||||
|
||||
/**
|
||||
* 应用名
|
||||
*/
|
||||
private String app;
|
||||
|
||||
/**
|
||||
* 流
|
||||
*/
|
||||
private String stream;
|
||||
|
||||
/**
|
||||
* 健全ID
|
||||
*/
|
||||
private String callId;
|
||||
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
private long startTime;
|
||||
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
private long endTime;
|
||||
|
||||
/**
|
||||
* ZLM Id
|
||||
*/
|
||||
private String mediaServerId;
|
||||
|
||||
/**
|
||||
* 文件名称
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 文件路径
|
||||
*/
|
||||
private String filePath;
|
||||
|
||||
/**
|
||||
* 文件夹
|
||||
*/
|
||||
private String folder;
|
||||
|
||||
/**
|
||||
* 收藏,收藏的文件不移除
|
||||
*/
|
||||
private Boolean collect;
|
||||
|
||||
/**
|
||||
* 保留,收藏的文件不移除
|
||||
*/
|
||||
private Boolean reserve;
|
||||
|
||||
/**
|
||||
* 文件大小
|
||||
*/
|
||||
private long fileSize;
|
||||
|
||||
/**
|
||||
* 文件时长
|
||||
*/
|
||||
private long timeLen;
|
||||
|
||||
public static CloudRecordItem getInstance(OnRecordMp4HookParam param) {
|
||||
CloudRecordItem cloudRecordItem = new CloudRecordItem();
|
||||
cloudRecordItem.setApp(param.getApp());
|
||||
cloudRecordItem.setStream(param.getStream());
|
||||
cloudRecordItem.setStartTime(param.getStart_time()*1000);
|
||||
cloudRecordItem.setFileName(param.getFile_name());
|
||||
cloudRecordItem.setFolder(param.getFolder());
|
||||
cloudRecordItem.setFileSize(param.getFile_size());
|
||||
cloudRecordItem.setFilePath(param.getFile_path());
|
||||
cloudRecordItem.setMediaServerId(param.getMediaServerId());
|
||||
cloudRecordItem.setTimeLen((long) param.getTime_len() * 1000);
|
||||
cloudRecordItem.setEndTime((param.getStart_time() + (long)param.getTime_len()) * 1000);
|
||||
return cloudRecordItem;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void setApp(String app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public String getStream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public void setStream(String stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public String getCallId() {
|
||||
return callId;
|
||||
}
|
||||
|
||||
public void setCallId(String callId) {
|
||||
this.callId = callId;
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setStartTime(long startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public long getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public void setEndTime(long endTime) {
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public String getMediaServerId() {
|
||||
return mediaServerId;
|
||||
}
|
||||
|
||||
public void setMediaServerId(String mediaServerId) {
|
||||
this.mediaServerId = mediaServerId;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public void setFilePath(String filePath) {
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public String getFolder() {
|
||||
return folder;
|
||||
}
|
||||
|
||||
public void setFolder(String folder) {
|
||||
this.folder = folder;
|
||||
}
|
||||
|
||||
public long getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public void setFileSize(long fileSize) {
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
|
||||
public long getTimeLen() {
|
||||
return timeLen;
|
||||
}
|
||||
|
||||
public void setTimeLen(long timeLen) {
|
||||
this.timeLen = timeLen;
|
||||
}
|
||||
|
||||
public Boolean getCollect() {
|
||||
return collect;
|
||||
}
|
||||
|
||||
public void setCollect(Boolean collect) {
|
||||
this.collect = collect;
|
||||
}
|
||||
|
||||
public Boolean getReserve() {
|
||||
return reserve;
|
||||
}
|
||||
|
||||
public void setReserve(Boolean reserve) {
|
||||
this.reserve = reserve;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package com.genersoft.iot.vmp.service.bean;
|
||||
|
||||
public class DownloadFileInfo {
|
||||
|
||||
private String httpPath;
|
||||
private String httpsPath;
|
||||
private String httpDomainPath;
|
||||
private String httpsDomainPath;
|
||||
|
||||
public String getHttpPath() {
|
||||
return httpPath;
|
||||
}
|
||||
|
||||
public void setHttpPath(String httpPath) {
|
||||
this.httpPath = httpPath;
|
||||
}
|
||||
|
||||
public String getHttpsPath() {
|
||||
return httpsPath;
|
||||
}
|
||||
|
||||
public void setHttpsPath(String httpsPath) {
|
||||
this.httpsPath = httpsPath;
|
||||
}
|
||||
|
||||
public String getHttpDomainPath() {
|
||||
return httpDomainPath;
|
||||
}
|
||||
|
||||
public void setHttpDomainPath(String httpDomainPath) {
|
||||
this.httpDomainPath = httpDomainPath;
|
||||
}
|
||||
|
||||
public String getHttpsDomainPath() {
|
||||
return httpsDomainPath;
|
||||
}
|
||||
|
||||
public void setHttpsDomainPath(String httpsDomainPath) {
|
||||
this.httpsDomainPath = httpsDomainPath;
|
||||
}
|
||||
}
|
@ -29,12 +29,12 @@ public class WvpRedisMsg {
|
||||
* 消息的ID
|
||||
*/
|
||||
private String serial;
|
||||
private Object content;
|
||||
private String content;
|
||||
|
||||
private final static String requestTag = "req";
|
||||
private final static String responseTag = "res";
|
||||
|
||||
public static WvpRedisMsg getRequestInstance(String fromId, String toId, String cmd, String serial, Object content) {
|
||||
public static WvpRedisMsg getRequestInstance(String fromId, String toId, String cmd, String serial, String content) {
|
||||
WvpRedisMsg wvpRedisMsg = new WvpRedisMsg();
|
||||
wvpRedisMsg.setType(requestTag);
|
||||
wvpRedisMsg.setFromId(fromId);
|
||||
@ -51,7 +51,7 @@ public class WvpRedisMsg {
|
||||
return wvpRedisMsg;
|
||||
}
|
||||
|
||||
public static WvpRedisMsg getResponseInstance(String fromId, String toId, String cmd, String serial, Object content) {
|
||||
public static WvpRedisMsg getResponseInstance(String fromId, String toId, String cmd, String serial, String content) {
|
||||
WvpRedisMsg wvpRedisMsg = new WvpRedisMsg();
|
||||
wvpRedisMsg.setType(responseTag);
|
||||
wvpRedisMsg.setFromId(fromId);
|
||||
@ -106,11 +106,11 @@ public class WvpRedisMsg {
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
public Object getContent() {
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(Object content) {
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,235 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
|
||||
import com.genersoft.iot.vmp.service.ICloudRecordService;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
|
||||
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
|
||||
import com.genersoft.iot.vmp.utils.CloudRecordUtils;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.*;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@DS("share")
|
||||
public class CloudRecordServiceImpl implements ICloudRecordService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(CloudRecordServiceImpl.class);
|
||||
|
||||
@Autowired
|
||||
private CloudRecordServiceMapper cloudRecordServiceMapper;
|
||||
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private AssistRESTfulUtils assistRESTfulUtils;
|
||||
|
||||
@Autowired
|
||||
private VideoStreamSessionManager streamSession;
|
||||
|
||||
@Override
|
||||
public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems) {
|
||||
// 开始时间和结束时间在数据库中都是以秒为单位的
|
||||
Long startTimeStamp = null;
|
||||
Long endTimeStamp = null;
|
||||
if (startTime != null ) {
|
||||
if (!DateUtil.verification(startTime, DateUtil.formatter)) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "开始时间格式错误,正确格式为: " + DateUtil.formatter);
|
||||
}
|
||||
startTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime);
|
||||
|
||||
}
|
||||
if (endTime != null ) {
|
||||
if (!DateUtil.verification(endTime, DateUtil.formatter)) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "结束时间格式错误,正确格式为: " + DateUtil.formatter);
|
||||
}
|
||||
endTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);
|
||||
|
||||
}
|
||||
PageHelper.startPage(page, count);
|
||||
List<CloudRecordItem> all = cloudRecordServiceMapper.getList(query, app, stream, startTimeStamp, endTimeStamp,
|
||||
null, mediaServerItems);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getDateList(String app, String stream, int year, int month, List<MediaServerItem> mediaServerItems) {
|
||||
LocalDate startDate = LocalDate.of(year, month, 1);
|
||||
LocalDate endDate;
|
||||
if (month == 12) {
|
||||
endDate = LocalDate.of(year + 1, 1, 1);
|
||||
}else {
|
||||
endDate = LocalDate.of(year, month + 1, 1);
|
||||
}
|
||||
long startTimeStamp = startDate.atStartOfDay().toInstant(ZoneOffset.ofHours(8)).getEpochSecond();
|
||||
long endTimeStamp = endDate.atStartOfDay().toInstant(ZoneOffset.ofHours(8)).getEpochSecond();
|
||||
List<CloudRecordItem> cloudRecordItemList = cloudRecordServiceMapper.getList(null, app, stream, startTimeStamp,
|
||||
endTimeStamp, null, mediaServerItems);
|
||||
if (cloudRecordItemList.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Set<String> resultSet = new HashSet<>();
|
||||
cloudRecordItemList.stream().forEach(cloudRecordItem -> {
|
||||
String date = DateUtil.timestampTo_yyyy_MM_dd(cloudRecordItem.getStartTime());
|
||||
resultSet.add(date);
|
||||
});
|
||||
return new ArrayList<>(resultSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRecord(OnRecordMp4HookParam param) {
|
||||
CloudRecordItem cloudRecordItem = CloudRecordItem.getInstance(param);
|
||||
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
|
||||
if (streamAuthorityInfo != null) {
|
||||
cloudRecordItem.setCallId(streamAuthorityInfo.getCallId());
|
||||
}
|
||||
logger.info("[添加录像记录] {}/{} 文件大小:{}, 时长: {}秒", param.getApp(), param.getStream(), param.getFile_size(),param.getTime_len());
|
||||
cloudRecordServiceMapper.add(cloudRecordItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String addTask(String app, String stream, MediaServerItem mediaServerItem, String startTime, String endTime,
|
||||
String callId, String remoteHost, boolean filterMediaServer) {
|
||||
// 参数校验
|
||||
assert app != null;
|
||||
assert stream != null;
|
||||
if (mediaServerItem.getRecordAssistPort() == 0) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "为配置Assist服务");
|
||||
}
|
||||
Long startTimeStamp = null;
|
||||
Long endTimeStamp = null;
|
||||
if (startTime != null) {
|
||||
startTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime);
|
||||
}
|
||||
if (endTime != null) {
|
||||
endTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);
|
||||
}
|
||||
|
||||
List<MediaServerItem> mediaServers = new ArrayList<>();
|
||||
mediaServers.add(mediaServerItem);
|
||||
// 检索相关的录像文件
|
||||
List<String> filePathList = cloudRecordServiceMapper.queryRecordFilePathList(app, stream, startTimeStamp,
|
||||
endTimeStamp, callId, filterMediaServer ? mediaServers : null);
|
||||
if (filePathList == null || filePathList.isEmpty()) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未检索到视频文件");
|
||||
}
|
||||
JSONObject result = assistRESTfulUtils.addTask(mediaServerItem, app, stream, startTime, endTime, callId, filePathList, remoteHost);
|
||||
if (result.getInteger("code") != 0) {
|
||||
throw new ControllerException(result.getInteger("code"), result.getString("msg"));
|
||||
}
|
||||
return result.getString("data");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONArray queryTask(String app, String stream, String callId, String taskId, String mediaServerId,
|
||||
Boolean isEnd, String scheme) {
|
||||
MediaServerItem mediaServerItem = null;
|
||||
if (mediaServerId == null) {
|
||||
mediaServerItem = mediaServerService.getDefaultMediaServer();
|
||||
}else {
|
||||
mediaServerItem = mediaServerService.getOne(mediaServerId);
|
||||
}
|
||||
if (mediaServerItem == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的流媒体");
|
||||
}
|
||||
|
||||
JSONObject result = assistRESTfulUtils.queryTaskList(mediaServerItem, app, stream, callId, taskId, isEnd, scheme);
|
||||
if (result == null || result.getInteger("code") != 0) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), result == null ? "查询任务列表失败" : result.getString("msg"));
|
||||
}
|
||||
return result.getJSONArray("data");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int changeCollect(boolean result, String app, String stream, String mediaServerId, String startTime, String endTime, String callId) {
|
||||
// 开始时间和结束时间在数据库中都是以秒为单位的
|
||||
Long startTimeStamp = null;
|
||||
Long endTimeStamp = null;
|
||||
if (startTime != null ) {
|
||||
if (!DateUtil.verification(startTime, DateUtil.formatter)) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "开始时间格式错误,正确格式为: " + DateUtil.formatter);
|
||||
}
|
||||
startTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime);
|
||||
|
||||
}
|
||||
if (endTime != null ) {
|
||||
if (!DateUtil.verification(endTime, DateUtil.formatter)) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "结束时间格式错误,正确格式为: " + DateUtil.formatter);
|
||||
}
|
||||
endTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);
|
||||
|
||||
}
|
||||
|
||||
List<MediaServerItem> mediaServerItems;
|
||||
if (!ObjectUtils.isEmpty(mediaServerId)) {
|
||||
mediaServerItems = new ArrayList<>();
|
||||
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
|
||||
if (mediaServerItem == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到流媒体: " + mediaServerId);
|
||||
}
|
||||
mediaServerItems.add(mediaServerItem);
|
||||
} else {
|
||||
mediaServerItems = null;
|
||||
}
|
||||
|
||||
List<CloudRecordItem> all = cloudRecordServiceMapper.getList(null, app, stream, startTimeStamp, endTimeStamp,
|
||||
callId, mediaServerItems);
|
||||
if (all.isEmpty()) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到待收藏的视频");
|
||||
}
|
||||
int limitCount = 50;
|
||||
int resultCount = 0;
|
||||
if (all.size() > limitCount) {
|
||||
for (int i = 0; i < all.size(); i += limitCount) {
|
||||
int toIndex = i + limitCount;
|
||||
if (i + limitCount > all.size()) {
|
||||
toIndex = all.size();
|
||||
}
|
||||
resultCount += cloudRecordServiceMapper.updateCollectList(result, all.subList(i, toIndex));
|
||||
|
||||
}
|
||||
}else {
|
||||
resultCount = cloudRecordServiceMapper.updateCollectList(result, all);
|
||||
}
|
||||
return resultCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int changeCollectById(Integer recordId, boolean result) {
|
||||
return cloudRecordServiceMapper.changeCollectById(result, recordId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DownloadFileInfo getPlayUrlPath(Integer recordId) {
|
||||
CloudRecordItem recordItem = cloudRecordServiceMapper.queryOne(recordId);
|
||||
if (recordItem == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "资源不存在");
|
||||
}
|
||||
String filePath = recordItem.getFilePath();
|
||||
MediaServerItem mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId());
|
||||
return CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
|
||||
import com.genersoft.iot.vmp.service.IDeviceAlarmService;
|
||||
@ -12,6 +13,7 @@ import org.springframework.stereotype.Service;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@DS("master")
|
||||
public class DeviceAlarmServiceImpl implements IDeviceAlarmService {
|
||||
|
||||
@Autowired
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
@ -27,6 +28,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
* @author lin
|
||||
*/
|
||||
@Service
|
||||
@DS("master")
|
||||
public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(DeviceChannelServiceImpl.class);
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
@ -45,6 +46,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* 设备业务(目录订阅)
|
||||
*/
|
||||
@Service
|
||||
@DS("master")
|
||||
public class DeviceServiceImpl implements IDeviceService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class);
|
||||
@ -152,6 +154,19 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
sync(device);
|
||||
// TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台
|
||||
}
|
||||
// 上线添加订阅
|
||||
if (device.getSubscribeCycleForCatalog() > 0) {
|
||||
// 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
|
||||
addCatalogSubscribe(device);
|
||||
}
|
||||
if (device.getSubscribeCycleForMobilePosition() > 0) {
|
||||
addMobilePositionSubscribe(device);
|
||||
}
|
||||
if (userSetting.getDeviceStatusNotify()) {
|
||||
// 发送redis消息
|
||||
redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, true);
|
||||
}
|
||||
|
||||
}else {
|
||||
if (deviceChannelMapper.queryAllChannels(device.getDeviceId()).isEmpty()) {
|
||||
logger.info("[设备上线]: {},通道数为0,查询通道信息", device.getDeviceId());
|
||||
@ -164,22 +179,10 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
|
||||
}
|
||||
|
||||
// 上线添加订阅
|
||||
if (device.getSubscribeCycleForCatalog() > 0) {
|
||||
// 查询在线设备那些开启了订阅,为设备开启定时的目录订阅
|
||||
addCatalogSubscribe(device);
|
||||
}
|
||||
if (device.getSubscribeCycleForMobilePosition() > 0) {
|
||||
addMobilePositionSubscribe(device);
|
||||
}
|
||||
// 刷新过期任务
|
||||
String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId();
|
||||
// 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线
|
||||
dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId(), "首次注册后未能收到心跳"), device.getKeepaliveIntervalTime() * 1000 * 3);
|
||||
if (userSetting.getDeviceStatusNotify()) {
|
||||
// 发送redis消息
|
||||
redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, true);
|
||||
}
|
||||
|
||||
//
|
||||
// try {
|
||||
@ -203,6 +206,13 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
}
|
||||
String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + deviceId;
|
||||
dynamicTask.stop(registerExpireTaskKey);
|
||||
if (device.isOnLine()) {
|
||||
if (userSetting.getDeviceStatusNotify()) {
|
||||
// 发送redis消息
|
||||
redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, false);
|
||||
}
|
||||
}
|
||||
|
||||
device.setOnLine(false);
|
||||
redisCatchStorage.updateDevice(device);
|
||||
deviceMapper.update(device);
|
||||
@ -220,11 +230,6 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
// 移除订阅
|
||||
removeCatalogSubscribe(device);
|
||||
removeMobilePositionSubscribe(device);
|
||||
if (userSetting.getDeviceStatusNotify()) {
|
||||
// 发送redis消息
|
||||
redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), null, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -271,7 +276,7 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
// 设置最小值为30
|
||||
int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForMobilePosition(),30);
|
||||
// 刷新订阅
|
||||
dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, (subscribeCycleForCatalog) * 1000);
|
||||
dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog * 1000);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
|
||||
@ -25,6 +26,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@DS("master")
|
||||
public class GbStreamServiceImpl implements IGbStreamService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(GbStreamServiceImpl.class);
|
||||
@ -77,8 +79,6 @@ public class GbStreamServiceImpl implements IGbStreamService {
|
||||
}
|
||||
try {
|
||||
List<DeviceChannel> deviceChannelList = new ArrayList<>();
|
||||
|
||||
|
||||
for (int i = 0; i < gbStreams.size(); i++) {
|
||||
GbStream gbStream = gbStreams.get(i);
|
||||
gbStream.setCatalogId(catalogId);
|
||||
@ -251,18 +251,17 @@ public class GbStreamServiceImpl implements IGbStreamService {
|
||||
return ;
|
||||
}
|
||||
if (ObjectUtils.isEmpty(catalogId)) {
|
||||
catalogId = platform.getDeviceGBId();
|
||||
catalogId = null;
|
||||
}
|
||||
if (platformGbStreamMapper.delByPlatformAndCatalogId(platformId, catalogId) > 0) {
|
||||
List<GbStream> gbStreams = platformGbStreamMapper.queryChannelInParentPlatformAndCatalog(platformId, catalogId);
|
||||
List<DeviceChannel> deviceChannelList = new ArrayList<>();
|
||||
for (GbStream gbStream : gbStreams) {
|
||||
DeviceChannel deviceChannel = new DeviceChannel();
|
||||
deviceChannel.setChannelId(gbStream.getGbId());
|
||||
deviceChannelList.add(deviceChannel);
|
||||
}
|
||||
eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.DEL);
|
||||
List<GbStream> gbStreams = platformGbStreamMapper.queryChannelInParentPlatformAndCatalog(platformId, catalogId);
|
||||
List<DeviceChannel> deviceChannelList = new ArrayList<>();
|
||||
for (GbStream gbStream : gbStreams) {
|
||||
DeviceChannel deviceChannel = new DeviceChannel();
|
||||
deviceChannel.setChannelId(gbStream.getGbId());
|
||||
deviceChannelList.add(deviceChannel);
|
||||
}
|
||||
eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.DEL);
|
||||
platformGbStreamMapper.delByPlatformAndCatalogId(platformId, catalogId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionStatus;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
@ -20,6 +21,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
@Service
|
||||
@DS("master")
|
||||
public class InviteStreamServiceImpl implements IInviteStreamService {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(InviteStreamServiceImpl.class);
|
||||
@ -116,9 +118,12 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
|
||||
":" + (stream != null ? stream : "*")
|
||||
+ ":*";
|
||||
List<Object> scanResult = RedisUtil.scan(redisTemplate, key);
|
||||
if (scanResult.size() != 1) {
|
||||
if (scanResult.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (scanResult.size() != 1) {
|
||||
logger.warn("[获取InviteInfo] 发现 key: {}存在多条", key);
|
||||
}
|
||||
|
||||
return (InviteInfo) redisTemplate.opsForValue().get(scanResult.get(0));
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
|
||||
import com.genersoft.iot.vmp.service.ILogService;
|
||||
import com.genersoft.iot.vmp.storager.dao.LogMapper;
|
||||
@ -12,6 +13,7 @@ import org.springframework.stereotype.Service;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@DS("master")
|
||||
public class LogServiceImpl implements ILogService {
|
||||
|
||||
@Autowired
|
||||
|
@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.service.impl;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.common.CommonCallback;
|
||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
@ -55,6 +56,7 @@ import java.util.concurrent.ExecutionException;
|
||||
* 媒体服务器节点管理
|
||||
*/
|
||||
@Service
|
||||
@DS("master")
|
||||
@RequiredArgsConstructor
|
||||
public class MediaServerServiceImpl implements IMediaServerService {
|
||||
|
||||
@ -309,7 +311,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
|
||||
@Override
|
||||
public MediaServerItem getDefaultMediaServer() {
|
||||
|
||||
return mediaServerMapper.queryDefault();
|
||||
}
|
||||
|
||||
@ -424,17 +425,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
|
||||
|
||||
if (serverItem.isAutoConfig()) {
|
||||
// 查看assist服务的录像路径配置
|
||||
if (serverItem.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) {
|
||||
JSONObject info = assistRESTfulUtils.getInfo(serverItem, null);
|
||||
if (info != null && info.getInteger("code") != null && info.getInteger("code") == 0 ) {
|
||||
JSONObject dataJson = info.getJSONObject("data");
|
||||
if (dataJson != null) {
|
||||
String recordPath = dataJson.getString("record");
|
||||
userSetting.setRecordPath(recordPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable()));
|
||||
}
|
||||
final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId();
|
||||
@ -569,7 +559,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
logger.info("[ZLM] 正在设置 :{} -> {}:{}",
|
||||
mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort());
|
||||
String protocol = sslEnabled ? "https" : "http";
|
||||
String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort);
|
||||
String hookPrefix = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort);
|
||||
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline
|
||||
@ -578,20 +568,21 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
}
|
||||
param.put("hook.enable","1");
|
||||
param.put("hook.on_flow_report","");
|
||||
param.put("hook.on_play",String.format("%s/on_play", hookPrex));
|
||||
param.put("hook.on_play",String.format("%s/on_play", hookPrefix));
|
||||
param.put("hook.on_http_access","");
|
||||
param.put("hook.on_publish", String.format("%s/on_publish", hookPrex));
|
||||
param.put("hook.on_publish", String.format("%s/on_publish", hookPrefix));
|
||||
param.put("hook.on_record_ts","");
|
||||
param.put("hook.on_rtsp_auth","");
|
||||
param.put("hook.on_rtsp_realm","");
|
||||
param.put("hook.on_server_started",String.format("%s/on_server_started", hookPrex));
|
||||
param.put("hook.on_server_started",String.format("%s/on_server_started", hookPrefix));
|
||||
param.put("hook.on_shell_login","");
|
||||
param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrex));
|
||||
param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex));
|
||||
param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex));
|
||||
param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrex));
|
||||
param.put("hook.on_send_rtp_stopped",String.format("%s/on_send_rtp_stopped", hookPrex));
|
||||
param.put("hook.on_rtp_server_timeout",String.format("%s/on_rtp_server_timeout", hookPrex));
|
||||
param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrefix));
|
||||
param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrefix));
|
||||
param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrefix));
|
||||
param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrefix));
|
||||
param.put("hook.on_send_rtp_stopped",String.format("%s/on_send_rtp_stopped", hookPrefix));
|
||||
param.put("hook.on_rtp_server_timeout",String.format("%s/on_rtp_server_timeout", hookPrefix));
|
||||
param.put("hook.on_record_mp4",String.format("%s/on_record_mp4", hookPrefix));
|
||||
if (mediaServerItem.getRecordAssistPort() > 0) {
|
||||
if(mediaConfig.getRecordAssistIp().equals("127.0.0.1")){
|
||||
param.put("hook.on_record_mp4",String.format("http://127.0.0.1:%s/api/record/on_record_mp4", mediaServerItem.getRecordAssistPort()));
|
||||
@ -610,15 +601,14 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
param.put("protocol.continue_push_ms", "3000" );
|
||||
// 最多等待未初始化的Track时间,单位毫秒,超时之后会忽略未初始化的Track, 设置此选项优化那些音频错误的不规范流,
|
||||
// 等zlm支持给每个rtpServer设置关闭音频的时候可以不设置此选项
|
||||
// param.put("general.wait_track_ready_ms", "3000" );
|
||||
if (mediaServerItem.isRtpEnable() && !ObjectUtils.isEmpty(mediaServerItem.getRtpPortRange())) {
|
||||
param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-"));
|
||||
}
|
||||
|
||||
if (userSetting.getRecordPath() != null) {
|
||||
File recordPathFile = new File(userSetting.getRecordPath());
|
||||
File mp4SavePathFile = recordPathFile.getParentFile().getAbsoluteFile();
|
||||
param.put("protocol.mp4_save_path", mp4SavePathFile.getAbsoluteFile());
|
||||
if (!ObjectUtils.isEmpty(mediaServerItem.getRecordPath())) {
|
||||
File recordPathFile = new File(mediaServerItem.getRecordPath());
|
||||
param.put("protocol.mp4_save_path", recordPathFile.getParentFile().getPath());
|
||||
param.put("protocol.downloadRoot", recordPathFile.getParentFile().getPath());
|
||||
param.put("record.appName", recordPathFile.getName());
|
||||
}
|
||||
|
||||
@ -723,6 +713,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null);
|
||||
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId();
|
||||
redisTemplate.opsForValue().set(key, mediaServerItem);
|
||||
resetOnlineServerItem(mediaServerItem);
|
||||
clearRTPServer(mediaServerItem);
|
||||
}
|
||||
final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + mediaServerItem.getId();
|
||||
@ -750,15 +741,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkRtpServer(MediaServerItem mediaServerItem, String app, String stream) {
|
||||
JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, stream);
|
||||
if(rtpInfo.getInteger("code") == 0){
|
||||
return rtpInfo.getBoolean("exist");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaServerLoad getLoad(MediaServerItem mediaServerItem) {
|
||||
MediaServerLoad result = new MediaServerLoad();
|
||||
@ -772,88 +754,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RecordFile> getRecords(String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems) {
|
||||
Assert.notNull(app, "app不存在");
|
||||
Assert.notNull(stream, "stream不存在");
|
||||
Assert.notNull(startTime, "startTime不存在");
|
||||
Assert.notNull(endTime, "endTime不存在");
|
||||
Assert.notEmpty(mediaServerItems, "流媒体列表为空");
|
||||
|
||||
CompletableFuture[] completableFutures = new CompletableFuture[mediaServerItems.size()];
|
||||
for (int i = 0; i < mediaServerItems.size(); i++) {
|
||||
completableFutures[i] = getRecordFilesForOne(app, stream, startTime, endTime, mediaServerItems.get(i));
|
||||
}
|
||||
List<RecordFile> result = new ArrayList<>();
|
||||
for (int i = 0; i < completableFutures.length; i++) {
|
||||
try {
|
||||
List<RecordFile> list = (List<RecordFile>) completableFutures[i].get();
|
||||
if (!list.isEmpty()) {
|
||||
for (int g = 0; g < list.size(); g++) {
|
||||
list.get(g).setMediaServerId(mediaServerItems.get(i).getId());
|
||||
}
|
||||
result.addAll(list);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
Comparator<RecordFile> comparator = Comparator.comparing(RecordFile::getFileName);
|
||||
result.sort(comparator);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRecordDates(String app, String stream, int year, int month, List<MediaServerItem> mediaServerItems) {
|
||||
Assert.notNull(app, "app不存在");
|
||||
Assert.notNull(stream, "stream不存在");
|
||||
Assert.notEmpty(mediaServerItems, "流媒体列表为空");
|
||||
CompletableFuture[] completableFutures = new CompletableFuture[mediaServerItems.size()];
|
||||
|
||||
for (int i = 0; i < mediaServerItems.size(); i++) {
|
||||
completableFutures[i] = getRecordDatesForOne(app, stream, year, month, mediaServerItems.get(i));
|
||||
}
|
||||
List<String> result = new ArrayList<>();
|
||||
CompletableFuture.allOf(completableFutures).join();
|
||||
for (CompletableFuture completableFuture : completableFutures) {
|
||||
try {
|
||||
List<String> list = (List<String>) completableFuture.get();
|
||||
result.addAll(list);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
Collections.sort(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Async
|
||||
public CompletableFuture<List<String>> getRecordDatesForOne(String app, String stream, int year, int month, MediaServerItem mediaServerItem) {
|
||||
JSONObject fileListJson = assistRESTfulUtils.getDateList(mediaServerItem, app, stream, year, month);
|
||||
if (fileListJson != null && !fileListJson.isEmpty()) {
|
||||
if (fileListJson.getString("code") != null && fileListJson.getInteger("code") == 0) {
|
||||
JSONArray data = fileListJson.getJSONArray("data");
|
||||
return CompletableFuture.completedFuture(data.toJavaList(String.class));
|
||||
}
|
||||
}
|
||||
return CompletableFuture.completedFuture(new ArrayList<>());
|
||||
}
|
||||
|
||||
@Async
|
||||
public CompletableFuture<List<RecordFile>> getRecordFilesForOne(String app, String stream, String startTime, String endTime, MediaServerItem mediaServerItem) {
|
||||
JSONObject fileListJson = assistRESTfulUtils.getFileList(mediaServerItem, 1, 100000000, app, stream, startTime, endTime);
|
||||
if (fileListJson != null && !fileListJson.isEmpty()) {
|
||||
if (fileListJson.getString("code") != null && fileListJson.getInteger("code") == 0) {
|
||||
JSONObject data = fileListJson.getJSONObject("data");
|
||||
JSONArray list = data.getJSONArray("list");
|
||||
if (list != null) {
|
||||
return CompletableFuture.completedFuture(list.toJavaList(RecordFile.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
return CompletableFuture.completedFuture(new ArrayList<>());
|
||||
public List<MediaServerItem> getAllWithAssistPort() {
|
||||
return mediaServerMapper.queryAllWithAssistPort();
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public class MediaServiceImpl implements IMediaService {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
JSONObject mediaJSON = JSON.parseObject(JSON.toJSONString(data.get(0)), JSONObject.class);
|
||||
JSONObject mediaJSON = data.getJSONObject(0);
|
||||
JSONArray tracks = mediaJSON.getJSONArray("tracks");
|
||||
if (authority) {
|
||||
streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr, calld);
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
|
||||
import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
|
||||
@ -27,6 +28,7 @@ import java.util.Map;
|
||||
* @author lin
|
||||
*/
|
||||
@Service
|
||||
@DS("master")
|
||||
public class PlatformChannelServiceImpl implements IPlatformChannelService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(PlatformChannelServiceImpl.class);
|
||||
@ -165,10 +167,9 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
|
||||
catalogId = null;
|
||||
}
|
||||
|
||||
if ((result = platformChannelMapper.delChannelForGBByCatalogId(platformId, catalogId)) > 0) {
|
||||
List<DeviceChannel> deviceChannels = platformChannelMapper.queryAllChannelInCatalog(platformId, catalogId);
|
||||
eventPublisher.catalogEventPublish(platformId, deviceChannels, CatalogEvent.DEL);
|
||||
}
|
||||
return result;
|
||||
List<DeviceChannel> deviceChannels = platformChannelMapper.queryAllChannelInCatalog(platformId, catalogId);
|
||||
eventPublisher.catalogEventPublish(platformId, deviceChannels, CatalogEvent.DEL);
|
||||
|
||||
return platformChannelMapper.delChannelForGBByCatalogId(platformId, catalogId);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
@ -38,6 +39,7 @@ import java.util.*;
|
||||
* @author lin
|
||||
*/
|
||||
@Service
|
||||
@DS("master")
|
||||
public class PlatformServiceImpl implements IPlatformService {
|
||||
|
||||
private final static String REGISTER_KEY_PREFIX = "platform_register_";
|
||||
@ -149,7 +151,7 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
dynamicTask.stop(registerTaskKey);
|
||||
// 注销旧的
|
||||
try {
|
||||
if (parentPlatformOld.isStatus()) {
|
||||
if (parentPlatformOld.isStatus() && parentPlatformCatchOld != null) {
|
||||
logger.info("保存平台{}时发现旧平台在线,发送注销命令", parentPlatformOld.getServerGBId());
|
||||
commanderForPlatform.unregister(parentPlatformOld, parentPlatformCatchOld.getSipTransactionInfo(), null, eventResult -> {
|
||||
logger.info("[国标级联] 注销成功, 平台:{}", parentPlatformOld.getServerGBId());
|
||||
@ -266,6 +268,7 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
}
|
||||
if (parentPlatform.isAutoPushChannel()) {
|
||||
if (subscribeHolder.getCatalogSubscribe(parentPlatform.getServerGBId()) == null) {
|
||||
logger.info("[国标级联]:{}, 添加自动通道推送模拟订阅信息", parentPlatform.getServerGBId());
|
||||
addSimulatedSubscribeInfo(parentPlatform);
|
||||
}
|
||||
}else {
|
||||
@ -344,9 +347,16 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
// 清除心跳任务
|
||||
dynamicTask.stop(keepaliveTaskKey);
|
||||
}
|
||||
// 停止目录订阅回复
|
||||
logger.info("[平台离线] {}, 停止订阅回复", parentPlatform.getServerGBId());
|
||||
subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
|
||||
// 停止订阅回复
|
||||
SubscribeInfo catalogSubscribe = subscribeHolder.getCatalogSubscribe(parentPlatform.getServerGBId());
|
||||
if (catalogSubscribe != null) {
|
||||
if (catalogSubscribe.getExpires() > 0) {
|
||||
logger.info("[平台离线] {}, 停止目录订阅回复", parentPlatform.getServerGBId());
|
||||
subscribeHolder.removeCatalogSubscribe(parentPlatform.getServerGBId());
|
||||
}
|
||||
}
|
||||
logger.info("[平台离线] {}, 停止移动位置订阅回复", parentPlatform.getServerGBId());
|
||||
subscribeHolder.removeMobilePositionSubscribe(parentPlatform.getServerGBId());
|
||||
// 发起定时自动重新注册
|
||||
if (!stopRegister) {
|
||||
// 设置为60秒自动尝试重新注册
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionStatus;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
@ -13,25 +15,22 @@ import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.*;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
|
||||
import com.genersoft.iot.vmp.service.*;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
|
||||
import com.genersoft.iot.vmp.service.bean.*;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper;
|
||||
import com.genersoft.iot.vmp.utils.CloudRecordUtils;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
@ -56,6 +55,7 @@ import java.util.Vector;
|
||||
|
||||
@SuppressWarnings(value = {"rawtypes", "unchecked"})
|
||||
@Service
|
||||
@DS("master")
|
||||
public class PlayServiceImpl implements IPlayService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(PlayServiceImpl.class);
|
||||
@ -76,7 +76,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
private IInviteStreamService inviteStreamService;
|
||||
|
||||
@Autowired
|
||||
private DeferredResultHolder resultHolder;
|
||||
private ZlmHttpHookSubscribe subscribe;
|
||||
|
||||
@Autowired
|
||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||
@ -84,9 +84,6 @@ public class PlayServiceImpl implements IPlayService {
|
||||
@Autowired
|
||||
private ZLMServerFactory zlmServerFactory;
|
||||
|
||||
@Autowired
|
||||
private AssistRESTfulUtils assistRESTfulUtils;
|
||||
|
||||
@Autowired
|
||||
private IMediaService mediaService;
|
||||
|
||||
@ -106,7 +103,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
private DynamicTask dynamicTask;
|
||||
|
||||
@Autowired
|
||||
private ZlmHttpHookSubscribe subscribe;
|
||||
private CloudRecordServiceMapper cloudRecordServiceMapper;
|
||||
|
||||
|
||||
@Override
|
||||
@ -444,23 +441,6 @@ public class PlayServiceImpl implements IPlayService {
|
||||
return mediaServerItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaServerItem getNewMediaServerItemHasAssist(Device device) {
|
||||
if (device == null) {
|
||||
return null;
|
||||
}
|
||||
MediaServerItem mediaServerItem;
|
||||
if (ObjectUtils.isEmpty(device.getMediaServerId()) || "auto".equals(device.getMediaServerId())) {
|
||||
mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(true);
|
||||
} else {
|
||||
mediaServerItem = mediaServerService.getOne(device.getMediaServerId());
|
||||
}
|
||||
if (mediaServerItem == null) {
|
||||
logger.warn("[获取可用的ZLM节点]未找到可使用的ZLM...");
|
||||
}
|
||||
return mediaServerItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playBack(String deviceId, String channelId, String startTime,
|
||||
String endTime, ErrorCallback<Object> callback) {
|
||||
@ -678,7 +658,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
if (device == null) {
|
||||
return;
|
||||
}
|
||||
MediaServerItem newMediaServerItem = getNewMediaServerItemHasAssist(device);
|
||||
MediaServerItem newMediaServerItem = this.getNewMediaServerItem(device);
|
||||
if (newMediaServerItem == null) {
|
||||
callback.run(InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getCode(),
|
||||
InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getMsg(),
|
||||
@ -759,6 +739,28 @@ public class PlayServiceImpl implements IPlayService {
|
||||
// 处理收到200ok后的TCP主动连接以及SSRC不一致的问题
|
||||
InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channelId,
|
||||
downLoadTimeOutTaskKey, callback, inviteInfo, InviteSessionType.DOWNLOAD);
|
||||
|
||||
// 注册录像回调事件,录像下载结束后写入下载地址
|
||||
ZlmHttpHookSubscribe.Event hookEventForRecord = (mediaServerItemInuse, hookParam) -> {
|
||||
logger.info("[录像下载] 收到录像写入磁盘消息: , {}/{}-{}",
|
||||
inviteInfo.getDeviceId(), inviteInfo.getChannelId(), ssrcInfo.getStream());
|
||||
logger.info("[录像下载] 收到录像写入磁盘消息内容: " + hookParam);
|
||||
OnRecordMp4HookParam recordMp4HookParam = (OnRecordMp4HookParam)hookParam;
|
||||
String filePath = recordMp4HookParam.getFile_path();
|
||||
DownloadFileInfo downloadFileInfo = CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath);
|
||||
InviteInfo inviteInfoForNew = inviteStreamService.getInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId()
|
||||
, inviteInfo.getChannelId(), inviteInfo.getStream());
|
||||
inviteInfoForNew.getStreamInfo().setDownLoadFilePath(downloadFileInfo);
|
||||
inviteStreamService.updateInviteInfo(inviteInfoForNew);
|
||||
};
|
||||
HookSubscribeForRecordMp4 hookSubscribe = HookSubscribeFactory.on_record_mp4(
|
||||
mediaServerItem.getId(), "rtp", ssrcInfo.getStream());
|
||||
|
||||
// 设置过期时间,下载失败时自动处理订阅数据
|
||||
// long difference = DateUtil.getDifference(startTime, endTime)/1000;
|
||||
// Instant expiresInstant = Instant.now().plusSeconds(TimeUnit.MINUTES.toSeconds(difference * 2));
|
||||
// hookSubscribe.setExpires(expiresInstant);
|
||||
subscribe.addSubscribe(hookSubscribe, hookEventForRecord);
|
||||
});
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
logger.error("[命令发送失败] 录像下载: {}", e.getMessage());
|
||||
@ -774,47 +776,71 @@ public class PlayServiceImpl implements IPlayService {
|
||||
@Override
|
||||
public StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream) {
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, stream);
|
||||
if (inviteInfo == null || inviteInfo.getStreamInfo() == null) {
|
||||
logger.warn("[获取下载进度] 未查询到录像下载的信息");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (inviteInfo != null && inviteInfo.getStreamInfo() != null) {
|
||||
if (inviteInfo.getStreamInfo().getProgress() == 1) {
|
||||
return inviteInfo.getStreamInfo();
|
||||
}
|
||||
|
||||
// 获取当前已下载时长
|
||||
String mediaServerId = inviteInfo.getStreamInfo().getMediaServerId();
|
||||
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
|
||||
if (mediaServerItem == null) {
|
||||
logger.warn("查询录像信息时发现节点已离线");
|
||||
return null;
|
||||
}
|
||||
if (mediaServerItem.getRecordAssistPort() > 0) {
|
||||
JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, inviteInfo.getStreamInfo().getApp(), inviteInfo.getStreamInfo().getStream(), null);
|
||||
if (jsonObject == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "连接Assist服务失败");
|
||||
}
|
||||
if (jsonObject.getInteger("code") == 0) {
|
||||
long duration = jsonObject.getLong("data");
|
||||
|
||||
if (duration == 0) {
|
||||
inviteInfo.getStreamInfo().setProgress(0);
|
||||
} else {
|
||||
String startTime = inviteInfo.getStreamInfo().getStartTime();
|
||||
String endTime = inviteInfo.getStreamInfo().getEndTime();
|
||||
long start = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime);
|
||||
long end = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);
|
||||
|
||||
BigDecimal currentCount = new BigDecimal(duration / 1000);
|
||||
BigDecimal totalCount = new BigDecimal(end - start);
|
||||
BigDecimal divide = currentCount.divide(totalCount, 2, RoundingMode.HALF_UP);
|
||||
double process = divide.doubleValue();
|
||||
inviteInfo.getStreamInfo().setProgress(process);
|
||||
}
|
||||
inviteStreamService.updateInviteInfo(inviteInfo);
|
||||
}
|
||||
}
|
||||
if (inviteInfo.getStreamInfo().getProgress() == 1) {
|
||||
return inviteInfo.getStreamInfo();
|
||||
}
|
||||
return null;
|
||||
|
||||
// 获取当前已下载时长
|
||||
String mediaServerId = inviteInfo.getStreamInfo().getMediaServerId();
|
||||
MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
|
||||
if (mediaServerItem == null) {
|
||||
logger.warn("[获取下载进度] 查询录像信息时发现节点不存在");
|
||||
return null;
|
||||
}
|
||||
SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, null, stream);
|
||||
|
||||
if (ssrcTransaction == null) {
|
||||
logger.warn("[获取下载进度] 下载已结束");
|
||||
return null;
|
||||
}
|
||||
|
||||
JSONObject mediaListJson= zlmresTfulUtils.getMediaList(mediaServerItem, "rtp", stream);
|
||||
if (mediaListJson == null) {
|
||||
logger.warn("[获取下载进度] 从zlm查询进度失败");
|
||||
return null;
|
||||
}
|
||||
if (mediaListJson.getInteger("code") != 0) {
|
||||
logger.warn("[获取下载进度] 从zlm查询进度出现错误: {}", mediaListJson.getString("msg"));
|
||||
return null;
|
||||
}
|
||||
JSONArray data = mediaListJson.getJSONArray("data");
|
||||
if (data == null) {
|
||||
logger.warn("[获取下载进度] 从zlm查询进度时未返回数据");
|
||||
return null;
|
||||
}
|
||||
JSONObject mediaJSON = data.getJSONObject(0);
|
||||
JSONArray tracks = mediaJSON.getJSONArray("tracks");
|
||||
if (tracks.isEmpty()) {
|
||||
logger.warn("[获取下载进度] 从zlm查询进度时未返回数据");
|
||||
return null;
|
||||
}
|
||||
JSONObject jsonObject = tracks.getJSONObject(0);
|
||||
long duration = jsonObject.getLongValue("duration");
|
||||
if (duration == 0) {
|
||||
inviteInfo.getStreamInfo().setProgress(0);
|
||||
} else {
|
||||
String startTime = inviteInfo.getStreamInfo().getStartTime();
|
||||
String endTime = inviteInfo.getStreamInfo().getEndTime();
|
||||
// 此时start和end单位是秒
|
||||
long start = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime);
|
||||
long end = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);
|
||||
|
||||
BigDecimal currentCount = new BigDecimal(duration);
|
||||
BigDecimal totalCount = new BigDecimal((end - start) * 1000);
|
||||
BigDecimal divide = currentCount.divide(totalCount, 2, RoundingMode.HALF_UP);
|
||||
double process = divide.doubleValue();
|
||||
if (process > 0.999) {
|
||||
process = 1.0;
|
||||
}
|
||||
inviteInfo.getStreamInfo().setProgress(process);
|
||||
}
|
||||
inviteStreamService.updateInviteInfo(inviteInfo);
|
||||
return inviteInfo.getStreamInfo();
|
||||
}
|
||||
|
||||
private StreamInfo onPublishHandlerForDownload(MediaServerItem mediaServerItemInuse, HookParam hookParam, String deviceId, String channelId, String startTime, String endTime) {
|
||||
@ -948,7 +974,12 @@ public class PlayServiceImpl implements IPlayService {
|
||||
throw new ServiceException("mediaServer不存在");
|
||||
}
|
||||
// zlm 暂停RTP超时检查
|
||||
JSONObject jsonObject = zlmresTfulUtils.pauseRtpCheck(mediaServerItem, streamId);
|
||||
// 使用zlm中的流ID
|
||||
String streamKey = inviteInfo.getStream();
|
||||
if (!mediaServerItem.isRtpEnable()) {
|
||||
streamKey = Long.toHexString(Long.parseLong(inviteInfo.getSsrcInfo().getSsrc())).toUpperCase();
|
||||
}
|
||||
JSONObject jsonObject = zlmresTfulUtils.pauseRtpCheck(mediaServerItem, streamKey);
|
||||
if (jsonObject == null || jsonObject.getInteger("code") != 0) {
|
||||
throw new ServiceException("暂停RTP接收失败");
|
||||
}
|
||||
@ -971,7 +1002,12 @@ public class PlayServiceImpl implements IPlayService {
|
||||
throw new ServiceException("mediaServer不存在");
|
||||
}
|
||||
// zlm 暂停RTP超时检查
|
||||
JSONObject jsonObject = zlmresTfulUtils.resumeRtpCheck(mediaServerItem, streamId);
|
||||
// 使用zlm中的流ID
|
||||
String streamKey = inviteInfo.getStream();
|
||||
if (!mediaServerItem.isRtpEnable()) {
|
||||
streamKey = Long.toHexString(Long.parseLong(inviteInfo.getSsrcInfo().getSsrc())).toUpperCase();
|
||||
}
|
||||
JSONObject jsonObject = zlmresTfulUtils.resumeRtpCheck(mediaServerItem, streamKey);
|
||||
if (jsonObject == null || jsonObject.getInteger("code") != 0) {
|
||||
throw new ServiceException("继续RTP接收失败");
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.service.IRoleService;
|
||||
import com.genersoft.iot.vmp.storager.dao.RoleMapper;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.Role;
|
||||
@ -9,6 +10,7 @@ import org.springframework.stereotype.Service;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@DS("master")
|
||||
public class RoleServerImpl implements IRoleService {
|
||||
|
||||
@Autowired
|
||||
|
@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.common.GeneralCallback;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
@ -53,6 +54,7 @@ import java.util.stream.Collectors;
|
||||
* 视频代理业务
|
||||
*/
|
||||
@Service
|
||||
@DS("master")
|
||||
public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(StreamProxyServiceImpl.class);
|
||||
@ -132,7 +134,13 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
}
|
||||
JSONArray dataArray = jsonObject.getJSONArray("data");
|
||||
JSONObject mediaServerConfig = dataArray.getJSONObject(0);
|
||||
if (ObjectUtils.isEmpty(param.getFfmpegCmdKey())) {
|
||||
param.setFfmpegCmdKey("ffmpeg.cmd");
|
||||
}
|
||||
String ffmpegCmd = mediaServerConfig.getString(param.getFfmpegCmdKey());
|
||||
if (ffmpegCmd == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "ffmpeg拉流代理无法获取ffmpeg cmd");
|
||||
}
|
||||
String schema = getSchemaFromFFmpegCmd(ffmpegCmd);
|
||||
if (schema == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "ffmpeg拉流代理无法从ffmpeg cmd中获取到输出格式");
|
||||
@ -460,7 +468,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
streamProxyMapper.deleteAutoRemoveItemByMediaServerId(mediaServerId);
|
||||
|
||||
// 移除拉流代理生成的流信息
|
||||
// syncPullStream(mediaServerId);
|
||||
syncPullStream(mediaServerId);
|
||||
|
||||
// 恢复流代理, 只查找这个这个流媒体
|
||||
List<StreamProxyItem> streamProxyListForEnable = storager.getStreamProxyListForEnableInMediaServer(
|
||||
|
@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.alibaba.fastjson2.TypeReference;
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.conf.MediaConfig;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
@ -36,6 +37,7 @@ import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@DS("master")
|
||||
public class StreamPushServiceImpl implements IStreamPushService {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(StreamPushServiceImpl.class);
|
||||
@ -282,6 +284,8 @@ public class StreamPushServiceImpl implements IStreamPushService {
|
||||
redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
|
||||
// 移除redis内流的信息
|
||||
redisCatchStorage.removeStream(mediaServerItem.getId(), "PUSH", offlineOnStreamChangedHookParam.getApp(), offlineOnStreamChangedHookParam.getStream());
|
||||
// 冗余数据,自己系统中自用
|
||||
redisCatchStorage.removePushListItem(offlineOnStreamChangedHookParam.getApp(), offlineOnStreamChangedHookParam.getStream(), mediaServerItem.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,6 +323,9 @@ public class StreamPushServiceImpl implements IStreamPushService {
|
||||
jsonObject.put("register", false);
|
||||
jsonObject.put("mediaServerId", mediaServerId);
|
||||
redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
|
||||
|
||||
// 冗余数据,自己系统中自用
|
||||
redisCatchStorage.removePushListItem(onStreamChangedHookParam.getApp(), onStreamChangedHookParam.getStream(), mediaServerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.service.IUserService;
|
||||
import com.genersoft.iot.vmp.storager.dao.UserMapper;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.User;
|
||||
@ -12,6 +13,7 @@ import org.springframework.util.DigestUtils;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@DS("master")
|
||||
public class UserServiceImpl implements IUserService {
|
||||
|
||||
@Autowired
|
||||
|
@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.*;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||
import org.slf4j.Logger;
|
||||
@ -77,6 +78,9 @@ public class RedisGbPlayMsgListener implements MessageListener {
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
|
||||
@Autowired
|
||||
private DynamicTask dynamicTask;
|
||||
@ -113,8 +117,8 @@ public class RedisGbPlayMsgListener implements MessageListener {
|
||||
while (!taskQueue.isEmpty()) {
|
||||
Message msg = taskQueue.poll();
|
||||
try {
|
||||
JSONObject msgJSON = JSON.parseObject(msg.getBody(), JSONObject.class);
|
||||
WvpRedisMsg wvpRedisMsg = JSON.to(WvpRedisMsg.class, msgJSON);
|
||||
WvpRedisMsg wvpRedisMsg = JSON.parseObject(msg.getBody(), WvpRedisMsg.class);
|
||||
logger.info("[收到REDIS通知] 消息: {}", JSON.toJSONString(wvpRedisMsg));
|
||||
if (!userSetting.getServerId().equals(wvpRedisMsg.getToId())) {
|
||||
continue;
|
||||
}
|
||||
@ -123,7 +127,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
|
||||
|
||||
switch (wvpRedisMsg.getCmd()){
|
||||
case WvpRedisMsgCmd.GET_SEND_ITEM:
|
||||
RequestSendItemMsg content = JSON.to(RequestSendItemMsg.class, wvpRedisMsg.getContent());
|
||||
RequestSendItemMsg content = JSON.parseObject(wvpRedisMsg.getContent(), RequestSendItemMsg.class);
|
||||
requestSendItemMsgHand(content, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial());
|
||||
break;
|
||||
case WvpRedisMsgCmd.REQUEST_PUSH_STREAM:
|
||||
@ -242,7 +246,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
|
||||
result.setData(content);
|
||||
|
||||
WvpRedisMsg response = WvpRedisMsg.getResponseInstance(userSetting.getServerId(), toId,
|
||||
WvpRedisMsgCmd.REQUEST_PUSH_STREAM, serial, result);
|
||||
WvpRedisMsgCmd.REQUEST_PUSH_STREAM, serial, JSON.toJSONString(result));
|
||||
JSONObject jsonObject = (JSONObject)JSON.toJSON(response);
|
||||
redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
|
||||
}
|
||||
@ -260,7 +264,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
|
||||
result.setMsg("流媒体不存在");
|
||||
|
||||
WvpRedisMsg response = WvpRedisMsg.getResponseInstance(userSetting.getServerId(), toId,
|
||||
WvpRedisMsgCmd.GET_SEND_ITEM, serial, result);
|
||||
WvpRedisMsgCmd.GET_SEND_ITEM, serial, JSON.toJSONString(result));
|
||||
|
||||
JSONObject jsonObject = (JSONObject)JSON.toJSON(response);
|
||||
redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
|
||||
@ -283,7 +287,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
|
||||
WVPResult<SendRtpItem> result = new WVPResult<>();
|
||||
result.setCode(ERROR_CODE_TIMEOUT);
|
||||
WvpRedisMsg response = WvpRedisMsg.getResponseInstance(
|
||||
userSetting.getServerId(), toId, WvpRedisMsgCmd.GET_SEND_ITEM, serial, result
|
||||
userSetting.getServerId(), toId, WvpRedisMsgCmd.GET_SEND_ITEM, serial, JSON.toJSONString(result)
|
||||
);
|
||||
JSONObject jsonObject = (JSONObject)JSON.toJSON(response);
|
||||
redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
|
||||
@ -322,9 +326,10 @@ public class RedisGbPlayMsgListener implements MessageListener {
|
||||
responseSendItemMsg.setSendRtpItem(sendRtpItem);
|
||||
responseSendItemMsg.setMediaServerItem(mediaServerItem);
|
||||
result.setData(responseSendItemMsg);
|
||||
redisCatchStorage.updateSendRTPSever(sendRtpItem);
|
||||
|
||||
WvpRedisMsg response = WvpRedisMsg.getResponseInstance(
|
||||
userSetting.getServerId(), toId, WvpRedisMsgCmd.GET_SEND_ITEM, serial, result
|
||||
userSetting.getServerId(), toId, WvpRedisMsgCmd.GET_SEND_ITEM, serial, JSON.toJSONString(result)
|
||||
);
|
||||
JSONObject jsonObject = (JSONObject)JSON.toJSON(response);
|
||||
redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
|
||||
@ -350,7 +355,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
|
||||
requestSendItemMsg.setServerId(serverId);
|
||||
String key = UUID.randomUUID().toString();
|
||||
WvpRedisMsg redisMsg = WvpRedisMsg.getRequestInstance(userSetting.getServerId(), serverId, WvpRedisMsgCmd.GET_SEND_ITEM,
|
||||
key, requestSendItemMsg);
|
||||
key, JSON.toJSONString(requestSendItemMsg));
|
||||
|
||||
JSONObject jsonObject = (JSONObject)JSON.toJSON(redisMsg);
|
||||
logger.info("[请求推流SendItem] {}: {}", serverId, jsonObject);
|
||||
@ -375,7 +380,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
|
||||
public void sendMsgForStartSendRtpStream(String serverId, RequestPushStreamMsg param, PlayMsgCallbackForStartSendRtpStream callback) {
|
||||
String key = UUID.randomUUID().toString();
|
||||
WvpRedisMsg redisMsg = WvpRedisMsg.getRequestInstance(userSetting.getServerId(), serverId,
|
||||
WvpRedisMsgCmd.REQUEST_PUSH_STREAM, key, param);
|
||||
WvpRedisMsgCmd.REQUEST_PUSH_STREAM, key, JSON.toJSONString(param));
|
||||
|
||||
JSONObject jsonObject = (JSONObject)JSON.toJSON(redisMsg);
|
||||
logger.info("[REDIS 请求其他平台推流] {}: {}", serverId, jsonObject);
|
||||
|
@ -50,11 +50,12 @@ public class RedisGpsMsgListener implements MessageListener {
|
||||
Message msg = taskQueue.poll();
|
||||
try {
|
||||
GPSMsgInfo gpsMsgInfo = JSON.parseObject(msg.getBody(), GPSMsgInfo.class);
|
||||
logger.info("[REDIS的位置变化通知], {}", JSON.toJSONString(gpsMsgInfo));
|
||||
// 只是放入redis缓存起来
|
||||
redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo);
|
||||
}catch (Exception e) {
|
||||
logger.warn("[REDIS的ALARM通知] 发现未处理的异常, \r\n{}", JSON.toJSONString(message));
|
||||
logger.error("[REDIS的ALARM通知] 异常内容: ", e);
|
||||
logger.warn("[REDIS的位置变化通知] 发现未处理的异常, \r\n{}", JSON.toJSONString(message));
|
||||
logger.error("[REDIS的位置变化通知] 异常内容: ", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -73,12 +73,20 @@ public class RedisPushStreamCloseResponseListener implements MessageListener {
|
||||
MessageForPushChannel pushChannel = JSON.parseObject(message.getBody(), MessageForPushChannel.class);
|
||||
StreamPushItem push = streamPushService.getPush(pushChannel.getApp(), pushChannel.getStream());
|
||||
if (push != null) {
|
||||
if (redisCatchStorage.isChannelSendingRTP(push.getGbId())) {
|
||||
List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId(
|
||||
push.getGbId());
|
||||
if (sendRtpItems.size() > 0) {
|
||||
for (SendRtpItem sendRtpItem : sendRtpItems) {
|
||||
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
|
||||
List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId(
|
||||
push.getGbId());
|
||||
if (!sendRtpItems.isEmpty()) {
|
||||
for (SendRtpItem sendRtpItem : sendRtpItems) {
|
||||
ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
|
||||
if (parentPlatform != null) {
|
||||
redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), sendRtpItem.getCallId(), sendRtpItem.getStreamId());
|
||||
try {
|
||||
commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
if (push.isSelf()) {
|
||||
// 停止向上级推流
|
||||
String streamId = sendRtpItem.getStreamId();
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
@ -90,12 +98,6 @@ public class RedisPushStreamCloseResponseListener implements MessageListener {
|
||||
MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
|
||||
redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), sendRtpItem.getCallId(), sendRtpItem.getStreamId());
|
||||
zlmServerFactory.stopSendRtpStream(mediaInfo, param);
|
||||
|
||||
try {
|
||||
commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
|
||||
}
|
||||
if (InviteStreamType.PUSH == sendRtpItem.getPlayType()) {
|
||||
MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
|
||||
sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(),
|
||||
|
@ -208,4 +208,8 @@ public interface IRedisCatchStorage {
|
||||
void sendPlatformStartPlayMsg(MessageForPushChannel messageForPushChannel);
|
||||
|
||||
void sendPlatformStopPlayMsg(MessageForPushChannel messageForPushChannel);
|
||||
|
||||
void addPushListItem(String app, String stream, OnStreamChangedHookParam param);
|
||||
|
||||
void removePushListItem(String app, String stream, String mediaServerId);
|
||||
}
|
||||
|
@ -0,0 +1,122 @@
|
||||
package com.genersoft.iot.vmp.storager.dao;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
|
||||
import org.apache.ibatis.annotations.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface CloudRecordServiceMapper {
|
||||
|
||||
@Insert(" <script>" +
|
||||
"INSERT INTO wvp_cloud_record (" +
|
||||
" app," +
|
||||
" stream," +
|
||||
"<if test=\"callId != null\"> call_id,</if>" +
|
||||
" start_time," +
|
||||
" end_time," +
|
||||
" media_server_id," +
|
||||
" file_name," +
|
||||
" folder," +
|
||||
" file_path," +
|
||||
" file_size," +
|
||||
" time_len ) " +
|
||||
"VALUES (" +
|
||||
" #{app}," +
|
||||
" #{stream}," +
|
||||
" <if test=\"callId != null\"> #{callId},</if>" +
|
||||
" #{startTime}," +
|
||||
" #{endTime}," +
|
||||
" #{mediaServerId}," +
|
||||
" #{fileName}," +
|
||||
" #{folder}," +
|
||||
" #{filePath}," +
|
||||
" #{fileSize}," +
|
||||
" #{timeLen})" +
|
||||
" </script>")
|
||||
int add(CloudRecordItem cloudRecordItem);
|
||||
|
||||
@Select(" <script>" +
|
||||
"select * " +
|
||||
" from wvp_cloud_record " +
|
||||
" where 0 = 0" +
|
||||
" <if test='query != null'> AND (app LIKE concat('%',#{query},'%') OR stream LIKE concat('%',#{query},'%') )</if> " +
|
||||
" <if test= 'app != null '> and app=#{app}</if>" +
|
||||
" <if test= 'stream != null '> and stream=#{stream}</if>" +
|
||||
" <if test= 'startTimeStamp != null '> and end_time >= #{startTimeStamp}</if>" +
|
||||
" <if test= 'endTimeStamp != null '> and start_time <= #{endTimeStamp}</if>" +
|
||||
" <if test= 'callId != null '> and call_id = #{callId}</if>" +
|
||||
" <if test= 'mediaServerItemList != null ' > and media_server_id in " +
|
||||
" <foreach collection='mediaServerItemList' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
|
||||
" </if>" +
|
||||
" order by start_time DESC" +
|
||||
|
||||
" </script>")
|
||||
List<CloudRecordItem> getList(@Param("query") String query, @Param("app") String app, @Param("stream") String stream,
|
||||
@Param("startTimeStamp")Long startTimeStamp, @Param("endTimeStamp")Long endTimeStamp,
|
||||
@Param("callId")String callId, List<MediaServerItem> mediaServerItemList);
|
||||
|
||||
|
||||
@Select(" <script>" +
|
||||
"select file_path" +
|
||||
" from wvp_cloud_record " +
|
||||
" where 0 = 0" +
|
||||
" <if test= 'app != null '> and app=#{app}</if>" +
|
||||
" <if test= 'stream != null '> and stream=#{stream}</if>" +
|
||||
" <if test= 'startTimeStamp != null '> and end_time >= #{startTimeStamp}</if>" +
|
||||
" <if test= 'endTimeStamp != null '> and start_time <= #{endTimeStamp}</if>" +
|
||||
" <if test= 'callId != null '> and call_id = #{callId}</if>" +
|
||||
" <if test= 'mediaServerItemList != null ' > and media_server_id in " +
|
||||
" <foreach collection='mediaServerItemList' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
|
||||
" </if>" +
|
||||
" </script>")
|
||||
List<String> queryRecordFilePathList(@Param("app") String app, @Param("stream") String stream,
|
||||
@Param("startTimeStamp")Long startTimeStamp, @Param("endTimeStamp")Long endTimeStamp,
|
||||
@Param("callId")String callId, List<MediaServerItem> mediaServerItemList);
|
||||
|
||||
@Update(" <script>" +
|
||||
"update wvp_cloud_record set collect = #{collect} where file_path in " +
|
||||
" <foreach collection='cloudRecordItemList' item='item' open='(' separator=',' close=')' > #{item.filePath}</foreach>" +
|
||||
" </script>")
|
||||
int updateCollectList(@Param("collect") boolean collect, List<CloudRecordItem> cloudRecordItemList);
|
||||
|
||||
@Delete(" <script>" +
|
||||
"delete from wvp_cloud_record where media_server_id=#{mediaServerId} and file_path in " +
|
||||
" <foreach collection='filePathList' item='item' open='(' separator=',' close=')' > #{item}</foreach>" +
|
||||
" </script>")
|
||||
void deleteByFileList(List<String> filePathList, @Param("mediaServerId") String mediaServerId);
|
||||
|
||||
|
||||
@Select(" <script>" +
|
||||
"select *" +
|
||||
" from wvp_cloud_record " +
|
||||
" where collect = false and end_time <= #{endTimeStamp} and media_server_id = #{mediaServerId} " +
|
||||
" </script>")
|
||||
List<CloudRecordItem> queryRecordListForDelete(@Param("endTimeStamp")Long endTimeStamp, String mediaServerId);
|
||||
|
||||
@Update(" <script>" +
|
||||
"update wvp_cloud_record set collect = #{collect} where id = #{recordId} " +
|
||||
" </script>")
|
||||
int changeCollectById(@Param("collect") boolean collect, @Param("recordId") Integer recordId);
|
||||
|
||||
@Delete(" <script>" +
|
||||
"delete from wvp_cloud_record where id in " +
|
||||
" <foreach collection='cloudRecordItemIdList' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
|
||||
" </script>")
|
||||
int deleteList(List<CloudRecordItem> cloudRecordItemIdList);
|
||||
|
||||
@Select(" <script>" +
|
||||
"select *" +
|
||||
" from wvp_cloud_record " +
|
||||
"where call_id = #{callId}" +
|
||||
" </script>")
|
||||
List<CloudRecordItem> getListByCallId(@Param("callId") String callId);
|
||||
|
||||
@Select(" <script>" +
|
||||
"select *" +
|
||||
" from wvp_cloud_record " +
|
||||
"where id = #{id}" +
|
||||
" </script>")
|
||||
CloudRecordItem queryOne(@Param("id") Integer id);
|
||||
}
|
@ -107,7 +107,11 @@ public interface DeviceChannelMapper {
|
||||
"wvp_device_channel dc " +
|
||||
"WHERE " +
|
||||
"dc.device_id = #{deviceId} " +
|
||||
" <if test='query != null'> AND (dc.channel_id LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%'))</if> " +
|
||||
" <if test='query != null'> AND (" +
|
||||
"dc.channel_id LIKE concat('%',#{query},'%') " +
|
||||
"OR dc.name LIKE concat('%',#{query},'%') " +
|
||||
"OR dc.custom_name LIKE concat('%',#{query},'%')" +
|
||||
")</if> " +
|
||||
" <if test='parentChannelId != null'> AND (dc.parent_id=#{parentChannelId} OR dc.civil_code = #{parentChannelId}) </if> " +
|
||||
" <if test='online == true' > AND dc.status= true</if>" +
|
||||
" <if test='online == false' > AND dc.status= false</if>" +
|
||||
|
@ -158,7 +158,7 @@ public interface GbStreamMapper {
|
||||
" <foreach collection='list' item='item' index='index' separator=';'>"+
|
||||
"UPDATE wvp_gb_stream " +
|
||||
" SET name=#{item.name},"+
|
||||
" gb_id=#{item.gb_id}"+
|
||||
" gb_id=#{item.gbId}"+
|
||||
" WHERE app=#{item.app} and stream=#{item.stream}"+
|
||||
"</foreach>"+
|
||||
"</script>")
|
||||
|
@ -31,6 +31,8 @@ public interface MediaServerMapper {
|
||||
"rtp_port_range,"+
|
||||
"send_rtp_port_range,"+
|
||||
"record_assist_port,"+
|
||||
"record_day,"+
|
||||
"record_path,"+
|
||||
"default_server,"+
|
||||
"create_time,"+
|
||||
"update_time,"+
|
||||
@ -55,6 +57,8 @@ public interface MediaServerMapper {
|
||||
"#{rtpPortRange}, " +
|
||||
"#{sendRtpPortRange}, " +
|
||||
"#{recordAssistPort}, " +
|
||||
"#{recordDay}, " +
|
||||
"#{recordPath}, " +
|
||||
"#{defaultServer}, " +
|
||||
"#{createTime}, " +
|
||||
"#{updateTime}, " +
|
||||
@ -82,6 +86,8 @@ public interface MediaServerMapper {
|
||||
"<if test=\"secret != null\">, secret=#{secret}</if>" +
|
||||
"<if test=\"recordAssistPort != null\">, record_assist_port=#{recordAssistPort}</if>" +
|
||||
"<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" +
|
||||
"<if test=\"recordDay != null\">, record_day=#{recordDay}</if>" +
|
||||
"<if test=\"recordPath != null\">, record_path=#{recordPath}</if>" +
|
||||
"WHERE id=#{id}"+
|
||||
" </script>"})
|
||||
int update(MediaServerItem mediaServerItem);
|
||||
@ -105,6 +111,8 @@ public interface MediaServerMapper {
|
||||
"<if test=\"sendRtpPortRange != null\">, send_rtp_port_range=#{sendRtpPortRange}</if>" +
|
||||
"<if test=\"secret != null\">, secret=#{secret}</if>" +
|
||||
"<if test=\"recordAssistPort != null\">, record_assist_port=#{recordAssistPort}</if>" +
|
||||
"<if test=\"recordDay != null\">, record_day=#{recordDay}</if>" +
|
||||
"<if test=\"recordPath != null\">, record_path=#{recordPath}</if>" +
|
||||
"<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" +
|
||||
"WHERE ip=#{ip} and http_port=#{httpPort}"+
|
||||
" </script>"})
|
||||
@ -130,4 +138,8 @@ public interface MediaServerMapper {
|
||||
|
||||
@Select("SELECT * FROM wvp_media_server WHERE default_server=true")
|
||||
MediaServerItem queryDefault();
|
||||
|
||||
@Select("SELECT * FROM wvp_media_server WHERE record_assist_port > 0")
|
||||
List<MediaServerItem> queryAllWithAssistPort();
|
||||
|
||||
}
|
||||
|
@ -58,7 +58,10 @@ public interface PlatformChannelMapper {
|
||||
@Select("SELECT dc.* from wvp_platform_gb_channel pgc left join wvp_device_channel dc on dc.id = pgc.device_channel_id WHERE dc.channel_id=#{channelId} and pgc.platform_id=#{platformId}")
|
||||
List<DeviceChannel> queryChannelInParentPlatform(@Param("platformId") String platformId, @Param("channelId") String channelId);
|
||||
|
||||
@Select("SELECT dc.* from wvp_platform_gb_channel pgc left join wvp_device_channel dc on dc.id = pgc.device_channel_id WHERE pgc.platform_id=#{platformId} and pgc.catalog_id=#{catalogId}")
|
||||
@Select("<script> "+
|
||||
"SELECT dc.* from wvp_platform_gb_channel pgc left join wvp_device_channel dc on dc.id = pgc.device_channel_id WHERE pgc.platform_id=#{platformId} " +
|
||||
" <if test='catalogId != null' > and pgc.catalog_id=#{catalogId}</if>" +
|
||||
"</script>")
|
||||
List<DeviceChannel> queryAllChannelInCatalog(@Param("platformId") String platformId, @Param("catalogId") String catalogId);
|
||||
|
||||
@Select(" select dc.channel_id as id, dc.name as name, pgc.platform_id as platform_id, pgc.catalog_id as parent_id, 0 as children_count, 1 as type " +
|
||||
|
@ -53,11 +53,14 @@ public interface PlatformGbStreamMapper {
|
||||
"WHERE gs.app=#{app} AND gs.stream=#{stream} AND pgs.platform_id=#{platformId}")
|
||||
StreamProxyItem selectOne(@Param("app") String app, @Param("stream") String stream, @Param("platformId") String platformId);
|
||||
|
||||
@Select("select gs.* \n" +
|
||||
"from wvp_gb_stream gs\n" +
|
||||
@Select("<script> " +
|
||||
"select gs.* " +
|
||||
" from wvp_gb_stream gs\n" +
|
||||
" left join wvp_platform_gb_stream pgs\n" +
|
||||
" on gs.gb_stream_id = pgs.gb_stream_id\n" +
|
||||
"where pgs.platform_id=#{platformId} and pgs.catalog_id=#{catalogId}")
|
||||
" where pgs.platform_id=#{platformId} " +
|
||||
" <if test='catalogId != null' > and pgs.catalog_id=#{catalogId}</if>" +
|
||||
"</script>")
|
||||
List<GbStream> queryChannelInParentPlatformAndCatalog(@Param("platformId") String platformId, @Param("catalogId") String catalogId);
|
||||
|
||||
@Select("select gs.gb_id as id, gs.name as name, pgs.platform_id as platform_id, pgs.catalog_id as catalog_id , 0 as children_count, 2 as type\n" +
|
||||
@ -103,6 +106,9 @@ public interface PlatformGbStreamMapper {
|
||||
"</script>")
|
||||
void delByAppAndStreamsByPlatformId(@Param("gbStreams") List<GbStream> gbStreams, @Param("platformId") String platformId);
|
||||
|
||||
@Delete("DELETE from wvp_platform_gb_stream WHERE platform_id=#{platformId} and catalog_id=#{catalogId}")
|
||||
@Delete("<script> "+
|
||||
"DELETE from wvp_platform_gb_stream WHERE platform_id=#{platformId}" +
|
||||
" <if test='catalogId != null' > and catalog_id=#{catalogId}</if>" +
|
||||
"</script>")
|
||||
int delByPlatformAndCatalogId(@Param("platformId") String platformId, @Param("catalogId") String catalogId);
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ import java.util.List;
|
||||
public interface StreamPushMapper {
|
||||
|
||||
@Insert("INSERT INTO wvp_stream_push (app, stream, total_reader_count, origin_type, origin_type_str, " +
|
||||
"push_time, alive_second, media_server_id, update_time, create_time, push_ing, self) VALUES" +
|
||||
"push_time, alive_second, media_server_id, server_id, update_time, create_time, push_ing, self) VALUES" +
|
||||
"(#{app}, #{stream}, #{totalReaderCount}, #{originType}, #{originTypeStr}, " +
|
||||
"#{pushTime}, #{aliveSecond}, #{mediaServerId} , #{updateTime} , #{createTime}, " +
|
||||
"#{pushTime}, #{aliveSecond}, #{mediaServerId} , #{serverId} , #{updateTime} , #{createTime}, " +
|
||||
"#{pushIng}, #{self} )")
|
||||
int add(StreamPushItem streamPushItem);
|
||||
|
||||
@ -24,6 +24,7 @@ public interface StreamPushMapper {
|
||||
"UPDATE wvp_stream_push " +
|
||||
"SET update_time=#{updateTime}" +
|
||||
"<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" +
|
||||
"<if test=\"serverId != null\">, server_id=#{serverId}</if>" +
|
||||
"<if test=\"totalReaderCount != null\">, total_reader_count=#{totalReaderCount}</if>" +
|
||||
"<if test=\"originType != null\">, origin_type=#{originType}</if>" +
|
||||
"<if test=\"originTypeStr != null\">, origin_type_str=#{originTypeStr}</if>" +
|
||||
@ -89,10 +90,10 @@ public interface StreamPushMapper {
|
||||
|
||||
@Insert("<script>" +
|
||||
"Insert INTO wvp_stream_push (app, stream, total_reader_count, origin_type, origin_type_str, " +
|
||||
"create_time, alive_second, media_server_id, status, push_ing) " +
|
||||
"create_time, alive_second, media_server_id, server_id, status, push_ing) " +
|
||||
"VALUES <foreach collection='streamPushItems' item='item' index='index' separator=','>" +
|
||||
"( #{item.app}, #{item.stream}, #{item.totalReaderCount}, #{item.originType}, " +
|
||||
"#{item.originTypeStr},#{item.createTime}, #{item.aliveSecond}, #{item.mediaServerId}, #{item.status} ," +
|
||||
"#{item.originTypeStr},#{item.createTime}, #{item.aliveSecond}, #{item.mediaServerId},#{item.serverId}, #{item.status} ," +
|
||||
" #{item.pushIng} )" +
|
||||
" </foreach>" +
|
||||
"</script>")
|
||||
|
@ -609,14 +609,13 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
|
||||
@Override
|
||||
public void sendDeviceOrChannelStatus(String deviceId, String channelId, boolean online) {
|
||||
String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_DEVICE_STATUS;
|
||||
logger.info("[redis通知] 发送 推送设备/通道状态, {}/{}-{}", deviceId, channelId, online);
|
||||
StringBuilder msg = new StringBuilder();
|
||||
msg.append(deviceId);
|
||||
if (channelId != null) {
|
||||
msg.append(":").append(channelId);
|
||||
}
|
||||
msg.append(" ").append(online? "ON":"OFF");
|
||||
logger.info("[redis通知] 推送状态-> {} ", msg);
|
||||
logger.info("[redis通知] 推送设备/通道状态-> {} ", msg);
|
||||
// 使用 RedisTemplate<Object, Object> 发送字符串消息会导致发送的消息多带了双引号
|
||||
stringRedisTemplate.convertAndSend(key, msg.toString());
|
||||
}
|
||||
@ -650,4 +649,20 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
|
||||
logger.info("[redis发送通知] 发送 上级平台停止观看 {}: {}/{}->{}", key, msg.getApp(), msg.getStream(), msg.getPlatFormId());
|
||||
redisTemplate.convertAndSend(key, JSON.toJSON(msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPushListItem(String app, String stream, OnStreamChangedHookParam param) {
|
||||
String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream;
|
||||
redisTemplate.opsForValue().set(key, param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePushListItem(String app, String stream, String mediaServerId) {
|
||||
String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream;
|
||||
OnStreamChangedHookParam param = (OnStreamChangedHookParam)redisTemplate.opsForValue().get(key);
|
||||
if (param != null && param.getMediaServerId().equalsIgnoreCase(mediaServerId)) {
|
||||
redisTemplate.delete(key);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
package com.genersoft.iot.vmp.utils;
|
||||
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
|
||||
|
||||
public class CloudRecordUtils {
|
||||
|
||||
public static DownloadFileInfo getDownloadFilePath(MediaServerItem mediaServerItem, String filePath) {
|
||||
DownloadFileInfo downloadFileInfo = new DownloadFileInfo();
|
||||
|
||||
String pathTemplate = "%s://%s:%s/index/api/downloadFile?file_path=" + filePath;
|
||||
|
||||
downloadFileInfo.setHttpPath(String.format(pathTemplate, "http", mediaServerItem.getStreamIp(),
|
||||
mediaServerItem.getHttpPort()));
|
||||
|
||||
if (mediaServerItem.getHttpSSlPort() > 0) {
|
||||
downloadFileInfo.setHttpsPath(String.format(pathTemplate, "https", mediaServerItem.getStreamIp(),
|
||||
mediaServerItem.getHttpSSlPort()));
|
||||
}
|
||||
return downloadFileInfo;
|
||||
}
|
||||
}
|
@ -40,11 +40,17 @@ public class DateUtil {
|
||||
*/
|
||||
public static final String URL_PATTERN = "yyyyMMddHHmmss";
|
||||
|
||||
/**
|
||||
* 日期格式
|
||||
*/
|
||||
public static final String date_PATTERN = "yyyy-MM-dd";
|
||||
|
||||
public static final String zoneStr = "Asia/Shanghai";
|
||||
|
||||
public static final DateTimeFormatter formatterCompatibleISO8601 = DateTimeFormatter.ofPattern(ISO8601_COMPATIBLE_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
|
||||
public static final DateTimeFormatter formatterISO8601 = DateTimeFormatter.ofPattern(ISO8601_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
|
||||
public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
|
||||
public static final DateTimeFormatter DateFormatter = DateTimeFormatter.ofPattern(date_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
|
||||
public static final DateTimeFormatter urlFormatter = DateTimeFormatter.ofPattern(URL_PATTERN, Locale.getDefault()).withZone(ZoneId.of(zoneStr));
|
||||
|
||||
public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) {
|
||||
@ -71,6 +77,22 @@ public class DateUtil {
|
||||
return instant.getEpochSecond();
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间戳 转 yyyy_MM_dd_HH_mm_ss
|
||||
*/
|
||||
public static String timestampTo_yyyy_MM_dd_HH_mm_ss(long timestamp) {
|
||||
Instant instant = Instant.ofEpochSecond(timestamp);
|
||||
return formatter.format(LocalDateTime.ofInstant(instant, ZoneId.of(zoneStr)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间戳 转 yyyy_MM_dd
|
||||
*/
|
||||
public static String timestampTo_yyyy_MM_dd(long timestamp) {
|
||||
Instant instant = Instant.ofEpochMilli(timestamp);
|
||||
return DateFormatter.format(LocalDateTime.ofInstant(instant, ZoneId.of(zoneStr)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前时间
|
||||
* @return
|
||||
@ -117,4 +139,13 @@ public class DateUtil {
|
||||
Instant beforeInstant = Instant.from(formatter.parse(keepaliveTime));
|
||||
return ChronoUnit.MILLIS.between(beforeInstant, Instant.now());
|
||||
}
|
||||
|
||||
public static long getDifference(String startTime, String endTime) {
|
||||
if (ObjectUtils.isEmpty(startTime) || ObjectUtils.isEmpty(endTime)) {
|
||||
return 0;
|
||||
}
|
||||
Instant startInstant = Instant.from(formatter.parse(startTime));
|
||||
Instant endInstant = Instant.from(formatter.parse(endTime));
|
||||
return ChronoUnit.MILLIS.between(endInstant, startInstant);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.genersoft.iot.vmp.vmanager.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
@Schema(description = "流信息")
|
||||
@ -93,6 +94,9 @@ public class StreamContent {
|
||||
@Schema(description = "结束时间")
|
||||
private String endTime;
|
||||
|
||||
@Schema(description = "文件下载地址(录像下载使用)")
|
||||
private DownloadFileInfo downLoadFilePath;
|
||||
|
||||
private double progress;
|
||||
|
||||
public StreamContent(StreamInfo streamInfo) {
|
||||
@ -170,6 +174,10 @@ public class StreamContent {
|
||||
this.startTime = streamInfo.getStartTime();
|
||||
this.endTime = streamInfo.getEndTime();
|
||||
this.progress = streamInfo.getProgress();
|
||||
|
||||
if (streamInfo.getDownLoadFilePath() != null) {
|
||||
this.downLoadFilePath = streamInfo.getDownLoadFilePath();
|
||||
}
|
||||
}
|
||||
|
||||
public String getApp() {
|
||||
@ -411,4 +419,12 @@ public class StreamContent {
|
||||
public void setProgress(double progress) {
|
||||
this.progress = progress;
|
||||
}
|
||||
|
||||
public DownloadFileInfo getDownLoadFilePath() {
|
||||
return downLoadFilePath;
|
||||
}
|
||||
|
||||
public void setDownLoadFilePath(DownloadFileInfo downLoadFilePath) {
|
||||
this.downLoadFilePath = downLoadFilePath;
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,19 @@
|
||||
package com.genersoft.iot.vmp.vmanager.cloudRecord;
|
||||
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.conf.security.JwtUtils;
|
||||
import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
|
||||
import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
|
||||
import com.genersoft.iot.vmp.service.ICloudRecordService;
|
||||
import com.genersoft.iot.vmp.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
|
||||
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.PageInfo;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.RecordFile;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
@ -23,6 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
@ -34,28 +37,15 @@ import java.util.List;
|
||||
@RequestMapping("/api/cloud/record")
|
||||
public class CloudRecordController {
|
||||
|
||||
@Autowired
|
||||
private ZLMServerFactory zlmServerFactory;
|
||||
|
||||
@Autowired
|
||||
private SendRtpPortManager sendRtpPortManager;
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(CloudRecordController.class);
|
||||
|
||||
@Autowired
|
||||
private ZlmHttpHookSubscribe hookSubscribe;
|
||||
private ICloudRecordService cloudRecordService;
|
||||
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
@Autowired
|
||||
private DynamicTask dynamicTask;
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<Object, Object> redisTemplate;
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("/date/list")
|
||||
@ -66,8 +56,8 @@ public class CloudRecordController {
|
||||
@Parameter(name = "month", description = "月,置空则查询当月", required = false)
|
||||
@Parameter(name = "mediaServerId", description = "流媒体ID,置空则查询全部", required = false)
|
||||
public List<String> openRtpServer(
|
||||
@RequestParam String app,
|
||||
@RequestParam String stream,
|
||||
@RequestParam(required = true) String app,
|
||||
@RequestParam(required = true) String stream,
|
||||
@RequestParam(required = false) int year,
|
||||
@RequestParam(required = false) int month,
|
||||
@RequestParam(required = false) String mediaServerId
|
||||
@ -97,26 +87,28 @@ public class CloudRecordController {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
return mediaServerService.getRecordDates(app, stream, year, month, mediaServerItems);
|
||||
return cloudRecordService.getDateList(app, stream, year, month, mediaServerItems);
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "分页查询云端录像", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "app", description = "应用名", required = true)
|
||||
@Parameter(name = "stream", description = "流ID", required = true)
|
||||
@Parameter(name = "page", description = "当前页", required = false)
|
||||
@Parameter(name = "count", description = "每页查询数量", required = false)
|
||||
@Parameter(name = "startTime", description = "开始时间(yyyy-MM-dd HH:mm:ss)", required = true)
|
||||
@Parameter(name = "endTime", description = "结束时间(yyyy-MM-dd HH:mm:ss)", required = true)
|
||||
@Parameter(name = "query", description = "检索内容", required = false)
|
||||
@Parameter(name = "app", description = "应用名", required = false)
|
||||
@Parameter(name = "stream", description = "流ID", required = false)
|
||||
@Parameter(name = "page", description = "当前页", required = true)
|
||||
@Parameter(name = "count", description = "每页查询数量", required = true)
|
||||
@Parameter(name = "startTime", description = "开始时间(yyyy-MM-dd HH:mm:ss)", required = false)
|
||||
@Parameter(name = "endTime", description = "结束时间(yyyy-MM-dd HH:mm:ss)", required = false)
|
||||
@Parameter(name = "mediaServerId", description = "流媒体ID,置空则查询全部流媒体", required = false)
|
||||
public PageInfo<RecordFile> openRtpServer(
|
||||
@RequestParam String app,
|
||||
@RequestParam String stream,
|
||||
public PageInfo<CloudRecordItem> openRtpServer(
|
||||
@RequestParam(required = false) String query,
|
||||
@RequestParam(required = false) String app,
|
||||
@RequestParam(required = false) String stream,
|
||||
@RequestParam int page,
|
||||
@RequestParam int count,
|
||||
@RequestParam String startTime,
|
||||
@RequestParam String endTime,
|
||||
@RequestParam(required = false) String startTime,
|
||||
@RequestParam(required = false) String endTime,
|
||||
@RequestParam(required = false) String mediaServerId
|
||||
|
||||
) {
|
||||
@ -135,13 +127,147 @@ public class CloudRecordController {
|
||||
mediaServerItems = mediaServerService.getAll();
|
||||
}
|
||||
if (mediaServerItems.isEmpty()) {
|
||||
return new PageInfo<>();
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "当前无流媒体");
|
||||
}
|
||||
List<RecordFile> records = mediaServerService.getRecords(app, stream, startTime, endTime, mediaServerItems);
|
||||
PageInfo<RecordFile> pageInfo = new PageInfo<>(records);
|
||||
pageInfo.startPage(page, count);
|
||||
return pageInfo;
|
||||
if (query != null && ObjectUtils.isEmpty(query.trim())) {
|
||||
query = null;
|
||||
}
|
||||
if (app != null && ObjectUtils.isEmpty(app.trim())) {
|
||||
app = null;
|
||||
}
|
||||
if (stream != null && ObjectUtils.isEmpty(stream.trim())) {
|
||||
stream = null;
|
||||
}
|
||||
if (startTime != null && ObjectUtils.isEmpty(startTime.trim())) {
|
||||
startTime = null;
|
||||
}
|
||||
if (endTime != null && ObjectUtils.isEmpty(endTime.trim())) {
|
||||
endTime = null;
|
||||
}
|
||||
return cloudRecordService.getList(page, count, query, app, stream, startTime, endTime, mediaServerItems);
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("/task/add")
|
||||
@Operation(summary = "添加合并任务")
|
||||
@Parameter(name = "app", description = "应用名", required = false)
|
||||
@Parameter(name = "stream", description = "流ID", required = false)
|
||||
@Parameter(name = "mediaServerId", description = "流媒体ID", required = false)
|
||||
@Parameter(name = "startTime", description = "鉴权ID", required = false)
|
||||
@Parameter(name = "endTime", description = "鉴权ID", required = false)
|
||||
@Parameter(name = "callId", description = "鉴权ID", required = false)
|
||||
@Parameter(name = "remoteHost", description = "返回地址时的远程地址", required = false)
|
||||
public String addTask(
|
||||
HttpServletRequest request,
|
||||
@RequestParam(required = false) String app,
|
||||
@RequestParam(required = false) String stream,
|
||||
@RequestParam(required = false) String mediaServerId,
|
||||
@RequestParam(required = false) String startTime,
|
||||
@RequestParam(required = false) String endTime,
|
||||
@RequestParam(required = false) String callId,
|
||||
@RequestParam(required = false) String remoteHost
|
||||
){
|
||||
MediaServerItem mediaServerItem;
|
||||
if (mediaServerId == null) {
|
||||
mediaServerItem = mediaServerService.getDefaultMediaServer();
|
||||
}else {
|
||||
mediaServerItem = mediaServerService.getOne(mediaServerId);
|
||||
}
|
||||
if (mediaServerItem == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的流媒体");
|
||||
}else {
|
||||
if (remoteHost == null) {
|
||||
remoteHost = request.getScheme() + "://" + mediaServerItem.getIp() + ":" + mediaServerItem.getRecordAssistPort();
|
||||
}
|
||||
}
|
||||
return cloudRecordService.addTask(app, stream, mediaServerItem, startTime, endTime, callId, remoteHost, mediaServerId != null);
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("/task/list")
|
||||
@Operation(summary = "查询合并任务")
|
||||
@Parameter(name = "taskId", description = "任务Id", required = false)
|
||||
@Parameter(name = "mediaServerId", description = "流媒体ID", required = false)
|
||||
@Parameter(name = "isEnd", description = "是否结束", required = false)
|
||||
public JSONArray queryTaskList(
|
||||
HttpServletRequest request,
|
||||
@RequestParam(required = false) String app,
|
||||
@RequestParam(required = false) String stream,
|
||||
@RequestParam(required = false) String callId,
|
||||
@RequestParam(required = false) String taskId,
|
||||
@RequestParam(required = false) String mediaServerId,
|
||||
@RequestParam(required = false) Boolean isEnd
|
||||
){
|
||||
if (ObjectUtils.isEmpty(mediaServerId)) {
|
||||
mediaServerId = null;
|
||||
}
|
||||
|
||||
return cloudRecordService.queryTask(app, stream, callId, taskId, mediaServerId, isEnd, request.getScheme());
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("/collect/add")
|
||||
@Operation(summary = "添加收藏")
|
||||
@Parameter(name = "app", description = "应用名", required = false)
|
||||
@Parameter(name = "stream", description = "流ID", required = false)
|
||||
@Parameter(name = "mediaServerId", description = "流媒体ID", required = false)
|
||||
@Parameter(name = "startTime", description = "鉴权ID", required = false)
|
||||
@Parameter(name = "endTime", description = "鉴权ID", required = false)
|
||||
@Parameter(name = "callId", description = "鉴权ID", required = false)
|
||||
@Parameter(name = "recordId", description = "录像记录的ID,用于精准收藏一个视频文件", required = false)
|
||||
public int addCollect(
|
||||
@RequestParam(required = false) String app,
|
||||
@RequestParam(required = false) String stream,
|
||||
@RequestParam(required = false) String mediaServerId,
|
||||
@RequestParam(required = false) String startTime,
|
||||
@RequestParam(required = false) String endTime,
|
||||
@RequestParam(required = false) String callId,
|
||||
@RequestParam(required = false) Integer recordId
|
||||
){
|
||||
logger.info("[云端录像] 添加收藏,app={},stream={},mediaServerId={},startTime={},endTime={},callId={},recordId={}",
|
||||
app, stream, mediaServerId, startTime, endTime, callId, recordId);
|
||||
if (recordId != null) {
|
||||
return cloudRecordService.changeCollectById(recordId, true);
|
||||
}else {
|
||||
return cloudRecordService.changeCollect(true, app, stream, mediaServerId, startTime, endTime, callId);
|
||||
}
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("/collect/delete")
|
||||
@Operation(summary = "移除收藏")
|
||||
@Parameter(name = "app", description = "应用名", required = false)
|
||||
@Parameter(name = "stream", description = "流ID", required = false)
|
||||
@Parameter(name = "mediaServerId", description = "流媒体ID", required = false)
|
||||
@Parameter(name = "startTime", description = "鉴权ID", required = false)
|
||||
@Parameter(name = "endTime", description = "鉴权ID", required = false)
|
||||
@Parameter(name = "callId", description = "鉴权ID", required = false)
|
||||
@Parameter(name = "recordId", description = "录像记录的ID,用于精准精准移除一个视频文件的收藏", required = false)
|
||||
public int deleteCollect(
|
||||
@RequestParam(required = false) String app,
|
||||
@RequestParam(required = false) String stream,
|
||||
@RequestParam(required = false) String mediaServerId,
|
||||
@RequestParam(required = false) String startTime,
|
||||
@RequestParam(required = false) String endTime,
|
||||
@RequestParam(required = false) String callId,
|
||||
@RequestParam(required = false) Integer recordId
|
||||
){
|
||||
logger.info("[云端录像] 移除收藏,app={},stream={},mediaServerId={},startTime={},endTime={},callId={},recordId={}",
|
||||
app, stream, mediaServerId, startTime, endTime, callId, recordId);
|
||||
if (recordId != null) {
|
||||
return cloudRecordService.changeCollectById(recordId, false);
|
||||
}else {
|
||||
return cloudRecordService.changeCollect(false, app, stream, mediaServerId, startTime, endTime, callId);
|
||||
}
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("/play/path")
|
||||
@Operation(summary = "获取播放地址")
|
||||
@Parameter(name = "recordId", description = "录像记录的ID", required = true)
|
||||
public DownloadFileInfo getPlayUrlPath(
|
||||
@RequestParam(required = true) Integer recordId
|
||||
){
|
||||
return cloudRecordService.getPlayUrlPath(recordId);
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ public class GbStreamController {
|
||||
@ResponseBody
|
||||
public void del(@RequestBody GbStreamParam gbStreamParam){
|
||||
|
||||
if (gbStreamParam.getGbStreams() == null || gbStreamParam.getGbStreams().size() == 0) {
|
||||
if (gbStreamParam.getGbStreams() == null || gbStreamParam.getGbStreams().isEmpty()) {
|
||||
if (gbStreamParam.isAll()) {
|
||||
gbStreamService.delAllPlatformInfo(gbStreamParam.getPlatformId(), gbStreamParam.getCatalogId());
|
||||
}
|
||||
@ -105,7 +105,7 @@ public class GbStreamController {
|
||||
@PostMapping(value = "/add")
|
||||
@ResponseBody
|
||||
public void add(@RequestBody GbStreamParam gbStreamParam){
|
||||
if (gbStreamParam.getGbStreams() == null || gbStreamParam.getGbStreams().size() == 0) {
|
||||
if (gbStreamParam.getGbStreams() == null || gbStreamParam.getGbStreams().isEmpty()) {
|
||||
if (gbStreamParam.isAll()) {
|
||||
List<GbStream> allGBChannels = gbStreamService.getAllGBChannels(gbStreamParam.getPlatformId());
|
||||
gbStreamService.addPlatformInfo(allGBChannels, gbStreamParam.getPlatformId(), gbStreamParam.getCatalogId());
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.genersoft.iot.vmp.vmanager.gb28181.record;
|
||||
|
||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
@ -11,7 +13,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.service.IInviteStreamService;
|
||||
import com.genersoft.iot.vmp.service.IPlayService;
|
||||
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
@ -26,6 +30,7 @@ import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@ -58,6 +63,9 @@ public class GBRecordController {
|
||||
@Autowired
|
||||
private IPlayService playService;
|
||||
|
||||
@Autowired
|
||||
private IInviteStreamService inviteStreamService;
|
||||
|
||||
@Autowired
|
||||
private IDeviceService deviceService;
|
||||
|
||||
|
@ -1,51 +0,0 @@
|
||||
//package com.genersoft.iot.vmp.vmanager.record;
|
||||
//
|
||||
//import com.alibaba.fastjson2.JSONObject;
|
||||
//import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
|
||||
//import com.genersoft.iot.vmp.service.IRecordInfoServer;
|
||||
//import com.genersoft.iot.vmp.storager.dao.dto.RecordInfo;
|
||||
//import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||
//import com.github.pagehelper.PageInfo;
|
||||
//import io.swagger.annotations.Api;
|
||||
//import io.swagger.annotations.ApiImplicitParam;
|
||||
//import io.swagger.annotations.ApiImplicitParams;
|
||||
//import io.swagger.annotations.ApiOperation;
|
||||
//import org.springframework.beans.factory.annotation.Autowired;
|
||||
//import org.springframework.web.bind.annotation.*;
|
||||
//
|
||||
//@Tag(name = "云端录像")
|
||||
//
|
||||
//@RestController
|
||||
//@RequestMapping("/api/record")
|
||||
//public class RecordController {
|
||||
//
|
||||
// @Autowired
|
||||
// private IRecordInfoServer recordInfoServer;
|
||||
//
|
||||
// //@ApiOperation("录像列表查询")
|
||||
// @ApiImplicitParams({
|
||||
// @ApiImplicitParam(name="page", value = "当前页", required = true, dataTypeClass = Integer.class),
|
||||
// @ApiImplicitParam(name="count", value = "每页查询数量", required = true, dataTypeClass = Integer.class),
|
||||
// @ApiImplicitParam(name="query", value = "查询内容", dataTypeClass = String.class),
|
||||
// })
|
||||
// @GetMapping(value = "/app/list")
|
||||
// @ResponseBody
|
||||
// public Object list(@RequestParam(required = false)Integer page,
|
||||
// @RequestParam(required = false)Integer count ){
|
||||
//
|
||||
// PageInfo<RecordInfo> recordList = recordInfoServer.getRecordList(page - 1, page - 1 + count);
|
||||
// return recordList;
|
||||
// }
|
||||
//
|
||||
// //@ApiOperation("获取录像详情")
|
||||
// @ApiImplicitParams({
|
||||
// @ApiImplicitParam(name="recordInfo", value = "录像记录", required = true, dataTypeClass = RecordInfo.class)
|
||||
// })
|
||||
// @GetMapping(value = "/detail")
|
||||
// @ResponseBody
|
||||
// public JSONObject list(RecordInfo recordInfo, String time ){
|
||||
//
|
||||
//
|
||||
// return null;
|
||||
// }
|
||||
//}
|
@ -68,6 +68,7 @@ public class ApiDeviceController {
|
||||
// if (logger.isDebugEnabled()) {
|
||||
// logger.debug("查询所有视频设备API调用");
|
||||
// }
|
||||
|
||||
JSONObject result = new JSONObject();
|
||||
List<Device> devices;
|
||||
if (start == null || limit ==null) {
|
||||
@ -80,7 +81,7 @@ public class ApiDeviceController {
|
||||
}
|
||||
|
||||
JSONArray deviceJSONList = new JSONArray();
|
||||
for (Device device : devices) {
|
||||
devices.stream().forEach(device -> {
|
||||
JSONObject deviceJsonObject = new JSONObject();
|
||||
deviceJsonObject.put("ID", device.getDeviceId());
|
||||
deviceJsonObject.put("Name", device.getName());
|
||||
@ -99,7 +100,7 @@ public class ApiDeviceController {
|
||||
deviceJsonObject.put("UpdatedAt", "");
|
||||
deviceJsonObject.put("CreatedAt", "");
|
||||
deviceJSONList.add(deviceJsonObject);
|
||||
}
|
||||
});
|
||||
result.put("DeviceList",deviceJSONList);
|
||||
return result;
|
||||
}
|
||||
@ -114,7 +115,6 @@ public class ApiDeviceController {
|
||||
@RequestParam(required = false)String q,
|
||||
@RequestParam(required = false)Boolean online ){
|
||||
|
||||
|
||||
JSONObject result = new JSONObject();
|
||||
List<DeviceChannelExtend> deviceChannels;
|
||||
List<String> channelIds = null;
|
||||
@ -127,13 +127,19 @@ public class ApiDeviceController {
|
||||
deviceChannels = allDeviceChannelList;
|
||||
result.put("ChannelCount", deviceChannels.size());
|
||||
}else {
|
||||
deviceChannels = storager.queryChannelsByDeviceIdWithStartAndLimit(serial,channelIds, null, null, online,start, limit);
|
||||
int total = allDeviceChannelList.size();
|
||||
result.put("ChannelCount", total);
|
||||
if (start > allDeviceChannelList.size()) {
|
||||
deviceChannels = new ArrayList<>();
|
||||
}else {
|
||||
if (start + limit < allDeviceChannelList.size()) {
|
||||
deviceChannels = allDeviceChannelList.subList(start, start + limit);
|
||||
}else {
|
||||
deviceChannels = allDeviceChannelList.subList(start, allDeviceChannelList.size());
|
||||
}
|
||||
}
|
||||
result.put("ChannelCount", allDeviceChannelList.size());
|
||||
}
|
||||
|
||||
JSONArray channleJSONList = new JSONArray();
|
||||
for (DeviceChannelExtend deviceChannelExtend : deviceChannels) {
|
||||
deviceChannels.stream().forEach(deviceChannelExtend -> {
|
||||
JSONObject deviceJOSNChannel = new JSONObject();
|
||||
deviceJOSNChannel.put("ID", deviceChannelExtend.getChannelId());
|
||||
deviceJOSNChannel.put("DeviceID", deviceChannelExtend.getDeviceId());
|
||||
@ -166,7 +172,7 @@ public class ApiDeviceController {
|
||||
deviceJOSNChannel.put("StreamID", deviceChannelExtend.getStreamId()); // StreamID 直播流ID, 有值表示正在直播
|
||||
deviceJOSNChannel.put("NumOutputs ", -1); // 直播在线人数
|
||||
channleJSONList.add(deviceJOSNChannel);
|
||||
}
|
||||
});
|
||||
result.put("ChannelList", channleJSONList);
|
||||
return result;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ public class ApiStreamController {
|
||||
result.put("error","device[ " + serial + " ]未找到");
|
||||
resultDeferredResult.setResult(result);
|
||||
return resultDeferredResult;
|
||||
}else if (device.isOnLine()) {
|
||||
}else if (!device.isOnLine()) {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("error","device[ " + code + " ]offline");
|
||||
resultDeferredResult.setResult(result);
|
||||
|
@ -34,18 +34,42 @@ spring:
|
||||
poolMaxWait: 5
|
||||
# [必选] jdbc数据库配置
|
||||
datasource:
|
||||
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
|
||||
username: root
|
||||
password: root123
|
||||
hikari:
|
||||
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
|
||||
initialSize: 10 # 连接池初始化连接数
|
||||
maximum-pool-size: 200 # 连接池最大连接数
|
||||
minimum-idle: 5 # 连接池最小空闲连接数
|
||||
idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
|
||||
max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
|
||||
# kingbase配置
|
||||
# type: com.zaxxer.hikari.HikariDataSource
|
||||
# driver-class-name: com.kingbase8.Driver
|
||||
# url: jdbc:kingbase8://192.168.1.55:54321/wvp?useUnicode=true&characterEncoding=utf8
|
||||
# username: system
|
||||
# password: system
|
||||
# postgresql配置
|
||||
# type: com.zaxxer.hikari.HikariDataSource
|
||||
# driver-class-name: org.postgresql.Driver
|
||||
# url: jdbc:postgresql://192.168.1.242:3306/242wvp
|
||||
# username: root
|
||||
# password: SYceshizu1234
|
||||
# mysql配置
|
||||
dynamic:
|
||||
primary: master
|
||||
datasource:
|
||||
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
|
||||
username: root
|
||||
password: root123
|
||||
hikari:
|
||||
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
|
||||
initialSize: 50 # 连接池初始化连接数
|
||||
maximum-pool-size: 200 # 连接池最大连接数
|
||||
minimum-idle: 10 # 连接池最小空闲连接数
|
||||
idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
|
||||
max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
|
||||
share:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/wvp269_1?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: 12345678
|
||||
|
||||
|
||||
|
||||
# 修改分页插件为 postgresql, 数据库类型为mysql不需要
|
||||
@ -139,6 +163,10 @@ media:
|
||||
auto-config: true
|
||||
# [可选] zlm服务器的hook.admin_params=secret
|
||||
secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc
|
||||
# 录像路径
|
||||
record-path: ./www/record
|
||||
# 录像保存时长
|
||||
record-day: 7
|
||||
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
|
||||
rtp:
|
||||
# [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
|
||||
@ -182,7 +210,7 @@ user-settings:
|
||||
# 使用推流状态作为推流通道状态
|
||||
use-pushing-as-status: true
|
||||
# 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
|
||||
use-source-ip-as-stream-ip: true
|
||||
use-source-ip-as-stream-ip: false
|
||||
# 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放
|
||||
stream-on-demand: true
|
||||
# 推流鉴权, 默认开启
|
||||
|
@ -24,18 +24,22 @@ spring:
|
||||
timeout: 10000
|
||||
# mysql数据源
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true
|
||||
username: root
|
||||
password: root
|
||||
hikari:
|
||||
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
|
||||
initialSize: 10 # 连接池初始化连接数
|
||||
maximum-pool-size: 200 # 连接池最大连接数
|
||||
minimum-idle: 5 # 连接池最小空闲连接数
|
||||
idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
|
||||
max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
|
||||
dynamic:
|
||||
primary: master
|
||||
datasource:
|
||||
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
|
||||
username: root
|
||||
password: root123
|
||||
hikari:
|
||||
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
|
||||
initialSize: 50 # 连接池初始化连接数
|
||||
maximum-pool-size: 200 # 连接池最大连接数
|
||||
minimum-idle: 10 # 连接池最小空闲连接数
|
||||
idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
|
||||
max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
|
||||
#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
|
||||
server:
|
||||
port: 18978
|
||||
|
@ -18,13 +18,22 @@ spring:
|
||||
timeout: 10000
|
||||
# [必选] jdbc数据库配置
|
||||
datasource:
|
||||
# 使用mysql 打开23-28行注释, 删除29-36行
|
||||
name: wvp
|
||||
url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowMultiQueries=true&useSSL=false&allowMultiQueries=true
|
||||
username: root
|
||||
password: root
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
dynamic:
|
||||
primary: master
|
||||
datasource:
|
||||
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
|
||||
username: root
|
||||
password: root123
|
||||
hikari:
|
||||
connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
|
||||
initialSize: 50 # 连接池初始化连接数
|
||||
maximum-pool-size: 200 # 连接池最大连接数
|
||||
minimum-idle: 10 # 连接池最小空闲连接数
|
||||
idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
|
||||
max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
|
||||
|
||||
# [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
|
||||
server:
|
||||
|
@ -10,7 +10,6 @@ const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
|
||||
const portfinder = require('portfinder')
|
||||
|
||||
const HOST = process.env.HOST
|
||||
const PORT = process.env.PORT && Number(process.env.PORT)
|
||||
|
||||
const devWebpackConfig = merge(baseWebpackConfig, {
|
||||
@ -31,9 +30,8 @@ const devWebpackConfig = merge(baseWebpackConfig, {
|
||||
hot: true,
|
||||
contentBase: false, // since we use CopyWebpackPlugin.
|
||||
compress: true,
|
||||
host: HOST || config.dev.host,
|
||||
// host:'127.0.0.1',
|
||||
port: PORT || config.dev.port,
|
||||
host: config.dev.host,
|
||||
port: config.dev.port,
|
||||
open: config.dev.autoOpenBrowser,
|
||||
overlay: config.dev.errorOverlay
|
||||
? { warnings: false, errors: true }
|
||||
|
26485
web_src/package-lock.json
generated
26485
web_src/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,207 +1,281 @@
|
||||
<template>
|
||||
<div id="app" style="width: 100%">
|
||||
<div id="app" style="width: 100%">
|
||||
<div class="page-header">
|
||||
<div class="page-title">
|
||||
<el-page-header v-if="recordDetail" @back="backToList" content="云端录像"></el-page-header>
|
||||
<div v-if="!recordDetail">云端录像</div>
|
||||
<div >云端录像</div>
|
||||
</div>
|
||||
|
||||
<div class="page-header-btn">
|
||||
搜索:
|
||||
<el-input @input="getMediaServerList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
||||
prefix-icon="el-icon-search" v-model="search" clearable></el-input>
|
||||
开始时间:
|
||||
<el-date-picker
|
||||
v-model="startTime"
|
||||
type="datetime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
@change="getMediaServerList"
|
||||
placeholder="选择日期时间">
|
||||
</el-date-picker>
|
||||
结束时间:
|
||||
<el-date-picker
|
||||
v-model="endTime"
|
||||
type="datetime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
@change="getMediaServerList"
|
||||
placeholder="选择日期时间">
|
||||
</el-date-picker>
|
||||
节点选择:
|
||||
<el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServerId" placeholder="请选择" :disabled="recordDetail">
|
||||
<el-select size="mini" @change="getMediaServerList" style="width: 16rem; margin-right: 1rem;"
|
||||
v-model="mediaServerId" placeholder="请选择" >
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option
|
||||
v-for="item in mediaServerList"
|
||||
:key="item.id"
|
||||
:label="item.id"
|
||||
:value="item.id">
|
||||
v-for="item in mediaServerList"
|
||||
:key="item.id"
|
||||
:label="item.id"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-button v-if="!recordDetail" icon="el-icon-refresh-right" circle size="mini" :loading="loading" @click="getRecordList()"></el-button>
|
||||
<!-- <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteRecord()">批量删除</el-button>-->
|
||||
<el-button icon="el-icon-refresh-right" circle size="mini" :loading="loading"
|
||||
@click="getRecordList()"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!recordDetail">
|
||||
|
||||
<!--设备列表-->
|
||||
<el-table :data="recordList" style="width: 100%" :height="winHeight">
|
||||
<el-table-column prop="app" label="应用名" >
|
||||
</el-table-column>
|
||||
<el-table-column prop="stream" label="流ID" >
|
||||
</el-table-column>
|
||||
<el-table-column prop="time" label="时间" >
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="360" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="medium" icon="el-icon-folder-opened" type="text" @click="showRecordDetail(scope.row)">查看</el-button>
|
||||
<!-- <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteRecord(scope.row)">删除</el-button>-->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
style="float: right"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="currentChange"
|
||||
:current-page="currentPage"
|
||||
:page-size="count"
|
||||
:page-sizes="[15, 25, 35, 50]"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
:total="total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
|
||||
<!--设备列表-->
|
||||
<el-table :data="recordList" style="width: 100%" :height="winHeight">
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
<el-table-column prop="app" label="应用名">
|
||||
</el-table-column>
|
||||
<el-table-column prop="stream" label="流ID" width="380">
|
||||
</el-table-column>
|
||||
<el-table-column label="开始时间">
|
||||
<template slot-scope="scope">
|
||||
{{formatTimeStamp(scope.row.startTime)}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束时间">
|
||||
<template slot-scope="scope">
|
||||
{{formatTimeStamp(scope.row.endTime)}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="时长">
|
||||
<template slot-scope="scope">
|
||||
<el-tag>{{formatTime(scope.row.timeLen)}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="fileName" label="文件名称">
|
||||
</el-table-column>
|
||||
<el-table-column prop="mediaServerId" label="流媒体">
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="medium" icon="el-icon-video-play" type="text" @click="play(scope.row)">播放
|
||||
</el-button>
|
||||
<!-- <el-button size="medium" icon="el-icon-delete" type="text" style="color: #f56c6c"-->
|
||||
<!-- @click="deleteRecord(scope.row)">删除-->
|
||||
<!-- </el-button>-->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
style="float: right"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="currentChange"
|
||||
:current-page="currentPage"
|
||||
:page-size="count"
|
||||
:page-sizes="[15, 25, 35, 50]"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
:total="total">
|
||||
</el-pagination>
|
||||
<el-dialog
|
||||
:title="playerTitle"
|
||||
:visible.sync="showPlayer"
|
||||
width="50%">
|
||||
<easyPlayer ref="recordVideoPlayer" :videoUrl="videoUrl" :height="false" ></easyPlayer>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uiHeader from '../layout/UiHeader.vue'
|
||||
import MediaServer from './service/MediaServer'
|
||||
export default {
|
||||
name: 'app',
|
||||
components: {
|
||||
uiHeader
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
mediaServerList: [], // 滅体节点列表
|
||||
mediaServerId: null, // 媒体服务
|
||||
mediaServerPath: null, // 媒体服务地址
|
||||
recordList: [], // 设备列表
|
||||
chooseRecord: null, // 媒体服务
|
||||
import uiHeader from '../layout/UiHeader.vue'
|
||||
import MediaServer from './service/MediaServer'
|
||||
import easyPlayer from './common/easyPlayer.vue'
|
||||
import moment from 'moment'
|
||||
import axios from "axios";
|
||||
|
||||
updateLooper: 0, //数据刷新轮训标志
|
||||
winHeight: window.innerHeight - 250,
|
||||
currentPage:1,
|
||||
count:15,
|
||||
total:0,
|
||||
loading: false,
|
||||
mediaServerObj : new MediaServer(),
|
||||
recordDetail: false
|
||||
export default {
|
||||
name: 'app',
|
||||
components: {
|
||||
uiHeader,easyPlayer
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
search: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
showPlayer: false,
|
||||
playerTitle: '',
|
||||
videoUrl: '',
|
||||
playerStyle: {
|
||||
"margin": "auto",
|
||||
"margin-bottom": "20px",
|
||||
"width": window.innerWidth/2 + "px",
|
||||
"height": this.winHeight/2 + "px",
|
||||
},
|
||||
mediaServerList: [], // 滅体节点列表
|
||||
mediaServerId: "", // 媒体服务
|
||||
mediaServerPath: null, // 媒体服务地址
|
||||
recordList: [], // 设备列表
|
||||
chooseRecord: null, // 媒体服务
|
||||
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
updateLooper: 0, //数据刷新轮训标志
|
||||
winHeight: window.innerHeight - 250,
|
||||
currentPage: 1,
|
||||
count: 15,
|
||||
total: 0,
|
||||
loading: false,
|
||||
mediaServerObj: new MediaServer(),
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.initData();
|
||||
},
|
||||
destroyed() {
|
||||
// this.$destroy('videojs');
|
||||
},
|
||||
methods: {
|
||||
initData: function() {
|
||||
// 获取媒体节点列表
|
||||
this.getMediaServerList();
|
||||
// this.getRecordList();
|
||||
},
|
||||
currentChange: function(val){
|
||||
this.currentPage = val;
|
||||
this.getRecordList();
|
||||
},
|
||||
handleSizeChange: function(val){
|
||||
this.count = val;
|
||||
this.getRecordList();
|
||||
},
|
||||
getMediaServerList: function (){
|
||||
let that = this;
|
||||
that.mediaServerObj.getOnlineMediaServerList((data)=>{
|
||||
that.mediaServerList = data.data;
|
||||
if (that.mediaServerList.length > 0) {
|
||||
that.mediaServerId = that.mediaServerList[0].id
|
||||
that.setMediaServerPath(that.mediaServerId);
|
||||
that.getRecordList();
|
||||
}
|
||||
})
|
||||
},
|
||||
setMediaServerPath: function (serverId) {
|
||||
let that = this;
|
||||
let i;
|
||||
for (i = 0; i < that.mediaServerList.length; i++) {
|
||||
if (serverId === that.mediaServerList[i].id) {
|
||||
break;
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
mounted() {
|
||||
this.initData();
|
||||
},
|
||||
destroyed() {
|
||||
this.$destroy('recordVideoPlayer');
|
||||
},
|
||||
methods: {
|
||||
initData: function () {
|
||||
// 获取媒体节点列表
|
||||
this.getMediaServerList();
|
||||
this.getRecordList();
|
||||
},
|
||||
currentChange: function (val) {
|
||||
this.currentPage = val;
|
||||
this.getRecordList();
|
||||
},
|
||||
handleSizeChange: function (val) {
|
||||
this.count = val;
|
||||
this.getRecordList();
|
||||
},
|
||||
getMediaServerList: function () {
|
||||
let that = this;
|
||||
that.mediaServerObj.getOnlineMediaServerList((data) => {
|
||||
that.mediaServerList = data.data;
|
||||
})
|
||||
},
|
||||
setMediaServerPath: function (serverId) {
|
||||
let that = this;
|
||||
let i;
|
||||
for (i = 0; i < that.mediaServerList.length; i++) {
|
||||
if (serverId === that.mediaServerList[i].id) {
|
||||
break;
|
||||
}
|
||||
let port = that.mediaServerList[i].httpPort;
|
||||
if (location.protocol === "https:" && that.mediaServerList[i].httpSSlPort) {
|
||||
port = that.mediaServerList[i].httpSSlPort
|
||||
}
|
||||
let port = that.mediaServerList[i].httpPort;
|
||||
if (location.protocol === "https:" && that.mediaServerList[i].httpSSlPort) {
|
||||
port = that.mediaServerList[i].httpSSlPort
|
||||
}
|
||||
that.mediaServerPath = location.protocol + "//" + that.mediaServerList[i].streamIp + ":" + port
|
||||
console.log(that.mediaServerPath)
|
||||
},
|
||||
getRecordList: function () {
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/cloud/record/list`,
|
||||
params: {
|
||||
app: '',
|
||||
stream: '',
|
||||
query: this.search,
|
||||
startTime: this.startTime,
|
||||
endTime: this.endTime,
|
||||
mediaServerId: this.mediaServerId,
|
||||
page: this.currentPage,
|
||||
count: this.count
|
||||
}
|
||||
that.mediaServerPath = location.protocol + "//" + that.mediaServerList[i].streamIp + ":" + port
|
||||
console.log(that.mediaServerPath)
|
||||
},
|
||||
getRecordList: function (){
|
||||
let that = this;
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url:`/record_proxy/${that.mediaServerId}/api/record/list`,
|
||||
params: {
|
||||
page: that.currentPage,
|
||||
count: that.count
|
||||
}).then((res) => {
|
||||
console.log(res)
|
||||
if (res.data.code === 0) {
|
||||
this.total = res.data.data.total;
|
||||
this.recordList = res.data.data.list;
|
||||
}
|
||||
this.loading = false;
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
play(row) {
|
||||
console.log(row)
|
||||
this.chooseRecord = row;
|
||||
this.showPlayer = true;
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/cloud/record/play/path`,
|
||||
params: {
|
||||
recordId: row.id,
|
||||
}
|
||||
}).then((res) => {
|
||||
console.log(res)
|
||||
if (res.data.code === 0) {
|
||||
if (location.protocol === "https:") {
|
||||
this.videoUrl = res.data.data.httpsPath;
|
||||
}else {
|
||||
this.videoUrl = res.data.data.httpPath;
|
||||
}
|
||||
}).then(function (res) {
|
||||
console.log(res)
|
||||
if (res.data.code === 0) {
|
||||
that.total = res.data.data.total;
|
||||
that.recordList = res.data.data.list;
|
||||
console.log(222 )
|
||||
console.log(this.videoUrl )
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
getFileBasePath(item) {
|
||||
let basePath = ""
|
||||
if (axios.defaults.baseURL.startsWith("http")) {
|
||||
basePath = `${axios.defaults.baseURL}/record_proxy/${item.mediaServerId}`
|
||||
}else {
|
||||
basePath = `${window.location.origin}${axios.defaults.baseURL}/record_proxy/${item.mediaServerId}`
|
||||
}
|
||||
that.loading = false;
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
that.loading = false;
|
||||
});
|
||||
},
|
||||
backToList(){
|
||||
this.recordDetail= false;
|
||||
},
|
||||
chooseMediaChange(val){
|
||||
console.log(val)
|
||||
this.total = 0;
|
||||
this.recordList = [];
|
||||
this.setMediaServerPath(val);
|
||||
this.getRecordList();
|
||||
},
|
||||
showRecordDetail(row){
|
||||
this.recordDetail = true;
|
||||
this.chooseRecord = row;
|
||||
// 查询是否存在录像
|
||||
// this.$axios({
|
||||
// method: 'delete',
|
||||
// url:`/record_proxy/api/record/delete`,
|
||||
// params: {
|
||||
// page: this.currentPage,
|
||||
// count: this.count
|
||||
// }
|
||||
// }).then((res) => {
|
||||
// console.log(res)
|
||||
// this.total = res.data.data.total;
|
||||
// this.recordList = res.data.data.list;
|
||||
// }).catch(function (error) {
|
||||
// console.log(error);
|
||||
// });
|
||||
this.$router.push(`/cloudRecordDetail/${row.app}/${row.stream}`)
|
||||
},
|
||||
deleteRecord(){
|
||||
// TODO
|
||||
let that = this;
|
||||
this.$axios({
|
||||
method: 'delete',
|
||||
url:`/record_proxy/api/record/delete`,
|
||||
params: {
|
||||
page: that.currentPage,
|
||||
count: that.count
|
||||
}
|
||||
}).then(function (res) {
|
||||
console.log(res)
|
||||
if (res.data.code === 0) {
|
||||
that.total = res.data.data.total;
|
||||
that.recordList = res.data.data.list;
|
||||
}
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
return basePath;
|
||||
},
|
||||
deleteRecord() {
|
||||
// TODO
|
||||
let that = this;
|
||||
this.$axios({
|
||||
method: 'delete',
|
||||
url: `/record_proxy/api/record/delete`,
|
||||
params: {
|
||||
page: that.currentPage,
|
||||
count: that.count
|
||||
}
|
||||
}).then(function (res) {
|
||||
console.log(res)
|
||||
if (res.data.code === 0) {
|
||||
that.total = res.data.data.total;
|
||||
that.recordList = res.data.data.list;
|
||||
}
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
formatTime(time) {
|
||||
const h = parseInt(time / 3600)
|
||||
const minute = parseInt(time / 60 % 60)
|
||||
const second = Math.ceil(time % 60)
|
||||
|
||||
return (h > 0 ? h + `小时` : '') + (minute > 0 ? minute + '分' : '') + second + '秒'
|
||||
},
|
||||
formatTimeStamp(time) {
|
||||
return moment.unix(time).format('yyyy-MM-DD HH:mm:ss')
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
@ -37,13 +37,13 @@
|
||||
<div class="record-list-box" :style="recordListStyle">
|
||||
<ul v-if="detailFiles.length >0" class="infinite-list record-list" v-infinite-scroll="infiniteScroll" >
|
||||
<li v-for="(item,index) in detailFiles" :key="index" class="infinite-list-item record-list-item" >
|
||||
<el-tag v-if="choosedFile !== item.filename" @click="chooseFile(item)">
|
||||
<el-tag v-if="choosedFile !== item.fileName" @click="chooseFile(item)">
|
||||
<i class="el-icon-video-camera" ></i>
|
||||
{{ getFileShowName(item.fileName) }}
|
||||
{{ getFileShowName(item) }}
|
||||
</el-tag>
|
||||
<el-tag type="danger" v-if="choosedFile === item.filename">
|
||||
<el-tag type="danger" v-if="choosedFile === item.fileName">
|
||||
<i class="el-icon-video-camera" ></i>
|
||||
{{ getFileShowName(item.fileName) }}
|
||||
{{ getFileShowName(item) }}
|
||||
</el-tag>
|
||||
<a class="el-icon-download" style="color: #409EFF;font-weight: 600;margin-left: 10px;"
|
||||
:href="`${getFileBasePath(item)}/download.html?url=download/${app}/${stream}/${chooseDate}/${item.fileName}`"
|
||||
@ -135,7 +135,7 @@
|
||||
<script>
|
||||
// TODO 根据查询的时间列表设置滑轨的最大值与最小值,
|
||||
import uiHeader from '../layout/UiHeader.vue'
|
||||
import player from './dialog/easyPlayer.vue'
|
||||
import player from './common/easyPlayer.vue'
|
||||
import moment from 'moment'
|
||||
import axios from "axios";
|
||||
export default {
|
||||
@ -319,7 +319,7 @@
|
||||
this.choosedFile = "";
|
||||
}else {
|
||||
this.choosedFile = file.fileName;
|
||||
this.videoUrl = `${this.getFileBasePath(file)}/download/${this.app}/${this.stream}/${this.chooseDate}/${this.choosedFile}`
|
||||
this.videoUrl = `${this.getFileBasePath(file)}/download/${this.app}/${this.stream}/${this.chooseDate}/${file.fileName}`
|
||||
console.log(this.videoUrl)
|
||||
}
|
||||
|
||||
@ -327,9 +327,8 @@
|
||||
backToList() {
|
||||
this.$router.back()
|
||||
},
|
||||
getFileShowName(name) {
|
||||
return name.substring(0, 2) + ":" + name.substring(2, 4) + ":" + name.substring(4, 6) + "-" +
|
||||
name.substring(7, 9) + ":" + name.substring(9, 11) + ":" + name.substring(11, 13)
|
||||
getFileShowName(item) {
|
||||
return moment.unix(item.startTime).format('HH:mm:ss') + "-" + moment.unix(item.endTime).format('HH:mm:ss')
|
||||
},
|
||||
chooseMediaChange() {
|
||||
|
||||
@ -376,13 +375,8 @@
|
||||
},
|
||||
getTimeForFile(file){
|
||||
console.log(file)
|
||||
let timeStr = file.fileName.substring(0, 17);
|
||||
if(timeStr.indexOf("~") > 0){
|
||||
timeStr = timeStr.replaceAll("-",":")
|
||||
}
|
||||
let timeArr = timeStr.split("-");
|
||||
let starTime = new Date(this.chooseDate + " " + timeArr[0]);
|
||||
let endTime = new Date(this.chooseDate + " " + timeArr[1]);
|
||||
let starTime = new Date(file.startTime * 1000);
|
||||
let endTime = new Date(file.endTime * 1000);
|
||||
if(this.checkIsOver24h(starTime,endTime)){
|
||||
endTime = new Date(this.chooseDate + " " + "23:59:59");
|
||||
}
|
||||
@ -486,12 +480,13 @@
|
||||
let that = this;
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url:`/record_proxy/${that.mediaServerId}/api/record/file/download/task/add`,
|
||||
url:`/api/cloud/record/task/add`,
|
||||
params: {
|
||||
app: that.app,
|
||||
stream: that.stream,
|
||||
startTime: moment(this.taskTimeRange[0]).format('YYYY-MM-DD HH:mm:ss'),
|
||||
endTime: moment(this.taskTimeRange[1]).format('YYYY-MM-DD HH:mm:ss'),
|
||||
app: this.app,
|
||||
stream: this.stream,
|
||||
mediaServerId: this.mediaServerId,
|
||||
startTime: moment(this.taskTimeRange[0]).format('YYYY-MM-DD HH:mm:ss'),
|
||||
endTime: moment(this.taskTimeRange[1]).format('YYYY-MM-DD HH:mm:ss'),
|
||||
}
|
||||
}).then(function (res) {
|
||||
if (res.data.code === 0 ) {
|
||||
@ -511,8 +506,9 @@
|
||||
let that = this;
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url:`/record_proxy/${that.mediaServerId}/api/record/file/download/task/list`,
|
||||
url:`/api/cloud/record/task/list`,
|
||||
params: {
|
||||
mediaServerId: this.mediaServerId,
|
||||
isEnd: isEnd,
|
||||
}
|
||||
}).then(function (res) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div id="easyplayer"></div>
|
||||
<div id="easyplayer" ></div>
|
||||
</template>
|
||||
|
||||
<script>
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div ref="container" @dblclick="fullscreenSwich"
|
||||
style="width:100%;height:100%;background-color: #000000;margin:0 auto;position: relative;">
|
||||
style="width:100%;height:100%;min-height: 200px;background-color: #000000;margin:0 auto;position: relative;">
|
||||
<div class="buttons-box" id="buttonsBox">
|
||||
<div class="buttons-box-left">
|
||||
<i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick"></i>
|
||||
@ -80,9 +80,10 @@ export default {
|
||||
height = clientHeight
|
||||
width = (16 / 9) * height
|
||||
}
|
||||
|
||||
dom.style.width = width + 'px';
|
||||
dom.style.height = height + "px";
|
||||
if (width > 0 && height > 0) {
|
||||
dom.style.width = width + 'px';
|
||||
dom.style.height = height + "px";
|
||||
}
|
||||
},
|
||||
create() {
|
||||
let options = {
|
||||
|
@ -20,7 +20,7 @@
|
||||
<el-input v-model="form.name" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码" prop="password">
|
||||
<el-input type="password" v-model="form.password" clearable></el-input>
|
||||
<el-input v-model="form.password" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="收流IP" prop="sdpIp">
|
||||
<el-input type="sdpIp" v-model="form.sdpIp" clearable></el-input>
|
||||
|
@ -6,8 +6,7 @@
|
||||
<el-progress :percentage="percentage"></el-progress>
|
||||
</el-col>
|
||||
<el-col :span="6" >
|
||||
<el-button icon="el-icon-download" v-if="percentage < 100" size="mini" title="点击下载可将以缓存部分下载到本地" @click="download()">停止缓存并下载</el-button>
|
||||
<el-button icon="el-icon-download" v-if="downloadFile" size="mini" title="点击下载" @click="downloadFileClientEvent()">点击下载</el-button>
|
||||
<el-button icon="el-icon-download" v-if="downloadFile" size="mini" title="点击下载" @click="downloadFileClientEvent()">下载</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-dialog>
|
||||
@ -27,7 +26,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title: "四倍速下载中...",
|
||||
title: "下载中...",
|
||||
deviceId: "",
|
||||
channelId: "",
|
||||
app: "",
|
||||
@ -39,7 +38,6 @@ export default {
|
||||
streamInfo: null,
|
||||
taskId: null,
|
||||
getProgressRun: false,
|
||||
getProgressForFileRun: false,
|
||||
timer: null,
|
||||
downloadFile: null,
|
||||
|
||||
@ -62,7 +60,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
if (this.percentage == 100 ) {
|
||||
this.getFileDownload();
|
||||
|
||||
return;
|
||||
}
|
||||
setTimeout( ()=>{
|
||||
@ -75,7 +73,6 @@ export default {
|
||||
method: 'get',
|
||||
url: `/api/gb_record/download/progress/${this.deviceId}/${this.channelId}/${this.stream}`
|
||||
}).then((res)=> {
|
||||
console.log(res)
|
||||
if (res.data.code === 0) {
|
||||
this.streamInfo = res.data.data;
|
||||
if (parseFloat(res.data.progress) == 1) {
|
||||
@ -83,6 +80,15 @@ export default {
|
||||
}else {
|
||||
this.percentage = (parseFloat(res.data.data.progress)*100).toFixed(1);
|
||||
}
|
||||
if (this.streamInfo.downLoadFilePath) {
|
||||
if (location.protocol === "https:") {
|
||||
this.downloadFile = this.streamInfo.downLoadFilePath.httpsPath;
|
||||
}else {
|
||||
this.downloadFile = this.streamInfo.downLoadFilePath.httpPath;
|
||||
}
|
||||
this.getProgressRun = false;
|
||||
this.downloadFileClientEvent()
|
||||
}
|
||||
if (callback)callback();
|
||||
}else {
|
||||
this.$message({
|
||||
@ -108,24 +114,11 @@ export default {
|
||||
}
|
||||
this.showDialog=false;
|
||||
this.getProgressRun = false;
|
||||
this.getProgressForFileRun = false;
|
||||
},
|
||||
gbScale: function (scale){
|
||||
this.scale = scale;
|
||||
},
|
||||
download: function (){
|
||||
this.getProgressRun = false;
|
||||
if (this.streamInfo != null ) {
|
||||
if (this.streamInfo.progress < 1) {
|
||||
// 发送停止缓存
|
||||
this.stopDownloadRecord((res)=>{
|
||||
this.getFileDownload()
|
||||
})
|
||||
}else {
|
||||
this.getFileDownload()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
stopDownloadRecord: function (callback) {
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
@ -134,74 +127,20 @@ export default {
|
||||
if (callback) callback(res)
|
||||
});
|
||||
},
|
||||
getFileDownload: function (){
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url:`/record_proxy/${this.mediaServerId}/api/record/file/download/task/add`,
|
||||
params: {
|
||||
app: this.app,
|
||||
stream: this.stream,
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
}
|
||||
}).then((res) =>{
|
||||
if (res.data.code === 0 ) {
|
||||
// 查询进度
|
||||
this.title = "录像文件处理中..."
|
||||
this.taskId = res.data.data;
|
||||
this.percentage = 0.0;
|
||||
this.getProgressForFileRun = true;
|
||||
this.getProgressForFileTimer();
|
||||
}
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
getProgressForFileTimer: function (){
|
||||
if (!this.getProgressForFileRun || this.percentage == 100) {
|
||||
return;
|
||||
}
|
||||
setTimeout( ()=>{
|
||||
if (!this.showDialog) return;
|
||||
this.getProgressForFile(this.getProgressForFileTimer)
|
||||
}, 1000)
|
||||
},
|
||||
getProgressForFile: function (callback){
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url:`/record_proxy/${this.mediaServerId}/api/record/file/download/task/list`,
|
||||
params: {
|
||||
app: this.app,
|
||||
stream: this.stream,
|
||||
taskId: this.taskId,
|
||||
isEnd: true,
|
||||
}
|
||||
}).then((res) => {
|
||||
console.log(res)
|
||||
if (res.data.code === 0) {
|
||||
if (res.data.data.length === 0){
|
||||
this.percentage = 0
|
||||
// 往往在多次请求后(实验五分钟的视频是三次请求),才会返回数据,第一次请求通常是返回空数组
|
||||
if (callback)callback()
|
||||
return
|
||||
}
|
||||
// res.data.data应是数组类型
|
||||
this.percentage = parseFloat(res.data.data[0].percentage)*100
|
||||
if (res.data.data[0].percentage === '1') {
|
||||
this.getProgressForFileRun = false;
|
||||
this.downloadFile = res.data.data[0].downloadFile
|
||||
this.title = "文件处理完成,点击按扭下载"
|
||||
// window.open(res.data.data[0].downloadFile)
|
||||
}else {
|
||||
if (callback)callback()
|
||||
}
|
||||
}
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
downloadFileClientEvent: function (){
|
||||
window.open(this.downloadFile )
|
||||
// window.open(this.downloadFile )
|
||||
|
||||
let x = new XMLHttpRequest();
|
||||
x.open("GET", this.downloadFile, true);
|
||||
x.responseType = 'blob';
|
||||
x.onload=(e)=> {
|
||||
let url = window.URL.createObjectURL(x.response)
|
||||
let a = document.createElement('a');
|
||||
a.href = url
|
||||
a.download = this.deviceId + "-" + this.channelId + ".mp4";
|
||||
a.click()
|
||||
}
|
||||
x.send();
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
|
0
web_src/static/js/jessibuca/decoder.wasm
Normal file → Executable file
0
web_src/static/js/jessibuca/decoder.wasm
Normal file → Executable file
File diff suppressed because one or more lines are too long
63
打包/config/assist-application.yml
Executable file
63
打包/config/assist-application.yml
Executable file
@ -0,0 +1,63 @@
|
||||
spring:
|
||||
# REDIS数据库配置
|
||||
redis:
|
||||
# [可选] 超时时间
|
||||
timeout: 10000
|
||||
# 以下为单机配置
|
||||
# [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
|
||||
host: 127.0.0.1
|
||||
# [必须修改] 端口号
|
||||
port: 6379
|
||||
# [可选] 数据库 DB
|
||||
database: 1
|
||||
# [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
|
||||
password: adminadmin123.
|
||||
# 以下为集群配置
|
||||
# cluster:
|
||||
# nodes: 192.168.1.242:7001
|
||||
# password: 4767cb971b40a1300fa09b7f87b09d1c
|
||||
|
||||
# [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
|
||||
server:
|
||||
port: 18081
|
||||
# [可选] HTTPS配置, 默认不开启
|
||||
ssl:
|
||||
# [可选] 是否开启HTTPS访问
|
||||
enabled: false
|
||||
# [可选] 证书文件路径,放置在resource/目录下即可,修改xxx为文件名
|
||||
key-store: classpath:xxx.jks
|
||||
# [可选] 证书密码
|
||||
key-password: password
|
||||
# [可选] 证书类型, 默认为jks,根据实际修改
|
||||
key-store-type: JKS
|
||||
|
||||
# [根据业务需求配置]
|
||||
userSettings:
|
||||
# [必选 ] 服务ID
|
||||
id: 334533
|
||||
# [可选 ] 录像下载合成临时文件保存时长, 不配置默认取值recordDay(单位: 天)每天晚12点自动对过期文件执行清理
|
||||
# recordTempDay: 7
|
||||
# [必选 ] ffmpeg路径
|
||||
ffmpeg: lib/ffmpeg
|
||||
# [必选 ] ffprobe路径, 一般安装ffmpeg就会自带, 一般跟ffmpeg在同一目录,用于查询文件的信息
|
||||
ffprobe: lib/ffprobe
|
||||
# [可选 ] 限制 ffmpeg 合并文件使用的线程数,间接限制cpu使用率, 默认2 限制到50%
|
||||
threads: 2
|
||||
|
||||
swagger-ui:
|
||||
enabled: true
|
||||
# [可选] 日志配置, 一般不需要改
|
||||
logging:
|
||||
file:
|
||||
name: logs/wvp.log
|
||||
max-history: 30
|
||||
max-size: 10MB
|
||||
total-size-cap: 300MB
|
||||
level:
|
||||
root: WARN
|
||||
top:
|
||||
panll:
|
||||
assist: info
|
||||
net:
|
||||
bramp:
|
||||
ffmpeg: error
|
166
打包/config/config.ini
Executable file
166
打包/config/config.ini
Executable file
@ -0,0 +1,166 @@
|
||||
; auto-generated by mINI class {
|
||||
|
||||
[api]
|
||||
apiDebug=1
|
||||
defaultSnap=./www/logo.png
|
||||
secret=034523TF8yT83wh5Wvz73f7
|
||||
snapRoot=./www/snap/
|
||||
|
||||
[cluster]
|
||||
origin_url=
|
||||
retry_count=3
|
||||
timeout_sec=15
|
||||
|
||||
[ffmpeg]
|
||||
bin=/usr/bin/ffmpeg
|
||||
cmd=%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s
|
||||
log=./ffmpeg/ffmpeg.log
|
||||
restart_sec=0
|
||||
snap=%s -i %s -y -f mjpeg -t 0.001 %s
|
||||
|
||||
[general]
|
||||
check_nvidia_dev=1
|
||||
enableVhost=0
|
||||
enable_ffmpeg_log=0
|
||||
flowThreshold=1024
|
||||
maxStreamWaitMS=15000
|
||||
mediaServerId=GQ3TF8yT83wh5Wvz
|
||||
mergeWriteMS=0
|
||||
resetWhenRePlay=1
|
||||
streamNoneReaderDelayMS=15000
|
||||
unready_frame_cache=100
|
||||
wait_add_track_ms=3000
|
||||
wait_track_ready_ms=10000
|
||||
|
||||
[hls]
|
||||
broadcastRecordTs=0
|
||||
deleteDelaySec=10
|
||||
fileBufSize=65536
|
||||
segDur=2
|
||||
segKeep=0
|
||||
segNum=3
|
||||
segRetain=5
|
||||
|
||||
[hook]
|
||||
admin_params=secret=034523TF8yT83wh5Wvz73f7
|
||||
alive_interval=30.000000
|
||||
enable=1
|
||||
on_flow_report=
|
||||
on_http_access=
|
||||
on_play=http://192.168.1.3:18082/index/hook/on_play
|
||||
on_publish=http://192.168.1.3:18082/index/hook/on_publish
|
||||
on_record_mp4=
|
||||
on_record_ts=
|
||||
on_rtp_server_timeout=http://192.168.1.3:18082/index/hook/on_rtp_server_timeout
|
||||
on_rtsp_auth=
|
||||
on_rtsp_realm=
|
||||
on_send_rtp_stopped=http://192.168.1.3:18082/index/hook/on_send_rtp_stopped
|
||||
on_server_keepalive=http://192.168.1.3:18082/index/hook/on_server_keepalive
|
||||
on_server_started=http://192.168.1.3:18082/index/hook/on_server_started
|
||||
on_shell_login=
|
||||
on_stream_changed=http://192.168.1.3:18082/index/hook/on_stream_changed
|
||||
on_stream_none_reader=http://192.168.1.3:18082/index/hook/on_stream_none_reader
|
||||
on_stream_not_found=http://192.168.1.3:18082/index/hook/on_stream_not_found
|
||||
retry=1
|
||||
retry_delay=3.000000
|
||||
timeoutSec=20
|
||||
|
||||
[http]
|
||||
charSet=utf-8
|
||||
dirMenu=1
|
||||
forbidCacheSuffix=
|
||||
forwarded_ip_header=
|
||||
keepAliveSecond=15
|
||||
maxReqSize=40960
|
||||
notFound=<html><head><title>404 Not Found</title></head><body bgcolor="white"><center><h1>您访问的资源不存在!</h1></center><hr><center>ZLMediaKit(git hash:f6cba98/2023-02-06T14:18:21+08:00,branch:master,build time:2023-02-07T10:51:47)</center></body></html>
|
||||
port=6080
|
||||
rootPath=./www
|
||||
sendBufSize=65536
|
||||
sslport=16080
|
||||
virtualPath=
|
||||
|
||||
[multicast]
|
||||
addrMax=239.255.255.255
|
||||
addrMin=239.0.0.0
|
||||
udpTTL=64
|
||||
|
||||
[protocol]
|
||||
add_mute_audio=1
|
||||
continue_push_ms=3000
|
||||
enable_audio=1
|
||||
enable_fmp4=1
|
||||
enable_hls=1
|
||||
enable_mp4=0
|
||||
enable_rtmp=1
|
||||
enable_rtsp=1
|
||||
enable_ts=1
|
||||
fmp4_demand=0
|
||||
hls_demand=0
|
||||
hls_save_path=./www
|
||||
modify_stamp=0
|
||||
mp4_as_player=0
|
||||
mp4_max_second=3600
|
||||
mp4_save_path=./www
|
||||
rtmp_demand=0
|
||||
rtsp_demand=0
|
||||
ts_demand=0
|
||||
|
||||
[record]
|
||||
appName=record
|
||||
fastStart=0
|
||||
fileBufSize=65536
|
||||
fileRepeat=0
|
||||
sampleMS=500
|
||||
|
||||
[rtc]
|
||||
externIP=192.168.1.3
|
||||
port=8000
|
||||
preferredCodecA=PCMA,PCMU,opus,mpeg4-generic
|
||||
preferredCodecV=H264,H265,AV1,VP9,VP8
|
||||
rembBitRate=0
|
||||
tcpPort=8000
|
||||
timeoutSec=15
|
||||
|
||||
[rtmp]
|
||||
handshakeSecond=15
|
||||
keepAliveSecond=15
|
||||
modifyStamp=0
|
||||
port=1935
|
||||
sslport=19350
|
||||
|
||||
[rtp]
|
||||
audioMtuSize=600
|
||||
lowLatency=0
|
||||
rtpMaxSize=10
|
||||
videoMtuSize=1400
|
||||
|
||||
[rtp_proxy]
|
||||
dumpDir=
|
||||
h264_pt=98
|
||||
h265_pt=99
|
||||
opus_pt=100
|
||||
port=10000
|
||||
port_range=40000-40500
|
||||
ps_pt=96
|
||||
timeoutSec=15
|
||||
|
||||
[rtsp]
|
||||
authBasic=0
|
||||
directProxy=1
|
||||
handshakeSecond=15
|
||||
keepAliveSecond=15
|
||||
lowLatency=0
|
||||
port=10554
|
||||
sslport=
|
||||
|
||||
[shell]
|
||||
maxReqSize=1024
|
||||
port=9000
|
||||
|
||||
[srt]
|
||||
latencyMul=4
|
||||
pktBufSize=8192
|
||||
port=9000
|
||||
timeoutSec=5
|
||||
|
||||
; } ---
|
120
打包/config/wvp-application.yml
Executable file
120
打包/config/wvp-application.yml
Executable file
@ -0,0 +1,120 @@
|
||||
spring:
|
||||
# [可选]上传文件大小限制
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 10MB
|
||||
max-request-size: 100MB
|
||||
# REDIS数据库配置
|
||||
redis:
|
||||
# [可选] 超时时间
|
||||
timeout: 10000
|
||||
# 以下为单机配置
|
||||
# [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
|
||||
host: 127.0.0.1
|
||||
# # [必须修改] 端口号
|
||||
port: 6379
|
||||
# [可选] 数据库 DB
|
||||
database: 1
|
||||
# [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
|
||||
password: adminadmin123.
|
||||
# 以下为集群配置
|
||||
# cluster:
|
||||
# nodes: 192.168.1.66:9001,192.168.1.66:9002,192.168.1.66:9003,192.168.1.66:9004,192.168.1.66:9005,192.168.1.66:9006
|
||||
# password: adminadmin123.
|
||||
# [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置
|
||||
# mysql数据源
|
||||
datasource:
|
||||
# kingbase配置
|
||||
# type: com.zaxxer.hikari.HikariDataSource
|
||||
# driver-class-name: com.kingbase8.Driver
|
||||
# url: jdbc:kingbase8://192.168.1.55:54321/wvp?useUnicode=true&characterEncoding=utf8
|
||||
# username: system
|
||||
# password: system
|
||||
# postgresql配置
|
||||
# type: com.zaxxer.hikari.HikariDataSource
|
||||
# driver-class-name: org.postgresql.Driver
|
||||
# url: jdbc:postgresql://192.168.1.242:3306/242wvp
|
||||
# username: root
|
||||
# password: SYceshizu1234
|
||||
# mysql配置
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://192.168.1.242:3306/242wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: SYceshizu1234
|
||||
|
||||
|
||||
# kingbase 和 postgresql需要开启这个配置
|
||||
#pagehelper:
|
||||
# helper-dialect: postgresql
|
||||
|
||||
#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
|
||||
server:
|
||||
port: 18080
|
||||
|
||||
# 作为28181服务器的配置
|
||||
sip:
|
||||
# [必须修改] 本机的IP
|
||||
ip: 192.168.1.3
|
||||
# [可选] 28181服务监听的端口
|
||||
port: 15060
|
||||
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
|
||||
# 后两位为行业编码,定义参照附录D.3
|
||||
# 3701020049标识山东济南历下区 信息行业接入
|
||||
# [可选]
|
||||
domain: 3402000001
|
||||
# [可选]
|
||||
id: 34020000013000000001
|
||||
# [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验
|
||||
password: 12345678
|
||||
|
||||
#zlm 默认服务器配置
|
||||
media:
|
||||
# [必须修改] zlm服务器唯一id,用于触发hook时区别是哪台服务器,general.mediaServerId
|
||||
id: GQ3TF8yT83wh5Wvz
|
||||
# [必须修改] zlm服务器的内网IP
|
||||
ip: 192.168.1.3
|
||||
# [必须修改] zlm服务器的http.port
|
||||
http-port: 6080
|
||||
# [可选] zlm服务器的hook.admin_params=secret
|
||||
secret: 034523TF8yT83wh5Wvz73f7
|
||||
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
|
||||
rtp:
|
||||
# [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
|
||||
enable: true
|
||||
# [可选] 在此范围内选择端口用于媒体流传输,
|
||||
port-range: 30000,30500 # 端口范围
|
||||
# [可选] 国标级联在此范围内选择端口发送媒体流,请不要与收流端口范围重合
|
||||
send-port-range: 50502,50506 # 端口范围
|
||||
# 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
|
||||
record-assist-port: 18089
|
||||
# 录像路径
|
||||
record-path: ./www/record
|
||||
# 录像保存时长
|
||||
record-day: 7
|
||||
# [可选] 日志配置, 一般不需要改
|
||||
logging:
|
||||
config: classpath:logback-spring-local.xml
|
||||
|
||||
# [根据业务需求配置]
|
||||
user-settings:
|
||||
server-id: 741266
|
||||
auto-apply-play: true
|
||||
interface-authentication: true
|
||||
interface-authentication-excludes:
|
||||
- /api/v1/**
|
||||
- /api/media/stream_info_by_app_and_stream
|
||||
- /api/v1/control/ptz
|
||||
- /api/cloud/record/*/**
|
||||
# 推流直播是否录制
|
||||
record-push-live: true
|
||||
# 国标是否录制
|
||||
record-sip: false
|
||||
# 使用推流状态作为推流通道状态
|
||||
use-pushing-as-status: false
|
||||
# 设备上线时是否自动同步通道
|
||||
sync-channel-on-device-online: false
|
||||
# 消息通道功能-缺少国标ID是否给所有上级发送消息
|
||||
send-to-platforms-when-id-lost: false
|
||||
|
||||
|
323
数据库/2.6.9/初始化-mysql-2.6.9.sql
Normal file
323
数据库/2.6.9/初始化-mysql-2.6.9.sql
Normal file
@ -0,0 +1,323 @@
|
||||
/*建表*/
|
||||
create table wvp_device (
|
||||
id serial primary key ,
|
||||
device_id character varying(50) not null ,
|
||||
name character varying(255),
|
||||
manufacturer character varying(255),
|
||||
model character varying(255),
|
||||
firmware character varying(255),
|
||||
transport character varying(50),
|
||||
stream_mode character varying(50),
|
||||
on_line bool default false,
|
||||
register_time character varying(50),
|
||||
keepalive_time character varying(50),
|
||||
ip character varying(50),
|
||||
create_time character varying(50),
|
||||
update_time character varying(50),
|
||||
port integer,
|
||||
expires integer,
|
||||
subscribe_cycle_for_catalog integer DEFAULT 0,
|
||||
subscribe_cycle_for_mobile_position integer DEFAULT 0,
|
||||
mobile_position_submission_interval integer DEFAULT 5,
|
||||
subscribe_cycle_for_alarm integer DEFAULT 0,
|
||||
host_address character varying(50),
|
||||
charset character varying(50),
|
||||
ssrc_check bool default false,
|
||||
geo_coord_sys character varying(50),
|
||||
media_server_id character varying(50),
|
||||
custom_name character varying(255),
|
||||
sdp_ip character varying(50),
|
||||
local_ip character varying(50),
|
||||
password character varying(255),
|
||||
as_message_channel bool default false,
|
||||
keepalive_interval_time integer,
|
||||
switch_primary_sub_stream bool default false,
|
||||
broadcast_push_after_ack bool default false,
|
||||
constraint uk_device_device unique (device_id)
|
||||
);
|
||||
|
||||
create table wvp_device_alarm (
|
||||
id serial primary key ,
|
||||
device_id character varying(50) not null,
|
||||
channel_id character varying(50) not null,
|
||||
alarm_priority character varying(50),
|
||||
alarm_method character varying(50),
|
||||
alarm_time character varying(50),
|
||||
alarm_description character varying(255),
|
||||
longitude double precision,
|
||||
latitude double precision,
|
||||
alarm_type character varying(50),
|
||||
create_time character varying(50) not null
|
||||
);
|
||||
|
||||
create table wvp_device_channel (
|
||||
id serial primary key ,
|
||||
channel_id character varying(50) not null,
|
||||
name character varying(255),
|
||||
custom_name character varying(255),
|
||||
manufacture character varying(50),
|
||||
model character varying(50),
|
||||
owner character varying(50),
|
||||
civil_code character varying(50),
|
||||
block character varying(50),
|
||||
address character varying(50),
|
||||
parent_id character varying(50),
|
||||
safety_way integer,
|
||||
register_way integer,
|
||||
cert_num character varying(50),
|
||||
certifiable integer,
|
||||
err_code integer,
|
||||
end_time character varying(50),
|
||||
secrecy character varying(50),
|
||||
ip_address character varying(50),
|
||||
port integer,
|
||||
password character varying(255),
|
||||
ptz_type integer,
|
||||
custom_ptz_type integer,
|
||||
status bool default false,
|
||||
longitude double precision,
|
||||
custom_longitude double precision,
|
||||
latitude double precision,
|
||||
custom_latitude double precision,
|
||||
stream_id character varying(255),
|
||||
device_id character varying(50) not null,
|
||||
parental character varying(50),
|
||||
has_audio bool default false,
|
||||
create_time character varying(50) not null,
|
||||
update_time character varying(50) not null,
|
||||
sub_count integer,
|
||||
longitude_gcj02 double precision,
|
||||
latitude_gcj02 double precision,
|
||||
longitude_wgs84 double precision,
|
||||
latitude_wgs84 double precision,
|
||||
business_group_id character varying(50),
|
||||
gps_time character varying(50),
|
||||
constraint uk_wvp_device_channel_unique_device_channel unique (device_id, channel_id)
|
||||
);
|
||||
|
||||
create table wvp_device_mobile_position (
|
||||
id serial primary key,
|
||||
device_id character varying(50) not null,
|
||||
channel_id character varying(50) not null,
|
||||
device_name character varying(255),
|
||||
time character varying(50),
|
||||
longitude double precision,
|
||||
latitude double precision,
|
||||
altitude double precision,
|
||||
speed double precision,
|
||||
direction double precision,
|
||||
report_source character varying(50),
|
||||
longitude_gcj02 double precision,
|
||||
latitude_gcj02 double precision,
|
||||
longitude_wgs84 double precision,
|
||||
latitude_wgs84 double precision,
|
||||
create_time character varying(50)
|
||||
);
|
||||
|
||||
create table wvp_gb_stream (
|
||||
gb_stream_id serial primary key,
|
||||
app character varying(255) not null,
|
||||
stream character varying(255) not null,
|
||||
gb_id character varying(50) not null,
|
||||
name character varying(255),
|
||||
longitude double precision,
|
||||
latitude double precision,
|
||||
stream_type character varying(50),
|
||||
media_server_id character varying(50),
|
||||
create_time character varying(50),
|
||||
constraint uk_gb_stream_unique_gb_id unique (gb_id),
|
||||
constraint uk_gb_stream_unique_app_stream unique (app, stream)
|
||||
);
|
||||
|
||||
create table wvp_log (
|
||||
id serial primary key ,
|
||||
name character varying(50),
|
||||
type character varying(50),
|
||||
uri character varying(200),
|
||||
address character varying(50),
|
||||
result character varying(50),
|
||||
timing bigint,
|
||||
username character varying(50),
|
||||
create_time character varying(50)
|
||||
);
|
||||
|
||||
create table wvp_media_server (
|
||||
id character varying(255) primary key ,
|
||||
ip character varying(50),
|
||||
hook_ip character varying(50),
|
||||
sdp_ip character varying(50),
|
||||
stream_ip character varying(50),
|
||||
http_port integer,
|
||||
http_ssl_port integer,
|
||||
rtmp_port integer,
|
||||
rtmp_ssl_port integer,
|
||||
rtp_proxy_port integer,
|
||||
rtsp_port integer,
|
||||
rtsp_ssl_port integer,
|
||||
auto_config bool default false,
|
||||
secret character varying(50),
|
||||
rtp_enable bool default false,
|
||||
rtp_port_range character varying(50),
|
||||
send_rtp_port_range character varying(50),
|
||||
record_assist_port integer,
|
||||
default_server bool default false,
|
||||
create_time character varying(50),
|
||||
update_time character varying(50),
|
||||
hook_alive_interval integer,
|
||||
record_path character varying(255),
|
||||
record_day integer default 7,
|
||||
constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
|
||||
);
|
||||
|
||||
create table wvp_platform (
|
||||
id serial primary key ,
|
||||
enable bool default false,
|
||||
name character varying(255),
|
||||
server_gb_id character varying(50),
|
||||
server_gb_domain character varying(50),
|
||||
server_ip character varying(50),
|
||||
server_port integer,
|
||||
device_gb_id character varying(50),
|
||||
device_ip character varying(50),
|
||||
device_port character varying(50),
|
||||
username character varying(255),
|
||||
password character varying(50),
|
||||
expires character varying(50),
|
||||
keep_timeout character varying(50),
|
||||
transport character varying(50),
|
||||
character_set character varying(50),
|
||||
catalog_id character varying(50),
|
||||
ptz bool default false,
|
||||
rtcp bool default false,
|
||||
status bool default false,
|
||||
start_offline_push bool default false,
|
||||
administrative_division character varying(50),
|
||||
catalog_group integer,
|
||||
create_time character varying(50),
|
||||
update_time character varying(50),
|
||||
as_message_channel bool default false,
|
||||
auto_push_channel bool default false,
|
||||
constraint uk_platform_unique_server_gb_id unique (server_gb_id)
|
||||
);
|
||||
|
||||
create table wvp_platform_catalog (
|
||||
id character varying(50),
|
||||
platform_id character varying(50),
|
||||
name character varying(255),
|
||||
parent_id character varying(50),
|
||||
civil_code character varying(50),
|
||||
business_group_id character varying(50),
|
||||
constraint uk_platform_catalog_id_platform_id unique (id, platform_id)
|
||||
);
|
||||
|
||||
create table wvp_platform_gb_channel (
|
||||
id serial primary key ,
|
||||
platform_id character varying(50),
|
||||
catalog_id character varying(50),
|
||||
device_channel_id integer,
|
||||
constraint uk_platform_gb_channel_platform_id_catalog_id_device_channel_id unique (platform_id, catalog_id, device_channel_id)
|
||||
);
|
||||
|
||||
create table wvp_platform_gb_stream (
|
||||
id serial primary key,
|
||||
platform_id character varying(50),
|
||||
catalog_id character varying(50),
|
||||
gb_stream_id integer,
|
||||
constraint uk_platform_gb_stream_platform_id_catalog_id_gb_stream_id unique (platform_id, catalog_id, gb_stream_id)
|
||||
);
|
||||
|
||||
create table wvp_stream_proxy (
|
||||
id serial primary key,
|
||||
type character varying(50),
|
||||
app character varying(255),
|
||||
stream character varying(255),
|
||||
url character varying(255),
|
||||
src_url character varying(255),
|
||||
dst_url character varying(255),
|
||||
timeout_ms integer,
|
||||
ffmpeg_cmd_key character varying(255),
|
||||
rtp_type character varying(50),
|
||||
media_server_id character varying(50),
|
||||
enable_audio bool default false,
|
||||
enable_mp4 bool default false,
|
||||
enable bool default false,
|
||||
status boolean,
|
||||
enable_remove_none_reader bool default false,
|
||||
create_time character varying(50),
|
||||
name character varying(255),
|
||||
update_time character varying(50),
|
||||
stream_key character varying(255),
|
||||
enable_disable_none_reader bool default false,
|
||||
constraint uk_stream_proxy_app_stream unique (app, stream)
|
||||
);
|
||||
|
||||
create table wvp_stream_push (
|
||||
id serial primary key,
|
||||
app character varying(255),
|
||||
stream character varying(255),
|
||||
total_reader_count character varying(50),
|
||||
origin_type integer,
|
||||
origin_type_str character varying(50),
|
||||
create_time character varying(50),
|
||||
alive_second integer,
|
||||
media_server_id character varying(50),
|
||||
server_id character varying(50),
|
||||
push_time character varying(50),
|
||||
status bool default false,
|
||||
update_time character varying(50),
|
||||
push_ing bool default false,
|
||||
self bool default false,
|
||||
constraint uk_stream_push_app_stream unique (app, stream)
|
||||
);
|
||||
create table wvp_cloud_record (
|
||||
id serial primary key,
|
||||
app character varying(255),
|
||||
stream character varying(255),
|
||||
call_id character varying(255),
|
||||
start_time bigint,
|
||||
end_time bigint,
|
||||
media_server_id character varying(50),
|
||||
file_name character varying(255),
|
||||
folder character varying(255),
|
||||
file_path character varying(255),
|
||||
collect bool default false,
|
||||
file_size bigint,
|
||||
time_len bigint,
|
||||
constraint uk_stream_push_app_stream_path unique (app, stream, file_path)
|
||||
);
|
||||
|
||||
create table wvp_user (
|
||||
id serial primary key,
|
||||
username character varying(255),
|
||||
password character varying(255),
|
||||
role_id integer,
|
||||
create_time character varying(50),
|
||||
update_time character varying(50),
|
||||
push_key character varying(50),
|
||||
constraint uk_user_username unique (username)
|
||||
);
|
||||
|
||||
create table wvp_user_role (
|
||||
id serial primary key,
|
||||
name character varying(50),
|
||||
authority character varying(50),
|
||||
create_time character varying(50),
|
||||
update_time character varying(50)
|
||||
);
|
||||
create table wvp_resources_tree (
|
||||
id serial primary key ,
|
||||
is_catalog bool default true,
|
||||
device_channel_id integer ,
|
||||
gb_stream_id integer,
|
||||
name character varying(255),
|
||||
parentId integer,
|
||||
path character varying(255)
|
||||
);
|
||||
|
||||
|
||||
/*初始数据*/
|
||||
INSERT INTO wvp_user VALUES (1, 'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3');
|
||||
INSERT INTO wvp_user_role VALUES (1, 'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');
|
||||
|
||||
|
||||
|
@ -164,6 +164,8 @@ create table wvp_media_server (
|
||||
create_time character varying(50),
|
||||
update_time character varying(50),
|
||||
hook_alive_interval integer,
|
||||
record_path character varying(255),
|
||||
record_day integer default 7,
|
||||
constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
|
||||
);
|
||||
|
||||
@ -259,6 +261,7 @@ create table wvp_stream_push (
|
||||
create_time character varying(50),
|
||||
alive_second integer,
|
||||
media_server_id character varying(50),
|
||||
server_id character varying(50),
|
||||
push_time character varying(50),
|
||||
status bool default false,
|
||||
update_time character varying(50),
|
||||
@ -266,6 +269,22 @@ create table wvp_stream_push (
|
||||
self bool default false,
|
||||
constraint uk_stream_push_app_stream unique (app, stream)
|
||||
);
|
||||
create table wvp_cloud_record (
|
||||
id serial primary key,
|
||||
app character varying(255),
|
||||
stream character varying(255),
|
||||
call_id character varying(255),
|
||||
start_time int8,
|
||||
end_time int8,
|
||||
media_server_id character varying(50),
|
||||
file_name character varying(255),
|
||||
folder character varying(255),
|
||||
file_path character varying(255),
|
||||
collect bool default false,
|
||||
file_size int8,
|
||||
time_len int8,
|
||||
constraint uk_stream_push_app_stream_path unique (app, stream, file_path)
|
||||
);
|
||||
|
||||
create table wvp_user (
|
||||
id serial primary key,
|
503
数据库/2.6.9/更新-mysql-2.6.9.sql
Normal file
503
数据库/2.6.9/更新-mysql-2.6.9.sql
Normal file
@ -0,0 +1,503 @@
|
||||
|
||||
alter table device
|
||||
change deviceId device_id varchar(50) not null;
|
||||
|
||||
alter table device
|
||||
change streamMode stream_mode varchar(50) null;
|
||||
|
||||
alter table device
|
||||
change registerTime register_time varchar(50) null;
|
||||
|
||||
alter table device
|
||||
change keepaliveTime keepalive_time varchar(50) null;
|
||||
|
||||
alter table device
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table device
|
||||
change updateTime update_time varchar(50) not null;
|
||||
|
||||
alter table device
|
||||
change subscribeCycleForCatalog subscribe_cycle_for_catalog bool default false;
|
||||
|
||||
alter table device
|
||||
change subscribeCycleForMobilePosition subscribe_cycle_for_mobile_position bool default false;
|
||||
|
||||
alter table device
|
||||
change mobilePositionSubmissionInterval mobile_position_submission_interval int default 5 not null;
|
||||
|
||||
alter table device
|
||||
change subscribeCycleForAlarm subscribe_cycle_for_alarm bool default false;
|
||||
|
||||
alter table device
|
||||
change hostAddress host_address varchar(50) null;
|
||||
|
||||
alter table device
|
||||
change ssrcCheck ssrc_check bool default false;
|
||||
|
||||
alter table device
|
||||
change geoCoordSys geo_coord_sys varchar(50) not null;
|
||||
|
||||
alter table device
|
||||
drop column treeType;
|
||||
|
||||
alter table device
|
||||
change mediaServerId media_server_id varchar(50) default 'auto' null;
|
||||
|
||||
alter table device
|
||||
change sdpIp sdp_ip varchar(50) null;
|
||||
|
||||
alter table device
|
||||
change localIp local_ip varchar(50) null;
|
||||
|
||||
alter table device
|
||||
change asMessageChannel as_message_channel bool default false;
|
||||
|
||||
alter table device
|
||||
change keepaliveIntervalTime keepalive_interval_time int null;
|
||||
|
||||
alter table device
|
||||
change online on_line varchar(50) null;
|
||||
|
||||
alter table device
|
||||
add COLUMN switch_primary_sub_stream bool default false comment '开启主子码流切换的开关(0-不开启,1-开启)现在已知支持设备为 大华、TP——LINK全系设备';
|
||||
|
||||
alter table device_alarm
|
||||
change deviceId device_id varchar(50) not null;
|
||||
|
||||
alter table device_alarm
|
||||
change channelId channel_id varchar(50) not null;
|
||||
|
||||
alter table device_alarm
|
||||
change alarmPriority alarm_priority varchar(50) not null;
|
||||
|
||||
alter table device_alarm
|
||||
change alarmMethod alarm_method varchar(50) null;
|
||||
|
||||
alter table device_alarm
|
||||
change alarmTime alarm_time varchar(50) not null;
|
||||
|
||||
alter table device_alarm
|
||||
change alarmDescription alarm_description varchar(255) null;
|
||||
|
||||
alter table device_alarm
|
||||
change alarmType alarm_type varchar(50) null;
|
||||
|
||||
alter table device_alarm
|
||||
change createTime create_time varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change channelId channel_id varchar(50) not null;
|
||||
|
||||
alter table device_channel
|
||||
change civilCode civil_code varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change parentId parent_id varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change safetyWay safety_way int null;
|
||||
|
||||
alter table device_channel
|
||||
change registerWay register_way int null;
|
||||
|
||||
alter table device_channel
|
||||
change certNum cert_num varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change errCode err_code int null;
|
||||
|
||||
alter table device_channel
|
||||
change endTime end_time varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change ipAddress ip_address varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change PTZType ptz_type int null;
|
||||
|
||||
alter table device_channel
|
||||
change status status bool default false;
|
||||
|
||||
alter table device_channel
|
||||
change streamId stream_id varchar(255) null;
|
||||
|
||||
alter table device_channel
|
||||
change deviceId device_id varchar(50) not null;
|
||||
|
||||
|
||||
alter table device_channel
|
||||
change hasAudio has_audio bool default false;
|
||||
|
||||
alter table device_channel
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table device_channel
|
||||
change updateTime update_time varchar(50) not null;
|
||||
|
||||
alter table device_channel
|
||||
change subCount sub_count int default 0 null;
|
||||
|
||||
alter table device_channel
|
||||
change longitudeGcj02 longitude_gcj02 double null;
|
||||
|
||||
alter table device_channel
|
||||
change latitudeGcj02 latitude_gcj02 double null;
|
||||
|
||||
alter table device_channel
|
||||
change longitudeWgs84 longitude_wgs84 double null;
|
||||
|
||||
alter table device_channel
|
||||
change latitudeWgs84 latitude_wgs84 double null;
|
||||
|
||||
alter table device_channel
|
||||
change businessGroupId business_group_id varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change gpsTime gps_time varchar(50) null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change deviceId device_id varchar(50) not null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change channelId channel_id varchar(50) not null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change deviceName device_name varchar(255) null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change reportSource report_source varchar(50) null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change longitudeGcj02 longitude_gcj02 double null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change latitudeGcj02 latitude_gcj02 double null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change longitudeWgs84 longitude_wgs84 double null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change latitudeWgs84 latitude_wgs84 double null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change createTime create_time varchar(50) null;
|
||||
|
||||
alter table gb_stream
|
||||
change gbStreamId gb_stream_id int auto_increment;
|
||||
|
||||
alter table gb_stream
|
||||
change gbId gb_id varchar(50) not null;
|
||||
|
||||
alter table gb_stream
|
||||
change streamType stream_type varchar(50) null;
|
||||
|
||||
alter table gb_stream
|
||||
change mediaServerId media_server_id varchar(50) null;
|
||||
|
||||
alter table gb_stream
|
||||
change createTime create_time varchar(50) null;
|
||||
|
||||
alter table log
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
change hookIp hook_ip varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
add column send_rtp_port_range varchar(50) default null;
|
||||
|
||||
alter table media_server
|
||||
change sdpIp sdp_ip varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
change streamIp stream_ip varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
change httpPort http_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change httpSSlPort http_ssl_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change rtmpPort rtmp_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change rtmpSSlPort rtmp_ssl_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change rtpProxyPort rtp_proxy_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change rtspPort rtsp_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change rtspSSLPort rtsp_ssl_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change autoConfig auto_config bool default true;
|
||||
|
||||
alter table media_server
|
||||
change rtpEnable rtp_enable bool default false;
|
||||
|
||||
alter table media_server
|
||||
change rtpPortRange rtp_port_range varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
change recordAssistPort record_assist_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change defaultServer default_server bool default false;
|
||||
|
||||
alter table media_server
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
change updateTime update_time varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
change hookAliveInterval hook_alive_interval int not null;
|
||||
|
||||
alter table parent_platform
|
||||
change serverGBId server_gb_id varchar(50) not null;
|
||||
|
||||
alter table parent_platform
|
||||
change serverGBDomain server_gb_domain varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change serverIP server_ip varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change serverPort server_port int null;
|
||||
|
||||
alter table parent_platform
|
||||
change deviceGBId device_gb_id varchar(50) not null;
|
||||
|
||||
alter table parent_platform
|
||||
change deviceIp device_ip varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change devicePort device_port varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change keepTimeout keep_timeout varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change characterSet character_set varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change catalogId catalog_id varchar(50) not null;
|
||||
|
||||
alter table parent_platform
|
||||
change startOfflinePush start_offline_push bool default false;
|
||||
|
||||
alter table parent_platform
|
||||
change administrativeDivision administrative_division varchar(50) not null;
|
||||
|
||||
alter table parent_platform
|
||||
change catalogGroup catalog_group int default 1 null;
|
||||
|
||||
alter table parent_platform
|
||||
change createTime create_time varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change updateTime update_time varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
drop column treeType;
|
||||
|
||||
alter table parent_platform
|
||||
change asMessageChannel as_message_channel bool default false;
|
||||
|
||||
alter table parent_platform
|
||||
change enable enable bool default false;
|
||||
|
||||
alter table parent_platform
|
||||
change ptz ptz bool default false;
|
||||
|
||||
alter table parent_platform
|
||||
change rtcp rtcp bool default false;
|
||||
|
||||
alter table parent_platform
|
||||
change status status bool default false;
|
||||
|
||||
alter table parent_platform
|
||||
change status status bool default false;
|
||||
|
||||
alter table platform_catalog
|
||||
change platformId platform_id varchar(50) not null;
|
||||
|
||||
alter table platform_catalog
|
||||
change parentId parent_id varchar(50) null;
|
||||
|
||||
alter table platform_catalog
|
||||
change civilCode civil_code varchar(50) null;
|
||||
|
||||
alter table platform_catalog
|
||||
change businessGroupId business_group_id varchar(50) null;
|
||||
|
||||
alter table platform_gb_channel
|
||||
change platformId platform_id varchar(50) not null;
|
||||
|
||||
alter table platform_gb_channel
|
||||
change catalogId catalog_id varchar(50) not null;
|
||||
|
||||
alter table platform_gb_channel
|
||||
change deviceChannelId device_channel_id int not null;
|
||||
|
||||
alter table platform_gb_stream
|
||||
change platformId platform_id varchar(50) not null;
|
||||
|
||||
alter table platform_gb_stream
|
||||
change catalogId catalog_id varchar(50) not null;
|
||||
|
||||
alter table platform_gb_stream
|
||||
change gbStreamId gb_stream_id int not null;
|
||||
|
||||
alter table stream_proxy
|
||||
change mediaServerId media_server_id varchar(50) null;
|
||||
|
||||
alter table stream_proxy
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table stream_proxy
|
||||
change updateTime update_time varchar(50) null;
|
||||
|
||||
alter table stream_proxy
|
||||
change enable_remove_none_reader enable_remove_none_reader bool default false;
|
||||
|
||||
alter table stream_proxy
|
||||
change enable_disable_none_reader enable_disable_none_reader bool default false;
|
||||
|
||||
alter table stream_proxy
|
||||
change enable_audio enable_audio bool default false;
|
||||
|
||||
alter table stream_proxy
|
||||
change enable_mp4 enable_mp4 bool default false;
|
||||
|
||||
alter table stream_proxy
|
||||
change enable enable bool default false;
|
||||
|
||||
alter table stream_push
|
||||
change totalReaderCount total_reader_count varchar(50) null;
|
||||
|
||||
alter table stream_push
|
||||
change originType origin_type int null;
|
||||
|
||||
alter table stream_push
|
||||
change originTypeStr origin_type_str varchar(50) null;
|
||||
|
||||
alter table stream_push
|
||||
change createTime create_time varchar(50) null;
|
||||
|
||||
alter table stream_push
|
||||
change aliveSecond alive_second int null;
|
||||
|
||||
alter table stream_push
|
||||
change mediaServerId media_server_id varchar(50) null;
|
||||
|
||||
alter table stream_push
|
||||
change status status bool default false;
|
||||
|
||||
alter table stream_push
|
||||
change pushTime push_time varchar(50) null;
|
||||
|
||||
alter table stream_push
|
||||
change updateTime update_time varchar(50) null;
|
||||
|
||||
alter table stream_push
|
||||
change pushIng push_ing bool default false;
|
||||
|
||||
alter table stream_push
|
||||
change status status bool default false;
|
||||
|
||||
alter table stream_push
|
||||
change self self bool default false;
|
||||
|
||||
alter table stream_push
|
||||
drop column serverId;
|
||||
|
||||
|
||||
alter table user
|
||||
change roleId role_id int not null;
|
||||
|
||||
alter table user
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table user
|
||||
change updateTime update_time varchar(50) not null;
|
||||
|
||||
alter table user
|
||||
change pushKey push_key varchar(50) null;
|
||||
|
||||
alter table user_role
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table user_role
|
||||
change updateTime update_time varchar(50) not null;
|
||||
|
||||
rename table device to wvp_device;
|
||||
rename table device_alarm to wvp_device_alarm;
|
||||
rename table device_channel to wvp_device_channel;
|
||||
rename table device_mobile_position to wvp_device_mobile_position;
|
||||
rename table gb_stream to wvp_gb_stream;
|
||||
rename table log to wvp_log;
|
||||
rename table media_server to wvp_media_server;
|
||||
rename table parent_platform to wvp_platform;
|
||||
rename table platform_catalog to wvp_platform_catalog;
|
||||
rename table platform_gb_channel to wvp_platform_gb_channel;
|
||||
rename table platform_gb_stream to wvp_platform_gb_stream;
|
||||
rename table stream_proxy to wvp_stream_proxy;
|
||||
rename table stream_push to wvp_stream_push;
|
||||
rename table user to wvp_user;
|
||||
rename table user_role to wvp_user_role;
|
||||
|
||||
alter table wvp_device add column broadcast_push_after_ack bool default false;
|
||||
alter table wvp_device_channel add column custom_name varchar(255) null ;
|
||||
alter table wvp_device_channel add column custom_longitude double null ;
|
||||
alter table wvp_device_channel add column custom_latitude double null ;
|
||||
alter table wvp_device_channel add column custom_ptz_type int null ;
|
||||
|
||||
create table wvp_resources_tree (
|
||||
id serial primary key ,
|
||||
is_catalog bool default true,
|
||||
device_channel_id integer ,
|
||||
gb_stream_id integer,
|
||||
name character varying(255),
|
||||
parentId integer,
|
||||
path character varying(255)
|
||||
);
|
||||
|
||||
alter table wvp_platform
|
||||
add auto_push_channel bool default false;
|
||||
|
||||
alter table wvp_stream_proxy
|
||||
add stream_key character varying(255);
|
||||
|
||||
create table wvp_cloud_record (
|
||||
id serial primary key,
|
||||
app character varying(255),
|
||||
stream character varying(255),
|
||||
call_id character varying(255),
|
||||
start_time bigint,
|
||||
end_time bigint,
|
||||
media_server_id character varying(50),
|
||||
file_name character varying(255),
|
||||
folder character varying(255),
|
||||
file_path character varying(255),
|
||||
collect bool default false,
|
||||
file_size bigint,
|
||||
time_len bigint,
|
||||
constraint uk_stream_push_app_stream_path unique (app, stream, file_path)
|
||||
);
|
||||
|
||||
alter table wvp_media_server
|
||||
add record_path character varying(255);
|
||||
|
||||
alter table wvp_media_server
|
||||
add record_day integer default 7;
|
||||
|
||||
alter table wvp_stream_push
|
||||
add server_id character varying(50);
|
||||
|
||||
|
505
数据库/2.6.9/更新-postgresql-kingbase-2.6.9.sql
Normal file
505
数据库/2.6.9/更新-postgresql-kingbase-2.6.9.sql
Normal file
@ -0,0 +1,505 @@
|
||||
|
||||
alter table device
|
||||
change deviceId device_id varchar(50) not null;
|
||||
|
||||
alter table device
|
||||
change streamMode stream_mode varchar(50) null;
|
||||
|
||||
alter table device
|
||||
change registerTime register_time varchar(50) null;
|
||||
|
||||
alter table device
|
||||
change keepaliveTime keepalive_time varchar(50) null;
|
||||
|
||||
alter table device
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table device
|
||||
change updateTime update_time varchar(50) not null;
|
||||
|
||||
alter table device
|
||||
change subscribeCycleForCatalog subscribe_cycle_for_catalog bool default false;
|
||||
|
||||
alter table device
|
||||
change subscribeCycleForMobilePosition subscribe_cycle_for_mobile_position bool default false;
|
||||
|
||||
alter table device
|
||||
change mobilePositionSubmissionInterval mobile_position_submission_interval int default 5 not null;
|
||||
|
||||
alter table device
|
||||
change subscribeCycleForAlarm subscribe_cycle_for_alarm bool default false;
|
||||
|
||||
alter table device
|
||||
change hostAddress host_address varchar(50) null;
|
||||
|
||||
alter table device
|
||||
change ssrcCheck ssrc_check bool default false;
|
||||
|
||||
alter table device
|
||||
change geoCoordSys geo_coord_sys varchar(50) not null;
|
||||
|
||||
alter table device
|
||||
drop column treeType;
|
||||
|
||||
alter table device
|
||||
change mediaServerId media_server_id varchar(50) default 'auto' null;
|
||||
|
||||
alter table device
|
||||
change sdpIp sdp_ip varchar(50) null;
|
||||
|
||||
alter table device
|
||||
change localIp local_ip varchar(50) null;
|
||||
|
||||
alter table device
|
||||
change asMessageChannel as_message_channel bool default false;
|
||||
|
||||
alter table device
|
||||
change keepaliveIntervalTime keepalive_interval_time int null;
|
||||
|
||||
alter table device
|
||||
change online on_line varchar(50) null;
|
||||
|
||||
alter table device
|
||||
add COLUMN switch_primary_sub_stream bool default false comment '开启主子码流切换的开关(0-不开启,1-开启)现在已知支持设备为 大华、TP——LINK全系设备'
|
||||
|
||||
|
||||
alter table device_alarm
|
||||
change deviceId device_id varchar(50) not null;
|
||||
|
||||
alter table device_alarm
|
||||
change channelId channel_id varchar(50) not null;
|
||||
|
||||
alter table device_alarm
|
||||
change alarmPriority alarm_priority varchar(50) not null;
|
||||
|
||||
alter table device_alarm
|
||||
change alarmMethod alarm_method varchar(50) null;
|
||||
|
||||
alter table device_alarm
|
||||
change alarmTime alarm_time varchar(50) not null;
|
||||
|
||||
alter table device_alarm
|
||||
change alarmDescription alarm_description varchar(255) null;
|
||||
|
||||
alter table device_alarm
|
||||
change alarmType alarm_type varchar(50) null;
|
||||
|
||||
alter table device_alarm
|
||||
change createTime create_time varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change channelId channel_id varchar(50) not null;
|
||||
|
||||
alter table device_channel
|
||||
change civilCode civil_code varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change parentId parent_id varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change safetyWay safety_way int null;
|
||||
|
||||
alter table device_channel
|
||||
change registerWay register_way int null;
|
||||
|
||||
alter table device_channel
|
||||
change certNum cert_num varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change errCode err_code int null;
|
||||
|
||||
alter table device_channel
|
||||
change endTime end_time varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change ipAddress ip_address varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change PTZType ptz_type int null;
|
||||
|
||||
alter table device_channel
|
||||
change status status bool default false;
|
||||
|
||||
alter table device_channel
|
||||
change streamId stream_id varchar(255) null;
|
||||
|
||||
alter table device_channel
|
||||
change deviceId device_id varchar(50) not null;
|
||||
|
||||
|
||||
alter table device_channel
|
||||
change hasAudio has_audio bool default false;
|
||||
|
||||
alter table device_channel
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table device_channel
|
||||
change updateTime update_time varchar(50) not null;
|
||||
|
||||
alter table device_channel
|
||||
change subCount sub_count int default 0 null;
|
||||
|
||||
alter table device_channel
|
||||
change longitudeGcj02 longitude_gcj02 double null;
|
||||
|
||||
alter table device_channel
|
||||
change latitudeGcj02 latitude_gcj02 double null;
|
||||
|
||||
alter table device_channel
|
||||
change longitudeWgs84 longitude_wgs84 double null;
|
||||
|
||||
alter table device_channel
|
||||
change latitudeWgs84 latitude_wgs84 double null;
|
||||
|
||||
alter table device_channel
|
||||
change businessGroupId business_group_id varchar(50) null;
|
||||
|
||||
alter table device_channel
|
||||
change gpsTime gps_time varchar(50) null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change deviceId device_id varchar(50) not null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change channelId channel_id varchar(50) not null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change deviceName device_name varchar(255) null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change reportSource report_source varchar(50) null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change longitudeGcj02 longitude_gcj02 double null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change latitudeGcj02 latitude_gcj02 double null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change longitudeWgs84 longitude_wgs84 double null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change latitudeWgs84 latitude_wgs84 double null;
|
||||
|
||||
alter table device_mobile_position
|
||||
change createTime create_time varchar(50) null;
|
||||
|
||||
alter table gb_stream
|
||||
change gbStreamId gb_stream_id int auto_increment;
|
||||
|
||||
alter table gb_stream
|
||||
change gbId gb_id varchar(50) not null;
|
||||
|
||||
alter table gb_stream
|
||||
change streamType stream_type varchar(50) null;
|
||||
|
||||
alter table gb_stream
|
||||
change mediaServerId media_server_id varchar(50) null;
|
||||
|
||||
alter table gb_stream
|
||||
change createTime create_time varchar(50) null;
|
||||
|
||||
alter table log
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
change hookIp hook_ip varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
add column send_rtp_port_range varchar(50) default null;
|
||||
|
||||
alter table media_server
|
||||
change sdpIp sdp_ip varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
change streamIp stream_ip varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
change httpPort http_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change httpSSlPort http_ssl_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change rtmpPort rtmp_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change rtmpSSlPort rtmp_ssl_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change rtpProxyPort rtp_proxy_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change rtspPort rtsp_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change rtspSSLPort rtsp_ssl_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change autoConfig auto_config bool default true;
|
||||
|
||||
alter table media_server
|
||||
change rtpEnable rtp_enable bool default false;
|
||||
|
||||
alter table media_server
|
||||
change rtpPortRange rtp_port_range varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
change recordAssistPort record_assist_port int not null;
|
||||
|
||||
alter table media_server
|
||||
change defaultServer default_server bool default false;
|
||||
|
||||
alter table media_server
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
change updateTime update_time varchar(50) not null;
|
||||
|
||||
alter table media_server
|
||||
change hookAliveInterval hook_alive_interval int not null;
|
||||
|
||||
alter table parent_platform
|
||||
change serverGBId server_gb_id varchar(50) not null;
|
||||
|
||||
alter table parent_platform
|
||||
change serverGBDomain server_gb_domain varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change serverIP server_ip varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change serverPort server_port int null;
|
||||
|
||||
alter table parent_platform
|
||||
change deviceGBId device_gb_id varchar(50) not null;
|
||||
|
||||
alter table parent_platform
|
||||
change deviceIp device_ip varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change devicePort device_port varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change keepTimeout keep_timeout varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change characterSet character_set varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change catalogId catalog_id varchar(50) not null;
|
||||
|
||||
alter table parent_platform
|
||||
change startOfflinePush start_offline_push bool default false;
|
||||
|
||||
alter table parent_platform
|
||||
change administrativeDivision administrative_division varchar(50) not null;
|
||||
|
||||
alter table parent_platform
|
||||
change catalogGroup catalog_group int default 1 null;
|
||||
|
||||
alter table parent_platform
|
||||
change createTime create_time varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
change updateTime update_time varchar(50) null;
|
||||
|
||||
alter table parent_platform
|
||||
drop column treeType;
|
||||
|
||||
alter table parent_platform
|
||||
change asMessageChannel as_message_channel bool default false;
|
||||
|
||||
alter table parent_platform
|
||||
change enable enable bool default false;
|
||||
|
||||
alter table parent_platform
|
||||
change ptz ptz bool default false;
|
||||
|
||||
alter table parent_platform
|
||||
change rtcp rtcp bool default false;
|
||||
|
||||
alter table parent_platform
|
||||
change status status bool default false;
|
||||
|
||||
alter table parent_platform
|
||||
change status status bool default false;
|
||||
|
||||
alter table platform_catalog
|
||||
change platformId platform_id varchar(50) not null;
|
||||
|
||||
alter table platform_catalog
|
||||
change parentId parent_id varchar(50) null;
|
||||
|
||||
alter table platform_catalog
|
||||
change civilCode civil_code varchar(50) null;
|
||||
|
||||
alter table platform_catalog
|
||||
change businessGroupId business_group_id varchar(50) null;
|
||||
|
||||
alter table platform_gb_channel
|
||||
change platformId platform_id varchar(50) not null;
|
||||
|
||||
alter table platform_gb_channel
|
||||
change catalogId catalog_id varchar(50) not null;
|
||||
|
||||
alter table platform_gb_channel
|
||||
change deviceChannelId device_channel_id int not null;
|
||||
|
||||
alter table platform_gb_stream
|
||||
change platformId platform_id varchar(50) not null;
|
||||
|
||||
alter table platform_gb_stream
|
||||
change catalogId catalog_id varchar(50) not null;
|
||||
|
||||
alter table platform_gb_stream
|
||||
change gbStreamId gb_stream_id int not null;
|
||||
|
||||
alter table stream_proxy
|
||||
change mediaServerId media_server_id varchar(50) null;
|
||||
|
||||
alter table stream_proxy
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table stream_proxy
|
||||
change updateTime update_time varchar(50) null;
|
||||
|
||||
alter table stream_proxy
|
||||
change enable_remove_none_reader enable_remove_none_reader bool default false;
|
||||
|
||||
alter table stream_proxy
|
||||
change enable_disable_none_reader enable_disable_none_reader bool default false;
|
||||
|
||||
alter table stream_proxy
|
||||
change enable_audio enable_audio bool default false;
|
||||
|
||||
alter table stream_proxy
|
||||
change enable_mp4 enable_mp4 bool default false;
|
||||
|
||||
alter table stream_proxy
|
||||
change enable enable bool default false;
|
||||
|
||||
alter table stream_push
|
||||
change totalReaderCount total_reader_count varchar(50) null;
|
||||
|
||||
alter table stream_push
|
||||
change originType origin_type int null;
|
||||
|
||||
alter table stream_push
|
||||
change originTypeStr origin_type_str varchar(50) null;
|
||||
|
||||
alter table stream_push
|
||||
change createTime create_time varchar(50) null;
|
||||
|
||||
alter table stream_push
|
||||
change aliveSecond alive_second int null;
|
||||
|
||||
alter table stream_push
|
||||
change mediaServerId media_server_id varchar(50) null;
|
||||
|
||||
alter table stream_push
|
||||
change status status bool default false;
|
||||
|
||||
alter table stream_push
|
||||
change pushTime push_time varchar(50) null;
|
||||
|
||||
alter table stream_push
|
||||
change updateTime update_time varchar(50) null;
|
||||
|
||||
alter table stream_push
|
||||
change pushIng push_ing bool default false;
|
||||
|
||||
alter table stream_push
|
||||
change status status bool default false;
|
||||
|
||||
alter table stream_push
|
||||
change self self bool default false;
|
||||
|
||||
alter table stream_push
|
||||
drop column serverId;
|
||||
|
||||
|
||||
alter table user
|
||||
change roleId role_id int not null;
|
||||
|
||||
alter table user
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table user
|
||||
change updateTime update_time varchar(50) not null;
|
||||
|
||||
alter table user
|
||||
change pushKey push_key varchar(50) null;
|
||||
|
||||
alter table user_role
|
||||
change createTime create_time varchar(50) not null;
|
||||
|
||||
alter table user_role
|
||||
change updateTime update_time varchar(50) not null;
|
||||
|
||||
rename table device to wvp_device;
|
||||
rename table device_alarm to wvp_device_alarm;
|
||||
rename table device_channel to wvp_device_channel;
|
||||
rename table device_mobile_position to wvp_device_mobile_position;
|
||||
rename table gb_stream to wvp_gb_stream;
|
||||
rename table log to wvp_log;
|
||||
rename table media_server to wvp_media_server;
|
||||
rename table parent_platform to wvp_platform;
|
||||
rename table platform_catalog to wvp_platform_catalog;
|
||||
rename table platform_gb_channel to wvp_platform_gb_channel;
|
||||
rename table platform_gb_stream to wvp_platform_gb_stream;
|
||||
rename table stream_proxy to wvp_stream_proxy;
|
||||
rename table stream_push to wvp_stream_push;
|
||||
rename table user to wvp_user;
|
||||
rename table user_role to wvp_user_role;
|
||||
|
||||
alter table wvp_device add column broadcast_push_after_ack bool default false;
|
||||
alter table wvp_device_channel add column custom_name varchar(255) null ;
|
||||
alter table wvp_device_channel add column custom_longitude double null ;
|
||||
alter table wvp_device_channel add column custom_latitude double null ;
|
||||
alter table wvp_device_channel add column custom_ptz_type int null ;
|
||||
|
||||
create table wvp_resources_tree (
|
||||
id serial primary key ,
|
||||
is_catalog bool default true,
|
||||
device_channel_id integer ,
|
||||
gb_stream_id integer,
|
||||
name character varying(255),
|
||||
parentId integer,
|
||||
path character varying(255)
|
||||
);
|
||||
|
||||
alter table wvp_platform
|
||||
add auto_push_channel bool default false;
|
||||
|
||||
alter table wvp_stream_proxy
|
||||
add stream_key character varying(255);
|
||||
|
||||
create table wvp_cloud_record (
|
||||
id serial primary key,
|
||||
app character varying(255),
|
||||
stream character varying(255),
|
||||
call_id character varying(255),
|
||||
start_time int8,
|
||||
end_time int8,
|
||||
media_server_id character varying(50),
|
||||
file_name character varying(255),
|
||||
folder character varying(255),
|
||||
file_path character varying(255),
|
||||
collect bool default false,
|
||||
file_size int8,
|
||||
time_len int8,
|
||||
constraint uk_stream_push_app_stream_path unique (app, stream, file_path)
|
||||
);
|
||||
|
||||
alter table wvp_media_server
|
||||
add record_path character varying(255);
|
||||
|
||||
alter table wvp_media_server
|
||||
add record_day integer default 7;
|
||||
|
||||
alter table wvp_stream_push
|
||||
add server_id character varying(50);
|
||||
|
||||
|
||||
|
@ -120,7 +120,7 @@ alter table device_channel
|
||||
change status status bool default false;
|
||||
|
||||
alter table device_channel
|
||||
change streamId stream_id varchar(50) null;
|
||||
change streamId stream_id varchar(255) null;
|
||||
|
||||
alter table device_channel
|
||||
change deviceId device_id varchar(50) not null;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user