From 7d9cc96ef54399795deb5b7fc7682e6323dc1202 Mon Sep 17 00:00:00 2001
From: 648540858 <456panlinlin>
Date: 星期五, 25 三月 2022 16:05:14 +0800
Subject: [PATCH] 优化国标录像下载,添加进度条以及自动合并文件下载,需要结合新版assist服务使用。
---
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java | 24
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java | 28 +
src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java | 139 ++++++++
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java | 1
web_src/package-lock.json | 6
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java | 4
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java | 1
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java | 38 ++
web_src/src/components/dialog/devicePlayer.vue | 53 ++-
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java | 2
web_src/build/webpack.dev.conf.js | 1
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java | 11
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java | 2
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java | 6
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java | 1
web_src/config/index.js | 4
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java | 142 ++++++++
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java | 7
/dev/null | 190 -----------
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java | 9
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java | 11
web_src/src/components/dialog/recordDownload.vue | 195 +++++++++++
web_src/src/router/index.js | 6
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java | 121 +++++++
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java | 2
25 files changed, 761 insertions(+), 243 deletions(-)
diff --git a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
index 0626384..4e4ba15 100644
--- a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
+++ b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
@@ -31,6 +31,9 @@
private String rtc;
private String mediaServerId;
private Object tracks;
+ private String startTime;
+ private String endTime;
+ private double progress;
public static class TransactionInfo{
public String callId;
@@ -264,4 +267,29 @@
public void setHttps_ts(String https_ts) {
this.https_ts = https_ts;
}
+
+
+ public String getStartTime() {
+ return startTime;
+ }
+
+ public void setStartTime(String startTime) {
+ this.startTime = startTime;
+ }
+
+ public String getEndTime() {
+ return endTime;
+ }
+
+ public void setEndTime(String endTime) {
+ this.endTime = endTime;
+ }
+
+ public double getProgress() {
+ return progress;
+ }
+
+ public void setProgress(double progress) {
+ this.progress = progress;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
index c2dedec..87d2635 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
@@ -1,5 +1,7 @@
package com.genersoft.iot.vmp.gb28181.bean;
+import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
+
public class SsrcTransaction {
private String deviceId;
@@ -10,6 +12,7 @@
private byte[] dialog;
private String mediaServerId;
private String ssrc;
+ private VideoStreamSessionManager.SessionType type;
public String getDeviceId() {
return deviceId;
@@ -74,4 +77,12 @@
public void setSsrc(String ssrc) {
this.ssrc = ssrc;
}
+
+ public VideoStreamSessionManager.SessionType getType() {
+ return type;
+ }
+
+ public void setType(VideoStreamSessionManager.SessionType type) {
+ this.type = type;
+ }
}
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
index d511f42..50957f6 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
@@ -156,8 +156,6 @@
List<ParentPlatform> parentPlatforms = parentPlatformMap.get(gbId);
if (parentPlatforms != null && parentPlatforms.size() > 0) {
for (ParentPlatform platform : parentPlatforms) {
-// String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + platform.getServerGBId();
-// SubscribeInfo subscribeInfo = redisCatchStorage.getSubscribe(key);
SubscribeInfo subscribeInfo = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
if (subscribeInfo == null) continue;
logger.info("[Catalog浜嬩欢: {}]骞冲彴锛歿}锛屽奖鍝嶉�氶亾{}", event.getType(), platform.getServerGBId(), gbId);
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
index ba8f24c..6eed17e 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
@@ -30,6 +30,12 @@
@Autowired
private UserSetup userSetup;
+ public enum SessionType {
+ play,
+ playback,
+ download
+ }
+
/**
* 娣诲姞涓�涓偣鎾�/鍥炴斁鐨勪簨鍔′俊鎭�
* 鍚庣画鍙互閫氳繃娴両d/callID
@@ -40,7 +46,7 @@
* @param mediaServerId 鎵�浣跨敤鐨勬祦濯掍綋ID
* @param transaction 浜嬪姟
*/
- public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, ClientTransaction transaction){
+ public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, ClientTransaction transaction, SessionType type){
SsrcTransaction ssrcTransaction = new SsrcTransaction();
ssrcTransaction.setDeviceId(deviceId);
ssrcTransaction.setChannelId(channelId);
@@ -50,6 +56,7 @@
ssrcTransaction.setCallId(callId);
ssrcTransaction.setSsrc(ssrc);
ssrcTransaction.setMediaServerId(mediaServerId);
+ ssrcTransaction.setType(type);
redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId()
+ "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
index 409eedb..9cd89e0 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -115,7 +115,9 @@
* @param endTime 缁撴潫鏃堕棿,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss
* @param downloadSpeed 涓嬭浇鍊嶉�熷弬鏁�
*/
- void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, InviteStreamCallback event, SipSubscribe.Event errorEvent);
+ void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
+ String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
+ SipSubscribe.Event errorEvent);
/**
* 瑙嗛娴佸仠姝�
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
index 48bffd7..0f2242c 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -428,7 +428,7 @@
errorEvent.response(e);
}), e ->{
// 杩欓噷涓轰緥閬垮厤涓�涓�氶亾鐨勭偣鎾彧鏈変竴涓猚allID杩欎釜鍙傛暟浣跨敤涓�涓浐瀹氬��
- streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction());
+ streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction(), VideoStreamSessionManager.SessionType.play);
streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog);
});
@@ -537,7 +537,7 @@
transmitRequest(device, request, errorEvent, okEvent -> {
ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
- streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction());
+ streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction(), VideoStreamSessionManager.SessionType.playback);
streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog);
});
if (inviteStreamCallback != null) {
@@ -558,8 +558,9 @@
* @param downloadSpeed 涓嬭浇鍊嶉�熷弬鏁�
*/
@Override
- public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, InviteStreamCallback event
- , SipSubscribe.Event errorEvent) {
+ public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
+ String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
+ SipSubscribe.Event errorEvent) {
try {
logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
@@ -571,8 +572,6 @@
content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n");
content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" "
+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n");
-
-
String streamMode = device.getStreamMode().toUpperCase();
@@ -639,15 +638,20 @@
logger.debug("褰曞儚鍥炴斁娣诲姞璁㈤槄锛岃闃呭唴瀹癸細" + subscribeKey.toString());
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,
(MediaServerItem mediaServerItemInUse, JSONObject json)->{
- event.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
+ hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
});
Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc());
+ if (inviteStreamCallback != null) {
+ inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
+ }
+ transmitRequest(device, request, errorEvent, okEvent->{
+ ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
+ streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction(), VideoStreamSessionManager.SessionType.download);
+ streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog);
+ });
- ClientTransaction transaction = transmitRequest(device, request, errorEvent);
- streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction);
- streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction);
} catch ( SipException | ParseException | InvalidArgumentException e) {
e.printStackTrace();
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java
index f21dfc0..9550266 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java
@@ -104,6 +104,7 @@
DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
deviceChannel.setParental(0);
deviceChannel.setParentId(channelReduce.getCatalogId());
+ deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0, 6));
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
// 闃叉鍙戦�佽繃蹇�
Thread.sleep(100);
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
index 8235ade..e36a705 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
@@ -62,7 +62,12 @@
if (NotifyType.equals("121")){
logger.info("濯掍綋鎾斁瀹屾瘯锛岄�氱煡鍏虫祦");
String channelId =getText(rootElement, "DeviceID");
- redisCatchStorage.stopPlayback(device.getDeviceId(), channelId, null, callIdHeader.getCallId());
+// redisCatchStorage.stopPlayback(device.getDeviceId(), channelId, null, callIdHeader.getCallId());
+// redisCatchStorage.stopDownload(device.getDeviceId(), channelId, null, callIdHeader.getCallId());
+ StreamInfo streamInfo = redisCatchStorage.queryDownload(device.getDeviceId(), channelId, null, callIdHeader.getCallId());
+ // 璁剧疆杩涘害100%
+ streamInfo.setProgress(1);
+ redisCatchStorage.startDownload(streamInfo, callIdHeader.getCallId());
cmder.streamByeCmd(device.getDeviceId(), channelId, null, callIdHeader.getCallId());
// TODO 濡傛灉绾ц仈鎾斁锛岄渶瑕佺粰涓婄骇鍙戦�佹閫氱煡
diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
index d8c7250..959432c 100644
--- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
+++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
@@ -107,6 +107,7 @@
DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
deviceChannel.setParental(0);
deviceChannel.setParentId(channelReduce.getCatalogId());
+ deviceChannel.setCivilCode(parentPlatform.getDeviceGBId().substring(0, 6));
cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size);
// 闃叉鍙戦�佽繃蹇�
Thread.sleep(100);
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
new file mode 100644
index 0000000..249ec03
--- /dev/null
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
@@ -0,0 +1,139 @@
+package com.genersoft.iot.vmp.media.zlm;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
+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.StringUtils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class AssistRESTfulUtils {
+
+ private final static Logger logger = LoggerFactory.getLogger(AssistRESTfulUtils.class);
+
+ 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閫茶娣诲姞鏀旀埅鍣╨oggingInterceptor
+ httpClientBuilder.addInterceptor(logging);
+ }
+ return httpClientBuilder.build();
+ }
+
+
+ public JSONObject sendGet(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) {
+ OkHttpClient client = getClient();
+
+ if (mediaServerItem == null) {
+ return null;
+ }
+ if (StringUtils.isEmpty(mediaServerItem.getRecordAssistPort())) {
+ logger.warn("鏈惎鐢ˋssist鏈嶅姟");
+ return null;
+ }
+ StringBuffer stringBuffer = new StringBuffer();
+ stringBuffer.append(String.format("http://%s:%s/%s", mediaServerItem.getIp(), mediaServerItem.getRecordAssistPort(), api));
+ JSONObject responseJSON = null;
+
+ if (param != null && param.keySet().size() > 0) {
+ stringBuffer.append("?");
+ int index = 1;
+ for (String key : param.keySet()){
+ if (param.get(key) != null) {
+ stringBuffer.append(key + "=" + param.get(key));
+ if (index < param.size()) {
+ stringBuffer.append("&");
+ }
+ }
+ index++;
+ }
+ }
+
+ String url = stringBuffer.toString();
+ Request request = new Request.Builder()
+ .get()
+ .url(url)
+ .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 (ConnectException e) {
+ logger.error(String.format("杩炴帴Assist澶辫触: %s, %s", e.getCause().getMessage(), e.getMessage()));
+ logger.info("璇锋鏌edia閰嶇疆骞剁‘璁ssist宸插惎鍔�...");
+ }catch (IOException e) {
+ logger.error(String.format("[ %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("杩炴帴Assist澶辫触: %s, %s", e.getCause().getMessage(), e.getMessage()));
+ logger.info("璇锋鏌edia閰嶇疆骞剁‘璁ssist宸插惎鍔�...");
+ }
+ });
+ }
+
+
+
+ return responseJSON;
+ }
+
+
+ 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);
+ }
+
+}
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
index bd39a0c..c3c30a6 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -215,7 +215,16 @@
if (deviceChannel != null) {
ret.put("enable_audio", deviceChannel.isHasAudio());
}
+ // 濡傛灉鏄綍鍍忎笅杞藉氨璁剧疆瑙嗛闂撮殧鍗佺
+ if (ssrcTransactionForAll.get(0).getType() == VideoStreamSessionManager.SessionType.download) {
+ ret.put("mp4_max_second", 10);
+ ret.put("enable_mp4", true);
+ ret.put("enable_audio", true);
+ }
+
}
+
+
return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
}
@@ -324,7 +333,6 @@
if (mediaInfo != null) {
subscribe.response(mediaInfo, json);
}
-
}
// 娴佹秷澶辩Щ闄edis play
String app = item.getApp();
@@ -441,6 +449,7 @@
if ("rtp".equals(app)){
ret.put("close", true);
StreamInfo streamInfoForPlayCatch = redisCatchStorage.queryPlayByStreamId(streamId);
+ SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, null, streamId);
if (streamInfoForPlayCatch != null) {
// 濡傛灉鍦ㄧ粰涓婄骇鎺ㄦ祦锛屼篃涓嶅仠姝€��
if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) {
diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
index 84b36e3..3505225 100644
--- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
+++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
@@ -31,6 +31,7 @@
on_server_keepalive
}
+ @FunctionalInterface
public interface Event{
void response(MediaServerItem mediaServerItem, JSONObject response);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
index 4cff4a6..9e76493 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
@@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.service;
import com.alibaba.fastjson.JSONObject;
+import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;
@@ -34,4 +35,9 @@
DeferredResult<ResponseEntity<String>> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
void zlmServerOffline(String mediaServerId);
+
+ DeferredResult<ResponseEntity<String>> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
+ DeferredResult<ResponseEntity<String>> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
+
+ StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream);
}
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
index 9ee5867..7334184 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -12,6 +12,8 @@
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
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.DateUtil;
+import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
@@ -28,7 +30,6 @@
import com.genersoft.iot.vmp.service.IMediaService;
import com.genersoft.iot.vmp.service.IPlayService;
import gov.nist.javax.sip.stack.SIPDialog;
-import jdk.nashorn.internal.ir.RuntimeNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -38,10 +39,8 @@
import org.springframework.util.ResourceUtils;
import org.springframework.web.context.request.async.DeferredResult;
-import javax.sip.header.CallIdHeader;
-import javax.sip.header.Header;
-import javax.sip.message.Request;
import java.io.FileNotFoundException;
+import java.math.BigDecimal;
import java.util.*;
@SuppressWarnings(value = {"rawtypes", "unchecked"})
@@ -70,6 +69,9 @@
@Autowired
private ZLMRESTfulUtils zlmresTfulUtils;
+
+ @Autowired
+ private AssistRESTfulUtils assistRESTfulUtils;
@Autowired
private IMediaService mediaService;
@@ -344,7 +346,7 @@
return result;
}
- resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId, uuid, result);
+ resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid, result);
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
@@ -406,6 +408,136 @@
}
@Override
+ public DeferredResult<ResponseEntity<String>> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) {
+ Device device = storager.queryVideoDevice(deviceId);
+ if (device == null) return null;
+ MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
+ SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true);
+
+ return download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed,infoCallBack, hookCallBack);
+ }
+
+ @Override
+ public DeferredResult<ResponseEntity<String>> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) {
+ if (mediaServerItem == null || ssrcInfo == null) return null;
+ String uuid = UUID.randomUUID().toString();
+ String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId;
+ DeferredResult<ResponseEntity<String>> result = new DeferredResult<>(30000L);
+ Device device = storager.queryVideoDevice(deviceId);
+ if (device == null) {
+ result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
+ return result;
+ }
+
+ resultHolder.put(key, uuid, result);
+ RequestMessage msg = new RequestMessage();
+ msg.setId(uuid);
+ msg.setKey(key);
+ WVPResult<StreamInfo> wvpResult = new WVPResult<>();
+ msg.setData(wvpResult);
+ PlayBackResult<RequestMessage> downloadResult = new PlayBackResult<>();
+ downloadResult.setData(msg);
+
+ Timer timer = new Timer();
+ timer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ logger.warn(String.format("褰曞儚涓嬭浇璇锋眰瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
+ wvpResult.setCode(-1);
+ wvpResult.setMsg("褰曞儚涓嬭浇璇锋眰瓒呮椂");
+ downloadResult.setCode(-1);
+ hookCallBack.call(downloadResult);
+ SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, ssrcInfo.getStream());
+ // 鐐规挱瓒呮椂鍥炲BYE 鍚屾椂閲婃斁ssrc浠ュ強姝ゆ鐐规挱鐨勮祫婧�
+ if (dialog != null) {
+ // 鐐规挱瓒呮椂鍥炲BYE 鍚屾椂閲婃斁ssrc浠ュ強姝ゆ鐐规挱鐨勮祫婧�
+ cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
+ }else {
+ mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
+ mediaServerService.closeRTPServer(deviceId, channelId, ssrcInfo.getStream());
+ streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
+ }
+ cmder.streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), null);
+ // 鍥炲涔嬪墠鎵�鏈夌殑鐐规挱璇锋眰
+ hookCallBack.call(downloadResult);
+ }
+ }, userSetup.getPlayTimeout());
+ cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack,
+ inviteStreamInfo -> {
+ logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + inviteStreamInfo.getResponse().toJSONString());
+ timer.cancel();
+ StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);
+ streamInfo.setStartTime(startTime);
+ streamInfo.setEndTime(endTime);
+ if (streamInfo == null) {
+ logger.warn("褰曞儚涓嬭浇API璋冪敤澶辫触锛�");
+ wvpResult.setCode(-1);
+ wvpResult.setMsg("褰曞儚涓嬭浇API璋冪敤澶辫触");
+ downloadResult.setCode(-1);
+ hookCallBack.call(downloadResult);
+ return ;
+ }
+ redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());
+ wvpResult.setCode(0);
+ wvpResult.setMsg("success");
+ wvpResult.setData(streamInfo);
+ downloadResult.setCode(0);
+ downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
+ downloadResult.setResponse(inviteStreamInfo.getResponse());
+ hookCallBack.call(downloadResult);
+ }, event -> {
+ timer.cancel();
+ downloadResult.setCode(-1);
+ wvpResult.setCode(-1);
+ wvpResult.setMsg(String.format("褰曞儚涓嬭浇澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg));
+ downloadResult.setEvent(event);
+ hookCallBack.call(downloadResult);
+ streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
+ });
+ return result;
+ }
+
+ @Override
+ public StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream) {
+ StreamInfo streamInfo = redisCatchStorage.queryDownload(deviceId, channelId, stream, null);
+ if (streamInfo != null) {
+ if (streamInfo.getProgress() == 1) {
+ return streamInfo;
+ }
+
+ // 鑾峰彇褰撳墠宸蹭笅杞芥椂闀�
+ String mediaServerId = streamInfo.getMediaServerId();
+ MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
+ if (mediaServerItem == null) {
+ logger.warn("鏌ヨ褰曞儚淇℃伅鏃跺彂鐜拌妭鐐瑰凡绂荤嚎");
+ return null;
+ }
+ if (mediaServerItem.getRecordAssistPort() != 0) {
+ JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, streamInfo.getApp(), streamInfo.getStream(), null);
+ if (jsonObject != null && jsonObject.getInteger("code") == 0) {
+ long duration = jsonObject.getLong("data");
+
+ if (duration == 0) {
+ streamInfo.setProgress(0);
+ }else {
+ String startTime = streamInfo.getStartTime();
+ String endTime = streamInfo.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, BigDecimal.ROUND_HALF_UP);
+ double process = divide.doubleValue();
+ streamInfo.setProgress(process);
+ }
+ }
+ }
+ }
+ return streamInfo;
+ }
+
+ @Override
public void onPublishHandlerForDownload(InviteStreamInfo inviteStreamInfo, String deviceId, String channelId, String uuid) {
RequestMessage msg = new RequestMessage();
msg.setKey(DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId);
diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
index 564deb5..3e82e8d 100644
--- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
@@ -91,7 +91,7 @@
MediaServerItem mediaInfo;
WVPResult<StreamInfo> wvpResult = new WVPResult<>();
wvpResult.setCode(0);
- if ("auto".equals(param.getMediaServerId())){
+ if (param.getMediaServerId() == null || "auto".equals(param.getMediaServerId())){
mediaInfo = mediaServerService.getMediaServerForMinimumLoad();
}else {
mediaInfo = mediaServerService.getOne(param.getMediaServerId());
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
index 5094853..e669ab4 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -169,6 +169,8 @@
StreamInfo queryDownload(String deviceId, String channelId, String stream, String callId);
+ boolean stopDownload(String deviceId, String channelId, String stream, String callId);
+
/**
* 鏌ユ壘绗笁鏂圭郴缁熺暀涓嬬殑鍥芥爣棰勮鍊�
* @param queryKey
diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
index 6ad654e..4840446 100644
--- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
+++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -166,8 +166,42 @@
@Override
public boolean startDownload(StreamInfo stream, String callId) {
- return redis.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,
- userSetup.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream);
+ boolean result;
+ if (stream.getProgress() == 1) {
+ result = redis.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,
+ userSetup.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream);
+ }else {
+ result = redis.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,
+ userSetup.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream, 60*60);
+ }
+ return result;
+ }
+ @Override
+ public boolean stopDownload(String deviceId, String channelId, String stream, String callId) {
+ DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId);
+ if (deviceChannel != null) {
+ deviceChannel.setStreamId(null);
+ deviceChannel.setDeviceId(deviceId);
+ deviceChannelMapper.update(deviceChannel);
+ }
+ if (deviceId == null) deviceId = "*";
+ if (channelId == null) channelId = "*";
+ if (stream == null) stream = "*";
+ if (callId == null) callId = "*";
+ String key = String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,
+ userSetup.getServerId(),
+ deviceId,
+ channelId,
+ stream,
+ callId
+ );
+ List<Object> scan = redis.scan(key);
+ if (scan.size() > 0) {
+ for (Object keyObj : scan) {
+ redis.del((String) keyObj);
+ }
+ }
+ return true;
}
@Override
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
deleted file mode 100644
index 4ffbd4b..0000000
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.genersoft.iot.vmp.vmanager.gb28181.playback;
-
-import com.genersoft.iot.vmp.common.StreamInfo;
-import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;
-import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
-import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
-import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
-import com.genersoft.iot.vmp.service.IMediaServerService;
-import com.genersoft.iot.vmp.service.bean.SSRCInfo;
-import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
-import com.genersoft.iot.vmp.service.IPlayService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiImplicitParam;
-import io.swagger.annotations.ApiImplicitParams;
-import io.swagger.annotations.ApiOperation;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import com.alibaba.fastjson.JSONObject;
-import com.genersoft.iot.vmp.gb28181.bean.Device;
-import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
-import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
-import org.springframework.web.context.request.async.DeferredResult;
-
-import javax.sip.message.Response;
-import java.util.UUID;
-
-@Api(tags = "鍘嗗彶濯掍綋涓嬭浇")
-@CrossOrigin
-@RestController
-@RequestMapping("/api/download")
-public class DownloadController {
-
- private final static Logger logger = LoggerFactory.getLogger(DownloadController.class);
-
- @Autowired
- private SIPCommander cmder;
-
- @Autowired
- private IVideoManagerStorager storager;
-
- @Autowired
- private IRedisCatchStorage redisCatchStorage;
-
- // @Autowired
- // private ZLMRESTfulUtils zlmresTfulUtils;
-
- @Autowired
- private IPlayService playService;
-
- @Autowired
- private DeferredResultHolder resultHolder;
-
- @Autowired
- private IMediaServerService mediaServerService;
-
- @ApiOperation("寮�濮嬪巻鍙插獟浣撲笅杞�")
- @ApiImplicitParams({
- @ApiImplicitParam(name = "deviceId", value = "璁惧ID", dataTypeClass = String.class),
- @ApiImplicitParam(name = "channelId", value = "閫氶亾ID", dataTypeClass = String.class),
- @ApiImplicitParam(name = "startTime", value = "寮�濮嬫椂闂�", dataTypeClass = String.class),
- @ApiImplicitParam(name = "endTime", value = "缁撴潫鏃堕棿", dataTypeClass = String.class),
- @ApiImplicitParam(name = "downloadSpeed", value = "涓嬭浇鍊嶉��", dataTypeClass = String.class),
- })
- @GetMapping("/start/{deviceId}/{channelId}")
- public DeferredResult<ResponseEntity<String>> play(@PathVariable String deviceId, @PathVariable String channelId,
- String startTime, String endTime, String downloadSpeed) {
-
- if (logger.isDebugEnabled()) {
- logger.debug(String.format("鍘嗗彶濯掍綋涓嬭浇 API璋冪敤锛宒eviceId锛�%s锛宑hannelId锛�%s锛宒ownloadSpeed锛�%s", deviceId, channelId, downloadSpeed));
- }
- String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId;
- String uuid = UUID.randomUUID().toString();
- DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
- // 瓒呮椂澶勭悊
- result.onTimeout(()->{
- logger.warn(String.format("璁惧涓嬭浇鍝嶅簲瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
- RequestMessage msg = new RequestMessage();
- msg.setId(uuid);
- msg.setKey(key);
- msg.setData("Timeout");
- resultHolder.invokeAllResult(msg);
- });
- if(resultHolder.exist(key, null)) {
- return result;
- }
- resultHolder.put(key, uuid, result);
- Device device = storager.queryVideoDevice(deviceId);
-
- MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
- if (newMediaServerItem == null) {
- logger.warn(String.format("璁惧涓嬭浇鍝嶅簲瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
- RequestMessage msg = new RequestMessage();
- msg.setId(uuid);
- msg.setKey(key);
- msg.setData("Timeout");
- resultHolder.invokeAllResult(msg);
- return result;
- }
-
- SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true);
-
- cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (InviteStreamInfo inviteStreamInfo) -> {
- logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + inviteStreamInfo.getResponse().toJSONString());
- playService.onPublishHandlerForDownload(inviteStreamInfo, deviceId, channelId, uuid);
- }, event -> {
- RequestMessage msg = new RequestMessage();
- msg.setId(uuid);
- msg.setKey(key);
- msg.setData(String.format("鍥炴斁澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg));
- resultHolder.invokeAllResult(msg);
- });
-
- return result;
- }
-
- @ApiOperation("鍋滄鍘嗗彶濯掍綋涓嬭浇")
- @ApiImplicitParams({
- @ApiImplicitParam(name = "deviceId", value = "璁惧ID", dataTypeClass = String.class),
- @ApiImplicitParam(name = "channelId", value = "閫氶亾ID", dataTypeClass = String.class),
- @ApiImplicitParam(name = "stream", value = "娴両D", dataTypeClass = String.class),
- })
- @GetMapping("/stop/{deviceId}/{channelId}/{stream}")
- public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
-
- cmder.streamByeCmd(deviceId, channelId, stream, null);
-
- if (logger.isDebugEnabled()) {
- logger.debug(String.format("璁惧鍘嗗彶濯掍綋涓嬭浇鍋滄 API璋冪敤锛宒eviceId/channelId锛�%s_%s", deviceId, channelId));
- }
-
- if (deviceId != null && channelId != null) {
- JSONObject json = new JSONObject();
- json.put("deviceId", deviceId);
- json.put("channelId", channelId);
- return new ResponseEntity<String>(json.toString(), HttpStatus.OK);
- } else {
- logger.warn("璁惧鍘嗗彶濯掍綋涓嬭浇鍋滄API璋冪敤澶辫触锛�");
- return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
- }
- }
-}
diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
index e565981..d33dd2a 100644
--- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
+++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
@@ -1,6 +1,13 @@
package com.genersoft.iot.vmp.vmanager.gb28181.record;
+import com.alibaba.fastjson.JSONObject;
+import com.genersoft.iot.vmp.common.StreamInfo;
+import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
+import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
+import com.genersoft.iot.vmp.service.IMediaServerService;
+import com.genersoft.iot.vmp.service.IPlayService;
+import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@@ -8,6 +15,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
@@ -40,6 +48,12 @@
@Autowired
private DeferredResultHolder resultHolder;
+
+ @Autowired
+ private IPlayService playService;
+
+ @Autowired
+ private IMediaServerService mediaServerService;
@ApiOperation("褰曞儚鏌ヨ")
@ApiImplicitParams({
@@ -77,4 +91,111 @@
});
return result;
}
+
+ @ApiOperation("寮�濮嬪巻鍙插獟浣撲笅杞�")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "deviceId", value = "璁惧ID", dataTypeClass = String.class),
+ @ApiImplicitParam(name = "channelId", value = "閫氶亾ID", dataTypeClass = String.class),
+ @ApiImplicitParam(name = "startTime", value = "寮�濮嬫椂闂�", dataTypeClass = String.class),
+ @ApiImplicitParam(name = "endTime", value = "缁撴潫鏃堕棿", dataTypeClass = String.class),
+ @ApiImplicitParam(name = "downloadSpeed", value = "涓嬭浇鍊嶉��", dataTypeClass = String.class),
+ })
+ @GetMapping("/download/start/{deviceId}/{channelId}")
+ public DeferredResult<ResponseEntity<String>> download(@PathVariable String deviceId, @PathVariable String channelId,
+ String startTime, String endTime, String downloadSpeed) {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(String.format("鍘嗗彶濯掍綋涓嬭浇 API璋冪敤锛宒eviceId锛�%s锛宑hannelId锛�%s锛宒ownloadSpeed锛�%s", deviceId, channelId, downloadSpeed));
+ }
+// String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId;
+// String uuid = UUID.randomUUID().toString();
+// DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
+// // 瓒呮椂澶勭悊
+// result.onTimeout(()->{
+// logger.warn(String.format("璁惧涓嬭浇鍝嶅簲瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
+// RequestMessage msg = new RequestMessage();
+// msg.setId(uuid);
+// msg.setKey(key);
+// msg.setData("Timeout");
+// resultHolder.invokeAllResult(msg);
+// });
+// if(resultHolder.exist(key, null)) {
+// return result;
+// }
+// resultHolder.put(key, uuid, result);
+// Device device = storager.queryVideoDevice(deviceId);
+//
+// MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
+// if (newMediaServerItem == null) {
+// logger.warn(String.format("璁惧涓嬭浇鍝嶅簲瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
+// RequestMessage msg = new RequestMessage();
+// msg.setId(uuid);
+// msg.setKey(key);
+// msg.setData("Timeout");
+// resultHolder.invokeAllResult(msg);
+// return result;
+// }
+//
+// SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true);
+//
+// cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (InviteStreamInfo inviteStreamInfo) -> {
+// logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + inviteStreamInfo.getResponse().toJSONString());
+// playService.onPublishHandlerForDownload(inviteStreamInfo, deviceId, channelId, uuid);
+// }, event -> {
+// RequestMessage msg = new RequestMessage();
+// msg.setId(uuid);
+// msg.setKey(key);
+// msg.setData(String.format("鍥炴斁澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg));
+// resultHolder.invokeAllResult(msg);
+// });
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(String.format("璁惧鍥炴斁 API璋冪敤锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId));
+ }
+
+ DeferredResult<ResponseEntity<String>> result = playService.download(deviceId, channelId, startTime, endTime, Integer.parseInt(downloadSpeed), null, hookCallBack->{
+ resultHolder.invokeResult(hookCallBack.getData());
+ });
+
+ return result;
+ }
+
+ @ApiOperation("鍋滄鍘嗗彶濯掍綋涓嬭浇")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "deviceId", value = "璁惧ID", dataTypeClass = String.class),
+ @ApiImplicitParam(name = "channelId", value = "閫氶亾ID", dataTypeClass = String.class),
+ @ApiImplicitParam(name = "stream", value = "娴両D", dataTypeClass = String.class),
+ })
+ @GetMapping("/download/stop/{deviceId}/{channelId}/{stream}")
+ public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
+
+ cmder.streamByeCmd(deviceId, channelId, stream, null);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(String.format("璁惧鍘嗗彶濯掍綋涓嬭浇鍋滄 API璋冪敤锛宒eviceId/channelId锛�%s_%s", deviceId, channelId));
+ }
+
+ if (deviceId != null && channelId != null) {
+ JSONObject json = new JSONObject();
+ json.put("deviceId", deviceId);
+ json.put("channelId", channelId);
+ return new ResponseEntity<String>(json.toString(), HttpStatus.OK);
+ } else {
+ logger.warn("璁惧鍘嗗彶濯掍綋涓嬭浇鍋滄API璋冪敤澶辫触锛�");
+ return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ @ApiOperation("鑾峰彇鍘嗗彶濯掍綋涓嬭浇杩涘害")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "deviceId", value = "璁惧ID", dataTypeClass = String.class),
+ @ApiImplicitParam(name = "channelId", value = "閫氶亾ID", dataTypeClass = String.class),
+ @ApiImplicitParam(name = "stream", value = "娴両D", dataTypeClass = String.class),
+ })
+ @GetMapping("/download/progress/{deviceId}/{channelId}/{stream}")
+ public ResponseEntity<StreamInfo> getProgress(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
+
+ StreamInfo streamInfo = playService.getDownLoadInfo(deviceId, channelId, stream);
+ return new ResponseEntity<>(streamInfo, HttpStatus.OK);
+ }
}
diff --git a/web_src/build/webpack.dev.conf.js b/web_src/build/webpack.dev.conf.js
index 070ae22..55efd30 100755
--- a/web_src/build/webpack.dev.conf.js
+++ b/web_src/build/webpack.dev.conf.js
@@ -32,6 +32,7 @@
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
+ // host:'127.0.0.1',
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay
diff --git a/web_src/config/index.js b/web_src/config/index.js
index cec91b8..b1e1cbe 100644
--- a/web_src/config/index.js
+++ b/web_src/config/index.js
@@ -29,11 +29,13 @@
},
// Various Dev Server settings
- host: 'localhost', // can be overwritten by process.env.HOST
+ host:"127.0.0.1",
+ useLocalIp: false, // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
+ hot: true,//鑷姩淇濆瓨
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
diff --git a/web_src/package-lock.json b/web_src/package-lock.json
index 356bbcc..b1da39e 100644
--- a/web_src/package-lock.json
+++ b/web_src/package-lock.json
@@ -57,7 +57,7 @@
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
- "webpack-dev-server": "^2.9.1",
+ "webpack-dev-server": "^2.11.5",
"webpack-merge": "^4.1.0"
},
"engines": {
@@ -13382,7 +13382,7 @@
},
"node_modules/webpack-dev-server": {
"version": "2.11.5",
- "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.11.5.tgz",
+ "resolved": "https://registry.npmmirror.com/webpack-dev-server/-/webpack-dev-server-2.11.5.tgz",
"integrity": "sha512-7TdOKKt7G3sWEhPKV0zP+nD0c4V9YKUJ3wDdBwQsZNo58oZIRoVIu66pg7PYkBW8A74msP9C2kLwmxGHndz/pw==",
"dev": true,
"dependencies": {
@@ -25569,7 +25569,7 @@
},
"webpack-dev-server": {
"version": "2.11.5",
- "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.11.5.tgz",
+ "resolved": "https://registry.npmmirror.com/webpack-dev-server/-/webpack-dev-server-2.11.5.tgz",
"integrity": "sha512-7TdOKKt7G3sWEhPKV0zP+nD0c4V9YKUJ3wDdBwQsZNo58oZIRoVIu66pg7PYkBW8A74msP9C2kLwmxGHndz/pw==",
"dev": true,
"requires": {
diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue
index 5a08006..effd389 100644
--- a/web_src/src/components/dialog/devicePlayer.vue
+++ b/web_src/src/components/dialog/devicePlayer.vue
@@ -175,6 +175,7 @@
</el-tabs>
</div>
</el-dialog>
+ <recordDownload ref="recordDownload"></recordDownload>
</div>
</template>
@@ -183,15 +184,15 @@
// import LivePlayer from '@liveqing/liveplayer'
// import player from '../dialog/easyPlayer.vue'
import player from '../dialog/jessibuca.vue'
+import recordDownload from '../dialog/recordDownload.vue'
export default {
name: 'devicePlayer',
props: {},
components: {
- player,
+ player,recordDownload,
},
computed: {
getPlayerShared: function () {
-
return {
sharedUrl: window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl),
sharedIframe: '<iframe src="' + window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl) + '"></iframe>',
@@ -250,7 +251,7 @@
that.tracks = [];
that.tracksLoading = true;
that.tracksNotLoaded = false;
- if (tab.name == "codec") {
+ if (tab.name === "codec") {
this.$axios({
method: 'get',
url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtmp&app='+ this.app +'&stream='+ this.streamId
@@ -340,7 +341,7 @@
this.$refs.videoPlayer.pause()
that.$axios({
method: 'post',
- url: '/api/play/convert/' + that.streamId
+ url: '/api/gb_record/convert/' + that.streamId
}).then(function (res) {
if (res.data.code == 0) {
that.convertKey = res.data.key;
@@ -474,8 +475,8 @@
console.log(this.seekTime)
if (that.streamId != "") {
that.stopPlayRecord(function () {
- that.streamId = "",
- that.playRecord(row);
+ that.streamId = "";
+ that.playRecord(row);
})
} else {
this.$axios({
@@ -506,22 +507,36 @@
downloadRecord: function (row) {
let that = this;
if (that.streamId != "") {
- that.stopDownloadRecord(function () {
- that.streamId = "",
- that.downloadRecord(row);
+ that.stopDownloadRecord(function (res) {
+ if (res.code == 0) {
+ that.streamId = "";
+ that.downloadRecord(row);
+ }else {
+ this.$message({
+ showClose: true,
+ message: res.data.msg,
+ type: "error",
+ });
+ }
+
})
} else {
this.$axios({
method: 'get',
- url: '/api/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
+ url: '/api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
row.endTime + '&downloadSpeed=4'
}).then(function (res) {
- var streamInfo = res.data;
- that.app = streamInfo.app;
- that.streamId = streamInfo.stream;
- that.mediaServerId = streamInfo.mediaServerId;
- that.videoUrl = that.getUrlByStreamInfo(streamInfo);
- that.recordPlay = true;
+ if (res.data.code == 0) {
+ let streamInfo = res.data.data;
+ that.recordPlay = false;
+ that.$refs.recordDownload.openDialog(that.deviceId, that.channelId, streamInfo.app, streamInfo.stream, streamInfo.mediaServerId);
+ }else {
+ that.$message({
+ showClose: true,
+ message: res.data.msg,
+ type: "error",
+ });
+ }
});
}
},
@@ -530,9 +545,9 @@
this.videoUrl = '';
this.$axios({
method: 'get',
- url: '/api/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId
- }).then(function (res) {
- if (callback) callback()
+ url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId
+ }).then((res)=> {
+ if (callback) callback(res)
});
},
ptzCamera: function (command) {
diff --git a/web_src/src/components/dialog/recordDownload.vue b/web_src/src/components/dialog/recordDownload.vue
new file mode 100644
index 0000000..6b7ca1f
--- /dev/null
+++ b/web_src/src/components/dialog/recordDownload.vue
@@ -0,0 +1,195 @@
+<template>
+<div id="recordDownload" >
+ <el-dialog :title="title" v-if="showDialog" width="45rem" :append-to-body="true" :close-on-click-modal="false" :visible.sync="showDialog" :destroy-on-close="true" @close="close()" center>
+ <el-row>
+ <el-col :span="18" style="padding-top: 7px;">
+ <el-progress :percentage="percentage"></el-progress>
+ </el-col>
+ <el-col :span="6" >
+<!-- <el-dropdown size="mini" title="鎾斁鍊嶉��" style="margin-left: 1px;" @command="gbScale">-->
+<!-- <el-button-group>-->
+<!-- <el-button size="mini" style="width: 100%">-->
+<!-- {{scale}}鍊嶉�� <i class="el-icon-arrow-down el-icon--right"></i>-->
+<!-- </el-button>-->
+<!-- </el-button-group>-->
+<!-- <el-dropdown-menu slot="dropdown">-->
+<!-- <el-dropdown-item command="1">1鍊嶉��</el-dropdown-item>-->
+<!-- <el-dropdown-item command="2">2鍊嶉��</el-dropdown-item>-->
+<!-- <el-dropdown-item command="4">4鍊嶉��</el-dropdown-item>-->
+<!-- </el-dropdown-menu>-->
+<!-- </el-dropdown>-->
+ <el-button icon="el-icon-download" v-if="percentage < 100" size="mini" title="鐐瑰嚮涓嬭浇鍙皢浠ョ紦瀛橀儴鍒嗕笅杞藉埌鏈湴" @click="download()">鍋滄缂撳瓨骞朵笅杞�</el-button>
+ </el-col>
+ </el-row>
+ </el-dialog>
+</div>
+</template>
+
+
+<script>
+
+import moment from "moment";
+
+export default {
+ name: 'recordDownload',
+ created() {
+
+
+ },
+ data() {
+ return {
+ title: "鍥涘�嶉�熶笅杞戒腑...",
+ deviceId: "",
+ channelId: "",
+ app: "",
+ stream: "",
+ mediaServerId: "",
+ showDialog: false,
+ scale: 1,
+ percentage: 0.00,
+ streamInfo: null,
+ taskId: null,
+ getProgressRun: false,
+ getProgressForFileRun: false,
+
+ };
+ },
+ methods: {
+ openDialog: function (deviceId, channelId, app, stream, mediaServerId) {
+ this.deviceId = deviceId;
+ this.channelId = channelId;
+ this.app = app;
+ this.stream = stream;
+ this.mediaServerId = mediaServerId;
+ this.showDialog = true;
+ this.getProgressRun = true;
+ this.percentage = 0.0;
+ this.getProgressTimer()
+ },
+ getProgressTimer(){
+ if (!this.getProgressRun) {
+ return;
+ }
+ if (this.percentage == 100 ) {
+ this.getFileDownload();
+ return;
+ }
+ setTimeout( ()=>{
+ if (!this.showDialog) return;
+ this.getProgress(this.getProgressTimer())
+ }, 5000)
+ },
+ getProgress: function (callback){
+ this.$axios({
+ method: 'get',
+ url: `/api/gb_record/download/progress/${this.deviceId}/${this.channelId}/${this.stream}`
+ }).then((res)=> {
+ console.log(res)
+ console.log(res.data.progress)
+ this.streamInfo = res.data;
+ if (parseFloat(res.data.progress) == 1) {
+ this.percentage = 100;
+ }else {
+ this.percentage = (res.data.progress*100).toFixed(1);
+ }
+ if (callback)callback();
+ }).catch((e) =>{
+
+ });
+ },
+ close: function (){
+ if (this.streamInfo.progress < 100) {
+ this.stopDownloadRecord();
+ }
+ 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',
+ url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.stream
+ }).then((res)=> {
+ 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 && res.data.msg === "success") {
+ // 鏌ヨ杩涘害
+ 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) => {
+ if (res.data.code == 0) {
+ this.percentage = parseFloat(res.data.data.percentage)*100
+ if (res.data.data[0].percentage === '1') {
+ this.getProgressForFileRun = false;
+ window.open(res.data.data[0].downloadFile)
+ this.close();
+ }else {
+ if (callback)callback()
+ }
+ }
+ }).catch(function (error) {
+ console.log(error);
+ });
+ }
+ }
+};
+</script>
+
+<style>
+
+</style>
diff --git a/web_src/src/components/test.vue b/web_src/src/components/test.vue
deleted file mode 100644
index d780125..0000000
--- a/web_src/src/components/test.vue
+++ /dev/null
@@ -1,198 +0,0 @@
-<template>
-<div id="test">
- <div class="timeQuery" id="timeQuery">
- <div class="timeQuery-background" ></div>
- <div class="timeQuery-pointer">
- <div class="timeQuery-pointer-content" id="timeQueryPointer">
- <div class="timeQuery-pointer-handle" @mousedown.left="mousedownHandler" ></div>
- </div>
- </div>
-
- <div class="timeQuery-data" >
-
- <div class="timeQuery-data-cell" v-for="item of recordData" :style="'width:' + getDataWidth(item) + '%; left:' + getDataLeft(item) + '%'" ></div>
- <!-- <div class="timeQuery-data-cell" style="width: 30%; left: 20%" @click="timeChoose"></div>-->
- <!-- <div class="timeQuery-data-cell" style="width: 60%; left: 20%" @click="timeChoose"></div>-->
- </div>
-
- <div class="timeQuery-label" >
- <div class="timeQuery-label-cell" style="left: 0%">
- <div class="timeQuery-label-cell-label">0</div>
- </div>
- <div v-for="index of timeNode" class="timeQuery-label-cell" :style="'left:' + (100.0/timeNode*index).toFixed(4) + '%'">
- <div class="timeQuery-label-cell-label">{{24/timeNode * index}}</div>
- </div>
- </div>
- </div>
-
-</div>
-</template>
-
-<script>
-export default {
- name: "test",
- data() {
- return {
- mouseDown: false,
- timeNode: 24,
- recordData:[
- {
- startTime: "2021-04-18 00:00:00",
- endTime: "2021-04-18 00:00:09",
- },
- {
- startTime: "2021-04-18 00:00:09",
- endTime: "2021-04-18 01:00:05",
- },
- {
- startTime: "2021-04-18 02:00:01",
- endTime: "2021-04-18 04:25:05",
- },
- {
- startTime: "2021-04-18 05:00:01",
- endTime: "2021-04-18 20:00:05",
- },
- ]
- };
- },
- mounted() {
- document.body.addEventListener("mouseup", this.mouseupHandler, false)
- document.body.addEventListener("mousemove", this.mousemoveHandler, false)
- },
- methods:{
- getTimeNode(){
- let mine = 20
- let width = document.getElementById("timeQuery").offsetWidth
- if (width/20 > 24){
- return 24
- }else if (width/20 > 12) {
- return 12
- }else if (width/20 > 6) {
- return 6
- }
- },
- timeChoose(event){
- console.log(event)
- },
- getDataWidth(item){
- let startTime = new Date(item.startTime);
- let endTime = new Date(item.endTime);
- let result = parseFloat((endTime.getTime() - startTime.getTime())/(24*60*60*10))
- // console.log(result)
- return parseFloat((endTime.getTime() - startTime.getTime())/(24*60*60*10))
- },
- getDataLeft(item){
- let startTime = new Date(item.startTime);
- let differenceTime = startTime.getTime() - new Date(item.startTime.substr(0,10) + " 00:00:00").getTime()
- let result = differenceTime/(24*60*60*10)
- console.log(differenceTime)
- console.log(result)
- return parseFloat(differenceTime/(24*60*60*10));
- },
- mousedownHandler(event){
- this.mouseDown = true
- },
- mousemoveHandler(event){
- if (this.mouseDown){
- document.getElementById("timeQueryPointer").style.left = (event.clientX - 20)+ "px"
- }
- },
- mouseupHandler(event){
- this.mouseDown = false
- }
- }
-}
-</script>
-
-<style scoped>
- .timeQuery{
- width: 96%;
- margin-left: 2%;
- margin-right: 2%;
- margin-top: 20%;
- position: absolute;
- }
- .timeQuery-background{
- height: 16px;
- width: 100%;
- background-color: #ececec;
- position: absolute;
- left: 0;
- top: 0;
- z-index: 10;
- box-shadow: #9d9d9d 0px 0px 10px inset;
- }
- .timeQuery-data{
- height: 16px;
- width: 100%;
- position: absolute;
- left: 0;
- top: 0;
- z-index: 11;
- }
- .timeQuery-data-cell{
- height: 10px;
- background-color: #888787;
- position: absolute;
- z-index: 11;
- -webkit-box-shadow: #9d9d9d 0px 0px 10px inset;
- margin-top: 3px;
- top: 100%;
- }
- .timeQuery-label{
- height: 16px;
- width: 100%;
- position: absolute;
- pointer-events: none;
- left: 0;
- top: 0;
- z-index: 11;
- }
- .timeQuery-label-cell{
- height: 16px;
- position: absolute;
- z-index: 12;
- width: 0px;
- border-right: 1px solid #b7b7b7;
- }
- .timeQuery-label-cell-label {
- width: 23px;
- text-align: center;
- height: 18px;
- margin-left: -10px;
- margin-top: -30px;
- color: #444;
- }
- .timeQuery-pointer{
- width: 0px;
- height: 18px;
- position: absolute;
- left: 0;
- }
- .timeQuery-pointer-content{
- width: 0px;
- height: 70px;
- position: absolute;
- border-right: 2px solid #f60303;
- z-index: 14;
- top: -30px;
- }
- .timeQuery-pointer-handle {
- width: 0;
- height: 0;
- border-top: 12px solid transparent;
- border-right: 12px solid transparent;
- border-bottom: 20px solid #ff0909;
- border-left: 12px solid transparent;
- cursor: no-drop;
- position: absolute;
- left: -11px;
- top: 50px;
- }
- /*.timeQuery-cell:after{*/
- /* content: "";*/
- /* height: 14px;*/
- /* border: 1px solid #e70303;*/
- /* position: absolute;*/
- /*}*/
-</style>
diff --git a/web_src/src/components/test2.vue b/web_src/src/components/test2.vue
deleted file mode 100644
index 75f182e..0000000
--- a/web_src/src/components/test2.vue
+++ /dev/null
@@ -1,190 +0,0 @@
-<template>
-<div id="test2">
- <div class="timeQuery" style="width: 100%; height: 300px" id="timeQuery">
- </div>
-</div>
-</template>
-
-<script>
-
-import * as echarts from 'echarts';
-
-export default {
- name: "test2",
- data() {
- return {
- };
- },
- mounted() {
- var base = +new Date("2021-02-02 00:00:00");
- var oneDay = 24 * 3600 * 1000;
-
- var data = [[base, 10]];
-
- for (var i = 1; i < 24; i++) {
- var now = new Date(base += oneDay);
- data.push([
- new Date("2021-02-02 " + i+":00:00"), 10
- ]);
- }
- // 鍩轰簬鍑嗗濂界殑dom锛屽垵濮嬪寲echarts瀹炰緥
- var myChart = echarts.init(document.getElementById('timeQuery'));
- let option = {
-
- toolbox: {
- feature: {
- dataZoom: {
- yAxisIndex: 'none'
- },
- restore: {},
- saveAsImage: {}
- }
- },
- xAxis: {
- type: 'time',
- boundaryGap: false
- },
- yAxis: {
- type: 'value',
- show: false,
- splitLine:{show: false}, //鍘婚櫎缃戞牸绾�
- boundaryGap: [0, '100%']
- },
- dataZoom: [{
- type: 'inside',
- start: 0,
- end: 20
- }, {
- start: 0,
- end: 20
- }],
- series: [
- {
- name: '妯℃嫙鏁版嵁',
- type: 'line',
- smooth: false,
- symbol: 'none',
- areaStyle: {},
- data: data
- }
- ]
- };
- // 缁樺埗鍥捐〃
- myChart.setOption(option);
- },
- methods:{
- getTimeNode(){
- let mine = 20
- let width = document.getElementById("timeQuery").offsetWidth
- if (width/20 > 24){
- return 24
- }else if (width/20 > 12) {
- return 12
- }else if (width/20 > 6) {
- return 6
- }
- },
- hoveEvent(event){
- console.log(2222222)
- console.log(event)
- },
- timeChoose(event){
- console.log(event)
- },
- getDataWidth(item){
- let startTime = new Date(item.startTime);
- let endTime = new Date(item.endTime);
- let result = parseFloat((endTime.getTime() - startTime.getTime())/(24*60*60*10))
- // console.log(result)
- return parseFloat((endTime.getTime() - startTime.getTime())/(24*60*60*10))
- },
- getDataLeft(item){
- let startTime = new Date(item.startTime);
- let differenceTime = startTime.getTime() - new Date(item.startTime.substr(0,10) + " 00:00:00").getTime()
- let result = differenceTime/(24*60*60*10)
- console.log(differenceTime)
- console.log(result)
- return parseFloat(differenceTime/(24*60*60*10));
- }
- }
-}
-</script>
-
-<style scoped>
- .timeQuery{
- width: 96%;
- margin-left: 2%;
- margin-right: 2%;
- margin-top: 20%;
- position: absolute;
- }
- .timeQuery-background{
- height: 16px;
- width: 100%;
- background-color: #ececec;
- position: absolute;
- left: 0;
- top: 0;
- z-index: 10;
- box-shadow: #9d9d9d 0px 0px 10px inset;
- }
- .timeQuery-data{
- height: 16px;
- width: 100%;
- position: absolute;
- left: 0;
- top: 0;
- z-index: 11;
- }
- .timeQuery-data-cell{
- height: 10px;
- background-color: #888787;
- position: absolute;
- z-index: 11;
- -webkit-box-shadow: #9d9d9d 0px 0px 10px inset;
- margin-top: 3px;
- }
- .timeQuery-label{
- height: 16px;
- width: 100%;
- position: absolute;
- pointer-events: none;
- left: 0;
- top: 0;
- z-index: 11;
- }
- .timeQuery-label-cell{
- height: 16px;
- position: absolute;
- z-index: 12;
- width: 0px;
- border-right: 1px solid #b7b7b7;
- }
- .timeQuery-label-cell-label {
- width: 23px;
- text-align: center;
- height: 18px;
- margin-left: -10px;
- margin-top: -30px;
- color: #444;
- }
- .timeQuery-pointer{
- width: 0px;
- height: 18px;
- position: absolute;
- left: 0;
- }
- .timeQuery-pointer-content{
- width: 0px;
- height: 16px;
- position: absolute;
- border-right: 3px solid #f60303;
- z-index: 14;
- }
- /*.timeQuery-cell:after{*/
- /* content: "";*/
- /* height: 14px;*/
- /* border: 1px solid #e70303;*/
- /* position: absolute;*/
- /*}*/
-</style>
diff --git a/web_src/src/router/index.js b/web_src/src/router/index.js
index ad573cf..05bb1ae 100644
--- a/web_src/src/router/index.js
+++ b/web_src/src/router/index.js
@@ -11,7 +11,6 @@
import parentPlatformList from '../components/ParentPlatformList.vue'
import cloudRecord from '../components/CloudRecord.vue'
import mediaServerManger from '../components/MediaServerManger.vue'
-import test from '../components/test.vue'
import web from '../components/setting/Web.vue'
import sip from '../components/setting/Sip.vue'
import media from '../components/setting/Media.vue'
@@ -95,11 +94,6 @@
path: '/setting/media',
name: 'media',
component: media,
- },
- {
- path: '/test',
- name: 'test',
- component: test,
},
{
path: '/play/wasm/:url',
--
Gitblit v1.8.0