From 56859d09df8d4226882d43934acf32d60a3b51d7 Mon Sep 17 00:00:00 2001 From: panlinlin <648540858@qq.com> Date: 星期二, 30 三月 2021 18:46:34 +0800 Subject: [PATCH] 添加推流列表和拉流代理,下一步与国标关联 --- src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java | 28 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java | 21 web_src/src/components/PushVideoList.vue | 157 +--- web_src/package-lock.json | 20 web_src/src/components/dialog/chooseChannelForGb.vue | 0 web_src/src/main.js | 3 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java | 17 src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java | 10 web_src/src/components/dialog/devicePlayer.vue | 15 src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java | 37 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyDto.java | 112 ++++ src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java | 3 web_src/src/components/UiHeader.vue | 1 web_src/src/components/dialog/StreamProxyEdit.vue | 186 ++++++ src/main/java/com/genersoft/iot/vmp/vmanager/service/IStreamProxyService.java | 60 ++ web_src/src/components/dialog/player.vue | 0 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java | 55 + web_src/src/components/dialog/platformEdit.vue | 0 src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java | 10 web_src/src/components/StreamProxyList.vue | 297 ++++++++++ web_src/src/components/ParentPlatformList.vue | 4 src/main/java/com/genersoft/iot/vmp/vmanager/media/MediaController.java | 52 + src/main/resources/wvp.sqlite | 0 web_src/package.json | 1 src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java | 73 ++ src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java | 76 ++ src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java | 46 + /dev/null | 45 - web_src/src/components/dialog/chooseChannel.vue | 2 web_src/src/components/channelList.vue | 2 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java | 49 + src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/StreamProxyServiceImpl.java | 123 ++++ src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java | 46 + src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/MediaServiceImpl.java | 52 + web_src/src/router/index.js | 5 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java | 1 src/main/java/com/genersoft/iot/vmp/vmanager/service/IMediaService.java | 25 37 files changed, 1,417 insertions(+), 217 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java index 76390e4..eba9a5e 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaServerConfig.java @@ -35,6 +35,8 @@ private String wanIp; + private long updateTime; + @JSONField(name = "hls.fileBufSize") private String hlsFileBufSize; @@ -728,4 +730,12 @@ public void setWanIp(String wanIp) { this.wanIp = wanIp; } + + public long getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(long updateTime) { + this.updateTime = updateTime; + } } 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 51c6e1b..b2c1597 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 @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.media.zlm; +import java.util.List; import java.util.UUID; import com.alibaba.fastjson.JSON; @@ -272,26 +273,35 @@ } String streamId = json.getString("stream"); + String app = json.getString("app"); StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId); - JSONObject ret = new JSONObject(); - ret.put("code", 0); - ret.put("close", true); - if (streamInfo != null) { - if (redisCatchStorage.isChannelSendingRTP(streamInfo.getChannelId())) { - ret.put("close", false); - } else { + if ("rtp".equals(app)){ + JSONObject ret = new JSONObject(); + ret.put("code", 0); + ret.put("close", true); + if (streamInfo != null) { + if (redisCatchStorage.isChannelSendingRTP(streamInfo.getChannelId())) { + ret.put("close", false); + } else { + cmder.streamByeCmd(streamId); + redisCatchStorage.stopPlay(streamInfo); + storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); + } + }else{ cmder.streamByeCmd(streamId); - redisCatchStorage.stopPlay(streamInfo); - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); + streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId); + redisCatchStorage.stopPlayback(streamInfo); } - }else{ - cmder.streamByeCmd(streamId); - streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId); - redisCatchStorage.stopPlayback(streamInfo); + return new ResponseEntity<String>(ret.toString(),HttpStatus.OK); + }else { + JSONObject ret = new JSONObject(); + ret.put("code", 0); + ret.put("close", false); + return new ResponseEntity<String>(ret.toString(),HttpStatus.OK); } - return new ResponseEntity<String>(ret.toString(),HttpStatus.OK); + } /** @@ -350,10 +360,21 @@ // String data = json.getString("data"); // List<MediaServerConfig> mediaServerConfigs = JSON.parseArray(JSON.toJSONString(json), MediaServerConfig.class); // MediaServerConfig mediaServerConfig = mediaServerConfigs.get(0); + + List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(ZLMHttpHookSubscribe.HookType.on_server_started); + if (subscribes != null && subscribes.size() > 0) { + for (ZLMHttpHookSubscribe.Event subscribe : subscribes) { + subscribe.response(json); + } + } + MediaServerConfig mediaServerConfig = JSON.toJavaObject(json, MediaServerConfig.class); mediaServerConfig.setWanIp(StringUtils.isEmpty(mediaWanIp)? mediaIp: mediaWanIp); mediaServerConfig.setLocalIP(mediaIp); redisCatchStorage.updateMediaInfo(mediaServerConfig); + + // 閲嶆柊鍙戣捣浠g悊 + JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("msg", "success"); 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 995f916..129f8a3 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 @@ -3,7 +3,9 @@ import com.alibaba.fastjson.JSONObject; import org.springframework.stereotype.Component; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -67,4 +69,19 @@ } return event; } + + public List<ZLMHttpHookSubscribe.Event> getSubscribes(HookType type) { + ZLMHttpHookSubscribe.Event event= null; + Map<JSONObject, Event> eventMap = allSubscribes.get(type); + if (eventMap == null) { + return null; + } + List<ZLMHttpHookSubscribe.Event> result = new ArrayList<>(); + for (JSONObject key : eventMap.keySet()) { + result.add(eventMap.get(key)); + } + return result; + } + + } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java index b17151a..5ffa467 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java @@ -32,6 +32,7 @@ public void updateMediaList() { JSONObject mediaList = zlmresTfulUtils.getMediaList(); + if (mediaList == null) return; String dataStr = mediaList.getString("data"); Integer code = mediaList.getInteger("code"); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java index ad17fee..21752a0 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java @@ -131,4 +131,25 @@ public JSONObject stopSendRtp(Map<String, Object> param) { return sendPost("stopSendRtp",param); } + + public JSONObject addStreamProxy(String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) { + Map<String, Object> param = new HashMap<>(); + param.put("vhost", "__defaultVhost__"); + param.put("app", app); + param.put("stream", stream); + param.put("url", url); + param.put("enable_hls", enable_hls?1:0); + param.put("enable_mp4", enable_mp4?1:0); + param.put("rtp_type", rtp_type); + return sendPost("addStreamProxy",param); + } + + public JSONObject closeStreams(String app, String stream) { + Map<String, Object> param = new HashMap<>(); + param.put("vhost", "__defaultVhost__"); + param.put("app", app); + param.put("stream", stream); + param.put("force", 1); + return sendPost("close_streams",param); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java index e65fae0..15fa957 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java @@ -4,8 +4,11 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.conf.MediaServerConfig; +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; //import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import com.genersoft.iot.vmp.vmanager.service.IStreamProxyService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -16,6 +19,7 @@ import org.springframework.util.StringUtils; import java.util.HashMap; +import java.util.List; import java.util.Map; @Component @@ -24,8 +28,8 @@ private final static Logger logger = LoggerFactory.getLogger(ZLMRunner.class); - // @Autowired - // private IVideoManagerStorager storager; + @Autowired + private IVideoManagerStorager storager; @Autowired private IRedisCatchStorage redisCatchStorage; @@ -63,18 +67,27 @@ @Autowired private ZLMMediaListManager zlmMediaListManager; + @Autowired + private ZLMHttpHookSubscribe hookSubscribe; + + @Autowired + private IStreamProxyService streamProxyService; + @Override public void run(String... strings) throws Exception { + JSONObject subscribeKey = new JSONObject(); + // 璁㈤槄 zlm鍚姩浜嬩欢 + hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,subscribeKey,(response)->{ + MediaServerConfig mediaServerConfig = JSONObject.toJavaObject(response, MediaServerConfig.class); + zLmRunning(mediaServerConfig); + }); + // 鑾峰彇zlm淇℃伅 logger.info("绛夊緟zlm鎺ュ叆..."); MediaServerConfig mediaServerConfig = getMediaServerConfig(); + if (mediaServerConfig != null) { - logger.info("zlm鎺ュ叆鎴愬姛..."); - if (autoConfig) saveZLMConfig(); - mediaServerConfig = getMediaServerConfig(); - redisCatchStorage.updateMediaInfo(mediaServerConfig); - // 鏇存柊娴佸垪琛� - zlmMediaListManager.updateMediaList(); + zLmRunning(mediaServerConfig); } } @@ -85,8 +98,7 @@ JSONArray data = responseJSON.getJSONArray("data"); if (data != null && data.size() > 0) { mediaServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), MediaServerConfig.class); - mediaServerConfig.setLocalIP(mediaIp); - mediaServerConfig.setWanIp(StringUtils.isEmpty(mediaWanIp)? mediaIp: mediaWanIp); + } } else { logger.error("getMediaServerConfig澶辫触, 1s鍚庨噸璇�"); @@ -136,4 +148,27 @@ } } + /** + * zlm 杩炴帴鎴愬姛鎴栬�厇lm閲嶅惎鍚� + */ + private void zLmRunning(MediaServerConfig mediaServerConfig){ + logger.info("zlm鎺ュ叆鎴愬姛..."); + if (autoConfig) saveZLMConfig(); + MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); + if (System.currentTimeMillis() - mediaInfo.getUpdateTime() < 50){ + logger.info("zlm鍒氬垰鏇存柊锛屽拷鐣ヨ繖娆℃洿鏂�"); + return; + } + mediaServerConfig.setLocalIP(mediaIp); + mediaServerConfig.setWanIp(StringUtils.isEmpty(mediaWanIp)? mediaIp: mediaWanIp); + redisCatchStorage.updateMediaInfo(mediaServerConfig); + // 鏇存柊娴佸垪琛� + zlmMediaListManager.updateMediaList(); + // 鎭㈠娴佷唬鐞� + List<StreamProxyDto> streamProxyListForEnable = storager.getStreamProxyListForEnable(true); + for (StreamProxyDto streamProxyDto : streamProxyListForEnable) { + logger.info("鎭㈠娴佷唬鐞嗭紝" + streamProxyDto.getApp() + "/" + streamProxyDto.getStream()); + streamProxyService.addStreamProxyToZlm(streamProxyDto); + } + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyDto.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyDto.java new file mode 100644 index 0000000..8f03602 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyDto.java @@ -0,0 +1,112 @@ +package com.genersoft.iot.vmp.media.zlm.dto; + +public class StreamProxyDto { + private String type; + private String app; + private String stream; + private String url; + private String src_url; + private String dst_url; + private int timeout_ms; + private String ffmpeg_cmd_key; + private String rtp_type; + private boolean enable; + private boolean enable_hls; + private boolean enable_mp4; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getApp() { + return app; + } + + public void setApp(String app) { + this.app = app; + } + + public String getStream() { + return stream; + } + + public void setStream(String stream) { + this.stream = stream; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getSrc_url() { + return src_url; + } + + public void setSrc_url(String src_url) { + this.src_url = src_url; + } + + public String getDst_url() { + return dst_url; + } + + public void setDst_url(String dst_url) { + this.dst_url = dst_url; + } + + public int getTimeout_ms() { + return timeout_ms; + } + + public void setTimeout_ms(int timeout_ms) { + this.timeout_ms = timeout_ms; + } + + public String getFfmpeg_cmd_key() { + return ffmpeg_cmd_key; + } + + public void setFfmpeg_cmd_key(String ffmpeg_cmd_key) { + this.ffmpeg_cmd_key = ffmpeg_cmd_key; + } + + public String getRtp_type() { + return rtp_type; + } + + public void setRtp_type(String rtp_type) { + this.rtp_type = rtp_type; + } + + public boolean isEnable() { + return enable; + } + + public void setEnable(boolean enable) { + this.enable = enable; + } + + public boolean isEnable_hls() { + return enable_hls; + } + + public void setEnable_hls(boolean enable_hls) { + this.enable_hls = enable_hls; + } + + public boolean isEnable_mp4() { + return enable_mp4; + } + + public void setEnable_mp4(boolean enable_mp4) { + this.enable_mp4 = enable_mp4; + } +} 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 2866611..ca4ebae 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.storager; +import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.common.RealVideo; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.MediaServerConfig; @@ -116,5 +117,5 @@ * 鑾峰彇褰撳墠濯掍綋娴佸垪琛� * @return List<RealVideo> */ - List<Object> getMediaList(int start, int end); + JSONObject getMediaList(int start, int end); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java index 10360b0..7656898 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto; import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce; import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; import com.github.pagehelper.PageInfo; @@ -261,4 +262,49 @@ * @param deviceId */ public int clearMobilePositionsByDeviceId(String deviceId); + + /** + * 鏂板浠g悊娴� + * @param streamProxyDto + * @return + */ + public int addStreamProxy(StreamProxyDto streamProxyDto); + + /** + * 鏇存柊浠g悊娴� + * @param streamProxyDto + * @return + */ + public int updateStreamProxy(StreamProxyDto streamProxyDto); + + /** + * 绉婚櫎浠g悊娴� + * @param app + * @param stream + * @return + */ + public int deleteStreamProxy(String app, String stream); + + /** + * 鎸夌収鏄惁鍚敤鑾峰彇浠g悊娴� + * @param enable + * @return + */ + public List<StreamProxyDto> getStreamProxyListForEnable(boolean enable); + + /** + * 鎸夌収鏄痑pp鍜宻tream鑾峰彇浠g悊娴� + * @param app + * @param stream + * @return + */ + public StreamProxyDto queryStreamProxy(String app, String stream); + + /** + * 鑾峰彇浠g悊娴� + * @param page + * @param count + * @return + */ + PageInfo<StreamProxyDto> queryStreamProxyList(Integer page, Integer count); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java new file mode 100644 index 0000000..414125b --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java @@ -0,0 +1,46 @@ +package com.genersoft.iot.vmp.storager.dao; + +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto; +import org.apache.ibatis.annotations.*; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Mapper +@Repository +public interface StreamProxyMapper { + + @Insert("INSERT INTO stream_proxy (type, app, stream, url, src_url, dst_url, " + + "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_hls, enable_mp4, enable) VALUES" + + "('${type}','${app}', '${stream}', '${url}', '${src_url}', '${dst_url}', " + + "'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_hls}, ${enable_mp4}, ${enable} )") + int add(StreamProxyDto streamProxyDto); + + @Update("UPDATE stream_proxy " + + "SET type=#{type}, " + + "app=#{app}," + + "stream=#{stream}," + + "url=#{url}, " + + "src_url=#{src_url}," + + "dst_url=#{dst_url}, " + + "timeout_ms=#{timeout_ms}, " + + "ffmpeg_cmd_key=#{ffmpeg_cmd_key}, " + + "rtp_type=#{rtp_type}, " + + "enable_hls=#{enable_hls}, " + + "enable=#{enable}, " + + "enable_mp4=#{enable_mp4} " + + "WHERE app=#{app} AND stream=#{stream}") + int update(StreamProxyDto streamProxyDto); + + @Delete("DELETE FROM stream_proxy WHERE app=#{app} AND stream=#{stream}") + int del(String app, String stream); + + @Select("SELECT * FROM stream_proxy") + List<StreamProxyDto> selectAll(); + + @Select("SELECT * FROM stream_proxy WHERE enable=${enable}") + List<StreamProxyDto> selectForEnable(boolean enable); + + @Select("SELECT * FROM stream_proxy WHERE app=#{app} AND stream=#{stream}") + StreamProxyDto selectOne(String app, String stream); +} 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 9871083..7b7f599 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 @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.storager.impl; +import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.common.RealVideo; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.common.VideoManagerConstants; @@ -92,6 +93,7 @@ */ @Override public boolean updateMediaInfo(MediaServerConfig mediaServerConfig) { + mediaServerConfig.setUpdateTime(System.currentTimeMillis()); return redis.set(VideoManagerConstants.MEDIA_SERVER_PREFIX,mediaServerConfig); } @@ -280,9 +282,13 @@ * @return List<RealVideo> */ @Override - public List<Object> getMediaList(int start, int end) { + public JSONObject getMediaList(int start, int end) { String key = VideoManagerConstants.MEDIA_STREAM_PREFIX; Set<Object> realVideos = redis.ZRange(key, start, end); - return new ArrayList(realVideos); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("list", new ArrayList(realVideos)); + jsonObject.put("total", redis.zSize(key)); + + return jsonObject; } } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java index ac2ed5b..071bf68 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java @@ -5,14 +5,11 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.gb28181.bean.MobilePosition; -import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; -import com.genersoft.iot.vmp.storager.dao.DeviceMapper; -import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper; -import com.genersoft.iot.vmp.storager.dao.PatformChannelMapper; +import com.genersoft.iot.vmp.storager.dao.*; import com.genersoft.iot.vmp.vmanager.platform.bean.ChannelReduce; -import com.genersoft.iot.vmp.storager.dao.DeviceMobilePositionMapper; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import org.springframework.beans.factory.annotation.Autowired; @@ -48,6 +45,9 @@ @Autowired private PatformChannelMapper patformChannelMapper; + + @Autowired + private StreamProxyMapper streamProxyMapper; @@ -233,7 +233,7 @@ /** * 娣诲姞Mobile Position璁惧绉诲姩浣嶇疆 - * @param MobilePosition + * @param mobilePosition */ @Override public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) { @@ -388,4 +388,68 @@ return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId); } + /** + * 鏂板浠g悊娴� + * @param streamProxyDto + * @return + */ + @Override + public int addStreamProxy(StreamProxyDto streamProxyDto) { + return streamProxyMapper.add(streamProxyDto); + } + + /** + * 鏇存柊浠g悊娴� + * @param streamProxyDto + * @return + */ + @Override + public int updateStreamProxy(StreamProxyDto streamProxyDto) { + return streamProxyMapper.update(streamProxyDto); + } + + /** + * 绉婚櫎浠g悊娴� + * @param id + * @return + */ + @Override + public int deleteStreamProxy(String app, String stream) { + return streamProxyMapper.del(app, stream); + } + + /** + * 鏍规嵁鏄惁鍚敤鑾峰彇浠g悊娴佸垪琛� + * @param enable + * @return + */ + @Override + public List<StreamProxyDto> getStreamProxyListForEnable(boolean enable) { + return streamProxyMapper.selectForEnable(enable); + } + + /** + * 鍒嗛〉鏌ヨ浠g悊娴佸垪琛� + * @param page + * @param count + * @return + */ + @Override + public PageInfo<StreamProxyDto> queryStreamProxyList(Integer page, Integer count) { + PageHelper.startPage(page, count); + List<StreamProxyDto> all = streamProxyMapper.selectAll(); + return new PageInfo<>(all); + } + + + /** + * 鎸夌収鏄痑pp鍜宻tream鑾峰彇浠g悊娴� + * @param app + * @param stream + * @return + */ + @Override + public StreamProxyDto queryStreamProxy(String app, String stream){ + return streamProxyMapper.selectOne(app, stream); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/media/MediaController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/media/MediaController.java new file mode 100644 index 0000000..115e840 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/media/MediaController.java @@ -0,0 +1,52 @@ +package com.genersoft.iot.vmp.vmanager.media; + +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.vmanager.service.IMediaService; +import com.genersoft.iot.vmp.vmanager.service.IStreamProxyService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + + +@Controller +@CrossOrigin +@RequestMapping(value = "/api/media") +public class MediaController { + + private final static Logger logger = LoggerFactory.getLogger(MediaController.class); + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private IStreamProxyService streamProxyService; + + @Autowired + private IMediaService mediaService; + + + @RequestMapping(value = "/list") + @ResponseBody + public JSONObject list( @RequestParam(required = false)Integer page, + @RequestParam(required = false)Integer count, + @RequestParam(required = false)String q, + @RequestParam(required = false)Boolean online ){ + + JSONObject jsonObject = redisCatchStorage.getMediaList(page - 1, page - 1 + count); + return jsonObject; + } + + @RequestMapping(value = "/getStreamInfoByAppAndStream") + @ResponseBody + public StreamInfo getStreamInfoByAppAndStream(String app, String stream){ + return mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream); + } + + + + +} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java index 0c773e6..67045b4 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult; +import com.genersoft.iot.vmp.vmanager.service.IMediaService; import com.genersoft.iot.vmp.vmanager.service.IPlayService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,6 +55,9 @@ @Autowired private IPlayService playService; + + @Autowired + private IMediaService mediaService; @GetMapping("/play/{deviceId}/{channelId}") public DeferredResult<ResponseEntity<String>> play(@PathVariable String deviceId, @@ -159,18 +163,20 @@ JSONObject data = jsonObject.getJSONObject("data"); if (data != null) { result.put("key", data.getString("key")); - StreamInfo streamInfoResult = new StreamInfo(); - streamInfoResult.setRtmp(dstUrl); - streamInfoResult.setRtsp(String.format("rtsp://%s:%s/convert/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), streamId)); +// StreamInfo streamInfoResult = new StreamInfo(); +// streamInfoResult.setRtmp(dstUrl); +// streamInfoResult.setRtsp(String.format("rtsp://%s:%s/convert/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), streamId)); +// streamInfoResult.setStreamId(streamId); +// streamInfoResult.setFlv(String.format("http://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); +// streamInfoResult.setWs_flv(String.format("ws://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); +// streamInfoResult.setHls(String.format("http://%s:%s/convert/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); +// streamInfoResult.setWs_hls(String.format("ws://%s:%s/convert/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); +// streamInfoResult.setFmp4(String.format("http://%s:%s/convert/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); +// streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/convert/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); +// streamInfoResult.setTs(String.format("http://%s:%s/convert/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); +// streamInfoResult.setWs_ts(String.format("ws://%s:%s/convert/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); + StreamInfo streamInfoResult = mediaService.getStreamInfoByAppAndStream("convert", streamId); streamInfoResult.setStreamId(streamId); - streamInfoResult.setFlv(String.format("http://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); - streamInfoResult.setWs_flv(String.format("ws://%s:%s/convert/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); - streamInfoResult.setHls(String.format("http://%s:%s/convert/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); - streamInfoResult.setWs_hls(String.format("ws://%s:%s/convert/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); - streamInfoResult.setFmp4(String.format("http://%s:%s/convert/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); - streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/convert/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); - streamInfoResult.setTs(String.format("http://%s:%s/convert/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); - streamInfoResult.setWs_ts(String.format("ws://%s:%s/convert/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), streamId)); result.put("data", streamInfoResult); } }else { diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/IMediaService.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/IMediaService.java new file mode 100644 index 0000000..757a7ac --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/IMediaService.java @@ -0,0 +1,25 @@ +package com.genersoft.iot.vmp.vmanager.service; + +import com.genersoft.iot.vmp.common.StreamInfo; + +/** + * 濯掍綋淇℃伅涓氬姟 + */ +public interface IMediaService { + + /** + * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 閫氳繃zlm鎺ュ彛妫�鏌ユ槸鍚﹀瓨鍦� + * @param app + * @param stream + * @return + */ + StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream); + + /** + * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 鍙槸鍦板潃鎷兼帴 + * @param app + * @param stream + * @return + */ + StreamInfo getStreamInfoByAppAndStream(String app, String stream); +} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/IStreamProxyService.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/IStreamProxyService.java new file mode 100644 index 0000000..4a93cd2 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/IStreamProxyService.java @@ -0,0 +1,60 @@ +package com.genersoft.iot.vmp.vmanager.service; + +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto; +import com.genersoft.iot.vmp.vmanager.streamProxy.StreamProxyController; +import com.github.pagehelper.PageInfo; + +public interface IStreamProxyService { + + /** + * 淇濆瓨瑙嗛浠g悊 + * @param param + */ + void save(StreamProxyDto param); + + /** + * 娣诲姞瑙嗛浠g悊鍒皕lm + * @param param + * @return + */ + JSONObject addStreamProxyToZlm(StreamProxyDto param); + + /** + * 浠巣lm绉婚櫎瑙嗛浠g悊 + * @param param + * @return + */ + JSONObject removeStreamProxyFromZlm(StreamProxyDto param); + + /** + * 鍒嗛〉鏌ヨ + * @param page + * @param count + * @return + */ + PageInfo<StreamProxyDto> getAll(Integer page, Integer count); + + /** + * 鍒犻櫎瑙嗛浠g悊 + * @param app + * @param stream + */ + void del(String app, String stream); + + /** + * 鍚敤瑙嗛浠g悊 + * @param app + * @param stream + * @return + */ + boolean start(String app, String stream); + + /** + * 鍋滅敤鐢ㄨ棰戜唬鐞� + * @param app + * @param stream + * @return + */ + boolean stop(String app, String stream); +} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/MediaServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/MediaServiceImpl.java new file mode 100644 index 0000000..afd6cc9 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/MediaServiceImpl.java @@ -0,0 +1,52 @@ +package com.genersoft.iot.vmp.vmanager.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.conf.MediaServerConfig; +import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import com.genersoft.iot.vmp.vmanager.service.IMediaService; +import com.genersoft.iot.vmp.vmanager.service.IStreamProxyService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class MediaServiceImpl implements IMediaService { + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private IVideoManagerStorager storager; + + @Autowired + private ZLMRESTfulUtils zlmresTfulUtils; + + @Override + public StreamInfo getStreamInfoByAppAndStream(String app, String stream) { + MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); + StreamInfo streamInfoResult = new StreamInfo(); + streamInfoResult.setRtmp(String.format("rtmp://%s:%s/%s/%s", mediaInfo.getWanIp(), mediaInfo.getRtmpPort(), app, stream)); + streamInfoResult.setRtsp(String.format("rtsp://%s:%s/%s/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), app, stream)); + streamInfoResult.setFlv(String.format("http://%s:%s/%s/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); + streamInfoResult.setWs_flv(String.format("ws://%s:%s/%s/%s.flv", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); + streamInfoResult.setHls(String.format("http://%s:%s/%s/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); + streamInfoResult.setWs_hls(String.format("ws://%s:%s/%s/%s/hls.m3u8", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); + streamInfoResult.setFmp4(String.format("http://%s:%s/%s/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); + streamInfoResult.setWs_fmp4(String.format("ws://%s:%s/%s/%s.live.mp4", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); + streamInfoResult.setTs(String.format("http://%s:%s/%s/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); + streamInfoResult.setWs_ts(String.format("ws://%s:%s/%s/%s.live.ts", mediaInfo.getWanIp(), mediaInfo.getHttpPort(), app, stream)); + return streamInfoResult; + } + + @Override + public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream) { + StreamInfo streamInfo = null; + JSONObject mediaList = zlmresTfulUtils.getMediaList(app, stream); + if (mediaList != null) { + streamInfo = getStreamInfoByAppAndStream(app, stream); + } + return streamInfo; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java index 376040a..edd8710 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/PlayServiceImpl.java @@ -15,6 +15,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult; +import com.genersoft.iot.vmp.vmanager.service.IMediaService; import com.genersoft.iot.vmp.vmanager.service.IPlayService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,6 +46,9 @@ @Autowired private ZLMRESTfulUtils zlmresTfulUtils; + + @Autowired + private IMediaService mediaService; @Override @@ -148,26 +152,27 @@ public StreamInfo onPublishHandler(JSONObject resonse, String deviceId, String channelId, String uuid) { String streamId = resonse.getString("id"); - StreamInfo streamInfo = new StreamInfo(); + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream("rtp", streamId); +// StreamInfo streamInfo = new StreamInfo(); streamInfo.setStreamId(streamId); streamInfo.setDeviceID(deviceId); streamInfo.setChannelId(channelId); - MediaServerConfig mediaServerConfig = redisCatchStorage.getMediaInfo(); +// MediaServerConfig mediaServerConfig = redisCatchStorage.getMediaInfo(); - streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); - streamInfo.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); - - streamInfo.setFmp4(String.format("http://%s:%s/rtp/%s.live.mp4", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); - streamInfo.setWs_fmp4(String.format("ws://%s:%s/rtp/%s.live.mp4", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); - - streamInfo.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); - streamInfo.setWs_hls(String.format("ws://%s:%s/rtp/%s/hls.m3u8", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); - - streamInfo.setTs(String.format("http://%s:%s/rtp/%s.live.ts", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); - streamInfo.setWs_ts(String.format("ws://%s:%s/rtp/%s.live.ts", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); - - streamInfo.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaServerConfig.getWanIp(), mediaServerConfig.getRtmpPort(), streamId)); - streamInfo.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaServerConfig.getWanIp(), mediaServerConfig.getRtspPort(), streamId)); +// streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); +// streamInfo.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); +// +// streamInfo.setFmp4(String.format("http://%s:%s/rtp/%s.live.mp4", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); +// streamInfo.setWs_fmp4(String.format("ws://%s:%s/rtp/%s.live.mp4", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); +// +// streamInfo.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); +// streamInfo.setWs_hls(String.format("ws://%s:%s/rtp/%s/hls.m3u8", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); +// +// streamInfo.setTs(String.format("http://%s:%s/rtp/%s.live.ts", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); +// streamInfo.setWs_ts(String.format("ws://%s:%s/rtp/%s.live.ts", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId)); +// +// streamInfo.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaServerConfig.getWanIp(), mediaServerConfig.getRtmpPort(), streamId)); +// streamInfo.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaServerConfig.getWanIp(), mediaServerConfig.getRtspPort(), streamId)); return streamInfo; } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/StreamProxyServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/StreamProxyServiceImpl.java new file mode 100644 index 0000000..0655980 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/StreamProxyServiceImpl.java @@ -0,0 +1,123 @@ +package com.genersoft.iot.vmp.vmanager.service.impl; + +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.conf.MediaServerConfig; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; +import com.genersoft.iot.vmp.storager.dao.StreamProxyMapper; +import com.genersoft.iot.vmp.vmanager.service.IStreamProxyService; +import com.genersoft.iot.vmp.vmanager.streamProxy.StreamProxyController; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 瑙嗛浠g悊涓氬姟 + */ +@Service +public class StreamProxyServiceImpl implements IStreamProxyService { + + @Autowired + private IVideoManagerStorager videoManagerStorager; + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private ZLMRESTfulUtils zlmresTfulUtils; + + @Autowired + private StreamProxyMapper streamProxyMapper; + + + @Override + public void save(StreamProxyDto param) { + MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); + String dstUrl = String.format("rtmp://%s:%s/%s/%s", "127.0.0.1", mediaInfo.getRtmpPort(), param.getApp(), + param.getStream() ); + param.setDst_url(dstUrl); + // 鏇存柊 + if (videoManagerStorager.queryStreamProxy(param.getApp(), param.getStream()) != null) { + int result = videoManagerStorager.updateStreamProxy(param); + if (result > 0 && param.isEnable()) { + addStreamProxyToZlm(param); + } + }else { // 鏂板 + int result = videoManagerStorager.addStreamProxy(param); + if (result > 0 && param.isEnable()) { + addStreamProxyToZlm(param); + } + } + } + + @Override + public JSONObject addStreamProxyToZlm(StreamProxyDto param) { + JSONObject result = null; + if ("default".equals(param.getType())){ + result = zlmresTfulUtils.addStreamProxy(param.getApp(), param.getStream(), param.getUrl(), + param.isEnable_hls(), param.isEnable_mp4(), param.getRtp_type()); + }else if ("ffmpeg".equals(param.getType())) { + result = zlmresTfulUtils.addFFmpegSource(param.getSrc_url(), param.getDst_url(), + param.getTimeout_ms() + ""); + } + return result; + } + + @Override + public JSONObject removeStreamProxyFromZlm(StreamProxyDto param) { + JSONObject result = zlmresTfulUtils.closeStreams(param.getApp(), param.getStream()); + return result; + } + + @Override + public PageInfo<StreamProxyDto> getAll(Integer page, Integer count) { + return videoManagerStorager.queryStreamProxyList(page, count); + } + + @Override + public void del(String app, String stream) { + StreamProxyDto streamProxyDto = new StreamProxyDto(); + streamProxyDto.setApp(app); + streamProxyDto.setStream(stream); + JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto); + if (jsonObject.getInteger("code") == 0) { + videoManagerStorager.deleteStreamProxy(app, stream); + } + } + + @Override + public boolean start(String app, String stream) { + boolean result = false; + StreamProxyDto streamProxyDto = videoManagerStorager.queryStreamProxy(app, stream); + if (!streamProxyDto.isEnable() && streamProxyDto != null) { + JSONObject jsonObject = addStreamProxyToZlm(streamProxyDto); + if (jsonObject.getInteger("code") == 0) { + result = true; + streamProxyDto.setEnable(true); + videoManagerStorager.updateStreamProxy(streamProxyDto); + } + } + return result; + } + + @Override + public boolean stop(String app, String stream) { + boolean result = false; + StreamProxyDto streamProxyDto = videoManagerStorager.queryStreamProxy(app, stream); + if (streamProxyDto.isEnable() && streamProxyDto != null) { + JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto); + if (jsonObject.getInteger("code") == 0) { + result = true; + streamProxyDto.setEnable(false); + videoManagerStorager.updateStreamProxy(streamProxyDto); + } + } + return result; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java new file mode 100644 index 0000000..09d4174 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java @@ -0,0 +1,73 @@ +package com.genersoft.iot.vmp.vmanager.streamProxy; + +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.vmanager.service.IStreamProxyService; +import com.github.pagehelper.PageInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +/** + * 鎷夋祦浠g悊鎺ュ彛 + */ +@Controller +@CrossOrigin +@RequestMapping(value = "/api/proxy") +public class StreamProxyController { + + private final static Logger logger = LoggerFactory.getLogger(StreamProxyController.class); + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private IStreamProxyService streamProxyService; + + + @RequestMapping(value = "/list") + @ResponseBody + public PageInfo<StreamProxyDto> list(@RequestParam(required = false)Integer page, + @RequestParam(required = false)Integer count, + @RequestParam(required = false)String q, + @RequestParam(required = false)Boolean online ){ + + return streamProxyService.getAll(page, count); + } + + @RequestMapping(value = "/save") + @ResponseBody + public Object save(@RequestBody StreamProxyDto param){ + logger.info("娣诲姞浠g悊锛� " + JSONObject.toJSONString(param)); + streamProxyService.save(param); + return "success"; + } + + @RequestMapping(value = "/del") + @ResponseBody + public Object del(String app, String stream){ + logger.info("绉婚櫎浠g悊锛� " + app + "/" + stream); + streamProxyService.del(app, stream); + return "success"; + } + + @RequestMapping(value = "/start") + @ResponseBody + public Object start(String app, String stream){ + logger.info("鍚敤浠g悊锛� " + app + "/" + stream); + boolean result = streamProxyService.start(app, stream); + return "success"; + } + + @RequestMapping(value = "/stop") + @ResponseBody + public Object stop(String app, String stream){ + logger.info("鍋滅敤浠g悊锛� " + app + "/" + stream); + boolean result = streamProxyService.stop(app, stream); + return "success"; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/web/ApiMediaController.java b/src/main/java/com/genersoft/iot/vmp/web/ApiMediaController.java deleted file mode 100644 index 84910c5..0000000 --- a/src/main/java/com/genersoft/iot/vmp/web/ApiMediaController.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.genersoft.iot.vmp.web; - -import com.alibaba.fastjson.JSONObject; -import com.genersoft.iot.vmp.common.RealVideo; -import com.genersoft.iot.vmp.conf.SipConfig; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; - -import java.util.List; - -/** - * 鍏煎LiveGBS鐨凙PI锛氱郴缁熸帴鍙� - */ -@Controller -@CrossOrigin -@RequestMapping(value = "/api/v1/media") -public class ApiMediaController { - - private final static Logger logger = LoggerFactory.getLogger(ApiMediaController.class); - - @Autowired - private IRedisCatchStorage redisCatchStorage; - - - @RequestMapping(value = "/list") - @ResponseBody - public JSONObject list( @RequestParam(required = false)Integer start, - @RequestParam(required = false)Integer limit, - @RequestParam(required = false)String q, - @RequestParam(required = false)Boolean online ){ - - List<Object> mediaList = redisCatchStorage.getMediaList(start - 1, start - 1 + limit); - JSONObject jsonObject = new JSONObject(); - jsonObject.put("code", 0); - jsonObject.put("data", mediaList); - return jsonObject; - } -} diff --git a/src/main/resources/wvp.sqlite b/src/main/resources/wvp.sqlite index d50f18c..9147e22 100644 --- a/src/main/resources/wvp.sqlite +++ b/src/main/resources/wvp.sqlite Binary files differ diff --git a/web_src/package-lock.json b/web_src/package-lock.json index e4ed934..9e734e5 100644 --- a/web_src/package-lock.json +++ b/web_src/package-lock.json @@ -10924,6 +10924,26 @@ "clipboard": "^2.0.0" } }, + "vue-clipboards": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/vue-clipboards/-/vue-clipboards-1.3.0.tgz", + "integrity": "sha512-VMDYHpLQH0EUmqfk9b5XMrkvSu/HjNsLW2EBR4OS6JZHcv/PxmWYdoTBPVlp5eYrhWy07La8nWpRwAh09Mgufw==", + "requires": { + "clipboard": "^1.7.1" + }, + "dependencies": { + "clipboard": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-1.7.1.tgz", + "integrity": "sha1-Ng1taUbpmnof7zleQrqStem1oWs=", + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + } + } + }, "vue-cookies": { "version": "1.7.4", "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", diff --git a/web_src/package.json b/web_src/package.json index 4a9f766..b7a947c 100644 --- a/web_src/package.json +++ b/web_src/package.json @@ -21,6 +21,7 @@ "vue": "^2.6.11", "vue-baidu-map": "^0.21.22", "vue-clipboard2": "^0.3.1", + "vue-clipboards": "^1.3.0", "vue-cookies": "^1.7.4", "vue-router": "^3.1.6" }, diff --git a/web_src/src/components/ParentPlatformList.vue b/web_src/src/components/ParentPlatformList.vue index 298504b..32c999d 100644 --- a/web_src/src/components/ParentPlatformList.vue +++ b/web_src/src/components/ParentPlatformList.vue @@ -68,9 +68,9 @@ </template> <script> -import platformEdit from './platformEdit.vue' +import platformEdit from './dialog/platformEdit.vue' import uiHeader from './UiHeader.vue' -import chooseChannelDialog from './gb28181/chooseChannel.vue' +import chooseChannelDialog from './dialog/chooseChannel.vue' export default { name: 'app', components: { diff --git a/web_src/src/components/PushVideoList.vue b/web_src/src/components/PushVideoList.vue index 60a5c9e..4a93d7a 100644 --- a/web_src/src/components/PushVideoList.vue +++ b/web_src/src/components/PushVideoList.vue @@ -1,5 +1,5 @@ <template> - <div id="app"> + <div id="pushVideoList"> <el-container> <el-header> <uiHeader></uiHeader> @@ -7,28 +7,27 @@ <el-main> <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> <span style="font-size: 1rem; font-weight: bold;">鎺ㄦ祦鍒楄〃</span> - <div style="position: absolute; right: 1rem; top: 0.3rem;"> - <el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" @click="getDeviceList()"></el-button> - </div> </div> - <!-- <devicePlayer ref="devicePlayer"></devicePlayer> --> - <el-table :data="deviceList" border style="width: 100%" :height="winHeight"> - <el-table-column prop="schema" label="鍗忚" width="180" align="center"> + <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;"> + <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">娣诲姞浠g悊</el-button> + </div> + <devicePlayer ref="devicePlayer"></devicePlayer> + <el-table :data="pushList" border style="width: 100%" :height="winHeight"> + <el-table-column prop="app" label="APP" width="180" align="center"> </el-table-column> - <el-table-column prop="streamUrl" label="娴佸湴鍧�" width="240" align="center"> + <el-table-column prop="stream" label="娴両D" width="240" align="center"> </el-table-column> - <el-table-column prop="online" label="鍦ㄧ嚎浜烘暟" width="240" align="center"> + <el-table-column prop="totalReaderCount" label="鍦ㄧ嚎浜烘暟" width="240" align="center"> </el-table-column> - <el-table-column prop="startTime" label="寮�濮嬫椂闂�" align="center"> + <el-table-column prop="createStamp" label="寮�濮嬫椂闂�" align="center"> </el-table-column> <el-table-column label="鎿嶄綔" width="360" align="center" fixed="right"> <template slot-scope="scope"> - <el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " icon="el-icon-refresh" @click="refDevice(scope.row)">鍒锋柊</el-button> <el-button-group> - <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">鎾斁</el-button> - <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopDevicePush(scope.row)">鍋滄</el-button> + <el-button size="mini" icon="el-icon-video-play" @click="playPuhsh(scope.row)">鎾斁</el-button> + <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopPuhsh(scope.row)">鍋滄</el-button> </el-button-group> </template> </el-table-column> @@ -43,25 +42,27 @@ layout="total, sizes, prev, pager, next" :total="total"> </el-pagination> - + <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit> </el-main> </el-container> </div> </template> <script> + import streamProxyEdit from './dialog/StreamProxyEdit.vue' + import devicePlayer from './dialog/devicePlayer.vue' import uiHeader from './UiHeader.vue' export default { - name: 'app', + name: 'pushVideoList', components: { + devicePlayer, + streamProxyEdit, uiHeader }, data() { return { - deviceList: [], //璁惧鍒楄〃 - currentDevice: {}, //褰撳墠鎿嶄綔璁惧瀵硅薄 - - videoComponentList: [], + pushList: [], //璁惧鍒楄〃 + currentPusher: {}, //褰撳墠鎿嶄綔璁惧瀵硅薄 updateLooper: 0, //鏁版嵁鍒锋柊杞鏍囧織 currentDeviceChannelsLenth:0, winHeight: window.innerHeight - 200, @@ -72,23 +73,10 @@ }; }, computed: { - getcurrentDeviceChannels: function() { - let data = this.currentDevice['channelMap']; - let channels = null; - if (data) { - channels = Object.keys(data).map(key => { - return data[key]; - }); - this.currentDeviceChannelsLenth = channels.length; - } - - console.log("鏁版嵁锛�" + JSON.stringify(channels)); - return channels; - } }, mounted() { this.initData(); - this.updateLooper = setInterval(this.initData, 10000); + // this.updateLooper = setInterval(this.initData, 10000); }, destroyed() { this.$destroy('videojs'); @@ -96,20 +84,20 @@ }, methods: { initData: function() { - this.getDeviceList(); + this.getPushList(); }, currentChange: function(val){ this.currentPage = val; - this.getDeviceList(); + this.getPushList(); }, handleSizeChange: function(val){ this.count = val; - this.getDeviceList(); + this.getPushList(); }, - getDeviceList: function() { + getPushList: function() { let that = this; this.getDeviceListLoading = true; - this.$axios.get(`/api/devices`,{ + this.$axios.get(`/api/media/list`,{ params: { page: that.currentPage, count: that.count @@ -119,83 +107,44 @@ console.log(res); console.log(res.data.list); that.total = res.data.total; - that.deviceList = res.data.list; + that.pushList = res.data.list; that.getDeviceListLoading = false; }) .catch(function (error) { console.log(error); that.getDeviceListLoading = false; }); - }, - showChannelList: function(row) { - console.log(JSON.stringify(row)) - this.$router.push(`/channelList/${row.deviceId}/0/15/1`); + addStreamProxy: function(){ + console.log(2222) + this.$refs.streamProxyEdit.openDialog(null, this.initData) }, - showDevicePosition: function(row) { - console.log(JSON.stringify(row)) - this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`); + saveStreamProxy: function(){ }, - - //gb28181骞冲彴瀵规帴 - //鍒锋柊璁惧淇℃伅 - refDevice: function(itemData) { - ///api/devices/{deviceId}/sync - console.log("鍒锋柊瀵瑰簲璁惧:" + itemData.deviceId); - var that = this; - that.$refs[itemData.deviceId + 'refbtn' ].loading = true; - this.$axios({ - method: 'post', - url: '/api/devices/' + itemData.deviceId + '/sync' - }).then(function(res) { - console.log("鍒锋柊璁惧缁撴灉锛�"+JSON.stringify(res)); - if (!res.data.deviceId) { - that.$message({ - showClose: true, - message: res.data, - type: 'error' - }); - }else{ - that.$message({ - showClose: true, - message: '璇锋眰鎴愬姛', - type: 'success' - }); + playPuhsh: function(row){ + let that = this; + this.getListLoading = true; + this.$axios.get(`/api/media/getStreamInfoByAppAndStream`,{ + params: { + app: row.app, + stream: row.stream } - that.initData() - that.$refs[itemData.deviceId + 'refbtn' ].loading = false; - }).catch(function(e) { - console.error(e) - that.$refs[itemData.deviceId + 'refbtn' ].loading = false; - });; + }) + .then(function (res) { + that.getListLoading = false; + that.$refs.devicePlayer.openDialog("streamPlay", null, null, { + streamInfo: res.data, + hasAudio: true + }); + }) + .catch(function (error) { + console.log(error); + that.getListLoading = false; + }); }, - //閫氱煡璁惧涓婁紶濯掍綋娴� - sendDevicePush: function(itemData) { - // let deviceId = this.currentDevice.deviceId; - // let channelId = itemData.channelId; - // console.log("閫氱煡璁惧鎺ㄦ祦1锛�" + deviceId + " : " + channelId); - // let that = this; - // this.$axios({ - // method: 'get', - // url: '/api/play/' + deviceId + '/' + channelId - // }).then(function(res) { - // let ssrc = res.data.ssrc; - // that.$refs.devicePlayer.play(ssrc,deviceId,channelId); - // }).catch(function(e) { - // }); - }, - transportChange: function (row) { - console.log(row); - console.log(`淇敼浼犺緭鏂瑰紡涓� ${row.streamMode}锛�${row.deviceId} `); - let that = this; - this.$axios({ - method: 'get', - url: '/api/devices/' + row.deviceId + '/transport/' + row.streamMode - }).then(function(res) { - - }).catch(function(e) { - }); - } + stopPuhsh: function(row){ + console.log(row) + } } }; diff --git a/web_src/src/components/StreamProxyList.vue b/web_src/src/components/StreamProxyList.vue new file mode 100644 index 0000000..0a1e03d --- /dev/null +++ b/web_src/src/components/StreamProxyList.vue @@ -0,0 +1,297 @@ +<template> + <div id="streamProxyList"> + <el-container> + <el-header> + <uiHeader></uiHeader> + </el-header> + <el-main> + <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> + <span style="font-size: 1rem; font-weight: bold;">鎷夋祦浠g悊鍒楄〃</span> + </div> + <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;"> + <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">娣诲姞浠g悊</el-button> + </div> + <devicePlayer ref="devicePlayer"></devicePlayer> + <el-table :data="streamProxyList" border style="width: 100%" :height="winHeight"> + <el-table-column prop="app" label="搴旂敤鍚�" align="center" show-overflow-tooltip/> + <el-table-column prop="stream" label="娴両D" align="center" show-overflow-tooltip/> + <el-table-column label="娴佸湴鍧�" width="400" align="center" show-overflow-tooltip > + <template slot-scope="scope"> + <div slot="reference" class="name-wrapper"> + + <el-tag size="medium" v-if="scope.row.type == 'default'"> + <i class="cpoy-btn el-icon-document-copy" title="鐐瑰嚮鎷疯礉" v-clipboard="scope.row.url" @success="$message({type:'success', message:'鎴愬姛鎷疯礉鍒扮矘璐存澘'})"></i> + {{scope.row.url}} + </el-tag> + <el-tag size="medium" v-if="scope.row.type != 'default'"> + <i class="cpoy-btn el-icon-document-copy" title="鐐瑰嚮鎷疯礉" v-clipboard="scope.row.src_url" @success="$message({type:'success', message:'鎴愬姛鎷疯礉鍒扮矘璐存澘'})"></i> + {{scope.row.src_url}} + </el-tag> + </div> + </template> + </el-table-column> + + <el-table-column label="杞琀LS" width="120" align="center"> + <template slot-scope="scope"> + <div slot="reference" class="name-wrapper"> + <el-tag size="medium" v-if="scope.row.enable_hls">宸插惎鐢�</el-tag> + <el-tag size="medium" type="info" v-if="!scope.row.enable_hls">鏈惎鐢�</el-tag> + </div> + </template> + </el-table-column> + <el-table-column label="MP4褰曞埗" width="120" align="center"> + <template slot-scope="scope"> + <div slot="reference" class="name-wrapper"> + <el-tag size="medium" v-if="scope.row.enable_mp4">宸插惎鐢�</el-tag> + <el-tag size="medium" type="info" v-if="!scope.row.enable_mp4">鏈惎鐢�</el-tag> + </div> + </template> + </el-table-column> + <el-table-column label="鍚敤" width="120" align="center"> + <template slot-scope="scope"> + <div slot="reference" class="name-wrapper"> + <el-tag size="medium" v-if="scope.row.enable">宸插惎鐢�</el-tag> + <el-tag size="medium" type="info" v-if="!scope.row.enable">鏈惎鐢�</el-tag> + </div> + </template> + </el-table-column> + + + <el-table-column label="鎿嶄綔" width="360" align="center" fixed="right"> + <template slot-scope="scope"> + <el-button-group> + <el-button size="mini" icon="el-icon-video-play" v-if="scope.row.enable" @click="play(scope.row)">鎾斁</el-button> + <el-button size="mini" icon="el-icon-close" type="success" v-if="scope.row.enable" @click="stop(scope.row)">鍋滅敤</el-button> + <el-button size="mini" icon="el-icon-check" type="primary" v-if="!scope.row.enable" @click="start(scope.row)">鍚敤</el-button> + <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteStreamProxy(scope.row)">鍒犻櫎</el-button> + </el-button-group> + </template> + </el-table-column> + </el-table> + <el-pagination + style="float: right" + @size-change="handleSizeChange" + @current-change="currentChange" + :current-page="currentPage" + :page-size="count" + :page-sizes="[15, 25, 35, 50]" + layout="total, sizes, prev, pager, next" + :total="total"> + </el-pagination> + <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit> + </el-main> + </el-container> + </div> +</template> + +<script> + import streamProxyEdit from './dialog/StreamProxyEdit.vue' + import devicePlayer from './dialog/devicePlayer.vue' + import uiHeader from './UiHeader.vue' + export default { + name: 'streamProxyList', + components: { + devicePlayer, + streamProxyEdit, + uiHeader + }, + data() { + return { + streamProxyList: [], + currentPusher: {}, //褰撳墠鎿嶄綔璁惧瀵硅薄 + updateLooper: 0, //鏁版嵁鍒锋柊杞鏍囧織 + currentDeviceChannelsLenth:0, + winHeight: window.innerHeight - 200, + currentPage:1, + count:15, + total:0, + getListLoading: false + }; + }, + computed: { + }, + mounted() { + this.initData(); + // this.updateLooper = setInterval(this.initData, 10000); + }, + destroyed() { + this.$destroy('videojs'); + clearTimeout(this.updateLooper); + }, + methods: { + initData: function() { + this.getStreamProxyList(); + }, + currentChange: function(val){ + this.currentPage = val; + this.getStreamProxyList(); + }, + handleSizeChange: function(val){ + this.count = val; + this.getStreamProxyList(); + }, + getStreamProxyList: function() { + let that = this; + this.getListLoading = true; + this.$axios.get(`/api/proxy/list`,{ + params: { + page: that.currentPage, + count: that.count + } + } ) + .then(function (res) { + console.log(res); + console.log(res.data.list); + that.total = res.data.total; + that.streamProxyList = res.data.list; + that.getListLoading = false; + }) + .catch(function (error) { + console.log(error); + that.getListLoading = false; + }); + }, + addStreamProxy: function(){ + this.$refs.streamProxyEdit.openDialog(null, this.initData) + }, + saveStreamProxy: function(){ + }, + play: function(row){ + let that = this; + this.getListLoading = true; + this.$axios.get(`/api/media/getStreamInfoByAppAndStream`,{ + params: { + app: row.app, + stream: row.stream + } + }) + .then(function (res) { + that.getListLoading = false; + that.$refs.devicePlayer.openDialog("streamPlay", null, null, { + streamInfo: res.data, + hasAudio: true + }); + }) + .catch(function (error) { + console.log(error); + that.getListLoading = false; + }); + + }, + deleteStreamProxy: function(row){ + console.log(1111) + let that = this; + this.getListLoading = true; + this.$axios.get(`/api/proxy/del`,{ + params: { + app: row.app, + stream: row.stream + } + }) + .then(function (res) { + that.getListLoading = false; + that.initData() + }) + .catch(function (error) { + console.log(error); + that.getListLoading = false; + }); + }, + start: function(row){ + let that = this; + this.getListLoading = true; + this.$axios.get(`/api/proxy/start`,{ + params: { + app: row.app, + stream: row.stream + } + }) + .then(function (res) { + that.getListLoading = false; + that.initData() + }) + .catch(function (error) { + console.log(error); + that.getListLoading = false; + }); + }, + stop: function(row){ + let that = this; + this.getListLoading = true; + this.$axios.get(`/api/proxy/stop`,{ + params: { + app: row.app, + stream: row.stream + } + }) + .then(function (res) { + that.getListLoading = false; + that.initData() + }) + .catch(function (error) { + console.log(error); + that.getListLoading = false; + }); + } + + } + }; +</script> + +<style> + .videoList { + display: flex; + flex-wrap: wrap; + align-content: flex-start; + } + + .video-item { + position: relative; + width: 15rem; + height: 10rem; + margin-right: 1rem; + background-color: #000000; + } + + .video-item-img { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + margin: auto; + width: 100%; + height: 100%; + } + + .video-item-img:after { + content: ""; + display: inline-block; + position: absolute; + z-index: 2; + top: 0; + bottom: 0; + left: 0; + right: 0; + margin: auto; + width: 3rem; + height: 3rem; + background-image: url("../assets/loading.png"); + background-size: cover; + background-color: #000000; + } + + .video-item-title { + position: absolute; + bottom: 0; + color: #000000; + background-color: #ffffff; + line-height: 1.5rem; + padding: 0.3rem; + width: 14.4rem; + } + .cpoy-btn { + cursor: pointer; + margin-right: 10px; + } +</style> diff --git a/web_src/src/components/UiHeader.vue b/web_src/src/components/UiHeader.vue index fa1c442..ae0780b 100644 --- a/web_src/src/components/UiHeader.vue +++ b/web_src/src/components/UiHeader.vue @@ -4,6 +4,7 @@ <el-menu-item index="/">鎺у埗鍙�</el-menu-item> <el-menu-item index="/deviceList">璁惧鍒楄〃</el-menu-item> <el-menu-item index="/pushVideoList">鎺ㄦ祦鍒楄〃</el-menu-item> + <el-menu-item index="/streamProxyList">鎷夋祦浠g悊</el-menu-item> <el-menu-item index="/parentPlatformList/15/1">鍥芥爣绾ц仈</el-menu-item> <el-switch v-model="alarmNotify" active-text="鎶ヨ淇℃伅鎺ㄩ��" style="display: block float: right" @change="sseControl"></el-switch> <el-menu-item style="float: right;" @click="loginout">閫�鍑�</el-menu-item> diff --git a/web_src/src/components/channelList.vue b/web_src/src/components/channelList.vue index 6d893ce..b06ce25 100644 --- a/web_src/src/components/channelList.vue +++ b/web_src/src/components/channelList.vue @@ -75,7 +75,7 @@ </template> <script> -import devicePlayer from './gb28181/devicePlayer.vue' +import devicePlayer from './dialog/devicePlayer.vue' import uiHeader from './UiHeader.vue' import moment from "moment"; export default { diff --git a/web_src/src/components/dialog/StreamProxyEdit.vue b/web_src/src/components/dialog/StreamProxyEdit.vue new file mode 100644 index 0000000..a2b3c9e --- /dev/null +++ b/web_src/src/components/dialog/StreamProxyEdit.vue @@ -0,0 +1,186 @@ +<template> + <div id="addStreamProxy" v-loading="isLoging"> + <el-dialog + title="娣诲姞浠g悊" + width="40%" + top="2rem" + :close-on-click-modal="false" + :visible.sync="showDialog" + :destroy-on-close="true" + @close="close()" + > + <div id="shared" style="margin-top: 1rem;margin-right: 100px;"> + <el-form ref="streamProxy" :rules="rules" :model="proxyParam" label-width="140px"> + <el-form-item label="绫诲瀷" prop="type"> + <el-select + v-model="proxyParam.type" + style="width: 100%" + placeholder="璇烽�夋嫨浠g悊绫诲瀷" + > + <el-option label="榛樿" value="default"></el-option> + <el-option label="FFmpeg" value="ffmpeg"></el-option> + </el-select> + </el-form-item> + <el-form-item label="搴旂敤鍚�" prop="app"> + <el-input v-model="proxyParam.app" clearable></el-input> + </el-form-item> + <el-form-item label="娴両D" prop="stream"> + <el-input v-model="proxyParam.stream" clearable></el-input> + </el-form-item> + <el-form-item label="鎷夋祦鍦板潃" prop="url" v-if="proxyParam.type=='default'"> + <el-input v-model="proxyParam.url" clearable></el-input> + </el-form-item> + <el-form-item label="鎷夋祦鍦板潃" prop="src_url" v-if="proxyParam.type=='ffmpeg'"> + <el-input v-model="proxyParam.src_url" clearable></el-input> + </el-form-item> + <el-form-item label="瓒呮椂鏃堕棿" prop="timeout_ms" v-if="proxyParam.type=='ffmpeg'"> + <el-input v-model="proxyParam.timeout_ms" clearable></el-input> + </el-form-item> + <el-form-item label="FFmpeg鍛戒护妯℃澘" prop="ffmpeg_cmd_key" v-if="proxyParam.type=='ffmpeg'"> + <el-input v-model="proxyParam.ffmpeg_cmd_key" clearable></el-input> + </el-form-item> + <el-form-item label="鎷夋祦鏂瑰紡" prop="rtp_type" v-if="proxyParam.type=='default'"> + <el-select + v-model="proxyParam.rtp_type" + style="width: 100%" + placeholder="璇烽�夋嫨鎷夋祦鏂瑰紡" + > + <el-option label="TCP" value="0"></el-option> + <el-option label="UDP" value="1"></el-option> + <el-option label="缁勬挱" value="2"></el-option> + </el-select> + </el-form-item> + <el-form-item label="鍏朵粬閫夐」"> + <div style="float: left;"> + <el-checkbox label="鍚敤" v-model="proxyParam.enable" ></el-checkbox> + <el-checkbox label="杞琀LS" v-model="proxyParam.enable_hls" ></el-checkbox> + <el-checkbox label="MP4褰曞埗" v-model="proxyParam.enable_mp4" ></el-checkbox> + </div> + + </el-form-item> + <el-form-item> + <div style="float: right;"> + <el-button type="primary" @click="onSubmit">{{onSubmit_text}}</el-button> + <el-button @click="close">鍙栨秷</el-button> + </div> + + </el-form-item> + </el-form> + </div> + </el-dialog> + </div> +</template> + +<script> +export default { + name: "streamProxyEdit", + props: {}, + computed: {}, + created() {}, + data() { + // var deviceGBIdRules = async (rule, value, callback) => { + // console.log(value); + // if (value === "") { + // callback(new Error("璇疯緭鍏ヨ澶囧浗鏍囩紪鍙�")); + // } else { + // var exit = await this.deviceGBIdExit(value); + // console.log(exit); + // console.log(exit == "true"); + // console.log(exit === "true"); + // if (exit) { + // callback(new Error("璁惧鍥芥爣缂栧彿宸插瓨鍦�")); + // } else { + // callback(); + // } + // } + // }; + return { + listChangeCallback: null, + showDialog: false, + isLoging: false, + onSubmit_text: "绔嬪嵆鍒涘缓", + proxyParam: { + type: "default", + app: null, + stream: null, + url: "rtmp://58.200.131.2:1935/livetv/hunantv", + src_url: null, + timeout_ms: null, + ffmpeg_cmd_key: null, + rtp_type: null, + enable: true, + enable_hls: true, + enable_mp4: false, + }, + + rules: { + app: [{ required: true, message: "璇疯緭鍏ュ簲鐢ㄥ悕", trigger: "blur" }], + stream: [{ required: true, message: "璇疯緭鍏ユ祦ID", trigger: "blur" }], + url: [{ required: true, message: "璇疯緭鍏ヨ浠g悊鐨勬祦", trigger: "blur" }], + src_url: [{ required: true, message: "璇疯緭鍏ヨ浠g悊鐨勬祦", trigger: "blur" }], + timeout_ms: [{ required: true, message: "璇疯緭鍏Fmpeg鎺ㄦ祦鎴愬姛瓒呮椂鏃堕棿", trigger: "blur" }], + ffmpeg_cmd_key: [{ required: false, message: "璇疯緭鍏Fmpeg鍛戒护鍙傛暟妯℃澘锛堝彲閫夛級", trigger: "blur" }], + }, + }; + }, + methods: { + openDialog: function (proxyParam, callback) { + this.showDialog = true; + this.listChangeCallback = callback; + if (proxyParam != null) { + this.proxyParam = proxyParam; + this.onSubmit_text = "淇濆瓨"; + } else { + this.onSubmit_text = "绔嬪嵆鍒涘缓"; + } + }, + onSubmit: function () { + console.log("onSubmit"); + var that = this; + that.$axios + .post(`/api/proxy/save`, that.proxyParam) + .then(function (res) { + console.log(res); + console.log(res.data == "success"); + if (res.data == "success") { + that.$message({ + showClose: true, + message: "淇濆瓨鎴愬姛", + type: "success", + }); + that.showDialog = false; + if (that.listChangeCallback != null) { + that.listChangeCallback(); + } + } + }) + .catch(function (error) { + console.log(error); + }); + }, + close: function () { + console.log("鍏抽棴娣诲姞瑙嗛骞冲彴"); + this.showDialog = false; + this.$refs.streamProxy.resetFields(); + }, + deviceGBIdExit: async function (deviceGbId) { + var result = false; + var that = this; + await that.$axios + .post(`/api/platforms/exit/${deviceGbId}`) + .then(function (res) { + result = res.data; + }) + .catch(function (error) { + console.log(error); + }); + return result; + }, + checkExpires: function() { + if (this.platform.enable && this.platform.expires == "0") { + this.platform.expires = "300"; + } + } + }, +}; +</script> diff --git a/web_src/src/components/gb28181/chooseChannel.vue b/web_src/src/components/dialog/chooseChannel.vue similarity index 97% rename from web_src/src/components/gb28181/chooseChannel.vue rename to web_src/src/components/dialog/chooseChannel.vue index 810ebd3..219036c 100644 --- a/web_src/src/components/gb28181/chooseChannel.vue +++ b/web_src/src/components/dialog/chooseChannel.vue @@ -21,7 +21,7 @@ </template> <script> -import chooseChannelForGb from './chooseChannelForGb.vue' +import chooseChannelForGb from '../dialog/chooseChannelForGb.vue' export default { name: 'chooseChannel', props: {}, diff --git a/web_src/src/components/gb28181/chooseChannelForGb.vue b/web_src/src/components/dialog/chooseChannelForGb.vue similarity index 100% rename from web_src/src/components/gb28181/chooseChannelForGb.vue rename to web_src/src/components/dialog/chooseChannelForGb.vue diff --git a/web_src/src/components/gb28181/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue similarity index 98% rename from web_src/src/components/gb28181/devicePlayer.vue rename to web_src/src/components/dialog/devicePlayer.vue index 2341831..48d295a 100644 --- a/web_src/src/components/gb28181/devicePlayer.vue +++ b/web_src/src/components/dialog/devicePlayer.vue @@ -26,7 +26,7 @@ </div> </el-tab-pane> <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}--> - <el-tab-pane label="褰曞儚鏌ヨ" name="record"> + <el-tab-pane label="褰曞儚鏌ヨ" name="record" v-if="showRrecord"> <el-date-picker size="mini" v-model="videoHistory.date" type="date" value-format="yyyy-MM-dd" placeholder="鏃ユ湡" @change="queryRecords()"></el-date-picker> <el-table :data="videoHistory.searchHistoryResult" height="150" v-loading="recordsLoading"> <el-table-column label="鍚嶇О" prop="name"></el-table-column> @@ -42,7 +42,7 @@ </el-table> </el-tab-pane> <!--閬ユ帶鐣岄潰--> - <el-tab-pane label="浜戝彴鎺у埗" name="control"> + <el-tab-pane label="浜戝彴鎺у埗" name="control" v-if="showPtz"> <div style="display: flex; justify-content: left;"> <div class="control-wrapper"> <div class="control-btn control-top" @mousedown="ptzCamera(0, 2, 0)" @mouseup="ptzCamera(0, 0, 0)"> @@ -136,7 +136,7 @@ </template> <script> -import player from './player.vue' +import player from '../dialog/player.vue' export default { name: 'devicePlayer', props: {}, @@ -184,7 +184,9 @@ tracks: [], coverPlaying:false, tracksLoading: false, - recordPlay: "" + recordPlay: "", + showPtz: true, + showRrecord: true, }; }, methods: { @@ -230,6 +232,11 @@ this.videoHistory.date = param.date; this.queryRecords() break; + case "streamPlay": + this.showRrecord = false, + this.showPtz = false, + this.play(param.streamInfo, param.hasAudio) + break; case "control": break; } diff --git a/web_src/src/components/platformEdit.vue b/web_src/src/components/dialog/platformEdit.vue similarity index 100% rename from web_src/src/components/platformEdit.vue rename to web_src/src/components/dialog/platformEdit.vue diff --git a/web_src/src/components/gb28181/player.vue b/web_src/src/components/dialog/player.vue similarity index 100% rename from web_src/src/components/gb28181/player.vue rename to web_src/src/components/dialog/player.vue diff --git a/web_src/src/main.js b/web_src/src/main.js index 197fa17..ed1f36c 100644 --- a/web_src/src/main.js +++ b/web_src/src/main.js @@ -11,6 +11,8 @@ import VueClipboard from 'vue-clipboard2'; import { Notification } from 'element-ui'; import Fingerprint2 from 'fingerprintjs2'; +import VueClipboards from 'vue-clipboards'; + // 鐢熸垚鍞竴ID Fingerprint2.get(function(components) { @@ -32,6 +34,7 @@ Vue.use(VueClipboard); Vue.use(ElementUI); Vue.use(VueCookies); +Vue.use(VueClipboards); Vue.prototype.$axios = axios; Vue.prototype.$notify = Notification; diff --git a/web_src/src/router/index.js b/web_src/src/router/index.js index fc55dd5..4735e62 100644 --- a/web_src/src/router/index.js +++ b/web_src/src/router/index.js @@ -5,6 +5,7 @@ import deviceList from '../components/DeviceList.vue' import channelList from '../components/channelList.vue' import pushVideoList from '../components/PushVideoList.vue' +import streamProxyList from '../components/StreamProxyList.vue' import devicePosition from '../components/devicePosition.vue' import login from '../components/Login.vue' import parentPlatformList from '../components/ParentPlatformList.vue' @@ -33,6 +34,10 @@ component: pushVideoList, }, { + path: '/streamProxyList', + component: streamProxyList, + }, + { path: '/login', name: '鐧诲綍', component: login, -- Gitblit v1.8.0