From 56859d09df8d4226882d43934acf32d60a3b51d7 Mon Sep 17 00:00:00 2001 From: panlinlin <648540858@qq.com> Date: Tue, 30 Mar 2021 18:46:34 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8E=A8=E6=B5=81=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E5=92=8C=E6=8B=89=E6=B5=81=E4=BB=A3=E7=90=86=EF=BC=8C?= =?UTF-8?q?=E4=B8=8B=E4=B8=80=E6=AD=A5=E4=B8=8E=E5=9B=BD=E6=A0=87=E5=85=B3?= =?UTF-8?q?=E8=81=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/conf/MediaServerConfig.java | 10 + .../vmp/media/zlm/ZLMHttpHookListener.java | 49 ++- .../vmp/media/zlm/ZLMHttpHookSubscribe.java | 17 + .../vmp/media/zlm/ZLMMediaListManager.java | 1 + .../iot/vmp/media/zlm/ZLMRESTfulUtils.java | 21 ++ .../iot/vmp/media/zlm/ZLMRunner.java | 55 +++- .../iot/vmp/media/zlm/dto/StreamProxyDto.java | 112 +++++++ .../iot/vmp/storager/IRedisCatchStorage.java | 3 +- .../vmp/storager/IVideoManagerStorager.java | 46 +++ .../vmp/storager/dao/StreamProxyMapper.java | 46 +++ .../storager/impl/RedisCatchStorageImpl.java | 10 +- .../impl/VideoManagerStoragerImpl.java | 76 ++++- .../vmp/vmanager/media/MediaController.java | 52 +++ .../iot/vmp/vmanager/play/PlayController.java | 28 +- .../vmp/vmanager/service/IMediaService.java | 25 ++ .../vmanager/service/IStreamProxyService.java | 60 ++++ .../service/impl/MediaServiceImpl.java | 52 +++ .../service/impl/PlayServiceImpl.java | 39 ++- .../service/impl/StreamProxyServiceImpl.java | 123 ++++++++ .../streamProxy/StreamProxyController.java | 73 +++++ .../iot/vmp/web/ApiMediaController.java | 45 --- src/main/resources/wvp.sqlite | Bin 49152 -> 73728 bytes web_src/package-lock.json | 20 ++ web_src/package.json | 1 + web_src/src/components/ParentPlatformList.vue | 4 +- web_src/src/components/PushVideoList.vue | 157 ++++----- web_src/src/components/StreamProxyList.vue | 297 ++++++++++++++++++ web_src/src/components/UiHeader.vue | 1 + web_src/src/components/channelList.vue | 2 +- .../src/components/dialog/StreamProxyEdit.vue | 186 +++++++++++ .../{gb28181 => dialog}/chooseChannel.vue | 2 +- .../chooseChannelForGb.vue | 0 .../{gb28181 => dialog}/devicePlayer.vue | 15 +- .../components/{ => dialog}/platformEdit.vue | 0 .../components/{gb28181 => dialog}/player.vue | 0 web_src/src/main.js | 3 + web_src/src/router/index.js | 5 + 37 files changed, 1418 insertions(+), 218 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyDto.java create mode 100644 src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java create mode 100644 src/main/java/com/genersoft/iot/vmp/vmanager/media/MediaController.java create mode 100644 src/main/java/com/genersoft/iot/vmp/vmanager/service/IMediaService.java create mode 100644 src/main/java/com/genersoft/iot/vmp/vmanager/service/IStreamProxyService.java create mode 100644 src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/MediaServiceImpl.java create mode 100644 src/main/java/com/genersoft/iot/vmp/vmanager/service/impl/StreamProxyServiceImpl.java create mode 100644 src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java delete mode 100644 src/main/java/com/genersoft/iot/vmp/web/ApiMediaController.java create mode 100644 web_src/src/components/StreamProxyList.vue create mode 100644 web_src/src/components/dialog/StreamProxyEdit.vue rename web_src/src/components/{gb28181 => dialog}/chooseChannel.vue (97%) rename web_src/src/components/{gb28181 => dialog}/chooseChannelForGb.vue (100%) rename web_src/src/components/{gb28181 => dialog}/devicePlayer.vue (98%) rename web_src/src/components/{ => dialog}/platformEdit.vue (100%) rename web_src/src/components/{gb28181 => dialog}/player.vue (100%) 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 76390e43..eba9a5e1 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 @@ public class MediaServerConfig { private String wanIp; + private long updateTime; + @JSONField(name = "hls.fileBufSize") private String hlsFileBufSize; @@ -728,4 +730,12 @@ public class MediaServerConfig { 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 51c6e1bd..b2c15978 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 @@ public class ZLMHttpHookListener { } 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(ret.toString(),HttpStatus.OK); + }else { + JSONObject ret = new JSONObject(); + ret.put("code", 0); + ret.put("close", false); + return new ResponseEntity(ret.toString(),HttpStatus.OK); } - return new ResponseEntity(ret.toString(),HttpStatus.OK); + } /** @@ -350,10 +360,21 @@ public class ZLMHttpHookListener { // String data = json.getString("data"); // List mediaServerConfigs = JSON.parseArray(JSON.toJSONString(json), MediaServerConfig.class); // MediaServerConfig mediaServerConfig = mediaServerConfigs.get(0); + + List 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); + + // 重新发起代理 + 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 995f9166..129f8a38 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 @@ package com.genersoft.iot.vmp.media.zlm; 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 @@ public class ZLMHttpHookSubscribe { } return event; } + + public List getSubscribes(HookType type) { + ZLMHttpHookSubscribe.Event event= null; + Map eventMap = allSubscribes.get(type); + if (eventMap == null) { + return null; + } + List 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 b17151af..5ffa4670 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 class ZLMMediaListManager { 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 ad17feea..21752a03 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 class ZLMRESTfulUtils { public JSONObject stopSendRtp(Map param) { return sendPost("stopSendRtp",param); } + + public JSONObject addStreamProxy(String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) { + Map 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 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 e65fae03..15fa9573 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.JSON; 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.stereotype.Component; import org.springframework.util.StringUtils; import java.util.HashMap; +import java.util.List; import java.util.Map; @Component @@ -24,8 +28,8 @@ public class ZLMRunner implements CommandLineRunner { 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 @@ public class ZLMRunner implements CommandLineRunner { @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 @@ public class ZLMRunner implements CommandLineRunner { 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 @@ public class ZLMRunner implements CommandLineRunner { } } + /** + * zlm 连接成功或者zlm重启后 + */ + 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 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 00000000..8f036028 --- /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 2866611f..ca4ebaef 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 @@ public interface IRedisCatchStorage { * 获取当前媒体流列表 * @return List */ - List 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 10360b01..76568986 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 java.util.List; 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 @@ public interface IVideoManagerStorager { * @param deviceId */ public int clearMobilePositionsByDeviceId(String deviceId); + + /** + * 新增代理流 + * @param streamProxyDto + * @return + */ + public int addStreamProxy(StreamProxyDto streamProxyDto); + + /** + * 更新代理流 + * @param streamProxyDto + * @return + */ + public int updateStreamProxy(StreamProxyDto streamProxyDto); + + /** + * 移除代理流 + * @param app + * @param stream + * @return + */ + public int deleteStreamProxy(String app, String stream); + + /** + * 按照是否启用获取代理流 + * @param enable + * @return + */ + public List getStreamProxyListForEnable(boolean enable); + + /** + * 按照是app和stream获取代理流 + * @param app + * @param stream + * @return + */ + public StreamProxyDto queryStreamProxy(String app, String stream); + + /** + * 获取代理流 + * @param page + * @param count + * @return + */ + PageInfo 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 00000000..414125b0 --- /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 selectAll(); + + @Select("SELECT * FROM stream_proxy WHERE enable=${enable}") + List 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 98710833..7b7f5993 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 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { */ @Override public boolean updateMediaInfo(MediaServerConfig mediaServerConfig) { + mediaServerConfig.setUpdateTime(System.currentTimeMillis()); return redis.set(VideoManagerConstants.MEDIA_SERVER_PREFIX,mediaServerConfig); } @@ -280,9 +282,13 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { * @return List */ @Override - public List getMediaList(int start, int end) { + public JSONObject getMediaList(int start, int end) { String key = VideoManagerConstants.MEDIA_STREAM_PREFIX; Set 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 ac2ed5b0..071bf68f 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 java.util.*; 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; @@ -49,6 +46,9 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @Autowired private PatformChannelMapper patformChannelMapper; + @Autowired + private StreamProxyMapper streamProxyMapper; + @@ -233,7 +233,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { /** * 添加Mobile Position设备移动位置 - * @param MobilePosition + * @param mobilePosition */ @Override public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) { @@ -388,4 +388,68 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId); } + /** + * 新增代理流 + * @param streamProxyDto + * @return + */ + @Override + public int addStreamProxy(StreamProxyDto streamProxyDto) { + return streamProxyMapper.add(streamProxyDto); + } + + /** + * 更新代理流 + * @param streamProxyDto + * @return + */ + @Override + public int updateStreamProxy(StreamProxyDto streamProxyDto) { + return streamProxyMapper.update(streamProxyDto); + } + + /** + * 移除代理流 + * @param id + * @return + */ + @Override + public int deleteStreamProxy(String app, String stream) { + return streamProxyMapper.del(app, stream); + } + + /** + * 根据是否启用获取代理流列表 + * @param enable + * @return + */ + @Override + public List getStreamProxyListForEnable(boolean enable) { + return streamProxyMapper.selectForEnable(enable); + } + + /** + * 分页查询代理流列表 + * @param page + * @param count + * @return + */ + @Override + public PageInfo queryStreamProxyList(Integer page, Integer count) { + PageHelper.startPage(page, count); + List all = streamProxyMapper.selectAll(); + return new PageInfo<>(all); + } + + + /** + * 按照是app和stream获取代理流 + * @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 00000000..115e8408 --- /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 0c773e63..67045b44 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.gb28181.transmit.callback.RequestMessage; 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; @@ -55,6 +56,9 @@ public class PlayController { @Autowired private IPlayService playService; + @Autowired + private IMediaService mediaService; + @GetMapping("/play/{deviceId}/{channelId}") public DeferredResult> play(@PathVariable String deviceId, @PathVariable String channelId) { @@ -159,18 +163,20 @@ public class PlayController { 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 00000000..757a7acb --- /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 { + + /** + * 根据应用名和流ID获取播放地址, 通过zlm接口检查是否存在 + * @param app + * @param stream + * @return + */ + StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream); + + /** + * 根据应用名和流ID获取播放地址, 只是地址拼接 + * @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 00000000..4a93cd2a --- /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 { + + /** + * 保存视频代理 + * @param param + */ + void save(StreamProxyDto param); + + /** + * 添加视频代理到zlm + * @param param + * @return + */ + JSONObject addStreamProxyToZlm(StreamProxyDto param); + + /** + * 从zlm移除视频代理 + * @param param + * @return + */ + JSONObject removeStreamProxyFromZlm(StreamProxyDto param); + + /** + * 分页查询 + * @param page + * @param count + * @return + */ + PageInfo getAll(Integer page, Integer count); + + /** + * 删除视频代理 + * @param app + * @param stream + */ + void del(String app, String stream); + + /** + * 启用视频代理 + * @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 00000000..afd6cc96 --- /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 376040a3..edd8710c 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.media.zlm.ZLMRESTfulUtils; 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; @@ -46,6 +47,9 @@ public class PlayServiceImpl implements IPlayService { @Autowired private ZLMRESTfulUtils zlmresTfulUtils; + @Autowired + private IMediaService mediaService; + @Override public PlayResult play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) { @@ -148,26 +152,27 @@ public class PlayServiceImpl implements IPlayService { 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(); - - 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)); +// 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)); 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 00000000..06559800 --- /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; + +/** + * 视频代理业务 + */ +@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 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 00000000..09d4174c --- /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.*; + +/** + * 拉流代理接口 + */ +@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 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("添加代理: " + JSONObject.toJSONString(param)); + streamProxyService.save(param); + return "success"; + } + + @RequestMapping(value = "/del") + @ResponseBody + public Object del(String app, String stream){ + logger.info("移除代理: " + app + "/" + stream); + streamProxyService.del(app, stream); + return "success"; + } + + @RequestMapping(value = "/start") + @ResponseBody + public Object start(String app, String stream){ + logger.info("启用代理: " + app + "/" + stream); + boolean result = streamProxyService.start(app, stream); + return "success"; + } + + @RequestMapping(value = "/stop") + @ResponseBody + public Object stop(String app, String stream){ + logger.info("停用代理: " + 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 84910c5c..00000000 --- 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的API:系统接口 - */ -@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 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 d50f18c705ab4736968ab04510f22ce128257293..9147e22da5c6845d1bbc7d05cc5420d723384039 100644 GIT binary patch delta 621 zcmZo@U~V|TGC^AKDgy(95D*IjF$)6&quWFsWBscPdiFPYfg-#t{S5r;_+t4Cxc6|^ zb5(K~a)fh;v(>Qav7BV-XE9_kWd6XsZsWwsj4UixjJ*>ly0WmCF}6*d=)=NN&RD*2 zVi_ajjENJY*v%V5*u=e6C!gn$$S5u;N=?j-FDS~dsEjv6<_R<O39QVnzK%hW3f``f8cIN)Dd|AHuB6E|xsb&L(az36zkZyoZ-#a|CA~<7778;LVHz z916_u`EP6%R5;Jis4>w|j8Sm&XM5g;%?b(+_`$@)1rCc81QrDdOblS>Wrn6CK2W*= KYI+Y-BMSggGPXtl delta 239 zcmZoTz|zpbJV9FU0s{jB4-mt^&xtz5$`=^)>~HdNtz_V4_|2=z)xF_N!wT zH#TN$b1q3t%1JFqEK1EQi7&`WEJ@2R%8k#@NdXCMu3?+aI9ZR)kCQioffMYU$@Sc} zlh^SFGaq5FpE%KoldVyb4I*K{r^^Clt(!P;)nsuFhs}muevF$0I2D-R@?YC5sBo5_ TQEQ^37^Cp!kMjHiivkJ&gq%XB diff --git a/web_src/package-lock.json b/web_src/package-lock.json index e4ed934c..9e734e55 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 4a9f7660..b7a947c0 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 298504ba..32c999d5 100644 --- a/web_src/src/components/ParentPlatformList.vue +++ b/web_src/src/components/ParentPlatformList.vue @@ -68,9 +68,9 @@ + + diff --git a/web_src/src/components/UiHeader.vue b/web_src/src/components/UiHeader.vue index fa1c4424..ae0780be 100644 --- a/web_src/src/components/UiHeader.vue +++ b/web_src/src/components/UiHeader.vue @@ -4,6 +4,7 @@ 控制台 设备列表 推流列表 + 拉流代理 国标级联 退出 diff --git a/web_src/src/components/channelList.vue b/web_src/src/components/channelList.vue index 6d893ce4..b06ce258 100644 --- a/web_src/src/components/channelList.vue +++ b/web_src/src/components/channelList.vue @@ -75,7 +75,7 @@ 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 810ebd38..219036c5 100644 --- a/web_src/src/components/gb28181/chooseChannel.vue +++ b/web_src/src/components/dialog/chooseChannel.vue @@ -21,7 +21,7 @@