Commit 56859d09df8d4226882d43934acf32d60a3b51d7

Authored by panlinlin
1 parent f8fe76ad

添加推流列表和拉流代理,下一步与国标关联

Showing 37 changed files with 1418 additions and 218 deletions
src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java
@@ -35,6 +35,8 @@ public class MediaServerConfig { @@ -35,6 +35,8 @@ public class MediaServerConfig {
35 35
36 private String wanIp; 36 private String wanIp;
37 37
  38 + private long updateTime;
  39 +
38 @JSONField(name = "hls.fileBufSize") 40 @JSONField(name = "hls.fileBufSize")
39 private String hlsFileBufSize; 41 private String hlsFileBufSize;
40 42
@@ -728,4 +730,12 @@ public class MediaServerConfig { @@ -728,4 +730,12 @@ public class MediaServerConfig {
728 public void setWanIp(String wanIp) { 730 public void setWanIp(String wanIp) {
729 this.wanIp = wanIp; 731 this.wanIp = wanIp;
730 } 732 }
  733 +
  734 + public long getUpdateTime() {
  735 + return updateTime;
  736 + }
  737 +
  738 + public void setUpdateTime(long updateTime) {
  739 + this.updateTime = updateTime;
  740 + }
731 } 741 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
1 package com.genersoft.iot.vmp.media.zlm; 1 package com.genersoft.iot.vmp.media.zlm;
2 2
  3 +import java.util.List;
3 import java.util.UUID; 4 import java.util.UUID;
4 5
5 import com.alibaba.fastjson.JSON; 6 import com.alibaba.fastjson.JSON;
@@ -272,26 +273,35 @@ public class ZLMHttpHookListener { @@ -272,26 +273,35 @@ public class ZLMHttpHookListener {
272 } 273 }
273 274
274 String streamId = json.getString("stream"); 275 String streamId = json.getString("stream");
  276 + String app = json.getString("app");
275 StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId); 277 StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
276 278
277 - JSONObject ret = new JSONObject();  
278 - ret.put("code", 0);  
279 - ret.put("close", true);  
280 279
281 - if (streamInfo != null) {  
282 - if (redisCatchStorage.isChannelSendingRTP(streamInfo.getChannelId())) {  
283 - ret.put("close", false);  
284 - } else { 280 + if ("rtp".equals(app)){
  281 + JSONObject ret = new JSONObject();
  282 + ret.put("code", 0);
  283 + ret.put("close", true);
  284 + if (streamInfo != null) {
  285 + if (redisCatchStorage.isChannelSendingRTP(streamInfo.getChannelId())) {
  286 + ret.put("close", false);
  287 + } else {
  288 + cmder.streamByeCmd(streamId);
  289 + redisCatchStorage.stopPlay(streamInfo);
  290 + storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
  291 + }
  292 + }else{
285 cmder.streamByeCmd(streamId); 293 cmder.streamByeCmd(streamId);
286 - redisCatchStorage.stopPlay(streamInfo);  
287 - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); 294 + streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId);
  295 + redisCatchStorage.stopPlayback(streamInfo);
288 } 296 }
289 - }else{  
290 - cmder.streamByeCmd(streamId);  
291 - streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId);  
292 - redisCatchStorage.stopPlayback(streamInfo); 297 + return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
  298 + }else {
  299 + JSONObject ret = new JSONObject();
  300 + ret.put("code", 0);
  301 + ret.put("close", false);
  302 + return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
293 } 303 }
294 - return new ResponseEntity<String>(ret.toString(),HttpStatus.OK); 304 +
295 } 305 }
296 306
297 /** 307 /**
@@ -350,10 +360,21 @@ public class ZLMHttpHookListener { @@ -350,10 +360,21 @@ public class ZLMHttpHookListener {
350 // String data = json.getString("data"); 360 // String data = json.getString("data");
351 // List<MediaServerConfig> mediaServerConfigs = JSON.parseArray(JSON.toJSONString(json), MediaServerConfig.class); 361 // List<MediaServerConfig> mediaServerConfigs = JSON.parseArray(JSON.toJSONString(json), MediaServerConfig.class);
352 // MediaServerConfig mediaServerConfig = mediaServerConfigs.get(0); 362 // MediaServerConfig mediaServerConfig = mediaServerConfigs.get(0);
  363 +
  364 + List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(ZLMHttpHookSubscribe.HookType.on_server_started);
  365 + if (subscribes != null && subscribes.size() > 0) {
  366 + for (ZLMHttpHookSubscribe.Event subscribe : subscribes) {
  367 + subscribe.response(json);
  368 + }
  369 + }
  370 +
353 MediaServerConfig mediaServerConfig = JSON.toJavaObject(json, MediaServerConfig.class); 371 MediaServerConfig mediaServerConfig = JSON.toJavaObject(json, MediaServerConfig.class);
354 mediaServerConfig.setWanIp(StringUtils.isEmpty(mediaWanIp)? mediaIp: mediaWanIp); 372 mediaServerConfig.setWanIp(StringUtils.isEmpty(mediaWanIp)? mediaIp: mediaWanIp);
355 mediaServerConfig.setLocalIP(mediaIp); 373 mediaServerConfig.setLocalIP(mediaIp);
356 redisCatchStorage.updateMediaInfo(mediaServerConfig); 374 redisCatchStorage.updateMediaInfo(mediaServerConfig);
  375 +
  376 + // 重新发起代理
  377 +
357 JSONObject ret = new JSONObject(); 378 JSONObject ret = new JSONObject();
358 ret.put("code", 0); 379 ret.put("code", 0);
359 ret.put("msg", "success"); 380 ret.put("msg", "success");
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
@@ -3,7 +3,9 @@ package com.genersoft.iot.vmp.media.zlm; @@ -3,7 +3,9 @@ package com.genersoft.iot.vmp.media.zlm;
3 import com.alibaba.fastjson.JSONObject; 3 import com.alibaba.fastjson.JSONObject;
4 import org.springframework.stereotype.Component; 4 import org.springframework.stereotype.Component;
5 5
  6 +import java.util.ArrayList;
6 import java.util.HashMap; 7 import java.util.HashMap;
  8 +import java.util.List;
7 import java.util.Map; 9 import java.util.Map;
8 import java.util.concurrent.ConcurrentHashMap; 10 import java.util.concurrent.ConcurrentHashMap;
9 11
@@ -67,4 +69,19 @@ public class ZLMHttpHookSubscribe { @@ -67,4 +69,19 @@ public class ZLMHttpHookSubscribe {
67 } 69 }
68 return event; 70 return event;
69 } 71 }
  72 +
  73 + public List<ZLMHttpHookSubscribe.Event> getSubscribes(HookType type) {
  74 + ZLMHttpHookSubscribe.Event event= null;
  75 + Map<JSONObject, Event> eventMap = allSubscribes.get(type);
  76 + if (eventMap == null) {
  77 + return null;
  78 + }
  79 + List<ZLMHttpHookSubscribe.Event> result = new ArrayList<>();
  80 + for (JSONObject key : eventMap.keySet()) {
  81 + result.add(eventMap.get(key));
  82 + }
  83 + return result;
  84 + }
  85 +
  86 +
70 } 87 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
@@ -32,6 +32,7 @@ public class ZLMMediaListManager { @@ -32,6 +32,7 @@ public class ZLMMediaListManager {
32 32
33 public void updateMediaList() { 33 public void updateMediaList() {
34 JSONObject mediaList = zlmresTfulUtils.getMediaList(); 34 JSONObject mediaList = zlmresTfulUtils.getMediaList();
  35 + if (mediaList == null) return;
35 String dataStr = mediaList.getString("data"); 36 String dataStr = mediaList.getString("data");
36 37
37 Integer code = mediaList.getInteger("code"); 38 Integer code = mediaList.getInteger("code");
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
@@ -131,4 +131,25 @@ public class ZLMRESTfulUtils { @@ -131,4 +131,25 @@ public class ZLMRESTfulUtils {
131 public JSONObject stopSendRtp(Map<String, Object> param) { 131 public JSONObject stopSendRtp(Map<String, Object> param) {
132 return sendPost("stopSendRtp",param); 132 return sendPost("stopSendRtp",param);
133 } 133 }
  134 +
  135 + public JSONObject addStreamProxy(String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) {
  136 + Map<String, Object> param = new HashMap<>();
  137 + param.put("vhost", "__defaultVhost__");
  138 + param.put("app", app);
  139 + param.put("stream", stream);
  140 + param.put("url", url);
  141 + param.put("enable_hls", enable_hls?1:0);
  142 + param.put("enable_mp4", enable_mp4?1:0);
  143 + param.put("rtp_type", rtp_type);
  144 + return sendPost("addStreamProxy",param);
  145 + }
  146 +
  147 + public JSONObject closeStreams(String app, String stream) {
  148 + Map<String, Object> param = new HashMap<>();
  149 + param.put("vhost", "__defaultVhost__");
  150 + param.put("app", app);
  151 + param.put("stream", stream);
  152 + param.put("force", 1);
  153 + return sendPost("close_streams",param);
  154 + }
134 } 155 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
@@ -4,8 +4,11 @@ import com.alibaba.fastjson.JSON; @@ -4,8 +4,11 @@ import com.alibaba.fastjson.JSON;
4 import com.alibaba.fastjson.JSONArray; 4 import com.alibaba.fastjson.JSONArray;
5 import com.alibaba.fastjson.JSONObject; 5 import com.alibaba.fastjson.JSONObject;
6 import com.genersoft.iot.vmp.conf.MediaServerConfig; 6 import com.genersoft.iot.vmp.conf.MediaServerConfig;
  7 +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
7 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 8 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
8 //import com.genersoft.iot.vmp.storager.IVideoManagerStorager; 9 //import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  10 +import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  11 +import com.genersoft.iot.vmp.vmanager.service.IStreamProxyService;
9 import org.slf4j.Logger; 12 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory; 13 import org.slf4j.LoggerFactory;
11 import org.springframework.beans.factory.annotation.Autowired; 14 import org.springframework.beans.factory.annotation.Autowired;
@@ -16,6 +19,7 @@ import org.springframework.stereotype.Component; @@ -16,6 +19,7 @@ import org.springframework.stereotype.Component;
16 import org.springframework.util.StringUtils; 19 import org.springframework.util.StringUtils;
17 20
18 import java.util.HashMap; 21 import java.util.HashMap;
  22 +import java.util.List;
19 import java.util.Map; 23 import java.util.Map;
20 24
21 @Component 25 @Component
@@ -24,8 +28,8 @@ public class ZLMRunner implements CommandLineRunner { @@ -24,8 +28,8 @@ public class ZLMRunner implements CommandLineRunner {
24 28
25 private final static Logger logger = LoggerFactory.getLogger(ZLMRunner.class); 29 private final static Logger logger = LoggerFactory.getLogger(ZLMRunner.class);
26 30
27 - // @Autowired  
28 - // private IVideoManagerStorager storager; 31 + @Autowired
  32 + private IVideoManagerStorager storager;
29 33
30 @Autowired 34 @Autowired
31 private IRedisCatchStorage redisCatchStorage; 35 private IRedisCatchStorage redisCatchStorage;
@@ -63,18 +67,27 @@ public class ZLMRunner implements CommandLineRunner { @@ -63,18 +67,27 @@ public class ZLMRunner implements CommandLineRunner {
63 @Autowired 67 @Autowired
64 private ZLMMediaListManager zlmMediaListManager; 68 private ZLMMediaListManager zlmMediaListManager;
65 69
  70 + @Autowired
  71 + private ZLMHttpHookSubscribe hookSubscribe;
  72 +
  73 + @Autowired
  74 + private IStreamProxyService streamProxyService;
  75 +
66 @Override 76 @Override
67 public void run(String... strings) throws Exception { 77 public void run(String... strings) throws Exception {
  78 + JSONObject subscribeKey = new JSONObject();
  79 + // 订阅 zlm启动事件
  80 + hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,subscribeKey,(response)->{
  81 + MediaServerConfig mediaServerConfig = JSONObject.toJavaObject(response, MediaServerConfig.class);
  82 + zLmRunning(mediaServerConfig);
  83 + });
  84 +
68 // 获取zlm信息 85 // 获取zlm信息
69 logger.info("等待zlm接入..."); 86 logger.info("等待zlm接入...");
70 MediaServerConfig mediaServerConfig = getMediaServerConfig(); 87 MediaServerConfig mediaServerConfig = getMediaServerConfig();
  88 +
71 if (mediaServerConfig != null) { 89 if (mediaServerConfig != null) {
72 - logger.info("zlm接入成功...");  
73 - if (autoConfig) saveZLMConfig();  
74 - mediaServerConfig = getMediaServerConfig();  
75 - redisCatchStorage.updateMediaInfo(mediaServerConfig);  
76 - // 更新流列表  
77 - zlmMediaListManager.updateMediaList(); 90 + zLmRunning(mediaServerConfig);
78 } 91 }
79 } 92 }
80 93
@@ -85,8 +98,7 @@ public class ZLMRunner implements CommandLineRunner { @@ -85,8 +98,7 @@ public class ZLMRunner implements CommandLineRunner {
85 JSONArray data = responseJSON.getJSONArray("data"); 98 JSONArray data = responseJSON.getJSONArray("data");
86 if (data != null && data.size() > 0) { 99 if (data != null && data.size() > 0) {
87 mediaServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), MediaServerConfig.class); 100 mediaServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), MediaServerConfig.class);
88 - mediaServerConfig.setLocalIP(mediaIp);  
89 - mediaServerConfig.setWanIp(StringUtils.isEmpty(mediaWanIp)? mediaIp: mediaWanIp); 101 +
90 } 102 }
91 } else { 103 } else {
92 logger.error("getMediaServerConfig失败, 1s后重试"); 104 logger.error("getMediaServerConfig失败, 1s后重试");
@@ -136,4 +148,27 @@ public class ZLMRunner implements CommandLineRunner { @@ -136,4 +148,27 @@ public class ZLMRunner implements CommandLineRunner {
136 } 148 }
137 } 149 }
138 150
  151 + /**
  152 + * zlm 连接成功或者zlm重启后
  153 + */
  154 + private void zLmRunning(MediaServerConfig mediaServerConfig){
  155 + logger.info("zlm接入成功...");
  156 + if (autoConfig) saveZLMConfig();
  157 + MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
  158 + if (System.currentTimeMillis() - mediaInfo.getUpdateTime() < 50){
  159 + logger.info("zlm刚刚更新,忽略这次更新");
  160 + return;
  161 + }
  162 + mediaServerConfig.setLocalIP(mediaIp);
  163 + mediaServerConfig.setWanIp(StringUtils.isEmpty(mediaWanIp)? mediaIp: mediaWanIp);
  164 + redisCatchStorage.updateMediaInfo(mediaServerConfig);
  165 + // 更新流列表
  166 + zlmMediaListManager.updateMediaList();
  167 + // 恢复流代理
  168 + List<StreamProxyDto> streamProxyListForEnable = storager.getStreamProxyListForEnable(true);
  169 + for (StreamProxyDto streamProxyDto : streamProxyListForEnable) {
  170 + logger.info("恢复流代理," + streamProxyDto.getApp() + "/" + streamProxyDto.getStream());
  171 + streamProxyService.addStreamProxyToZlm(streamProxyDto);
  172 + }
  173 + }
139 } 174 }
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyDto.java 0 → 100644
  1 +package com.genersoft.iot.vmp.media.zlm.dto;
  2 +
  3 +public class StreamProxyDto {
  4 + private String type;
  5 + private String app;
  6 + private String stream;
  7 + private String url;
  8 + private String src_url;
  9 + private String dst_url;
  10 + private int timeout_ms;
  11 + private String ffmpeg_cmd_key;
  12 + private String rtp_type;
  13 + private boolean enable;
  14 + private boolean enable_hls;
  15 + private boolean enable_mp4;
  16 +
  17 + public String getType() {
  18 + return type;
  19 + }
  20 +
  21 + public void setType(String type) {
  22 + this.type = type;
  23 + }
  24 +
  25 + public String getApp() {
  26 + return app;
  27 + }
  28 +
  29 + public void setApp(String app) {
  30 + this.app = app;
  31 + }
  32 +
  33 + public String getStream() {
  34 + return stream;
  35 + }
  36 +
  37 + public void setStream(String stream) {
  38 + this.stream = stream;
  39 + }
  40 +
  41 + public String getUrl() {
  42 + return url;
  43 + }
  44 +
  45 + public void setUrl(String url) {
  46 + this.url = url;
  47 + }
  48 +
  49 + public String getSrc_url() {
  50 + return src_url;
  51 + }
  52 +
  53 + public void setSrc_url(String src_url) {
  54 + this.src_url = src_url;
  55 + }
  56 +
  57 + public String getDst_url() {
  58 + return dst_url;
  59 + }
  60 +
  61 + public void setDst_url(String dst_url) {
  62 + this.dst_url = dst_url;
  63 + }
  64 +
  65 + public int getTimeout_ms() {
  66 + return timeout_ms;
  67 + }
  68 +
  69 + public void setTimeout_ms(int timeout_ms) {
  70 + this.timeout_ms = timeout_ms;
  71 + }
  72 +
  73 + public String getFfmpeg_cmd_key() {
  74 + return ffmpeg_cmd_key;
  75 + }
  76 +
  77 + public void setFfmpeg_cmd_key(String ffmpeg_cmd_key) {
  78 + this.ffmpeg_cmd_key = ffmpeg_cmd_key;
  79 + }
  80 +
  81 + public String getRtp_type() {
  82 + return rtp_type;
  83 + }
  84 +
  85 + public void setRtp_type(String rtp_type) {
  86 + this.rtp_type = rtp_type;
  87 + }
  88 +
  89 + public boolean isEnable() {
  90 + return enable;
  91 + }
  92 +
  93 + public void setEnable(boolean enable) {
  94 + this.enable = enable;
  95 + }
  96 +
  97 + public boolean isEnable_hls() {
  98 + return enable_hls;
  99 + }
  100 +
  101 + public void setEnable_hls(boolean enable_hls) {
  102 + this.enable_hls = enable_hls;
  103 + }
  104 +
  105 + public boolean isEnable_mp4() {
  106 + return enable_mp4;
  107 + }
  108 +
  109 + public void setEnable_mp4(boolean enable_mp4) {
  110 + this.enable_mp4 = enable_mp4;
  111 + }
  112 +}
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
1 package com.genersoft.iot.vmp.storager; 1 package com.genersoft.iot.vmp.storager;
2 2
  3 +import com.alibaba.fastjson.JSONObject;
3 import com.genersoft.iot.vmp.common.RealVideo; 4 import com.genersoft.iot.vmp.common.RealVideo;
4 import com.genersoft.iot.vmp.common.StreamInfo; 5 import com.genersoft.iot.vmp.common.StreamInfo;
5 import com.genersoft.iot.vmp.conf.MediaServerConfig; 6 import com.genersoft.iot.vmp.conf.MediaServerConfig;
@@ -116,5 +117,5 @@ public interface IRedisCatchStorage { @@ -116,5 +117,5 @@ public interface IRedisCatchStorage {
116 * 获取当前媒体流列表 117 * 获取当前媒体流列表
117 * @return List<RealVideo> 118 * @return List<RealVideo>
118 */ 119 */
119 - List<Object> getMediaList(int start, int end); 120 + JSONObject getMediaList(int start, int end);
120 } 121 }
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java
@@ -5,6 +5,7 @@ import java.util.List; @@ -5,6 +5,7 @@ import java.util.List;
5 import com.genersoft.iot.vmp.gb28181.bean.Device; 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 6 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  8 +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
8 import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce; 9 import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce;
9 import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; 10 import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
10 import com.github.pagehelper.PageInfo; 11 import com.github.pagehelper.PageInfo;
@@ -261,4 +262,49 @@ public interface IVideoManagerStorager { @@ -261,4 +262,49 @@ public interface IVideoManagerStorager {
261 * @param deviceId 262 * @param deviceId
262 */ 263 */
263 public int clearMobilePositionsByDeviceId(String deviceId); 264 public int clearMobilePositionsByDeviceId(String deviceId);
  265 +
  266 + /**
  267 + * 新增代理流
  268 + * @param streamProxyDto
  269 + * @return
  270 + */
  271 + public int addStreamProxy(StreamProxyDto streamProxyDto);
  272 +
  273 + /**
  274 + * 更新代理流
  275 + * @param streamProxyDto
  276 + * @return
  277 + */
  278 + public int updateStreamProxy(StreamProxyDto streamProxyDto);
  279 +
  280 + /**
  281 + * 移除代理流
  282 + * @param app
  283 + * @param stream
  284 + * @return
  285 + */
  286 + public int deleteStreamProxy(String app, String stream);
  287 +
  288 + /**
  289 + * 按照是否启用获取代理流
  290 + * @param enable
  291 + * @return
  292 + */
  293 + public List<StreamProxyDto> getStreamProxyListForEnable(boolean enable);
  294 +
  295 + /**
  296 + * 按照是app和stream获取代理流
  297 + * @param app
  298 + * @param stream
  299 + * @return
  300 + */
  301 + public StreamProxyDto queryStreamProxy(String app, String stream);
  302 +
  303 + /**
  304 + * 获取代理流
  305 + * @param page
  306 + * @param count
  307 + * @return
  308 + */
  309 + PageInfo<StreamProxyDto> queryStreamProxyList(Integer page, Integer count);
264 } 310 }
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java 0 → 100644
  1 +package com.genersoft.iot.vmp.storager.dao;
  2 +
  3 +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
  4 +import org.apache.ibatis.annotations.*;
  5 +import org.springframework.stereotype.Repository;
  6 +
  7 +import java.util.List;
  8 +
  9 +@Mapper
  10 +@Repository
  11 +public interface StreamProxyMapper {
  12 +
  13 + @Insert("INSERT INTO stream_proxy (type, app, stream, url, src_url, dst_url, " +
  14 + "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_hls, enable_mp4, enable) VALUES" +
  15 + "('${type}','${app}', '${stream}', '${url}', '${src_url}', '${dst_url}', " +
  16 + "'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_hls}, ${enable_mp4}, ${enable} )")
  17 + int add(StreamProxyDto streamProxyDto);
  18 +
  19 + @Update("UPDATE stream_proxy " +
  20 + "SET type=#{type}, " +
  21 + "app=#{app}," +
  22 + "stream=#{stream}," +
  23 + "url=#{url}, " +
  24 + "src_url=#{src_url}," +
  25 + "dst_url=#{dst_url}, " +
  26 + "timeout_ms=#{timeout_ms}, " +
  27 + "ffmpeg_cmd_key=#{ffmpeg_cmd_key}, " +
  28 + "rtp_type=#{rtp_type}, " +
  29 + "enable_hls=#{enable_hls}, " +
  30 + "enable=#{enable}, " +
  31 + "enable_mp4=#{enable_mp4} " +
  32 + "WHERE app=#{app} AND stream=#{stream}")
  33 + int update(StreamProxyDto streamProxyDto);
  34 +
  35 + @Delete("DELETE FROM stream_proxy WHERE app=#{app} AND stream=#{stream}")
  36 + int del(String app, String stream);
  37 +
  38 + @Select("SELECT * FROM stream_proxy")
  39 + List<StreamProxyDto> selectAll();
  40 +
  41 + @Select("SELECT * FROM stream_proxy WHERE enable=${enable}")
  42 + List<StreamProxyDto> selectForEnable(boolean enable);
  43 +
  44 + @Select("SELECT * FROM stream_proxy WHERE app=#{app} AND stream=#{stream}")
  45 + StreamProxyDto selectOne(String app, String stream);
  46 +}
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
1 package com.genersoft.iot.vmp.storager.impl; 1 package com.genersoft.iot.vmp.storager.impl;
2 2
  3 +import com.alibaba.fastjson.JSONObject;
3 import com.genersoft.iot.vmp.common.RealVideo; 4 import com.genersoft.iot.vmp.common.RealVideo;
4 import com.genersoft.iot.vmp.common.StreamInfo; 5 import com.genersoft.iot.vmp.common.StreamInfo;
5 import com.genersoft.iot.vmp.common.VideoManagerConstants; 6 import com.genersoft.iot.vmp.common.VideoManagerConstants;
@@ -92,6 +93,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -92,6 +93,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
92 */ 93 */
93 @Override 94 @Override
94 public boolean updateMediaInfo(MediaServerConfig mediaServerConfig) { 95 public boolean updateMediaInfo(MediaServerConfig mediaServerConfig) {
  96 + mediaServerConfig.setUpdateTime(System.currentTimeMillis());
95 return redis.set(VideoManagerConstants.MEDIA_SERVER_PREFIX,mediaServerConfig); 97 return redis.set(VideoManagerConstants.MEDIA_SERVER_PREFIX,mediaServerConfig);
96 } 98 }
97 99
@@ -280,9 +282,13 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -280,9 +282,13 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
280 * @return List<RealVideo> 282 * @return List<RealVideo>
281 */ 283 */
282 @Override 284 @Override
283 - public List<Object> getMediaList(int start, int end) { 285 + public JSONObject getMediaList(int start, int end) {
284 String key = VideoManagerConstants.MEDIA_STREAM_PREFIX; 286 String key = VideoManagerConstants.MEDIA_STREAM_PREFIX;
285 Set<Object> realVideos = redis.ZRange(key, start, end); 287 Set<Object> realVideos = redis.ZRange(key, start, end);
286 - return new ArrayList(realVideos); 288 + JSONObject jsonObject = new JSONObject();
  289 + jsonObject.put("list", new ArrayList(realVideos));
  290 + jsonObject.put("total", redis.zSize(key));
  291 +
  292 + return jsonObject;
287 } 293 }
288 } 294 }
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
@@ -5,14 +5,11 @@ import java.util.*; @@ -5,14 +5,11 @@ import java.util.*;
5 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 5 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; 7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
  8 +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
8 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 9 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
9 import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; 10 import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
10 -import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;  
11 -import com.genersoft.iot.vmp.storager.dao.DeviceMapper;  
12 -import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;  
13 -import com.genersoft.iot.vmp.storager.dao.PatformChannelMapper; 11 +import com.genersoft.iot.vmp.storager.dao.*;
14 import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce; 12 import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce;
15 -import com.genersoft.iot.vmp.storager.dao.DeviceMobilePositionMapper;  
16 import com.github.pagehelper.PageHelper; 13 import com.github.pagehelper.PageHelper;
17 import com.github.pagehelper.PageInfo; 14 import com.github.pagehelper.PageInfo;
18 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.beans.factory.annotation.Autowired;
@@ -49,6 +46,9 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -49,6 +46,9 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
49 @Autowired 46 @Autowired
50 private PatformChannelMapper patformChannelMapper; 47 private PatformChannelMapper patformChannelMapper;
51 48
  49 + @Autowired
  50 + private StreamProxyMapper streamProxyMapper;
  51 +
52 52
53 53
54 54
@@ -233,7 +233,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -233,7 +233,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
233 233
234 /** 234 /**
235 * 添加Mobile Position设备移动位置 235 * 添加Mobile Position设备移动位置
236 - * @param MobilePosition 236 + * @param mobilePosition
237 */ 237 */
238 @Override 238 @Override
239 public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) { 239 public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) {
@@ -388,4 +388,68 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -388,4 +388,68 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
388 return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId); 388 return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId);
389 } 389 }
390 390
  391 + /**
  392 + * 新增代理流
  393 + * @param streamProxyDto
  394 + * @return
  395 + */
  396 + @Override
  397 + public int addStreamProxy(StreamProxyDto streamProxyDto) {
  398 + return streamProxyMapper.add(streamProxyDto);
  399 + }
  400 +
  401 + /**
  402 + * 更新代理流
  403 + * @param streamProxyDto
  404 + * @return
  405 + */
  406 + @Override
  407 + public int updateStreamProxy(StreamProxyDto streamProxyDto) {
  408 + return streamProxyMapper.update(streamProxyDto);
  409 + }
  410 +
  411 + /**
  412 + * 移除代理流
  413 + * @param id
  414 + * @return
  415 + */
  416 + @Override
  417 + public int deleteStreamProxy(String app, String stream) {
  418 + return streamProxyMapper.del(app, stream);
  419 + }
  420 +
  421 + /**
  422 + * 根据是否启用获取代理流列表
  423 + * @param enable
  424 + * @return
  425 + */
  426 + @Override
  427 + public List<StreamProxyDto> getStreamProxyListForEnable(boolean enable) {
  428 + return streamProxyMapper.selectForEnable(enable);
  429 + }
  430 +
  431 + /**
  432 + * 分页查询代理流列表
  433 + * @param page
  434 + * @param count
  435 + * @return
  436 + */
  437 + @Override
  438 + public PageInfo<StreamProxyDto> queryStreamProxyList(Integer page, Integer count) {
  439 + PageHelper.startPage(page, count);
  440 + List<StreamProxyDto> all = streamProxyMapper.selectAll();
  441 + return new PageInfo<>(all);
  442 + }
  443 +
  444 +
  445 + /**
  446 + * 按照是app和stream获取代理流
  447 + * @param app
  448 + * @param stream
  449 + * @return
  450 + */
  451 + @Override
  452 + public StreamProxyDto queryStreamProxy(String app, String stream){
  453 + return streamProxyMapper.selectOne(app, stream);
  454 + }
391 } 455 }
src/main/java/com/genersoft/iot/vmp/vmanager/media/MediaController.java 0 → 100644
  1 +package com.genersoft.iot.vmp.vmanager.media;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.genersoft.iot.vmp.common.StreamInfo;
  5 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  6 +import com.genersoft.iot.vmp.vmanager.service.IMediaService;
  7 +import com.genersoft.iot.vmp.vmanager.service.IStreamProxyService;
  8 +import org.slf4j.Logger;
  9 +import org.slf4j.LoggerFactory;
  10 +import org.springframework.beans.factory.annotation.Autowired;
  11 +import org.springframework.stereotype.Controller;
  12 +import org.springframework.web.bind.annotation.*;
  13 +
  14 +
  15 +@Controller
  16 +@CrossOrigin
  17 +@RequestMapping(value = "/api/media")
  18 +public class MediaController {
  19 +
  20 + private final static Logger logger = LoggerFactory.getLogger(MediaController.class);
  21 +
  22 + @Autowired
  23 + private IRedisCatchStorage redisCatchStorage;
  24 +
  25 + @Autowired
  26 + private IStreamProxyService streamProxyService;
  27 +
  28 + @Autowired
  29 + private IMediaService mediaService;
  30 +
  31 +
  32 + @RequestMapping(value = "/list")
  33 + @ResponseBody
  34 + public JSONObject list( @RequestParam(required = false)Integer page,
  35 + @RequestParam(required = false)Integer count,
  36 + @RequestParam(required = false)String q,
  37 + @RequestParam(required = false)Boolean online ){
  38 +
  39 + JSONObject jsonObject = redisCatchStorage.getMediaList(page - 1, page - 1 + count);
  40 + return jsonObject;
  41 + }
  42 +
  43 + @RequestMapping(value = "/getStreamInfoByAppAndStream")
  44 + @ResponseBody
  45 + public StreamInfo getStreamInfoByAppAndStream(String app, String stream){
  46 + return mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream);
  47 + }
  48 +
  49 +
  50 +
  51 +
  52 +}
src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java
@@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
8 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; 8 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
9 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 9 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
10 import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult; 10 import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
  11 +import com.genersoft.iot.vmp.vmanager.service.IMediaService;
11 import com.genersoft.iot.vmp.vmanager.service.IPlayService; 12 import com.genersoft.iot.vmp.vmanager.service.IPlayService;
12 import org.slf4j.Logger; 13 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory; 14 import org.slf4j.LoggerFactory;
@@ -55,6 +56,9 @@ public class PlayController { @@ -55,6 +56,9 @@ public class PlayController {
55 @Autowired 56 @Autowired
56 private IPlayService playService; 57 private IPlayService playService;
57 58
  59 + @Autowired
  60 + private IMediaService mediaService;
  61 +
58 @GetMapping("/play/{deviceId}/{channelId}") 62 @GetMapping("/play/{deviceId}/{channelId}")
59 public DeferredResult<ResponseEntity<String>> play(@PathVariable String deviceId, 63 public DeferredResult<ResponseEntity<String>> play(@PathVariable String deviceId,
60 @PathVariable String channelId) { 64 @PathVariable String channelId) {
@@ -159,18 +163,20 @@ public class PlayController { @@ -159,18 +163,20 @@ public class PlayController {
159 JSONObject data = jsonObject.getJSONObject("data"); 163 JSONObject data = jsonObject.getJSONObject("data");
160 if (data != null) { 164 if (data != null) {
161 result.put("key", data.getString("key")); 165 result.put("key", data.getString("key"));
162 - StreamInfo streamInfoResult = new StreamInfo();  
163 - streamInfoResult.setRtmp(dstUrl);  
164 - streamInfoResult.setRtsp(String.format("rtsp://%s:%s/convert/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), streamId)); 166 +// StreamInfo streamInfoResult = new StreamInfo();
  167 +// streamInfoResult.setRtmp(dstUrl);
  168 +// streamInfoResult.setRtsp(String.format("rtsp://%s:%s/convert/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), streamId));
  169 +// streamInfoResult.setStreamId(streamId);
  170 +// streamInfoResult.setFlv(String.format("http://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
  171 +// streamInfoResult.setWs_flv(String.format("ws://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
  172 +// streamInfoResult.setHls(String.format("http://%s:%s/convert/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
  173 +// streamInfoResult.setWs_hls(String.format("ws://%s:%s/convert/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
  174 +// streamInfoResult.setFmp4(String.format("http://%s:%s/convert/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
  175 +// streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/convert/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
  176 +// streamInfoResult.setTs(String.format("http://%s:%s/convert/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
  177 +// streamInfoResult.setWs_ts(String.format("ws://%s:%s/convert/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));
  178 + StreamInfo streamInfoResult = mediaService.getStreamInfoByAppAndStream("convert", streamId);
165 streamInfoResult.setStreamId(streamId); 179 streamInfoResult.setStreamId(streamId);
166 - streamInfoResult.setFlv(String.format("http://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));  
167 - streamInfoResult.setWs_flv(String.format("ws://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));  
168 - streamInfoResult.setHls(String.format("http://%s:%s/convert/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));  
169 - streamInfoResult.setWs_hls(String.format("ws://%s:%s/convert/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));  
170 - streamInfoResult.setFmp4(String.format("http://%s:%s/convert/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));  
171 - streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/convert/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));  
172 - streamInfoResult.setTs(String.format("http://%s:%s/convert/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));  
173 - streamInfoResult.setWs_ts(String.format("ws://%s:%s/convert/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId));  
174 result.put("data", streamInfoResult); 180 result.put("data", streamInfoResult);
175 } 181 }
176 }else { 182 }else {
src/main/java/com/genersoft/iot/vmp/vmanager/service/IMediaService.java 0 → 100644
  1 +package com.genersoft.iot.vmp.vmanager.service;
  2 +
  3 +import com.genersoft.iot.vmp.common.StreamInfo;
  4 +
  5 +/**
  6 + * 媒体信息业务
  7 + */
  8 +public interface IMediaService {
  9 +
  10 + /**
  11 + * 根据应用名和流ID获取播放地址, 通过zlm接口检查是否存在
  12 + * @param app
  13 + * @param stream
  14 + * @return
  15 + */
  16 + StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream);
  17 +
  18 + /**
  19 + * 根据应用名和流ID获取播放地址, 只是地址拼接
  20 + * @param app
  21 + * @param stream
  22 + * @return
  23 + */
  24 + StreamInfo getStreamInfoByAppAndStream(String app, String stream);
  25 +}
src/main/java/com/genersoft/iot/vmp/vmanager/service/IStreamProxyService.java 0 → 100644
  1 +package com.genersoft.iot.vmp.vmanager.service;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
  5 +import com.genersoft.iot.vmp.vmanager.streamProxy.StreamProxyController;
  6 +import com.github.pagehelper.PageInfo;
  7 +
  8 +public interface IStreamProxyService {
  9 +
  10 + /**
  11 + * 保存视频代理
  12 + * @param param
  13 + */
  14 + void save(StreamProxyDto param);
  15 +
  16 + /**
  17 + * 添加视频代理到zlm
  18 + * @param param
  19 + * @return
  20 + */
  21 + JSONObject addStreamProxyToZlm(StreamProxyDto param);
  22 +
  23 + /**
  24 + * 从zlm移除视频代理
  25 + * @param param
  26 + * @return
  27 + */
  28 + JSONObject removeStreamProxyFromZlm(StreamProxyDto param);
  29 +
  30 + /**
  31 + * 分页查询
  32 + * @param page
  33 + * @param count
  34 + * @return
  35 + */
  36 + PageInfo<StreamProxyDto> getAll(Integer page, Integer count);
  37 +
  38 + /**
  39 + * 删除视频代理
  40 + * @param app
  41 + * @param stream
  42 + */
  43 + void del(String app, String stream);
  44 +
  45 + /**
  46 + * 启用视频代理
  47 + * @param app
  48 + * @param stream
  49 + * @return
  50 + */
  51 + boolean start(String app, String stream);
  52 +
  53 + /**
  54 + * 停用用视频代理
  55 + * @param app
  56 + * @param stream
  57 + * @return
  58 + */
  59 + boolean stop(String app, String stream);
  60 +}
src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/MediaServiceImpl.java 0 → 100644
  1 +package com.genersoft.iot.vmp.vmanager.service.impl;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.genersoft.iot.vmp.common.StreamInfo;
  5 +import com.genersoft.iot.vmp.conf.MediaServerConfig;
  6 +import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
  7 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  8 +import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  9 +import com.genersoft.iot.vmp.vmanager.service.IMediaService;
  10 +import com.genersoft.iot.vmp.vmanager.service.IStreamProxyService;
  11 +import org.springframework.beans.factory.annotation.Autowired;
  12 +import org.springframework.stereotype.Service;
  13 +
  14 +@Service
  15 +public class MediaServiceImpl implements IMediaService {
  16 +
  17 + @Autowired
  18 + private IRedisCatchStorage redisCatchStorage;
  19 +
  20 + @Autowired
  21 + private IVideoManagerStorager storager;
  22 +
  23 + @Autowired
  24 + private ZLMRESTfulUtils zlmresTfulUtils;
  25 +
  26 + @Override
  27 + public StreamInfo getStreamInfoByAppAndStream(String app, String stream) {
  28 + MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
  29 + StreamInfo streamInfoResult = new StreamInfo();
  30 + streamInfoResult.setRtmp(String.format("rtmp://%s:%s/%s/%s", mediaInfo.getWanIp(), mediaInfo.getRtmpPort(), app, stream));
  31 + streamInfoResult.setRtsp(String.format("rtsp://%s:%s/%s/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), app, stream));
  32 + streamInfoResult.setFlv(String.format("http://%s:%s/%s/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream));
  33 + streamInfoResult.setWs_flv(String.format("ws://%s:%s/%s/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream));
  34 + streamInfoResult.setHls(String.format("http://%s:%s/%s/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream));
  35 + streamInfoResult.setWs_hls(String.format("ws://%s:%s/%s/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream));
  36 + streamInfoResult.setFmp4(String.format("http://%s:%s/%s/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream));
  37 + streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/%s/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream));
  38 + streamInfoResult.setTs(String.format("http://%s:%s/%s/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream));
  39 + streamInfoResult.setWs_ts(String.format("ws://%s:%s/%s/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream));
  40 + return streamInfoResult;
  41 + }
  42 +
  43 + @Override
  44 + public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream) {
  45 + StreamInfo streamInfo = null;
  46 + JSONObject mediaList = zlmresTfulUtils.getMediaList(app, stream);
  47 + if (mediaList != null) {
  48 + streamInfo = getStreamInfoByAppAndStream(app, stream);
  49 + }
  50 + return streamInfo;
  51 + }
  52 +}
src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java
@@ -15,6 +15,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; @@ -15,6 +15,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
16 import com.genersoft.iot.vmp.storager.IVideoManagerStorager; 16 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
17 import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult; 17 import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
  18 +import com.genersoft.iot.vmp.vmanager.service.IMediaService;
18 import com.genersoft.iot.vmp.vmanager.service.IPlayService; 19 import com.genersoft.iot.vmp.vmanager.service.IPlayService;
19 import org.slf4j.Logger; 20 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory; 21 import org.slf4j.LoggerFactory;
@@ -46,6 +47,9 @@ public class PlayServiceImpl implements IPlayService { @@ -46,6 +47,9 @@ public class PlayServiceImpl implements IPlayService {
46 @Autowired 47 @Autowired
47 private ZLMRESTfulUtils zlmresTfulUtils; 48 private ZLMRESTfulUtils zlmresTfulUtils;
48 49
  50 + @Autowired
  51 + private IMediaService mediaService;
  52 +
49 53
50 @Override 54 @Override
51 public PlayResult play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) { 55 public PlayResult play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) {
@@ -148,26 +152,27 @@ public class PlayServiceImpl implements IPlayService { @@ -148,26 +152,27 @@ public class PlayServiceImpl implements IPlayService {
148 152
149 public StreamInfo onPublishHandler(JSONObject resonse, String deviceId, String channelId, String uuid) { 153 public StreamInfo onPublishHandler(JSONObject resonse, String deviceId, String channelId, String uuid) {
150 String streamId = resonse.getString("id"); 154 String streamId = resonse.getString("id");
151 - StreamInfo streamInfo = new StreamInfo(); 155 + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream("rtp", streamId);
  156 +// StreamInfo streamInfo = new StreamInfo();
152 streamInfo.setStreamId(streamId); 157 streamInfo.setStreamId(streamId);
153 streamInfo.setDeviceID(deviceId); 158 streamInfo.setDeviceID(deviceId);
154 streamInfo.setChannelId(channelId); 159 streamInfo.setChannelId(channelId);
155 - MediaServerConfig mediaServerConfig = redisCatchStorage.getMediaInfo();  
156 -  
157 - streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));  
158 - streamInfo.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));  
159 -  
160 - streamInfo.setFmp4(String.format("http://%s:%s/rtp/%s.live.mp4", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));  
161 - streamInfo.setWs_fmp4(String.format("ws://%s:%s/rtp/%s.live.mp4", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));  
162 -  
163 - streamInfo.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));  
164 - streamInfo.setWs_hls(String.format("ws://%s:%s/rtp/%s/hls.m3u8", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));  
165 -  
166 - streamInfo.setTs(String.format("http://%s:%s/rtp/%s.live.ts", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));  
167 - streamInfo.setWs_ts(String.format("ws://%s:%s/rtp/%s.live.ts", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));  
168 -  
169 - streamInfo.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaServerConfig.getWanIp(), mediaServerConfig.getRtmpPort(), streamId));  
170 - streamInfo.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaServerConfig.getWanIp(), mediaServerConfig.getRtspPort(), streamId)); 160 +// MediaServerConfig mediaServerConfig = redisCatchStorage.getMediaInfo();
  161 +
  162 +// streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
  163 +// streamInfo.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
  164 +//
  165 +// streamInfo.setFmp4(String.format("http://%s:%s/rtp/%s.live.mp4", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
  166 +// streamInfo.setWs_fmp4(String.format("ws://%s:%s/rtp/%s.live.mp4", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
  167 +//
  168 +// streamInfo.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
  169 +// streamInfo.setWs_hls(String.format("ws://%s:%s/rtp/%s/hls.m3u8", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
  170 +//
  171 +// streamInfo.setTs(String.format("http://%s:%s/rtp/%s.live.ts", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
  172 +// streamInfo.setWs_ts(String.format("ws://%s:%s/rtp/%s.live.ts", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
  173 +//
  174 +// streamInfo.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaServerConfig.getWanIp(), mediaServerConfig.getRtmpPort(), streamId));
  175 +// streamInfo.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaServerConfig.getWanIp(), mediaServerConfig.getRtspPort(), streamId));
171 176
172 return streamInfo; 177 return streamInfo;
173 } 178 }
src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/StreamProxyServiceImpl.java 0 → 100644
  1 +package com.genersoft.iot.vmp.vmanager.service.impl;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.genersoft.iot.vmp.conf.MediaServerConfig;
  5 +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  6 +import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
  7 +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
  8 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  9 +import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
  10 +import com.genersoft.iot.vmp.storager.dao.StreamProxyMapper;
  11 +import com.genersoft.iot.vmp.vmanager.service.IStreamProxyService;
  12 +import com.genersoft.iot.vmp.vmanager.streamProxy.StreamProxyController;
  13 +import com.github.pagehelper.PageHelper;
  14 +import com.github.pagehelper.PageInfo;
  15 +import org.springframework.beans.factory.annotation.Autowired;
  16 +import org.springframework.stereotype.Service;
  17 +
  18 +import java.util.List;
  19 +
  20 +/**
  21 + * 视频代理业务
  22 + */
  23 +@Service
  24 +public class StreamProxyServiceImpl implements IStreamProxyService {
  25 +
  26 + @Autowired
  27 + private IVideoManagerStorager videoManagerStorager;
  28 +
  29 + @Autowired
  30 + private IRedisCatchStorage redisCatchStorage;
  31 +
  32 + @Autowired
  33 + private ZLMRESTfulUtils zlmresTfulUtils;
  34 +
  35 + @Autowired
  36 + private StreamProxyMapper streamProxyMapper;
  37 +
  38 +
  39 + @Override
  40 + public void save(StreamProxyDto param) {
  41 + MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
  42 + String dstUrl = String.format("rtmp://%s:%s/%s/%s", "127.0.0.1", mediaInfo.getRtmpPort(), param.getApp(),
  43 + param.getStream() );
  44 + param.setDst_url(dstUrl);
  45 + // 更新
  46 + if (videoManagerStorager.queryStreamProxy(param.getApp(), param.getStream()) != null) {
  47 + int result = videoManagerStorager.updateStreamProxy(param);
  48 + if (result > 0 && param.isEnable()) {
  49 + addStreamProxyToZlm(param);
  50 + }
  51 + }else { // 新增
  52 + int result = videoManagerStorager.addStreamProxy(param);
  53 + if (result > 0 && param.isEnable()) {
  54 + addStreamProxyToZlm(param);
  55 + }
  56 + }
  57 + }
  58 +
  59 + @Override
  60 + public JSONObject addStreamProxyToZlm(StreamProxyDto param) {
  61 + JSONObject result = null;
  62 + if ("default".equals(param.getType())){
  63 + result = zlmresTfulUtils.addStreamProxy(param.getApp(), param.getStream(), param.getUrl(),
  64 + param.isEnable_hls(), param.isEnable_mp4(), param.getRtp_type());
  65 + }else if ("ffmpeg".equals(param.getType())) {
  66 + result = zlmresTfulUtils.addFFmpegSource(param.getSrc_url(), param.getDst_url(),
  67 + param.getTimeout_ms() + "");
  68 + }
  69 + return result;
  70 + }
  71 +
  72 + @Override
  73 + public JSONObject removeStreamProxyFromZlm(StreamProxyDto param) {
  74 + JSONObject result = zlmresTfulUtils.closeStreams(param.getApp(), param.getStream());
  75 + return result;
  76 + }
  77 +
  78 + @Override
  79 + public PageInfo<StreamProxyDto> getAll(Integer page, Integer count) {
  80 + return videoManagerStorager.queryStreamProxyList(page, count);
  81 + }
  82 +
  83 + @Override
  84 + public void del(String app, String stream) {
  85 + StreamProxyDto streamProxyDto = new StreamProxyDto();
  86 + streamProxyDto.setApp(app);
  87 + streamProxyDto.setStream(stream);
  88 + JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto);
  89 + if (jsonObject.getInteger("code") == 0) {
  90 + videoManagerStorager.deleteStreamProxy(app, stream);
  91 + }
  92 + }
  93 +
  94 + @Override
  95 + public boolean start(String app, String stream) {
  96 + boolean result = false;
  97 + StreamProxyDto streamProxyDto = videoManagerStorager.queryStreamProxy(app, stream);
  98 + if (!streamProxyDto.isEnable() && streamProxyDto != null) {
  99 + JSONObject jsonObject = addStreamProxyToZlm(streamProxyDto);
  100 + if (jsonObject.getInteger("code") == 0) {
  101 + result = true;
  102 + streamProxyDto.setEnable(true);
  103 + videoManagerStorager.updateStreamProxy(streamProxyDto);
  104 + }
  105 + }
  106 + return result;
  107 + }
  108 +
  109 + @Override
  110 + public boolean stop(String app, String stream) {
  111 + boolean result = false;
  112 + StreamProxyDto streamProxyDto = videoManagerStorager.queryStreamProxy(app, stream);
  113 + if (streamProxyDto.isEnable() && streamProxyDto != null) {
  114 + JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto);
  115 + if (jsonObject.getInteger("code") == 0) {
  116 + result = true;
  117 + streamProxyDto.setEnable(false);
  118 + videoManagerStorager.updateStreamProxy(streamProxyDto);
  119 + }
  120 + }
  121 + return result;
  122 + }
  123 +}
src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java 0 → 100644
  1 +package com.genersoft.iot.vmp.vmanager.streamProxy;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  5 +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
  6 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  7 +import com.genersoft.iot.vmp.vmanager.service.IStreamProxyService;
  8 +import com.github.pagehelper.PageInfo;
  9 +import org.slf4j.Logger;
  10 +import org.slf4j.LoggerFactory;
  11 +import org.springframework.beans.factory.annotation.Autowired;
  12 +import org.springframework.stereotype.Controller;
  13 +import org.springframework.web.bind.annotation.*;
  14 +
  15 +/**
  16 + * 拉流代理接口
  17 + */
  18 +@Controller
  19 +@CrossOrigin
  20 +@RequestMapping(value = "/api/proxy")
  21 +public class StreamProxyController {
  22 +
  23 + private final static Logger logger = LoggerFactory.getLogger(StreamProxyController.class);
  24 +
  25 + @Autowired
  26 + private IRedisCatchStorage redisCatchStorage;
  27 +
  28 + @Autowired
  29 + private IStreamProxyService streamProxyService;
  30 +
  31 +
  32 + @RequestMapping(value = "/list")
  33 + @ResponseBody
  34 + public PageInfo<StreamProxyDto> list(@RequestParam(required = false)Integer page,
  35 + @RequestParam(required = false)Integer count,
  36 + @RequestParam(required = false)String q,
  37 + @RequestParam(required = false)Boolean online ){
  38 +
  39 + return streamProxyService.getAll(page, count);
  40 + }
  41 +
  42 + @RequestMapping(value = "/save")
  43 + @ResponseBody
  44 + public Object save(@RequestBody StreamProxyDto param){
  45 + logger.info("添加代理: " + JSONObject.toJSONString(param));
  46 + streamProxyService.save(param);
  47 + return "success";
  48 + }
  49 +
  50 + @RequestMapping(value = "/del")
  51 + @ResponseBody
  52 + public Object del(String app, String stream){
  53 + logger.info("移除代理: " + app + "/" + stream);
  54 + streamProxyService.del(app, stream);
  55 + return "success";
  56 + }
  57 +
  58 + @RequestMapping(value = "/start")
  59 + @ResponseBody
  60 + public Object start(String app, String stream){
  61 + logger.info("启用代理: " + app + "/" + stream);
  62 + boolean result = streamProxyService.start(app, stream);
  63 + return "success";
  64 + }
  65 +
  66 + @RequestMapping(value = "/stop")
  67 + @ResponseBody
  68 + public Object stop(String app, String stream){
  69 + logger.info("停用代理: " + app + "/" + stream);
  70 + boolean result = streamProxyService.stop(app, stream);
  71 + return "success";
  72 + }
  73 +}
src/main/java/com/genersoft/iot/vmp/web/ApiMediaController.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.web;  
2 -  
3 -import com.alibaba.fastjson.JSONObject;  
4 -import com.genersoft.iot.vmp.common.RealVideo;  
5 -import com.genersoft.iot.vmp.conf.SipConfig;  
6 -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;  
7 -import org.slf4j.Logger;  
8 -import org.slf4j.LoggerFactory;  
9 -import org.springframework.beans.factory.annotation.Autowired;  
10 -import org.springframework.stereotype.Controller;  
11 -import org.springframework.web.bind.annotation.CrossOrigin;  
12 -import org.springframework.web.bind.annotation.RequestMapping;  
13 -import org.springframework.web.bind.annotation.RequestParam;  
14 -import org.springframework.web.bind.annotation.ResponseBody;  
15 -  
16 -import java.util.List;  
17 -  
18 -/**  
19 - * 兼容LiveGBS的API:系统接口  
20 - */  
21 -@Controller  
22 -@CrossOrigin  
23 -@RequestMapping(value = "/api/v1/media")  
24 -public class ApiMediaController {  
25 -  
26 - private final static Logger logger = LoggerFactory.getLogger(ApiMediaController.class);  
27 -  
28 - @Autowired  
29 - private IRedisCatchStorage redisCatchStorage;  
30 -  
31 -  
32 - @RequestMapping(value = "/list")  
33 - @ResponseBody  
34 - public JSONObject list( @RequestParam(required = false)Integer start,  
35 - @RequestParam(required = false)Integer limit,  
36 - @RequestParam(required = false)String q,  
37 - @RequestParam(required = false)Boolean online ){  
38 -  
39 - List<Object> mediaList = redisCatchStorage.getMediaList(start - 1, start - 1 + limit);  
40 - JSONObject jsonObject = new JSONObject();  
41 - jsonObject.put("code", 0);  
42 - jsonObject.put("data", mediaList);  
43 - return jsonObject;  
44 - }  
45 -}  
src/main/resources/wvp.sqlite
No preview for this file type
web_src/package-lock.json
@@ -10924,6 +10924,26 @@ @@ -10924,6 +10924,26 @@
10924 "clipboard": "^2.0.0" 10924 "clipboard": "^2.0.0"
10925 } 10925 }
10926 }, 10926 },
  10927 + "vue-clipboards": {
  10928 + "version": "1.3.0",
  10929 + "resolved": "https://registry.npmjs.org/vue-clipboards/-/vue-clipboards-1.3.0.tgz",
  10930 + "integrity": "sha512-VMDYHpLQH0EUmqfk9b5XMrkvSu/HjNsLW2EBR4OS6JZHcv/PxmWYdoTBPVlp5eYrhWy07La8nWpRwAh09Mgufw==",
  10931 + "requires": {
  10932 + "clipboard": "^1.7.1"
  10933 + },
  10934 + "dependencies": {
  10935 + "clipboard": {
  10936 + "version": "1.7.1",
  10937 + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-1.7.1.tgz",
  10938 + "integrity": "sha1-Ng1taUbpmnof7zleQrqStem1oWs=",
  10939 + "requires": {
  10940 + "good-listener": "^1.2.2",
  10941 + "select": "^1.1.2",
  10942 + "tiny-emitter": "^2.0.0"
  10943 + }
  10944 + }
  10945 + }
  10946 + },
10927 "vue-cookies": { 10947 "vue-cookies": {
10928 "version": "1.7.4", 10948 "version": "1.7.4",
10929 "resolved": "https://registry.npm.taobao.org/vue-cookies/download/vue-cookies-1.7.4.tgz?cache=0&sync_timestamp=1598941352058&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-cookies%2Fdownload%2Fvue-cookies-1.7.4.tgz", 10949 "resolved": "https://registry.npm.taobao.org/vue-cookies/download/vue-cookies-1.7.4.tgz?cache=0&sync_timestamp=1598941352058&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-cookies%2Fdownload%2Fvue-cookies-1.7.4.tgz",
web_src/package.json
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 "vue": "^2.6.11", 21 "vue": "^2.6.11",
22 "vue-baidu-map": "^0.21.22", 22 "vue-baidu-map": "^0.21.22",
23 "vue-clipboard2": "^0.3.1", 23 "vue-clipboard2": "^0.3.1",
  24 + "vue-clipboards": "^1.3.0",
24 "vue-cookies": "^1.7.4", 25 "vue-cookies": "^1.7.4",
25 "vue-router": "^3.1.6" 26 "vue-router": "^3.1.6"
26 }, 27 },
web_src/src/components/ParentPlatformList.vue
@@ -68,9 +68,9 @@ @@ -68,9 +68,9 @@
68 </template> 68 </template>
69 69
70 <script> 70 <script>
71 -import platformEdit from './platformEdit.vue' 71 +import platformEdit from './dialog/platformEdit.vue'
72 import uiHeader from './UiHeader.vue' 72 import uiHeader from './UiHeader.vue'
73 -import chooseChannelDialog from './gb28181/chooseChannel.vue' 73 +import chooseChannelDialog from './dialog/chooseChannel.vue'
74 export default { 74 export default {
75 name: 'app', 75 name: 'app',
76 components: { 76 components: {
web_src/src/components/PushVideoList.vue
1 <template> 1 <template>
2 - <div id="app"> 2 + <div id="pushVideoList">
3 <el-container> 3 <el-container>
4 <el-header> 4 <el-header>
5 <uiHeader></uiHeader> 5 <uiHeader></uiHeader>
@@ -7,28 +7,27 @@ @@ -7,28 +7,27 @@
7 <el-main> 7 <el-main>
8 <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> 8 <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
9 <span style="font-size: 1rem; font-weight: bold;">推流列表</span> 9 <span style="font-size: 1rem; font-weight: bold;">推流列表</span>
10 - <div style="position: absolute; right: 1rem; top: 0.3rem;">  
11 - <el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" @click="getDeviceList()"></el-button>  
12 - </div>  
13 </div> 10 </div>
14 - <!-- <devicePlayer ref="devicePlayer"></devicePlayer> -->  
15 - <el-table :data="deviceList" border style="width: 100%" :height="winHeight">  
16 - <el-table-column prop="schema" label="协议" width="180" align="center"> 11 + <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
  12 + <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">添加代理</el-button>
  13 + </div>
  14 + <devicePlayer ref="devicePlayer"></devicePlayer>
  15 + <el-table :data="pushList" border style="width: 100%" :height="winHeight">
  16 + <el-table-column prop="app" label="APP" width="180" align="center">
17 </el-table-column> 17 </el-table-column>
18 - <el-table-column prop="streamUrl" label="流地址" width="240" align="center"> 18 + <el-table-column prop="stream" label="流ID" width="240" align="center">
19 </el-table-column> 19 </el-table-column>
20 - <el-table-column prop="online" label="在线人数" width="240" align="center"> 20 + <el-table-column prop="totalReaderCount" label="在线人数" width="240" align="center">
21 </el-table-column> 21 </el-table-column>
22 - <el-table-column prop="startTime" label="开始时间" align="center"> 22 + <el-table-column prop="createStamp" label="开始时间" align="center">
23 </el-table-column> 23 </el-table-column>
24 24
25 25
26 <el-table-column label="操作" width="360" align="center" fixed="right"> 26 <el-table-column label="操作" width="360" align="center" fixed="right">
27 <template slot-scope="scope"> 27 <template slot-scope="scope">
28 - <el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button>  
29 <el-button-group> 28 <el-button-group>
30 - <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button>  
31 - <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopDevicePush(scope.row)">停止</el-button> 29 + <el-button size="mini" icon="el-icon-video-play" @click="playPuhsh(scope.row)">播放</el-button>
  30 + <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopPuhsh(scope.row)">停止</el-button>
32 </el-button-group> 31 </el-button-group>
33 </template> 32 </template>
34 </el-table-column> 33 </el-table-column>
@@ -43,25 +42,27 @@ @@ -43,25 +42,27 @@
43 layout="total, sizes, prev, pager, next" 42 layout="total, sizes, prev, pager, next"
44 :total="total"> 43 :total="total">
45 </el-pagination> 44 </el-pagination>
46 - 45 + <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit>
47 </el-main> 46 </el-main>
48 </el-container> 47 </el-container>
49 </div> 48 </div>
50 </template> 49 </template>
51 50
52 <script> 51 <script>
  52 + import streamProxyEdit from './dialog/StreamProxyEdit.vue'
  53 + import devicePlayer from './dialog/devicePlayer.vue'
53 import uiHeader from './UiHeader.vue' 54 import uiHeader from './UiHeader.vue'
54 export default { 55 export default {
55 - name: 'app', 56 + name: 'pushVideoList',
56 components: { 57 components: {
  58 + devicePlayer,
  59 + streamProxyEdit,
57 uiHeader 60 uiHeader
58 }, 61 },
59 data() { 62 data() {
60 return { 63 return {
61 - deviceList: [], //设备列表  
62 - currentDevice: {}, //当前操作设备对象  
63 -  
64 - videoComponentList: [], 64 + pushList: [], //设备列表
  65 + currentPusher: {}, //当前操作设备对象
65 updateLooper: 0, //数据刷新轮训标志 66 updateLooper: 0, //数据刷新轮训标志
66 currentDeviceChannelsLenth:0, 67 currentDeviceChannelsLenth:0,
67 winHeight: window.innerHeight - 200, 68 winHeight: window.innerHeight - 200,
@@ -72,23 +73,10 @@ @@ -72,23 +73,10 @@
72 }; 73 };
73 }, 74 },
74 computed: { 75 computed: {
75 - getcurrentDeviceChannels: function() {  
76 - let data = this.currentDevice['channelMap'];  
77 - let channels = null;  
78 - if (data) {  
79 - channels = Object.keys(data).map(key => {  
80 - return data[key];  
81 - });  
82 - this.currentDeviceChannelsLenth = channels.length;  
83 - }  
84 -  
85 - console.log("数据:" + JSON.stringify(channels));  
86 - return channels;  
87 - }  
88 }, 76 },
89 mounted() { 77 mounted() {
90 this.initData(); 78 this.initData();
91 - this.updateLooper = setInterval(this.initData, 10000); 79 + // this.updateLooper = setInterval(this.initData, 10000);
92 }, 80 },
93 destroyed() { 81 destroyed() {
94 this.$destroy('videojs'); 82 this.$destroy('videojs');
@@ -96,20 +84,20 @@ @@ -96,20 +84,20 @@
96 }, 84 },
97 methods: { 85 methods: {
98 initData: function() { 86 initData: function() {
99 - this.getDeviceList(); 87 + this.getPushList();
100 }, 88 },
101 currentChange: function(val){ 89 currentChange: function(val){
102 this.currentPage = val; 90 this.currentPage = val;
103 - this.getDeviceList(); 91 + this.getPushList();
104 }, 92 },
105 handleSizeChange: function(val){ 93 handleSizeChange: function(val){
106 this.count = val; 94 this.count = val;
107 - this.getDeviceList(); 95 + this.getPushList();
108 }, 96 },
109 - getDeviceList: function() { 97 + getPushList: function() {
110 let that = this; 98 let that = this;
111 this.getDeviceListLoading = true; 99 this.getDeviceListLoading = true;
112 - this.$axios.get(`/api/devices`,{ 100 + this.$axios.get(`/api/media/list`,{
113 params: { 101 params: {
114 page: that.currentPage, 102 page: that.currentPage,
115 count: that.count 103 count: that.count
@@ -119,83 +107,44 @@ @@ -119,83 +107,44 @@
119 console.log(res); 107 console.log(res);
120 console.log(res.data.list); 108 console.log(res.data.list);
121 that.total = res.data.total; 109 that.total = res.data.total;
122 - that.deviceList = res.data.list; 110 + that.pushList = res.data.list;
123 that.getDeviceListLoading = false; 111 that.getDeviceListLoading = false;
124 }) 112 })
125 .catch(function (error) { 113 .catch(function (error) {
126 console.log(error); 114 console.log(error);
127 that.getDeviceListLoading = false; 115 that.getDeviceListLoading = false;
128 }); 116 });
129 -  
130 }, 117 },
131 - showChannelList: function(row) {  
132 - console.log(JSON.stringify(row))  
133 - this.$router.push(`/channelList/${row.deviceId}/0/15/1`); 118 + addStreamProxy: function(){
  119 + console.log(2222)
  120 + this.$refs.streamProxyEdit.openDialog(null, this.initData)
134 }, 121 },
135 - showDevicePosition: function(row) {  
136 - console.log(JSON.stringify(row))  
137 - this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`); 122 + saveStreamProxy: function(){
138 }, 123 },
139 -  
140 - //gb28181平台对接  
141 - //刷新设备信息  
142 - refDevice: function(itemData) {  
143 - ///api/devices/{deviceId}/sync  
144 - console.log("刷新对应设备:" + itemData.deviceId);  
145 - var that = this;  
146 - that.$refs[itemData.deviceId + 'refbtn' ].loading = true;  
147 - this.$axios({  
148 - method: 'post',  
149 - url: '/api/devices/' + itemData.deviceId + '/sync'  
150 - }).then(function(res) {  
151 - console.log("刷新设备结果:"+JSON.stringify(res));  
152 - if (!res.data.deviceId) {  
153 - that.$message({  
154 - showClose: true,  
155 - message: res.data,  
156 - type: 'error'  
157 - });  
158 - }else{  
159 - that.$message({  
160 - showClose: true,  
161 - message: '请求成功',  
162 - type: 'success'  
163 - }); 124 + playPuhsh: function(row){
  125 + let that = this;
  126 + this.getListLoading = true;
  127 + this.$axios.get(`/api/media/getStreamInfoByAppAndStream`,{
  128 + params: {
  129 + app: row.app,
  130 + stream: row.stream
164 } 131 }
165 - that.initData()  
166 - that.$refs[itemData.deviceId + 'refbtn' ].loading = false;  
167 - }).catch(function(e) {  
168 - console.error(e)  
169 - that.$refs[itemData.deviceId + 'refbtn' ].loading = false;  
170 - });;  
171 - },  
172 - //通知设备上传媒体流  
173 - sendDevicePush: function(itemData) {  
174 - // let deviceId = this.currentDevice.deviceId;  
175 - // let channelId = itemData.channelId;  
176 - // console.log("通知设备推流1:" + deviceId + " : " + channelId);  
177 - // let that = this;  
178 - // this.$axios({  
179 - // method: 'get',  
180 - // url: '/api/play/' + deviceId + '/' + channelId  
181 - // }).then(function(res) {  
182 - // let ssrc = res.data.ssrc;  
183 - // that.$refs.devicePlayer.play(ssrc,deviceId,channelId);  
184 - // }).catch(function(e) {  
185 - // }); 132 + })
  133 + .then(function (res) {
  134 + that.getListLoading = false;
  135 + that.$refs.devicePlayer.openDialog("streamPlay", null, null, {
  136 + streamInfo: res.data,
  137 + hasAudio: true
  138 + });
  139 + })
  140 + .catch(function (error) {
  141 + console.log(error);
  142 + that.getListLoading = false;
  143 + });
186 }, 144 },
187 - transportChange: function (row) {  
188 - console.log(row);  
189 - console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `);  
190 - let that = this;  
191 - this.$axios({  
192 - method: 'get',  
193 - url: '/api/devices/' + row.deviceId + '/transport/' + row.streamMode  
194 - }).then(function(res) {  
195 -  
196 - }).catch(function(e) {  
197 - });  
198 - } 145 + stopPuhsh: function(row){
  146 + console.log(row)
  147 + }
199 148
200 } 149 }
201 }; 150 };
web_src/src/components/StreamProxyList.vue 0 → 100644
  1 +<template>
  2 + <div id="streamProxyList">
  3 + <el-container>
  4 + <el-header>
  5 + <uiHeader></uiHeader>
  6 + </el-header>
  7 + <el-main>
  8 + <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
  9 + <span style="font-size: 1rem; font-weight: bold;">拉流代理列表</span>
  10 + </div>
  11 + <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
  12 + <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">添加代理</el-button>
  13 + </div>
  14 + <devicePlayer ref="devicePlayer"></devicePlayer>
  15 + <el-table :data="streamProxyList" border style="width: 100%" :height="winHeight">
  16 + <el-table-column prop="app" label="应用名" align="center" show-overflow-tooltip/>
  17 + <el-table-column prop="stream" label="流ID" align="center" show-overflow-tooltip/>
  18 + <el-table-column label="流地址" width="400" align="center" show-overflow-tooltip >
  19 + <template slot-scope="scope">
  20 + <div slot="reference" class="name-wrapper">
  21 +
  22 + <el-tag size="medium" v-if="scope.row.type == 'default'">
  23 + <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
  24 + {{scope.row.url}}
  25 + </el-tag>
  26 + <el-tag size="medium" v-if="scope.row.type != 'default'">
  27 + <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.src_url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
  28 + {{scope.row.src_url}}
  29 + </el-tag>
  30 + </div>
  31 + </template>
  32 + </el-table-column>
  33 +
  34 + <el-table-column label="转HLS" width="120" align="center">
  35 + <template slot-scope="scope">
  36 + <div slot="reference" class="name-wrapper">
  37 + <el-tag size="medium" v-if="scope.row.enable_hls">已启用</el-tag>
  38 + <el-tag size="medium" type="info" v-if="!scope.row.enable_hls">未启用</el-tag>
  39 + </div>
  40 + </template>
  41 + </el-table-column>
  42 + <el-table-column label="MP4录制" width="120" align="center">
  43 + <template slot-scope="scope">
  44 + <div slot="reference" class="name-wrapper">
  45 + <el-tag size="medium" v-if="scope.row.enable_mp4">已启用</el-tag>
  46 + <el-tag size="medium" type="info" v-if="!scope.row.enable_mp4">未启用</el-tag>
  47 + </div>
  48 + </template>
  49 + </el-table-column>
  50 + <el-table-column label="启用" width="120" align="center">
  51 + <template slot-scope="scope">
  52 + <div slot="reference" class="name-wrapper">
  53 + <el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
  54 + <el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
  55 + </div>
  56 + </template>
  57 + </el-table-column>
  58 +
  59 +
  60 + <el-table-column label="操作" width="360" align="center" fixed="right">
  61 + <template slot-scope="scope">
  62 + <el-button-group>
  63 + <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.enable" @click="play(scope.row)">播放</el-button>
  64 + <el-button size="mini" icon="el-icon-close" type="success" v-if="scope.row.enable" @click="stop(scope.row)">停用</el-button>
  65 + <el-button size="mini" icon="el-icon-check" type="primary" v-if="!scope.row.enable" @click="start(scope.row)">启用</el-button>
  66 + <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteStreamProxy(scope.row)">删除</el-button>
  67 + </el-button-group>
  68 + </template>
  69 + </el-table-column>
  70 + </el-table>
  71 + <el-pagination
  72 + style="float: right"
  73 + @size-change="handleSizeChange"
  74 + @current-change="currentChange"
  75 + :current-page="currentPage"
  76 + :page-size="count"
  77 + :page-sizes="[15, 25, 35, 50]"
  78 + layout="total, sizes, prev, pager, next"
  79 + :total="total">
  80 + </el-pagination>
  81 + <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit>
  82 + </el-main>
  83 + </el-container>
  84 + </div>
  85 +</template>
  86 +
  87 +<script>
  88 + import streamProxyEdit from './dialog/StreamProxyEdit.vue'
  89 + import devicePlayer from './dialog/devicePlayer.vue'
  90 + import uiHeader from './UiHeader.vue'
  91 + export default {
  92 + name: 'streamProxyList',
  93 + components: {
  94 + devicePlayer,
  95 + streamProxyEdit,
  96 + uiHeader
  97 + },
  98 + data() {
  99 + return {
  100 + streamProxyList: [],
  101 + currentPusher: {}, //当前操作设备对象
  102 + updateLooper: 0, //数据刷新轮训标志
  103 + currentDeviceChannelsLenth:0,
  104 + winHeight: window.innerHeight - 200,
  105 + currentPage:1,
  106 + count:15,
  107 + total:0,
  108 + getListLoading: false
  109 + };
  110 + },
  111 + computed: {
  112 + },
  113 + mounted() {
  114 + this.initData();
  115 + // this.updateLooper = setInterval(this.initData, 10000);
  116 + },
  117 + destroyed() {
  118 + this.$destroy('videojs');
  119 + clearTimeout(this.updateLooper);
  120 + },
  121 + methods: {
  122 + initData: function() {
  123 + this.getStreamProxyList();
  124 + },
  125 + currentChange: function(val){
  126 + this.currentPage = val;
  127 + this.getStreamProxyList();
  128 + },
  129 + handleSizeChange: function(val){
  130 + this.count = val;
  131 + this.getStreamProxyList();
  132 + },
  133 + getStreamProxyList: function() {
  134 + let that = this;
  135 + this.getListLoading = true;
  136 + this.$axios.get(`/api/proxy/list`,{
  137 + params: {
  138 + page: that.currentPage,
  139 + count: that.count
  140 + }
  141 + } )
  142 + .then(function (res) {
  143 + console.log(res);
  144 + console.log(res.data.list);
  145 + that.total = res.data.total;
  146 + that.streamProxyList = res.data.list;
  147 + that.getListLoading = false;
  148 + })
  149 + .catch(function (error) {
  150 + console.log(error);
  151 + that.getListLoading = false;
  152 + });
  153 + },
  154 + addStreamProxy: function(){
  155 + this.$refs.streamProxyEdit.openDialog(null, this.initData)
  156 + },
  157 + saveStreamProxy: function(){
  158 + },
  159 + play: function(row){
  160 + let that = this;
  161 + this.getListLoading = true;
  162 + this.$axios.get(`/api/media/getStreamInfoByAppAndStream`,{
  163 + params: {
  164 + app: row.app,
  165 + stream: row.stream
  166 + }
  167 + })
  168 + .then(function (res) {
  169 + that.getListLoading = false;
  170 + that.$refs.devicePlayer.openDialog("streamPlay", null, null, {
  171 + streamInfo: res.data,
  172 + hasAudio: true
  173 + });
  174 + })
  175 + .catch(function (error) {
  176 + console.log(error);
  177 + that.getListLoading = false;
  178 + });
  179 +
  180 + },
  181 + deleteStreamProxy: function(row){
  182 + console.log(1111)
  183 + let that = this;
  184 + this.getListLoading = true;
  185 + this.$axios.get(`/api/proxy/del`,{
  186 + params: {
  187 + app: row.app,
  188 + stream: row.stream
  189 + }
  190 + })
  191 + .then(function (res) {
  192 + that.getListLoading = false;
  193 + that.initData()
  194 + })
  195 + .catch(function (error) {
  196 + console.log(error);
  197 + that.getListLoading = false;
  198 + });
  199 + },
  200 + start: function(row){
  201 + let that = this;
  202 + this.getListLoading = true;
  203 + this.$axios.get(`/api/proxy/start`,{
  204 + params: {
  205 + app: row.app,
  206 + stream: row.stream
  207 + }
  208 + })
  209 + .then(function (res) {
  210 + that.getListLoading = false;
  211 + that.initData()
  212 + })
  213 + .catch(function (error) {
  214 + console.log(error);
  215 + that.getListLoading = false;
  216 + });
  217 + },
  218 + stop: function(row){
  219 + let that = this;
  220 + this.getListLoading = true;
  221 + this.$axios.get(`/api/proxy/stop`,{
  222 + params: {
  223 + app: row.app,
  224 + stream: row.stream
  225 + }
  226 + })
  227 + .then(function (res) {
  228 + that.getListLoading = false;
  229 + that.initData()
  230 + })
  231 + .catch(function (error) {
  232 + console.log(error);
  233 + that.getListLoading = false;
  234 + });
  235 + }
  236 +
  237 + }
  238 + };
  239 +</script>
  240 +
  241 +<style>
  242 + .videoList {
  243 + display: flex;
  244 + flex-wrap: wrap;
  245 + align-content: flex-start;
  246 + }
  247 +
  248 + .video-item {
  249 + position: relative;
  250 + width: 15rem;
  251 + height: 10rem;
  252 + margin-right: 1rem;
  253 + background-color: #000000;
  254 + }
  255 +
  256 + .video-item-img {
  257 + position: absolute;
  258 + top: 0;
  259 + bottom: 0;
  260 + left: 0;
  261 + right: 0;
  262 + margin: auto;
  263 + width: 100%;
  264 + height: 100%;
  265 + }
  266 +
  267 + .video-item-img:after {
  268 + content: "";
  269 + display: inline-block;
  270 + position: absolute;
  271 + z-index: 2;
  272 + top: 0;
  273 + bottom: 0;
  274 + left: 0;
  275 + right: 0;
  276 + margin: auto;
  277 + width: 3rem;
  278 + height: 3rem;
  279 + background-image: url("../assets/loading.png");
  280 + background-size: cover;
  281 + background-color: #000000;
  282 + }
  283 +
  284 + .video-item-title {
  285 + position: absolute;
  286 + bottom: 0;
  287 + color: #000000;
  288 + background-color: #ffffff;
  289 + line-height: 1.5rem;
  290 + padding: 0.3rem;
  291 + width: 14.4rem;
  292 + }
  293 + .cpoy-btn {
  294 + cursor: pointer;
  295 + margin-right: 10px;
  296 + }
  297 +</style>
web_src/src/components/UiHeader.vue
@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 <el-menu-item index="/">控制台</el-menu-item> 4 <el-menu-item index="/">控制台</el-menu-item>
5 <el-menu-item index="/deviceList">设备列表</el-menu-item> 5 <el-menu-item index="/deviceList">设备列表</el-menu-item>
6 <el-menu-item index="/pushVideoList">推流列表</el-menu-item> 6 <el-menu-item index="/pushVideoList">推流列表</el-menu-item>
  7 + <el-menu-item index="/streamProxyList">拉流代理</el-menu-item>
7 <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item> 8 <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>
8 <el-switch v-model="alarmNotify" active-text="报警信息推送" style="display: block float: right" @change="sseControl"></el-switch> 9 <el-switch v-model="alarmNotify" active-text="报警信息推送" style="display: block float: right" @change="sseControl"></el-switch>
9 <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item> 10 <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>
web_src/src/components/channelList.vue
@@ -75,7 +75,7 @@ @@ -75,7 +75,7 @@
75 </template> 75 </template>
76 76
77 <script> 77 <script>
78 -import devicePlayer from './gb28181/devicePlayer.vue' 78 +import devicePlayer from './dialog/devicePlayer.vue'
79 import uiHeader from './UiHeader.vue' 79 import uiHeader from './UiHeader.vue'
80 import moment from "moment"; 80 import moment from "moment";
81 export default { 81 export default {
web_src/src/components/dialog/StreamProxyEdit.vue 0 → 100644
  1 +<template>
  2 + <div id="addStreamProxy" v-loading="isLoging">
  3 + <el-dialog
  4 + title="添加代理"
  5 + width="40%"
  6 + top="2rem"
  7 + :close-on-click-modal="false"
  8 + :visible.sync="showDialog"
  9 + :destroy-on-close="true"
  10 + @close="close()"
  11 + >
  12 + <div id="shared" style="margin-top: 1rem;margin-right: 100px;">
  13 + <el-form ref="streamProxy" :rules="rules" :model="proxyParam" label-width="140px">
  14 + <el-form-item label="类型" prop="type">
  15 + <el-select
  16 + v-model="proxyParam.type"
  17 + style="width: 100%"
  18 + placeholder="请选择代理类型"
  19 + >
  20 + <el-option label="默认" value="default"></el-option>
  21 + <el-option label="FFmpeg" value="ffmpeg"></el-option>
  22 + </el-select>
  23 + </el-form-item>
  24 + <el-form-item label="应用名" prop="app">
  25 + <el-input v-model="proxyParam.app" clearable></el-input>
  26 + </el-form-item>
  27 + <el-form-item label="流ID" prop="stream">
  28 + <el-input v-model="proxyParam.stream" clearable></el-input>
  29 + </el-form-item>
  30 + <el-form-item label="拉流地址" prop="url" v-if="proxyParam.type=='default'">
  31 + <el-input v-model="proxyParam.url" clearable></el-input>
  32 + </el-form-item>
  33 + <el-form-item label="拉流地址" prop="src_url" v-if="proxyParam.type=='ffmpeg'">
  34 + <el-input v-model="proxyParam.src_url" clearable></el-input>
  35 + </el-form-item>
  36 + <el-form-item label="超时时间" prop="timeout_ms" v-if="proxyParam.type=='ffmpeg'">
  37 + <el-input v-model="proxyParam.timeout_ms" clearable></el-input>
  38 + </el-form-item>
  39 + <el-form-item label="FFmpeg命令模板" prop="ffmpeg_cmd_key" v-if="proxyParam.type=='ffmpeg'">
  40 + <el-input v-model="proxyParam.ffmpeg_cmd_key" clearable></el-input>
  41 + </el-form-item>
  42 + <el-form-item label="拉流方式" prop="rtp_type" v-if="proxyParam.type=='default'">
  43 + <el-select
  44 + v-model="proxyParam.rtp_type"
  45 + style="width: 100%"
  46 + placeholder="请选择拉流方式"
  47 + >
  48 + <el-option label="TCP" value="0"></el-option>
  49 + <el-option label="UDP" value="1"></el-option>
  50 + <el-option label="组播" value="2"></el-option>
  51 + </el-select>
  52 + </el-form-item>
  53 + <el-form-item label="其他选项">
  54 + <div style="float: left;">
  55 + <el-checkbox label="启用" v-model="proxyParam.enable" ></el-checkbox>
  56 + <el-checkbox label="转HLS" v-model="proxyParam.enable_hls" ></el-checkbox>
  57 + <el-checkbox label="MP4录制" v-model="proxyParam.enable_mp4" ></el-checkbox>
  58 + </div>
  59 +
  60 + </el-form-item>
  61 + <el-form-item>
  62 + <div style="float: right;">
  63 + <el-button type="primary" @click="onSubmit">{{onSubmit_text}}</el-button>
  64 + <el-button @click="close">取消</el-button>
  65 + </div>
  66 +
  67 + </el-form-item>
  68 + </el-form>
  69 + </div>
  70 + </el-dialog>
  71 + </div>
  72 +</template>
  73 +
  74 +<script>
  75 +export default {
  76 + name: "streamProxyEdit",
  77 + props: {},
  78 + computed: {},
  79 + created() {},
  80 + data() {
  81 + // var deviceGBIdRules = async (rule, value, callback) => {
  82 + // console.log(value);
  83 + // if (value === "") {
  84 + // callback(new Error("请输入设备国标编号"));
  85 + // } else {
  86 + // var exit = await this.deviceGBIdExit(value);
  87 + // console.log(exit);
  88 + // console.log(exit == "true");
  89 + // console.log(exit === "true");
  90 + // if (exit) {
  91 + // callback(new Error("设备国标编号已存在"));
  92 + // } else {
  93 + // callback();
  94 + // }
  95 + // }
  96 + // };
  97 + return {
  98 + listChangeCallback: null,
  99 + showDialog: false,
  100 + isLoging: false,
  101 + onSubmit_text: "立即创建",
  102 + proxyParam: {
  103 + type: "default",
  104 + app: null,
  105 + stream: null,
  106 + url: "rtmp://58.200.131.2:1935/livetv/hunantv",
  107 + src_url: null,
  108 + timeout_ms: null,
  109 + ffmpeg_cmd_key: null,
  110 + rtp_type: null,
  111 + enable: true,
  112 + enable_hls: true,
  113 + enable_mp4: false,
  114 + },
  115 +
  116 + rules: {
  117 + app: [{ required: true, message: "请输入应用名", trigger: "blur" }],
  118 + stream: [{ required: true, message: "请输入流ID", trigger: "blur" }],
  119 + url: [{ required: true, message: "请输入要代理的流", trigger: "blur" }],
  120 + src_url: [{ required: true, message: "请输入要代理的流", trigger: "blur" }],
  121 + timeout_ms: [{ required: true, message: "请输入FFmpeg推流成功超时时间", trigger: "blur" }],
  122 + ffmpeg_cmd_key: [{ required: false, message: "请输入FFmpeg命令参数模板(可选)", trigger: "blur" }],
  123 + },
  124 + };
  125 + },
  126 + methods: {
  127 + openDialog: function (proxyParam, callback) {
  128 + this.showDialog = true;
  129 + this.listChangeCallback = callback;
  130 + if (proxyParam != null) {
  131 + this.proxyParam = proxyParam;
  132 + this.onSubmit_text = "保存";
  133 + } else {
  134 + this.onSubmit_text = "立即创建";
  135 + }
  136 + },
  137 + onSubmit: function () {
  138 + console.log("onSubmit");
  139 + var that = this;
  140 + that.$axios
  141 + .post(`/api/proxy/save`, that.proxyParam)
  142 + .then(function (res) {
  143 + console.log(res);
  144 + console.log(res.data == "success");
  145 + if (res.data == "success") {
  146 + that.$message({
  147 + showClose: true,
  148 + message: "保存成功",
  149 + type: "success",
  150 + });
  151 + that.showDialog = false;
  152 + if (that.listChangeCallback != null) {
  153 + that.listChangeCallback();
  154 + }
  155 + }
  156 + })
  157 + .catch(function (error) {
  158 + console.log(error);
  159 + });
  160 + },
  161 + close: function () {
  162 + console.log("关闭添加视频平台");
  163 + this.showDialog = false;
  164 + this.$refs.streamProxy.resetFields();
  165 + },
  166 + deviceGBIdExit: async function (deviceGbId) {
  167 + var result = false;
  168 + var that = this;
  169 + await that.$axios
  170 + .post(`/api/platforms/exit/${deviceGbId}`)
  171 + .then(function (res) {
  172 + result = res.data;
  173 + })
  174 + .catch(function (error) {
  175 + console.log(error);
  176 + });
  177 + return result;
  178 + },
  179 + checkExpires: function() {
  180 + if (this.platform.enable && this.platform.expires == "0") {
  181 + this.platform.expires = "300";
  182 + }
  183 + }
  184 + },
  185 +};
  186 +</script>
web_src/src/components/gb28181/chooseChannel.vue renamed to web_src/src/components/dialog/chooseChannel.vue
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 </template> 21 </template>
22 22
23 <script> 23 <script>
24 -import chooseChannelForGb from './chooseChannelForGb.vue' 24 +import chooseChannelForGb from '../dialog/chooseChannelForGb.vue'
25 export default { 25 export default {
26 name: 'chooseChannel', 26 name: 'chooseChannel',
27 props: {}, 27 props: {},
web_src/src/components/gb28181/chooseChannelForGb.vue renamed to web_src/src/components/dialog/chooseChannelForGb.vue
web_src/src/components/gb28181/devicePlayer.vue renamed to web_src/src/components/dialog/devicePlayer.vue
@@ -26,7 +26,7 @@ @@ -26,7 +26,7 @@
26 </div> 26 </div>
27 </el-tab-pane> 27 </el-tab-pane>
28 <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}--> 28 <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->
29 - <el-tab-pane label="录像查询" name="record"> 29 + <el-tab-pane label="录像查询" name="record" v-if="showRrecord">
30 <el-date-picker size="mini" v-model="videoHistory.date" type="date" value-format="yyyy-MM-dd" placeholder="日期" @change="queryRecords()"></el-date-picker> 30 <el-date-picker size="mini" v-model="videoHistory.date" type="date" value-format="yyyy-MM-dd" placeholder="日期" @change="queryRecords()"></el-date-picker>
31 <el-table :data="videoHistory.searchHistoryResult" height="150" v-loading="recordsLoading"> 31 <el-table :data="videoHistory.searchHistoryResult" height="150" v-loading="recordsLoading">
32 <el-table-column label="名称" prop="name"></el-table-column> 32 <el-table-column label="名称" prop="name"></el-table-column>
@@ -42,7 +42,7 @@ @@ -42,7 +42,7 @@
42 </el-table> 42 </el-table>
43 </el-tab-pane> 43 </el-tab-pane>
44 <!--遥控界面--> 44 <!--遥控界面-->
45 - <el-tab-pane label="云台控制" name="control"> 45 + <el-tab-pane label="云台控制" name="control" v-if="showPtz">
46 <div style="display: flex; justify-content: left;"> 46 <div style="display: flex; justify-content: left;">
47 <div class="control-wrapper"> 47 <div class="control-wrapper">
48 <div class="control-btn control-top" @mousedown="ptzCamera(0, 2, 0)" @mouseup="ptzCamera(0, 0, 0)"> 48 <div class="control-btn control-top" @mousedown="ptzCamera(0, 2, 0)" @mouseup="ptzCamera(0, 0, 0)">
@@ -136,7 +136,7 @@ @@ -136,7 +136,7 @@
136 </template> 136 </template>
137 137
138 <script> 138 <script>
139 -import player from './player.vue' 139 +import player from '../dialog/player.vue'
140 export default { 140 export default {
141 name: 'devicePlayer', 141 name: 'devicePlayer',
142 props: {}, 142 props: {},
@@ -184,7 +184,9 @@ export default { @@ -184,7 +184,9 @@ export default {
184 tracks: [], 184 tracks: [],
185 coverPlaying:false, 185 coverPlaying:false,
186 tracksLoading: false, 186 tracksLoading: false,
187 - recordPlay: "" 187 + recordPlay: "",
  188 + showPtz: true,
  189 + showRrecord: true,
188 }; 190 };
189 }, 191 },
190 methods: { 192 methods: {
@@ -230,6 +232,11 @@ export default { @@ -230,6 +232,11 @@ export default {
230 this.videoHistory.date = param.date; 232 this.videoHistory.date = param.date;
231 this.queryRecords() 233 this.queryRecords()
232 break; 234 break;
  235 + case "streamPlay":
  236 + this.showRrecord = false,
  237 + this.showPtz = false,
  238 + this.play(param.streamInfo, param.hasAudio)
  239 + break;
233 case "control": 240 case "control":
234 break; 241 break;
235 } 242 }
web_src/src/components/platformEdit.vue renamed to web_src/src/components/dialog/platformEdit.vue
web_src/src/components/gb28181/player.vue renamed to web_src/src/components/dialog/player.vue
web_src/src/main.js
@@ -11,6 +11,8 @@ import echarts from &#39;echarts&#39;; @@ -11,6 +11,8 @@ import echarts from &#39;echarts&#39;;
11 import VueClipboard from 'vue-clipboard2'; 11 import VueClipboard from 'vue-clipboard2';
12 import { Notification } from 'element-ui'; 12 import { Notification } from 'element-ui';
13 import Fingerprint2 from 'fingerprintjs2'; 13 import Fingerprint2 from 'fingerprintjs2';
  14 +import VueClipboards from 'vue-clipboards';
  15 +
14 16
15 // 生成唯一ID 17 // 生成唯一ID
16 Fingerprint2.get(function(components) { 18 Fingerprint2.get(function(components) {
@@ -32,6 +34,7 @@ Fingerprint2.get(function(components) { @@ -32,6 +34,7 @@ Fingerprint2.get(function(components) {
32 Vue.use(VueClipboard); 34 Vue.use(VueClipboard);
33 Vue.use(ElementUI); 35 Vue.use(ElementUI);
34 Vue.use(VueCookies); 36 Vue.use(VueCookies);
  37 +Vue.use(VueClipboards);
35 Vue.prototype.$axios = axios; 38 Vue.prototype.$axios = axios;
36 Vue.prototype.$notify = Notification; 39 Vue.prototype.$notify = Notification;
37 40
web_src/src/router/index.js
@@ -5,6 +5,7 @@ import control from &#39;../components/control.vue&#39; @@ -5,6 +5,7 @@ import control from &#39;../components/control.vue&#39;
5 import deviceList from '../components/DeviceList.vue' 5 import deviceList from '../components/DeviceList.vue'
6 import channelList from '../components/channelList.vue' 6 import channelList from '../components/channelList.vue'
7 import pushVideoList from '../components/PushVideoList.vue' 7 import pushVideoList from '../components/PushVideoList.vue'
  8 +import streamProxyList from '../components/StreamProxyList.vue'
8 import devicePosition from '../components/devicePosition.vue' 9 import devicePosition from '../components/devicePosition.vue'
9 import login from '../components/Login.vue' 10 import login from '../components/Login.vue'
10 import parentPlatformList from '../components/ParentPlatformList.vue' 11 import parentPlatformList from '../components/ParentPlatformList.vue'
@@ -33,6 +34,10 @@ export default new VueRouter({ @@ -33,6 +34,10 @@ export default new VueRouter({
33 component: pushVideoList, 34 component: pushVideoList,
34 }, 35 },
35 { 36 {
  37 + path: '/streamProxyList',
  38 + component: streamProxyList,
  39 + },
  40 + {
36 path: '/login', 41 path: '/login',
37 name: '登录', 42 name: '登录',
38 component: login, 43 component: login,