Merge branch 'refs/heads/master' into 1078

This commit is contained in:
648540858 2024-05-28 18:40:44 +08:00
commit 37b79633f0
52 changed files with 1539 additions and 212 deletions

View File

@ -7,6 +7,7 @@ import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.annotation.Order;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.beans.factory.annotation.Value;
@ -18,6 +19,7 @@ import org.springframework.context.annotation.Configuration;
*/
@Configuration
@Order(1)
@ConditionalOnProperty(value = "user-settings.doc-enable", havingValue = "true", matchIfMissing = true)
public class SpringDocConfig {
@Value("${doc.enabled: true}")

View File

@ -54,6 +54,8 @@ public class UserSetting {
private Boolean deviceStatusNotify = Boolean.TRUE;
private Boolean useCustomSsrcForParentInvite = Boolean.TRUE;
private Boolean docEnable = Boolean.TRUE;
private String serverId = "000000";
private String thirdPartyGBIdReg = "[\\s\\S]*";
@ -315,4 +317,12 @@ public class UserSetting {
public void setRegisterKeepIntDialog(boolean registerKeepIntDialog) {
this.registerKeepIntDialog = registerKeepIntDialog;
}
public Boolean getDocEnable() {
return docEnable;
}
public void setDocEnable(Boolean docEnable) {
this.docEnable = docEnable;
}
}

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.conf.redis;
import com.alibaba.fastjson2.support.spring.data.redis.GenericFastJsonRedisSerializer;
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
@ -25,4 +26,20 @@ public class RedisTemplateConfig {
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
@Bean
public RedisTemplate<String, MobilePosition> getRedisTemplateForMobilePosition(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, MobilePosition> redisTemplate = new RedisTemplate<>();
// 使用fastJson序列化
GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
// value值的序列化采用fastJsonRedisSerializer
redisTemplate.setValueSerializer(fastJsonRedisSerializer);
redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
// key的序列化采用StringRedisSerializer
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
}

View File

@ -35,10 +35,15 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
// 忽略登录请求的token验证
String requestURI = request.getRequestURI();
if ((requestURI.startsWith("/doc.html") || requestURI.startsWith("/swagger-ui") ) && !userSetting.getDocEnable()) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
if (requestURI.equalsIgnoreCase("/api/user/login")) {
chain.doFilter(request, response);
return;
}
if (!userSetting.isInterfaceAuthentication()) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() );
SecurityContextHolder.getContext().setAuthentication(token);

View File

@ -117,7 +117,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.authorizeRequests()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll()
.antMatchers("/api/user/login", "/index/hook/**","/index/hook/abl/**", "/swagger-ui/**", "/doc.html").permitAll()
.antMatchers("/api/user/login", "/index/hook/**","/index/hook/abl/**", "/swagger-ui/**", "/doc.html#/**").permitAll()
.anyRequest().authenticated()
// 异常处理器
.and()

View File

@ -104,7 +104,7 @@ public class SipRunner implements CommandLineRunner {
redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(),sendRtpItem.getChannelId(), sendRtpItem.getCallId(),sendRtpItem.getStream());
if (mediaServerItem != null) {
ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc());
boolean stopResult = mediaServerService.stopSendRtp(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getSsrc());
boolean stopResult = mediaServerService.initStopSendRtp(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getSsrc());
if (stopResult) {
ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId());
if (platform != null) {

View File

@ -168,6 +168,7 @@ public class SIPRequestHeaderProvider {
// via
ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(sipLayer.getLocalIp(device.getLocalIp()), sipConfig.getPort(), device.getTransport(), SipUtils.getNewViaTag());
// viaHeader.setRPort();
viaHeaders.add(viaHeader);
//from
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());

View File

@ -515,9 +515,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
if (parentPlatform == null) {
return;
}
if (logger.isDebugEnabled()) {
logger.debug("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
}
logger.info("[发送 移动位置订阅] {}/{}->{},{}", parentPlatform.getServerGBId(), gpsMsgInfo.getId(), gpsMsgInfo.getLng(), gpsMsgInfo.getLat());
String characterSet = parentPlatform.getCharacterSet();
StringBuffer deviceStatusXml = new StringBuffer(600);

View File

@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP
import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.service.IDeviceChannelService;
import com.genersoft.iot.vmp.service.IMobilePositionService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import org.dom4j.DocumentException;
@ -20,15 +21,11 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import javax.sip.RequestEvent;
import javax.sip.header.FromHeader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
@ -54,6 +51,9 @@ public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessor
@Autowired
private IDeviceChannelService deviceChannelService;
@Autowired
private IMobilePositionService mobilePositionService;
public void process(RequestEvent evt) {
if (taskQueue.size() >= userSetting.getMaxNotifyCountQueue()) {
@ -64,13 +64,10 @@ public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessor
}
@Scheduled(fixedRate = 200) //每200毫秒执行一次
@Transactional
public void executeTaskQueue() {
if (taskQueue.isEmpty()) {
return;
}
Map<String, DeviceChannel> updateChannelMap = new ConcurrentHashMap<>();
List<MobilePosition> addMobilePositionList = new ArrayList<>();
for (HandlerCatchData take : taskQueue) {
if (take == null) {
continue;
@ -146,20 +143,11 @@ public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessor
}
}
// logger.info("[收到移动位置订阅通知]{}/{}->{}.{}, 时间: {}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(),
// mobilePosition.getLongitude(), mobilePosition.getLatitude(), System.currentTimeMillis() - startTime);
logger.debug("[收到移动位置订阅通知]{}/{}->{}.{}, 时间: {}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(),
mobilePosition.getLongitude(), mobilePosition.getLatitude(), System.currentTimeMillis() - startTime);
mobilePosition.setReportSource("Mobile Position");
// 更新device channel 的经纬度
DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setDeviceId(device.getDeviceId());
deviceChannel.setLongitude(mobilePosition.getLongitude());
deviceChannel.setLatitude(mobilePosition.getLatitude());
deviceChannel.setGpsTime(mobilePosition.getTime());
updateChannelMap.put(deviceId + mobilePosition.getChannelId(), deviceChannel);
addMobilePositionList.add(mobilePosition);
mobilePositionService.add(mobilePosition);
// 向关联了该通道并且开启移动位置订阅的上级平台发送移动位置订阅消息
try {
eventPublisher.mobilePositionEventPublish(mobilePosition);
@ -199,21 +187,6 @@ public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessor
}
}
taskQueue.clear();
if(!updateChannelMap.isEmpty()) {
List<DeviceChannel> channels = new ArrayList<>(updateChannelMap.values());
logger.info("[移动位置订阅]更新通道位置: {}", channels.size());
deviceChannelService.batchUpdateChannel(channels);
updateChannelMap.clear();
}
if (userSetting.isSavePositionHistory() && !addMobilePositionList.isEmpty()) {
try {
logger.info("[移动位置订阅] 添加通道轨迹点位: {}", addMobilePositionList.size());
deviceChannelService.batchAddMobilePosition(addMobilePositionList);
}catch (Exception e) {
logger.info("[移动位置订阅] b添加通道轨迹点位保存失败 {}", addMobilePositionList.size());
}
addMobilePositionList.clear();
}
}
@Scheduled(fixedRate = 10000)
public void execute(){

View File

@ -100,6 +100,9 @@ public class MediaServer {
@Schema(description = "类型: zlm/abl")
private String type;
@Schema(description = "转码的前缀")
private String transcodeSuffix;
public MediaServer() {
}
@ -126,6 +129,7 @@ public class MediaServer {
rtpEnable = false; // 默认使用单端口;直到用户自己设置开启多端口
rtpPortRange = zlmServerConfig.getPortRange().replace("_",","); // 默认使用30000,30500作为级联时发送流的端口号
recordAssistPort = 0; // 默认关闭
transcodeSuffix = zlmServerConfig.getTranscodeSuffix();
}
@ -376,4 +380,12 @@ public class MediaServer {
public void setWsFlvSSLPort(int wsFlvSSLPort) {
this.wsFlvSSLPort = wsFlvSSLPort;
}
public String getTranscodeSuffix() {
return transcodeSuffix;
}
public void setTranscodeSuffix(String transcodeSuffix) {
this.transcodeSuffix = transcodeSuffix;
}
}

View File

@ -10,6 +10,7 @@ public class RecordInfo {
private String url;
private long startTime;
private double timeLen;
private String params;
public static RecordInfo getInstance(OnRecordMp4HookParam hookParam) {
RecordInfo recordInfo = new RecordInfo();
@ -79,6 +80,14 @@ public class RecordInfo {
this.timeLen = timeLen;
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
@Override
public String toString() {
return "RecordInfo{" +
@ -87,6 +96,7 @@ public class RecordInfo {
", 文件大小=" + fileSize +
", 开始时间=" + startTime +
", 时长=" + timeLen +
", params=" + params +
'}';
}
}

View File

@ -29,6 +29,8 @@ public interface IMediaNodeServerService {
boolean stopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc);
boolean initStopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc);
boolean deleteRecordDirectory(MediaServer mediaServer, String app, String stream, String date, String fileName);
List<StreamInfo> getMediaList(MediaServer mediaServer, String app, String stream, String callId);
@ -58,4 +60,6 @@ public interface IMediaNodeServerService {
void startSendRtpPassive(MediaServer mediaServer, SendRtpItem sendRtpItem, Integer timeout);
void startSendRtpStream(MediaServer mediaServer, SendRtpItem sendRtpItem);
Long updateDownloadProcess(MediaServer mediaServer, String app, String stream);
}

View File

@ -76,6 +76,8 @@ public interface IMediaServerService {
boolean stopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc);
boolean initStopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc);
boolean deleteRecordDirectory(MediaServer mediaServerItem, String app, String stream, String date, String fileName);
List<StreamInfo> getMediaList(MediaServer mediaInfo, String app, String stream, String callId);
@ -149,4 +151,6 @@ public interface IMediaServerService {
String app, String stream, String channelId, boolean tcp, boolean rtcp);
MediaServer getMediaServerByAppAndStream(String app, String stream);
Long updateDownloadProcess(MediaServer mediaServerItem, String app, String stream);
}

View File

@ -595,6 +595,16 @@ public class MediaServerServiceImpl implements IMediaServerService {
return mediaNodeServerService.stopSendRtp(mediaInfo, app, stream, ssrc);
}
@Override
public boolean initStopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc) {
IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaInfo.getType());
if (mediaNodeServerService == null) {
logger.info("[stopSendRtp] 失败, mediaServer的类型 {},未找到对应的实现类", mediaInfo.getType());
return false;
}
return mediaNodeServerService.initStopSendRtp(mediaInfo, app, stream, ssrc);
}
@Override
public boolean deleteRecordDirectory(MediaServer mediaServer, String app, String stream, String date, String fileName) {
IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType());
@ -911,4 +921,14 @@ public class MediaServerServiceImpl implements IMediaServerService {
}
return null;
}
@Override
public Long updateDownloadProcess(MediaServer mediaServer, String app, String stream) {
IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType());
if (mediaNodeServerService == null) {
logger.info("[updateDownloadProcess] 失败, mediaServer的类型 {},未找到对应的实现类", mediaServer.getType());
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到mediaServer对应的实现类");
}
return mediaNodeServerService.updateDownloadProcess(mediaServer, app, stream);
}
}

View File

@ -104,7 +104,6 @@ public class SendRtpPortManager {
return port;
}
}
}
interface CheckPortCallback{

View File

@ -24,6 +24,7 @@ import com.genersoft.iot.vmp.service.*;
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.MediaServerUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -35,7 +36,6 @@ import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
@ -149,7 +149,7 @@ public class ZLMHttpHookListener {
@PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8")
public HookResult onPlay(@RequestBody OnPlayHookParam param) {
Map<String, String> paramMap = urlParamToMap(param.getParams());
Map<String, String> paramMap = MediaServerUtils.urlParamToMap(param.getParams());
// 对于播放流进行鉴权
boolean authenticateResult = mediaService.authenticatePlay(param.getApp(), param.getStream(), paramMap.get("callId"));
if (!authenticateResult) {
@ -202,6 +202,11 @@ public class ZLMHttpHookListener {
if (mediaServer == null) {
return HookResult.SUCCESS();
}
if (!ObjectUtils.isEmpty(mediaServer.getTranscodeSuffix())
&& !"null".equalsIgnoreCase(mediaServer.getTranscodeSuffix())
&& param.getStream().endsWith(mediaServer.getTranscodeSuffix()) ) {
return HookResult.SUCCESS();
}
if (param.getSchema().equalsIgnoreCase("rtsp")) {
if (param.isRegist()) {
logger.info("[ZLM HOOK] 流注册, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream());
@ -226,6 +231,19 @@ public class ZLMHttpHookListener {
logger.info("[ZLM HOOK]流无人观看:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(),
param.getApp(), param.getStream());
MediaServer mediaInfo = mediaServerService.getOne(param.getMediaServerId());
if (mediaInfo == null) {
JSONObject ret = new JSONObject();
ret.put("code", 0);
return ret;
}
if (!ObjectUtils.isEmpty(mediaInfo.getTranscodeSuffix())
&& !"null".equalsIgnoreCase(mediaInfo.getTranscodeSuffix())
&& param.getStream().endsWith(mediaInfo.getTranscodeSuffix()) ) {
param.setStream(param.getStream().substring(0, param.getStream().lastIndexOf(mediaInfo.getTranscodeSuffix()) -1 ));
}
JSONObject ret = new JSONObject();
boolean close = mediaService.closeStreamOnNoneReader(param.getMediaServerId(), param.getApp(), param.getStream(), param.getSchema());
ret.put("code", 0);
@ -348,22 +366,4 @@ public class ZLMHttpHookListener {
return HookResult.SUCCESS();
}
private Map<String, String> urlParamToMap(String params) {
HashMap<String, String> map = new HashMap<>();
if (ObjectUtils.isEmpty(params)) {
return map;
}
String[] paramsArray = params.split("&");
if (paramsArray.length == 0) {
return map;
}
for (String param : paramsArray) {
String[] paramArray = param.split("=");
if (paramArray.length == 2) {
map.put(paramArray[0], paramArray[1]);
}
}
return map;
}
}

View File

@ -144,6 +144,23 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService {
}
@Override
public boolean initStopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc) {
Map<String, Object> param = new HashMap<>();
param.put("vhost", "__defaultVhost__");
param.put("app", app);
param.put("stream", stream);
if (!ObjectUtils.isEmpty(ssrc)) {
param.put("ssrc", ssrc);
}
JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaInfo, param);
if (jsonObject == null || jsonObject.getInteger("code") != 0 ) {
logger.error("停止发流失败: {}, 参数:{}", jsonObject.getString("msg"), JSON.toJSONString(param));
return false;
}
return true;
}
@Override
public boolean deleteRecordDirectory(MediaServer mediaServer, String app, String stream, String date, String fileName) {
logger.info("[zlm-deleteRecordDirectory] 删除磁盘文件, server: {} {}:{}->{}/{}", mediaServer.getId(), app, stream, date, fileName);
@ -367,4 +384,14 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService {
throw new ControllerException(jsonObject.getInteger("code"), jsonObject.getString("msg"));
}
}
@Override
public Long updateDownloadProcess(MediaServer mediaServer, String app, String stream) {
MediaInfo mediaInfo = getMediaInfo(mediaServer, app, stream);
if (mediaInfo == null) {
logger.warn("[获取下载进度] 查询进度失败, 节点Id {} {}/{}", mediaServer.getId(), app, stream);
return null;
}
return mediaInfo.getDuration();
}
}

View File

@ -331,6 +331,9 @@ public class ZLMServerConfig extends HookParam {
@JSONField(name = "shell.shell")
private String shellPhell;
@JSONField(name = "transcode.suffix")
private String transcodeSuffix;
public String getHookIp() {
return hookIp;
@ -1211,4 +1214,12 @@ public class ZLMServerConfig extends HookParam {
public void setHookOnRtpServerTimeout(String hookOnRtpServerTimeout) {
this.hookOnRtpServerTimeout = hookOnRtpServerTimeout;
}
public String getTranscodeSuffix() {
return transcodeSuffix;
}
public void setTranscodeSuffix(String transcodeSuffix) {
this.transcodeSuffix = transcodeSuffix;
}
}

View File

@ -15,6 +15,7 @@ public class OnRecordMp4HookParam extends HookParam{
private String vhost;
private long start_time;
private double time_len;
private String params;
public String getApp() {
return app;
@ -96,6 +97,14 @@ public class OnRecordMp4HookParam extends HookParam{
this.time_len = time_len;
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
@Override
public String toString() {
return "OnRecordMp4HookParam{" +
@ -109,6 +118,7 @@ public class OnRecordMp4HookParam extends HookParam{
", vhost='" + vhost + '\'' +
", start_time=" + start_time +
", time_len=" + time_len +
", params=" + params +
'}';
}
}

View File

@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.media.zlm.dto.hook;
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
import java.util.List;
import java.util.Map;
/**
* @author lin
@ -98,6 +99,16 @@ public class OnStreamChangedHookParam extends HookParam{
*/
private String vhost;
/**
* 额外的参数字符串
*/
private String params;
/**
* 额外的参数
*/
private Map<String, String> paramMap;
public boolean isRegist() {
return regist;
}
@ -496,6 +507,23 @@ public class OnStreamChangedHookParam extends HookParam{
this.callId = callId;
}
public Map<String, String> getParamMap() {
return paramMap;
}
public void setParamMap(Map<String, String> paramMap) {
this.paramMap = paramMap;
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
@Override
public String toString() {
return "OnStreamChangedHookParam{" +

View File

@ -17,7 +17,7 @@ public interface ICloudRecordService {
/**
* 分页回去云端录像列表
*/
PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems);
PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems, String callId);
/**
* 获取所有的日期
@ -50,4 +50,6 @@ public interface ICloudRecordService {
* 获取播放地址
*/
DownloadFileInfo getPlayUrlPath(Integer recordId);
List<CloudRecordItem> getAllList(String query, String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems, String callId, List<Integer> ids);
}

View File

@ -0,0 +1,13 @@
package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
import java.util.List;
public interface IMobilePositionService {
void add(List<MobilePosition> mobilePositionList);
void add(MobilePosition mobilePosition);
}

View File

@ -1,7 +1,9 @@
package com.genersoft.iot.vmp.service.bean;
import com.genersoft.iot.vmp.media.event.media.MediaRecordMp4Event;
import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam;
import com.genersoft.iot.vmp.utils.MediaServerUtils;
import java.util.Map;
/**
* 云端录像数据
@ -89,6 +91,10 @@ public class CloudRecordItem {
cloudRecordItem.setMediaServerId(param.getMediaServer().getId());
cloudRecordItem.setTimeLen((long) param.getRecordInfo().getTimeLen() * 1000);
cloudRecordItem.setEndTime((param.getRecordInfo().getStartTime() + (long)param.getRecordInfo().getTimeLen()) * 1000);
Map<String, String> paramsMap = MediaServerUtils.urlParamToMap(param.getRecordInfo().getParams());
if (paramsMap.get("callId") != null) {
cloudRecordItem.setCallId(paramsMap.get("callId"));
}
return cloudRecordItem;
}

View File

@ -5,12 +5,12 @@ 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.event.media.MediaRecordMp4Event;
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.event.media.MediaRecordMp4Event;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.service.ICloudRecordService;
import com.genersoft.iot.vmp.media.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;
@ -28,13 +28,18 @@ import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.time.*;
import java.util.*;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Service
@DS("share")
public class CloudRecordServiceImpl implements ICloudRecordService {
private final static Logger logger = LoggerFactory.getLogger(CloudRecordServiceImpl.class);
@Autowired
@ -53,7 +58,7 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
private VideoStreamSessionManager streamSession;
@Override
public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems) {
public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems, String callId) {
// 开始时间和结束时间在数据库中都是以秒为单位的
Long startTimeStamp = null;
Long endTimeStamp = null;
@ -73,7 +78,7 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
}
PageHelper.startPage(page, count);
List<CloudRecordItem> all = cloudRecordServiceMapper.getList(query, app, stream, startTimeStamp, endTimeStamp,
null, mediaServerItems);
callId, mediaServerItems, null);
return new PageInfo<>(all);
}
@ -89,7 +94,7 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
long startTimeStamp = startDate.atStartOfDay().toInstant(ZoneOffset.ofHours(8)).getEpochSecond() * 1000;
long endTimeStamp = endDate.atStartOfDay().toInstant(ZoneOffset.ofHours(8)).getEpochSecond() * 1000;
List<CloudRecordItem> cloudRecordItemList = cloudRecordServiceMapper.getList(null, app, stream, startTimeStamp,
endTimeStamp, null, mediaServerItems);
endTimeStamp, null, mediaServerItems, null);
if (cloudRecordItemList.isEmpty()) {
return new ArrayList<>();
}
@ -105,11 +110,13 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
@EventListener
public void onApplicationEvent(MediaRecordMp4Event event) {
CloudRecordItem cloudRecordItem = CloudRecordItem.getInstance(event);
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(event.getApp(), event.getStream());
if (streamAuthorityInfo != null) {
cloudRecordItem.setCallId(streamAuthorityInfo.getCallId());
if (ObjectUtils.isEmpty(cloudRecordItem.getCallId())) {
StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(event.getApp(), event.getStream());
if (streamAuthorityInfo != null) {
cloudRecordItem.setCallId(streamAuthorityInfo.getCallId());
}
}
logger.info("[添加录像记录] {}/{} 内容:{}", event.getApp(), event.getStream(), event.getRecordInfo());
logger.info("[添加录像记录] {}/{}, callId: {}, 内容:{}", event.getApp(), event.getStream(), cloudRecordItem.getCallId(), event.getRecordInfo());
cloudRecordServiceMapper.add(cloudRecordItem);
}
@ -199,7 +206,7 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
}
List<CloudRecordItem> all = cloudRecordServiceMapper.getList(null, app, stream, startTimeStamp, endTimeStamp,
callId, mediaServerItems);
callId, mediaServerItems, null);
if (all.isEmpty()) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到待收藏的视频");
}
@ -235,4 +242,27 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
MediaServer mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId());
return CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath);
}
@Override
public List<CloudRecordItem> getAllList(String query, String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems, String callId, List<Integer> ids) {
// 开始时间和结束时间在数据库中都是以秒为单位的
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_ssToTimestampMs(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_ssToTimestampMs(endTime);
}
return cloudRecordServiceMapper.getList(query, app, stream, startTimeStamp, endTimeStamp,
callId, mediaServerItems, ids);
}
}

View File

@ -18,6 +18,7 @@ import com.genersoft.iot.vmp.service.*;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.MediaServerUtils;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo;
import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo;
@ -26,12 +27,10 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -101,7 +100,7 @@ public class MediaServiceImpl implements IMediaService {
}
if (userSetting.getPushAuthority()) {
// 对于推流进行鉴权
Map<String, String> paramMap = urlParamToMap(params);
Map<String, String> paramMap = MediaServerUtils.urlParamToMap(params);
// 推流鉴权
if (params == null) {
logger.info("推流鉴权失败: 缺少必要参数sign=md5(user表的pushKey)");
@ -210,24 +209,6 @@ public class MediaServiceImpl implements IMediaService {
return result;
}
private Map<String, String> urlParamToMap(String params) {
HashMap<String, String> map = new HashMap<>();
if (ObjectUtils.isEmpty(params)) {
return map;
}
String[] paramsArray = params.split("&");
if (paramsArray.length == 0) {
return map;
}
for (String param : paramsArray) {
String[] paramArray = param.split("=");
if (paramArray.length == 2) {
map.put(paramArray[0], paramArray[1]);
}
}
return map;
}
@Override
public boolean closeStreamOnNoneReader(String mediaServerId, String app, String stream, String schema) {
boolean result = false;

View File

@ -0,0 +1,95 @@
package com.genersoft.iot.vmp.service.impl;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
import com.genersoft.iot.vmp.service.IMobilePositionService;
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
import com.genersoft.iot.vmp.storager.dao.DeviceMobilePositionMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class MobilePositionServiceImpl implements IMobilePositionService {
@Autowired
private DeviceChannelMapper channelMapper;
@Autowired
private DeviceMobilePositionMapper mobilePositionMapper;
@Autowired
private UserSetting userSetting;
@Autowired
private RedisTemplate<String, MobilePosition> redisTemplate;
private final static Logger logger = LoggerFactory.getLogger(MobilePositionServiceImpl.class);
private final String REDIS_MOBILE_POSITION_LIST = "redis_mobile_position_list";
@Override
public void add(MobilePosition mobilePosition) {
List<MobilePosition> list = new ArrayList<>();
list.add(mobilePosition);
add(list);
}
@Override
public void add(List<MobilePosition> mobilePositionList) {
redisTemplate.opsForList().leftPushAll(REDIS_MOBILE_POSITION_LIST, mobilePositionList);
}
private List<MobilePosition> get(int length) {
Long size = redisTemplate.opsForList().size(REDIS_MOBILE_POSITION_LIST);
if (size == null || size == 0) {
return new ArrayList<>();
}
List<MobilePosition> mobilePositions;
if (size > length) {
mobilePositions = redisTemplate.opsForList().rightPop(REDIS_MOBILE_POSITION_LIST, length);
}else {
mobilePositions = redisTemplate.opsForList().rightPop(REDIS_MOBILE_POSITION_LIST, size);
}
return mobilePositions;
}
@Scheduled(fixedRate = 1000)
@Transactional
public void executeTaskQueue() {
int countLimit = 3000;
List<MobilePosition> mobilePositions = get(countLimit);
if (mobilePositions == null || mobilePositions.isEmpty()) {
return;
}
if (userSetting.getSavePositionHistory()) {
mobilePositionMapper.batchadd(mobilePositions);
}
logger.info("[移动位置订阅]更新通道位置: {}", mobilePositions.size());
Map<String, DeviceChannel> updateChannelMap = new HashMap<>();
for (MobilePosition mobilePosition : mobilePositions) {
DeviceChannel deviceChannel = new DeviceChannel();
deviceChannel.setDeviceId(mobilePosition.getDeviceId());
deviceChannel.setLongitude(mobilePosition.getLongitude());
deviceChannel.setLatitude(mobilePosition.getLatitude());
deviceChannel.setGpsTime(mobilePosition.getTime());
updateChannelMap.put(mobilePosition.getDeviceId() + mobilePosition.getChannelId(), deviceChannel);
}
List<DeviceChannel> channels = new ArrayList<>(updateChannelMap.values());
channelMapper.batchUpdatePosition(channels);
}
}

View File

@ -1081,12 +1081,8 @@ public class PlayServiceImpl implements IPlayService {
return null;
}
String app = "rtp";
MediaInfo mediaInfo = mediaServerService.getMediaInfo(mediaServerItem, app, stream);
if (mediaInfo == null) {
logger.warn("[获取下载进度] 查询进度失败, 节点Id {} {}/{}", mediaServerId, app, stream);
return null;
}
if (mediaInfo.getDuration() == 0) {
Long duration = mediaServerService.updateDownloadProcess(mediaServerItem, app, stream);
if (duration == null || duration == 0) {
inviteInfo.getStreamInfo().setProgress(0);
} else {
String startTime = inviteInfo.getStreamInfo().getStartTime();
@ -1095,7 +1091,7 @@ public class PlayServiceImpl implements IPlayService {
long start = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime);
long end = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);
BigDecimal currentCount = new BigDecimal(mediaInfo.getDuration());
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();

View File

@ -349,6 +349,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
}
String msgResult;
if ("ffmpeg".equalsIgnoreCase(param.getType())){
if (param.getTimeoutMs() == 0) {
param.setTimeoutMs(15);
}
result = mediaServerService.addFFmpegSource(mediaServer, param.getSrcUrl().trim(), param.getDstUrl(),
param.getTimeoutMs(), param.isEnableAudio(), param.isEnableMp4(),
param.getFfmpegCmdKey());
@ -406,6 +409,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
gbStreamMapper.del(app, stream);
videoManagerStorager.deleteStreamProxy(app, stream);
redisCatchStorage.removeStream(streamProxyItem.getMediaServerId(), "PULL", app, stream);
redisCatchStorage.removeStream(streamProxyItem.getMediaServerId(), "PUSH", app, stream);
Boolean result = removeStreamProxyFromZlm(streamProxyItem);
if (result != null && result) {
logger.info("[移除代理] 代理: {}/{}, 从zlm移除成功", app, stream);

View File

@ -50,12 +50,15 @@ public interface CloudRecordServiceMapper {
" <if test= 'mediaServerItemList != null ' > and media_server_id in " +
" <foreach collection='mediaServerItemList' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
" </if>" +
" <if test= 'ids != null ' > and id in " +
" <foreach collection='ids' item='item' open='(' separator=',' close=')' > #{item}</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<MediaServer> mediaServerItemList);
@Param("callId")String callId, List<MediaServer> mediaServerItemList,
List<Integer> ids);
@Select(" <script>" +

View File

@ -402,23 +402,6 @@ public interface DeviceChannelMapper {
" </script>"})
int updatePosition(DeviceChannel deviceChannel);
@Update({"<script>" +
"<foreach collection='deviceChannelList' item='item' separator=';'>" +
" UPDATE" +
" wvp_device_channel" +
" SET gps_time=#{item.gpsTime}" +
"<if test='item.longitude != null'>, longitude=#{item.longitude}</if>" +
"<if test='item.latitude != null'>, latitude=#{item.latitude}</if>" +
"<if test='item.longitudeGcj02 != null'>, longitude_gcj02=#{item.longitudeGcj02}</if>" +
"<if test='item.latitudeGcj02 != null'>, latitude_gcj02=#{item.latitudeGcj02}</if>" +
"<if test='item.longitudeWgs84 != null'>, longitude_wgs84=#{item.longitudeWgs84}</if>" +
"<if test='item.latitudeWgs84 != null'>, latitude_wgs84=#{item.latitudeWgs84}</if>" +
"WHERE device_id=#{item.deviceId} " +
" <if test='item.channelId != null' > AND channel_id=#{item.channelId}</if>" +
"</foreach>" +
"</script>"})
int batchUpdatePosition(List<DeviceChannel> deviceChannelList);
@Select("SELECT * FROM wvp_device_channel WHERE length(trim(stream_id)) > 0")
List<DeviceChannel> getAllChannelInPlay();
@ -572,4 +555,24 @@ public interface DeviceChannelMapper {
" <if test='channelId != null'> and channel_id = #{channelId} </if>" +
"</script>")
void updateChannelStreamIdentification(DeviceChannel channel);
@Update({"<script>" +
"<foreach collection='channelList' item='item' separator=';'>" +
" UPDATE" +
" wvp_device_channel" +
" SET update_time=#{item.updateTime}" +
"<if test='item.longitude != null'>, longitude=#{item.longitude}</if>" +
"<if test='item.latitude != null'>, latitude=#{item.latitude}</if>" +
"<if test='item.longitudeGcj02 != null'>, longitude_gcj02=#{item.longitudeGcj02}</if>" +
"<if test='item.latitudeGcj02 != null'>, latitude_gcj02=#{item.latitudeGcj02}</if>" +
"<if test='item.longitudeWgs84 != null'>, longitude_wgs84=#{item.longitudeWgs84}</if>" +
"<if test='item.latitudeWgs84 != null'>, latitude_wgs84=#{item.latitudeWgs84}</if>" +
"<if test='item.gpsTime != null'>, gps_time=#{item.gpsTime}</if>" +
"<if test='item.id > 0'>WHERE id=#{item.id}</if>" +
"<if test='item.id == 0'>WHERE device_id=#{item.deviceId} AND channel_id=#{item.channelId}</if>" +
"</foreach>" +
"</script>"})
void batchUpdatePosition(List<DeviceChannel> channelList);
}

View File

@ -49,7 +49,7 @@ public interface DeviceMobilePositionMapper {
void batchadd2(List<MobilePosition> mobilePositions);
@Insert("<script> " +
"<foreach collection='mobilePositions' index='index' item='item' separator=','> " +
"<foreach collection='mobilePositions' index='index' item='item' separator=';'> " +
"insert into wvp_device_mobile_position " +
"(device_id,channel_id, device_name,time,longitude,latitude,altitude,speed,direction,report_source," +
"longitude_gcj02,latitude_gcj02,longitude_wgs84,latitude_wgs84,create_time)"+
@ -57,7 +57,7 @@ public interface DeviceMobilePositionMapper {
"(#{item.deviceId}, #{item.channelId}, #{item.deviceName}, #{item.time}, #{item.longitude}, " +
"#{item.latitude}, #{item.altitude}, #{item.speed},#{item.direction}," +
"#{item.reportSource}, #{item.longitudeGcj02}, #{item.latitudeGcj02}, #{item.longitudeWgs84}, #{item.latitudeWgs84}, " +
"#{item.createTime}); " +
"#{item.createTime}) " +
"</foreach> " +
"</script>")
void batchadd(List<MobilePosition> mobilePositions);

View File

@ -41,6 +41,7 @@ public interface MediaServerMapper {
"type,"+
"create_time,"+
"update_time,"+
"transcode_suffix,"+
"hook_alive_interval"+
") VALUES " +
"(" +
@ -72,6 +73,7 @@ public interface MediaServerMapper {
"#{type}, " +
"#{createTime}, " +
"#{updateTime}, " +
"#{transcodeSuffix}, " +
"#{hookAliveInterval})")
int add(MediaServer mediaServerItem);
@ -102,6 +104,7 @@ public interface MediaServerMapper {
"<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>" +
"<if test=\"transcodeSuffix != null\">, transcode_suffix=#{transcodeSuffix}</if>" +
"<if test=\"type != null\">, type=#{type}</if>" +
"WHERE id=#{id}"+
" </script>"})
@ -133,6 +136,7 @@ public interface MediaServerMapper {
"<if test=\"recordDay != null\">, record_day=#{recordDay}</if>" +
"<if test=\"recordPath != null\">, record_path=#{recordPath}</if>" +
"<if test=\"type != null\">, type=#{type}</if>" +
"<if test=\"transcodeSuffix != null\">, transcode_suffix=#{transcodeSuffix}</if>" +
"<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" +
"WHERE ip=#{ip} and http_port=#{httpPort}"+
" </script>"})

View File

@ -82,12 +82,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
@Override
public void resetAllCSEQ() {
String scanKey = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetting.getServerId() + "_*";
List<Object> keys = RedisUtil.scan(redisTemplate, scanKey);
for (Object o : keys) {
String key = (String) o;
redisTemplate.opsForValue().set(key, 1);
}
String key = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetting.getServerId();
redisTemplate.opsForValue().set(key, 1);
}
@Override
@ -576,7 +572,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
@Override
public void sendMobilePositionMsg(JSONObject jsonObject) {
String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION;
// logger.info("[redis发送通知] 发送 移动位置 {}: {}", key, jsonObject.toString());
logger.debug("[redis发送通知] 发送 移动位置 {}: {}", key, jsonObject.toString());
redisTemplate.convertAndSend(key, jsonObject);
}

View File

@ -119,6 +119,14 @@ public class DateUtil {
return formatter.format(LocalDateTime.ofInstant(instant, ZoneId.of(zoneStr)));
}
/**
* 时间戳 yyyy_MM_dd_HH_mm_ss
*/
public static String timestampMsToUrlToyyyy_MM_dd_HH_mm_ss(long timestamp) {
Instant instant = Instant.ofEpochMilli(timestamp);
return urlFormatter.format(LocalDateTime.ofInstant(instant, ZoneId.of(zoneStr)));
}
/**
* yyyy_MM_dd_HH_mm_ss 转时间戳毫秒
*

View File

@ -0,0 +1,26 @@
package com.genersoft.iot.vmp.utils;
import org.springframework.util.ObjectUtils;
import java.util.HashMap;
import java.util.Map;
public class MediaServerUtils {
public static Map<String, String> urlParamToMap(String params) {
HashMap<String, String> map = new HashMap<>();
if (ObjectUtils.isEmpty(params)) {
return map;
}
String[] paramsArray = params.split("&");
if (paramsArray.length == 0) {
return map;
}
for (String param : paramsArray) {
String[] paramArray = param.split("=");
if (paramArray.length == 2) {
map.put(paramArray[0], paramArray[1]);
}
}
return map;
}
}

View File

@ -8,7 +8,9 @@ import com.genersoft.iot.vmp.service.ICloudRecordService;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.CloudRecordItem;
import com.genersoft.iot.vmp.service.bean.DownloadFileInfo;
import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.cloudRecord.bean.CloudRecordUrl;
import com.github.pagehelper.PageInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@ -21,9 +23,15 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@SuppressWarnings("rawtypes")
@Tag(name = "云端录像接口")
@ -67,22 +75,22 @@ public class CloudRecordController {
if (ObjectUtils.isEmpty(month)) {
month = calendar.get(Calendar.MONTH) + 1;
}
List<MediaServer> mediaServerItems;
List<MediaServer> mediaServers;
if (!ObjectUtils.isEmpty(mediaServerId)) {
mediaServerItems = new ArrayList<>();
MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId);
if (mediaServerItem == null) {
mediaServers = new ArrayList<>();
MediaServer mediaServer = mediaServerService.getOne(mediaServerId);
if (mediaServer == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到流媒体: " + mediaServerId);
}
mediaServerItems.add(mediaServerItem);
mediaServers.add(mediaServer);
} else {
mediaServerItems = mediaServerService.getAllOnlineList();
mediaServers = mediaServerService.getAllOnlineList();
}
if (mediaServerItems.isEmpty()) {
if (mediaServers.isEmpty()) {
return new ArrayList<>();
}
return cloudRecordService.getDateList(app, stream, year, month, mediaServerItems);
return cloudRecordService.getDateList(app, stream, year, month, mediaServers);
}
@ResponseBody
@ -96,6 +104,7 @@ public class CloudRecordController {
@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)
@Parameter(name = "callId", description = "每次录像的唯一标识,置空则查询全部流媒体", required = false)
public PageInfo<CloudRecordItem> openRtpServer(
@RequestParam(required = false) String query,
@RequestParam(required = false) String app,
@ -104,24 +113,25 @@ public class CloudRecordController {
@RequestParam int count,
@RequestParam(required = false) String startTime,
@RequestParam(required = false) String endTime,
@RequestParam(required = false) String mediaServerId
@RequestParam(required = false) String mediaServerId,
@RequestParam(required = false) String callId
) {
logger.info("[云端录像] 查询 app->{}, stream->{}, mediaServerId->{}, page->{}, count->{}, startTime->{}, endTime->{}",
app, stream, mediaServerId, page, count, startTime, endTime);
logger.info("[云端录像] 查询 app->{}, stream->{}, mediaServerId->{}, page->{}, count->{}, startTime->{}, endTime->{}, callId->{}",
app, stream, mediaServerId, page, count, startTime, endTime, callId);
List<MediaServer> mediaServerItems;
List<MediaServer> mediaServers;
if (!ObjectUtils.isEmpty(mediaServerId)) {
mediaServerItems = new ArrayList<>();
MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId);
if (mediaServerItem == null) {
mediaServers = new ArrayList<>();
MediaServer mediaServer = mediaServerService.getOne(mediaServerId);
if (mediaServer == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到流媒体: " + mediaServerId);
}
mediaServerItems.add(mediaServerItem);
mediaServers.add(mediaServer);
} else {
mediaServerItems = mediaServerService.getAllOnlineList();
mediaServers = mediaServerService.getAllOnlineList();
}
if (mediaServerItems.isEmpty()) {
if (mediaServers.isEmpty()) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "当前无流媒体");
}
if (query != null && ObjectUtils.isEmpty(query.trim())) {
@ -139,7 +149,10 @@ public class CloudRecordController {
if (endTime != null && ObjectUtils.isEmpty(endTime.trim())) {
endTime = null;
}
return cloudRecordService.getList(page, count, query, app, stream, startTime, endTime, mediaServerItems);
if (callId != null && ObjectUtils.isEmpty(callId.trim())) {
callId = null;
}
return cloudRecordService.getList(page, count, query, app, stream, startTime, endTime, mediaServers, callId);
}
@ResponseBody
@ -162,20 +175,20 @@ public class CloudRecordController {
@RequestParam(required = false) String callId,
@RequestParam(required = false) String remoteHost
){
MediaServer mediaServerItem;
MediaServer mediaServer;
if (mediaServerId == null) {
mediaServerItem = mediaServerService.getDefaultMediaServer();
mediaServer = mediaServerService.getDefaultMediaServer();
}else {
mediaServerItem = mediaServerService.getOne(mediaServerId);
mediaServer = mediaServerService.getOne(mediaServerId);
}
if (mediaServerItem == null) {
if (mediaServer == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的流媒体");
}else {
if (remoteHost == null) {
remoteHost = request.getScheme() + "://" + mediaServerItem.getIp() + ":" + mediaServerItem.getRecordAssistPort();
remoteHost = request.getScheme() + "://" + mediaServer.getIp() + ":" + mediaServer.getRecordAssistPort();
}
}
return cloudRecordService.addTask(app, stream, mediaServerItem, startTime, endTime, callId, remoteHost, mediaServerId != null);
return cloudRecordService.addTask(app, stream, mediaServer, startTime, endTime, callId, remoteHost, mediaServerId != null);
}
@ResponseBody
@ -265,4 +278,212 @@ public class CloudRecordController {
){
return cloudRecordService.getPlayUrlPath(recordId);
}
/************************* 以下这些接口只适合wvp和zlm部署在同一台服务器的情况且wvp只有一个zlm节点的情况 ***************************************/
/**
* 下载指定录像文件的压缩包
* @param query 检索内容
* @param app 应用名
* @param stream 流ID
* @param startTime 开始时间(yyyy-MM-dd HH:mm:ss)
* @param endTime 结束时间(yyyy-MM-dd HH:mm:ss)
* @param mediaServerId 流媒体ID置空则查询全部流媒体
* @param callId 每次录像的唯一标识置空则查询全部流媒体
* @param ids 指定的Id
*/
@ResponseBody
@GetMapping("/zip")
public void downloadZipFile(
HttpServletResponse response,
@RequestParam(required = false) String query,
@RequestParam(required = false) String app,
@RequestParam(required = false) String stream,
@RequestParam(required = false) String startTime,
@RequestParam(required = false) String endTime,
@RequestParam(required = false) String mediaServerId,
@RequestParam(required = false) String callId,
@RequestParam(required = false) List<Integer> ids
) {
logger.info("[下载指定录像文件的压缩包] 查询 app->{}, stream->{}, mediaServerId->{}, startTime->{}, endTime->{}, callId->{}",
app, stream, mediaServerId, startTime, endTime, callId);
List<MediaServer> mediaServers;
if (!ObjectUtils.isEmpty(mediaServerId)) {
mediaServers = new ArrayList<>();
MediaServer mediaServer = mediaServerService.getOne(mediaServerId);
if (mediaServer == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到流媒体: " + mediaServerId);
}
mediaServers.add(mediaServer);
} else {
mediaServers = mediaServerService.getAll();
}
if (mediaServers.isEmpty()) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "当前无流媒体");
}
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;
}
if (callId != null && ObjectUtils.isEmpty(callId.trim())) {
callId = null;
}
if (stream != null && callId != null) {
response.addHeader( "Content-Disposition", "attachment;filename=" + stream + "_" + callId + ".zip" );
}
List<CloudRecordItem> cloudRecordItemList = cloudRecordService.getAllList(query, app, stream, startTime, endTime, mediaServers, callId, ids);
if (ObjectUtils.isEmpty(cloudRecordItemList)) {
return;
}
try {
ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
for (CloudRecordItem cloudRecordItem : cloudRecordItemList) {
zos.putNextEntry(new ZipEntry(DateUtil.timestampMsToUrlToyyyy_MM_dd_HH_mm_ss(cloudRecordItem.getStartTime()) + ".mp4"));
File file = new File(cloudRecordItem.getFilePath());
if (!file.exists() || file.isDirectory()) {
continue;
}
FileInputStream fis = new FileInputStream(cloudRecordItem.getFilePath());
byte[] buf = new byte[2*1024];
int len;
while ((len = fis.read(buf)) != -1){
zos.write(buf, 0, len);
}
zos.closeEntry();
fis.close();
}
zos.close();
} catch (IOException e) {
logger.error("[下载指定录像文件的压缩包] 失败: 查询 app->{}, stream->{}, mediaServerId->{}, startTime->{}, endTime->{}, callId->{}",
app, stream, mediaServerId, startTime, endTime, callId, e);
}
}
/**
*
* @param query 检索内容
* @param app 应用名
* @param stream 流ID
* @param startTime 开始时间(yyyy-MM-dd HH:mm:ss)
* @param endTime 结束时间(yyyy-MM-dd HH:mm:ss)
* @param mediaServerId 流媒体ID置空则查询全部流媒体
* @param callId 每次录像的唯一标识置空则查询全部流媒体
* @param remoteHost 拼接播放地址时使用的远程地址
*/
@ResponseBody
@GetMapping("/list-url")
@Operation(summary = "分页查询云端录像", security = @SecurityRequirement(name = JwtUtils.HEADER))
@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)
@Parameter(name = "callId", description = "每次录像的唯一标识,置空则查询全部流媒体", required = false)
public PageInfo<CloudRecordUrl> getListWithUrl(
HttpServletRequest request,
@RequestParam(required = false) String query,
@RequestParam(required = false) String app,
@RequestParam(required = false) String stream,
@RequestParam int page,
@RequestParam int count,
@RequestParam(required = false) String startTime,
@RequestParam(required = false) String endTime,
@RequestParam(required = false) String mediaServerId,
@RequestParam(required = false) String callId,
@RequestParam(required = false) String remoteHost
) {
logger.info("[云端录像] 查询URL app->{}, stream->{}, mediaServerId->{}, page->{}, count->{}, startTime->{}, endTime->{}, callId->{}",
app, stream, mediaServerId, page, count, startTime, endTime, callId);
List<MediaServer> mediaServers;
if (!ObjectUtils.isEmpty(mediaServerId)) {
mediaServers = new ArrayList<>();
MediaServer mediaServer = mediaServerService.getOne(mediaServerId);
if (mediaServer == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到流媒体: " + mediaServerId);
}
mediaServers.add(mediaServer);
} else {
mediaServers = mediaServerService.getAll();
}
if (mediaServers.isEmpty()) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "当前无流媒体");
}
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;
}
if (callId != null && ObjectUtils.isEmpty(callId.trim())) {
callId = null;
}
MediaServer mediaServer = mediaServerService.getDefaultMediaServer();
if (mediaServer == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到流媒体节点");
}
if (remoteHost == null) {
remoteHost = request.getScheme() + "://" + request.getLocalAddr() + ":" +
(request.getScheme().equals("https")? mediaServer.getHttpSSlPort() : mediaServer.getHttpPort());
}
PageInfo<CloudRecordItem> cloudRecordItemPageInfo = cloudRecordService.getList(page, count, query, app, stream, startTime, endTime, mediaServers, callId);
PageInfo<CloudRecordUrl> cloudRecordUrlPageInfo = new PageInfo<>();
if (!ObjectUtils.isEmpty(cloudRecordItemPageInfo)) {
cloudRecordUrlPageInfo.setPageNum(cloudRecordItemPageInfo.getPageNum());
cloudRecordUrlPageInfo.setPageSize(cloudRecordItemPageInfo.getPageSize());
cloudRecordUrlPageInfo.setSize(cloudRecordItemPageInfo.getSize());
cloudRecordUrlPageInfo.setEndRow(cloudRecordItemPageInfo.getEndRow());
cloudRecordUrlPageInfo.setStartRow(cloudRecordItemPageInfo.getStartRow());
cloudRecordUrlPageInfo.setPages(cloudRecordItemPageInfo.getPages());
cloudRecordUrlPageInfo.setPrePage(cloudRecordItemPageInfo.getPrePage());
cloudRecordUrlPageInfo.setNextPage(cloudRecordItemPageInfo.getNextPage());
cloudRecordUrlPageInfo.setIsFirstPage(cloudRecordItemPageInfo.isIsFirstPage());
cloudRecordUrlPageInfo.setIsLastPage(cloudRecordItemPageInfo.isIsLastPage());
cloudRecordUrlPageInfo.setHasPreviousPage(cloudRecordItemPageInfo.isHasPreviousPage());
cloudRecordUrlPageInfo.setHasNextPage(cloudRecordItemPageInfo.isHasNextPage());
cloudRecordUrlPageInfo.setNavigatePages(cloudRecordItemPageInfo.getNavigatePages());
cloudRecordUrlPageInfo.setNavigateFirstPage(cloudRecordItemPageInfo.getNavigateFirstPage());
cloudRecordUrlPageInfo.setNavigateLastPage(cloudRecordItemPageInfo.getNavigateLastPage());
cloudRecordUrlPageInfo.setNavigatepageNums(cloudRecordItemPageInfo.getNavigatepageNums());
cloudRecordUrlPageInfo.setTotal(cloudRecordItemPageInfo.getTotal());
List<CloudRecordUrl> cloudRecordUrlList = new ArrayList<>(cloudRecordItemPageInfo.getList().size());
List<CloudRecordItem> cloudRecordItemList = cloudRecordItemPageInfo.getList();
for (CloudRecordItem cloudRecordItem : cloudRecordItemList) {
CloudRecordUrl cloudRecordUrl = new CloudRecordUrl();
cloudRecordUrl.setId(cloudRecordItem.getId());
cloudRecordUrl.setDownloadUrl(remoteHost + "/index/api/downloadFile?file_path=" + cloudRecordItem.getFilePath()
+ "&save_name=" + cloudRecordItem.getStream() + "_" + cloudRecordItem.getCallId() + "_" + DateUtil.timestampMsToUrlToyyyy_MM_dd_HH_mm_ss(cloudRecordItem.getStartTime()) );
cloudRecordUrl.setPlayUrl(remoteHost + "/index/api/downloadFile?file_path=" + cloudRecordItem.getFilePath());
cloudRecordUrlList.add(cloudRecordUrl);
}
cloudRecordUrlPageInfo.setList(cloudRecordUrlList);
}
return cloudRecordUrlPageInfo;
}
}

View File

@ -0,0 +1,32 @@
package com.genersoft.iot.vmp.vmanager.cloudRecord.bean;
public class CloudRecordUrl {
private String playUrl;
private String downloadUrl;
private int id;
public String getPlayUrl() {
return playUrl;
}
public void setPlayUrl(String playUrl) {
this.playUrl = playUrl;
}
public String getDownloadUrl() {
return downloadUrl;
}
public void setDownloadUrl(String downloadUrl) {
this.downloadUrl = downloadUrl;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}

View File

@ -31,6 +31,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
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.*;
import org.springframework.web.context.request.async.DeferredResult;
@ -129,6 +130,9 @@ public class PlayController {
}
streamInfo.channgeStreamIp(host);
}
if (!ObjectUtils.isEmpty(newMediaServerItem.getTranscodeSuffix()) && !"null".equalsIgnoreCase(newMediaServerItem.getTranscodeSuffix())) {
streamInfo.setStream(streamInfo.getStream() + "_" + newMediaServerItem.getTranscodeSuffix());
}
wvpResult.setData(new StreamContent(streamInfo));
}else {
wvpResult.setCode(code);

View File

@ -241,6 +241,8 @@ user-settings:
register-again-after-time: 60
# 国标续订方式true为续订每次注册在同一个会话里false为重新注册每次使用新的会话
register-keep-int-dialog: false
# 开启接口文档页面。 默认开启生产环境建议关闭遇到swagger相关的漏洞时也可以关闭
doc-enable: true
# 跨域配置,不配置此项则允许所有跨域请求,配置后则只允许配置的页面的地址请求, 可以配置多个
allowed-origins:
- http://localhost:8008

View File

@ -112,7 +112,4 @@ user-settings:
auto-apply-play: true
# 设备/通道状态变化时发送消息
device-status-notify: true
# [可选] 日志配置, 一般不需要改
logging:
config: classpath:logback-spring.xml

View File

@ -1,6 +1,7 @@
<template>
<div ref="container" @dblclick="fullscreenSwich"
style="width:100%; height: 100%; background-color: #000000;margin:0 auto;position: relative;">
<div style="width:100%; padding-top: 56.25%; position: relative;"></div>
<div class="buttons-box" id="buttonsBox">
<div class="buttons-box-left">
<i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick"></i>
@ -66,6 +67,9 @@ export default {
// });
// ro.observe(this.$refs.container);
// },
mounted(){
this.updatePlayerDomSize();
},
watch: {
videoUrl: {
handler(val, _) {
@ -91,6 +95,7 @@ export default {
if (width > 0 && height > 0) {
dom.style.width = width + 'px';
dom.style.height = height + "px";
dom.style.paddingTop = 0;
console.log(width)
console.log(height)
}

View File

@ -7,7 +7,7 @@
v-if="Object.keys(this.player).length > 1">
<el-tab-pane label="Jessibuca" name="jessibuca">
<jessibucaPlayer v-if="activePlayer === 'jessibuca'" ref="jessibuca" :visible.sync="showVideoDialog"
:videoUrl="videoUrl" :error="videoError" :message="videoError" style="height: 515px"
:videoUrl="videoUrl" :error="videoError" :message="videoError"
:hasAudio="hasAudio" fluent autoplay live></jessibucaPlayer>
</el-tab-pane>
<el-tab-pane label="WebRTC" name="webRTC">
@ -19,7 +19,7 @@
</el-tabs>
<jessibucaPlayer v-if="Object.keys(this.player).length == 1 && this.player.jessibuca" ref="jessibuca"
:visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError"
height="100px" :hasAudio="hasAudio" fluent autoplay live></jessibucaPlayer>
:hasAudio="hasAudio" fluent autoplay live></jessibucaPlayer>
<rtc-player v-if="Object.keys(this.player).length == 1 && this.player.webRTC" ref="jessibuca"
:visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError"
height="100px" :hasAudio="hasAudio" fluent autoplay live></rtc-player>

View File

@ -34,7 +34,7 @@
<el-form-item label="本地IP" prop="deviceIp">
<el-select v-model="platform.deviceIp" placeholder="请选择与上级相通的网卡" style="width: 100%">
<el-option
v-for="ip in deviceIp"
v-for="ip in deviceIps"
:key="ip"
:label="ip"
:value="ip">
@ -58,7 +58,7 @@
<el-input v-model="platform.username"></el-input>
</el-form-item>
<el-form-item label="SIP认证密码" prop="password">
<el-input v-model="platform.password" ></el-input>
<el-input v-model="platform.password"></el-input>
</el-form-item>
<el-form-item label="注册周期(秒)" prop="expires">
<el-input v-model="platform.expires"></el-input>
@ -100,16 +100,17 @@
</el-form-item>
<el-form-item label="其他选项">
<el-checkbox label="启用" v-model="platform.enable" @change="checkExpires"></el-checkbox>
<!-- <el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox>-->
<!-- <el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox>-->
<el-checkbox label="拉起推流" v-model="platform.startOfflinePush"></el-checkbox>
<el-checkbox label="RTCP保活" v-model="platform.rtcp" @change="rtcpCheckBoxChange"></el-checkbox>
<el-checkbox label="消息通道" v-model="platform.asMessageChannel" ></el-checkbox>
<el-checkbox label="推送通道" v-model="platform.autoPushChannel" ></el-checkbox>
<el-checkbox label="消息通道" v-model="platform.asMessageChannel"></el-checkbox>
<el-checkbox label="推送通道" v-model="platform.autoPushChannel"></el-checkbox>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">{{
onSubmit_text
}}</el-button>
onSubmit_text
}}
</el-button>
<el-button @click="close">取消</el-button>
</el-form-item>
</el-form>
@ -172,52 +173,56 @@ export default {
administrativeDivision: "",
sendStreamIp: null,
},
deviceIp: [], // IP
deviceIps: [], // IP
rules: {
name: [{ required: true, message: "请输入平台名称", trigger: "blur" }],
name: [{required: true, message: "请输入平台名称", trigger: "blur"}],
serverGBId: [
{ required: true, message: "请输入SIP服务国标编码", trigger: "blur" },
{required: true, message: "请输入SIP服务国标编码", trigger: "blur"},
],
serverGBDomain: [
{ required: true, message: "请输入SIP服务国标域", trigger: "blur" },
{required: true, message: "请输入SIP服务国标域", trigger: "blur"},
],
serverIP: [{ required: true, message: "请输入SIP服务IP", trigger: "blur" }],
serverPort: [{ required: true, message: "请输入SIP服务端口", trigger: "blur" }],
deviceGBId: [{ validator: deviceGBIdRules, trigger: "blur" }],
username: [{ required: false, message: "请输入SIP认证用户名", trigger: "blur" }],
password: [{ required: false, message: "请输入SIP认证密码", trigger: "blur" }],
expires: [{ required: true, message: "请输入注册周期", trigger: "blur" }],
keepTimeout: [{ required: true, message: "请输入心跳周期", trigger: "blur" }],
transport: [{ required: true, message: "请选择信令传输", trigger: "blur" }],
characterSet: [{ required: true, message: "请选择编码字符集", trigger: "blur" }],
serverIP: [{required: true, message: "请输入SIP服务IP", trigger: "blur"}],
serverPort: [{required: true, message: "请输入SIP服务端口", trigger: "blur"}],
deviceGBId: [{validator: deviceGBIdRules, trigger: "blur"}],
username: [{required: false, message: "请输入SIP认证用户名", trigger: "blur"}],
password: [{required: false, message: "请输入SIP认证密码", trigger: "blur"}],
expires: [{required: true, message: "请输入注册周期", trigger: "blur"}],
keepTimeout: [{required: true, message: "请输入心跳周期", trigger: "blur"}],
transport: [{required: true, message: "请选择信令传输", trigger: "blur"}],
characterSet: [{required: true, message: "请选择编码字符集", trigger: "blur"}],
deviceIp: [{required: true, message: "请选择本地IP", trigger: "blur"}],
},
};
},
methods: {
openDialog: function (platform, callback) {
var that = this;
if (platform == null) {
this.onSubmit_text = "立即创建";
this.saveUrl = "/api/platform/add";
this.$axios({
method: 'get',
url:`/api/platform/server_config`
}).then(function (res) {
console.log(res);
this.$axios({
method: 'get',
url: `/api/platform/server_config`
}).then(function (res) {
if (platform == null) {
if (res.data.code === 0) {
that.platform.deviceGBId = res.data.data.username;
that.deviceIp = res.data.data.deviceIp.split(',');
that.deviceIps = res.data.data.deviceIp.split(',');
that.platform.deviceIp = that.deviceIps[0];
that.platform.devicePort = res.data.data.devicePort;
that.platform.username = res.data.data.username;
that.platform.password = res.data.data.password;
that.platform.sendStreamIp = res.data.data.sendStreamIp;
that.platform.administrativeDivision = res.data.data.username.substr(0, 6);
}
}).catch(function (error) {
console.log(error);
});
}else {
} else {
that.deviceIps = res.data.data.deviceIp.split(',');
}
}).catch(function (error) {
console.log(error);
});
if (platform == null) {
this.onSubmit_text = "立即创建";
this.saveUrl = "/api/platform/add";
} else {
this.platform.id = platform.id;
this.platform.enable = platform.enable;
this.platform.ptz = platform.ptz;
@ -230,7 +235,7 @@ export default {
this.platform.serverIP = platform.serverIP;
this.platform.serverPort = platform.serverPort;
this.platform.deviceGBId = platform.deviceGBId;
this.deviceIp = platform.deviceIp.split(',');
this.platform.deviceIp = platform.deviceIp;
this.platform.devicePort = platform.devicePort;
this.platform.username = platform.username;
this.platform.password = platform.password;
@ -256,7 +261,7 @@ export default {
},
deviceGBIdChange: function () {
this.platform.username = this.platform.deviceGBId ;
this.platform.username = this.platform.deviceGBId;
if (this.platform.administrativeDivision == null) {
this.platform.administrativeDivision = this.platform.deviceGBId.substr(0, 6);
}
@ -264,12 +269,12 @@ export default {
onSubmit: function () {
this.saveForm()
},
saveForm: function (){
saveForm: function () {
this.$axios({
method: 'post',
url: this.saveUrl,
data: this.platform
}).then((res) =>{
}).then((res) => {
if (res.data.code === 0) {
this.$message({
showClose: true,
@ -280,14 +285,14 @@ export default {
if (this.listChangeCallback != null) {
this.listChangeCallback();
}
}else {
} else {
this.$message({
showClose: true,
message: res.data.msg,
type: "error",
});
}
}).catch((error)=> {
}).catch((error) => {
console.log(error);
});
},
@ -325,24 +330,25 @@ export default {
var result = false;
var that = this;
await that.$axios({
method: 'get',
url:`/api/platform/exit/${deviceGbId}`})
method: 'get',
url: `/api/platform/exit/${deviceGbId}`
})
.then(function (res) {
if (res.data.code === 0) {
result = res.data.data;
}
if (res.data.code === 0) {
result = res.data.data;
}
})
.catch(function (error) {
console.log(error);
});
return result;
},
checkExpires: function() {
checkExpires: function () {
if (this.platform.enable && this.platform.expires === "0") {
this.platform.expires = "3600";
}
},
rtcpCheckBoxChange: function (result){
rtcpCheckBoxChange: function (result) {
if (result) {
this.$message({
showClose: true,
@ -363,10 +369,12 @@ input::-webkit-inner-spin-button {
appearance: none;
margin: 0;
}
/* 火狐 */
input{
-moz-appearance:textfield;
input {
-moz-appearance: textfield;
}
.control-wrapper-not-used {
position: relative;
width: 6.25rem;

View File

@ -97,9 +97,9 @@ enable_ts=1
fmp4_demand=0
hls_demand=0
hls_save_path=./www
modify_stamp=0
modify_stamp=2
mp4_as_player=0
mp4_max_second=3600
mp4_max_second=300
mp4_save_path=./www
rtmp_demand=0
rtsp_demand=0
@ -163,4 +163,16 @@ pktBufSize=8192
port=9000
timeoutSec=5
[transcode]
acodec=pcma
decoder_h264=h264_qsv,h264_videotoolbox,h264_bm,libopenh264
decoder_h265=hevc_qsv,hevc_videotoolbox,hevc_bm
enable_ffmpeg_log=0
encoder_h264=h264_qsv,h264_videotoolbox,h264_bm,libx264,libopenh264
encoder_h265=hevc_qsv,hevc_videotoolbox,hevc_bm,libx265
filter=
suffix=transport
vcodec=H264
; } ---

View File

@ -171,6 +171,7 @@ create table wvp_media_server (
hook_alive_interval integer,
record_path character varying(255),
record_day integer default 7,
transcode_suffix character varying(255),
constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
);
@ -319,6 +320,7 @@ create table wvp_resources_tree (
parentId integer,
path character varying(255)
);
create table wvp_user_api_key (
id serial primary key ,
user_id bigint,
@ -331,6 +333,7 @@ create table wvp_user_api_key (
update_time character varying(50)
);
/*初始数据*/
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');

View File

@ -171,6 +171,7 @@ create table wvp_media_server (
hook_alive_interval integer,
record_path character varying(255),
record_day integer default 7,
transcode_suffix character varying(255),
constraint uk_media_server_unique_ip_http_port unique (ip, http_port)
);
@ -319,6 +320,7 @@ create table wvp_resources_tree (
parentId integer,
path character varying(255)
);
create table wvp_user_api_key (
id serial primary key ,
user_id bigint,
@ -331,6 +333,7 @@ create table wvp_user_api_key (
update_time character varying(50)
);
/*初始数据*/
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');

View File

@ -1,3 +1,6 @@
alter table wvp_media_server
add transcode_suffix character varying(255);
alter table wvp_media_server
add type character varying(50) default 'zlm';

View File

@ -1,3 +1,6 @@
alter table wvp_media_server
add transcode_suffix character varying(255);
alter table wvp_media_server
add type character varying(50) default 'zlm';

View File

@ -0,0 +1,342 @@
/*建表*/
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,
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),
stream_identification 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,
flv_port integer,
flv_ssl_port integer,
ws_flv_port integer,
ws_flv_ssl_port integer,
auto_config bool default false,
secret character varying(50),
type character varying(50) default 'zlm',
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,
transcode_suffix character varying(255),
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,
send_stream_ip character varying(50),
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)
);
create table wvp_user_api_key (
id serial primary key ,
user_id bigint,
app character varying(255) ,
api_key text,
expired_at bigint,
remark character varying(255),
enable bool default true,
create_time character varying(50),
update_time character varying(50)
);
/*初始数据*/
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');

View File

@ -0,0 +1,342 @@
/*建表*/
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,
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),
stream_identification 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,
flv_port integer,
flv_ssl_port integer,
ws_flv_port integer,
ws_flv_ssl_port integer,
auto_config bool default false,
secret character varying(50),
type character varying(50) default 'zlm',
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,
transcode_suffix character varying(255),
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,
send_stream_ip character varying(50),
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 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,
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)
);
create table wvp_user_api_key (
id serial primary key ,
user_id bigint,
app character varying(255) ,
api_key text,
expired_at bigint,
remark character varying(255),
enable bool default true,
create_time character varying(50),
update_time character varying(50)
);
/*初始数据*/
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');

View File

@ -0,0 +1,26 @@
alter table wvp_media_server
add transcode_suffix character varying(255);
alter table wvp_media_server
add type character varying(50) default 'zlm';
alter table wvp_media_server
add flv_port integer;
alter table wvp_media_server
add flv_ssl_port integer;
alter table wvp_media_server
add ws_flv_port integer;
alter table wvp_media_server
add ws_flv_ssl_port integer;
create table wvp_user_api_key (
id serial primary key ,
user_id bigint,
app character varying(255) ,
api_key text,
expired_at bigint,
remark character varying(255),
enable bool default true,
create_time character varying(50),
update_time character varying(50)
);

View File

@ -0,0 +1,26 @@
alter table wvp_media_server
add transcode_suffix character varying(255);
alter table wvp_media_server
add type character varying(50) default 'zlm';
alter table wvp_media_server
add flv_port integer;
alter table wvp_media_server
add flv_ssl_port integer;
alter table wvp_media_server
add ws_flv_port integer;
alter table wvp_media_server
add ws_flv_ssl_port integer;
create table wvp_user_api_key (
id serial primary key ,
user_id bigint,
app character varying(255) ,
api_key text,
expired_at bigint,
remark character varying(255),
enable bool default true,
create_time character varying(50),
update_time character varying(50)
);