Commit edb033ccd7df53e2444f38c9657946ce15856153

Authored by panlinlin
1 parent 9a4b0de1

添加获取直播流的api

src/main/java/com/genersoft/iot/vmp/common/RealVideo.java 0 → 100644
  1 +package com.genersoft.iot.vmp.common;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
  5 +import org.jetbrains.annotations.NotNull;
  6 +
  7 +import java.util.List;
  8 +
  9 +
  10 +public class RealVideo implements Comparable<RealVideo>{
  11 +
  12 + /**
  13 + * 应用名
  14 + */
  15 + private String app;
  16 +
  17 + /**
  18 + * 流id
  19 + */
  20 + private String stream;
  21 +
  22 + /**
  23 + * 观看总人数,包括hls/rtsp/rtmp/http-flv/ws-flv
  24 + */
  25 + private String totalReaderCount;
  26 +
  27 + /**
  28 + * 协议 包括hls/rtsp/rtmp/http-flv/ws-flv
  29 + */
  30 + private List<MediaSchema> schemas;
  31 +
  32 + /**
  33 + * 产生源类型,
  34 + * unknown = 0,
  35 + * rtmp_push=1,
  36 + * rtsp_push=2,
  37 + * rtp_push=3,
  38 + * pull=4,
  39 + * ffmpeg_pull=5,
  40 + * mp4_vod=6,
  41 + * device_chn=7
  42 + */
  43 + private int originType;
  44 +
  45 + /**
  46 + * 客户端和服务器网络信息,可能为null类型
  47 + */
  48 + private MediaItem.OriginSock originSock;
  49 +
  50 + /**
  51 + * 产生源类型的字符串描述
  52 + */
  53 + private String originTypeStr;
  54 +
  55 + /**
  56 + * 产生源的url
  57 + */
  58 + private String originUrl;
  59 +
  60 + /**
  61 + * GMT unix系统时间戳,单位秒
  62 + */
  63 + private Long createStamp;
  64 +
  65 + /**
  66 + * 存活时间,单位秒
  67 + */
  68 + private Long aliveSecond;
  69 +
  70 + /**
  71 + * 音视频轨道
  72 + */
  73 + private List<MediaItem.MediaTrack> tracks;
  74 +
  75 + /**
  76 + * 音视频轨道
  77 + */
  78 + private String vhost;
  79 +
  80 + public String getVhost() {
  81 + return vhost;
  82 + }
  83 +
  84 + public void setVhost(String vhost) {
  85 + this.vhost = vhost;
  86 + }
  87 +
  88 + @Override
  89 + public int compareTo(@NotNull RealVideo realVideo) {
  90 + return new Long(this.createStamp - realVideo.getCreateStamp().intValue()).intValue();
  91 + }
  92 +
  93 + public static class MediaSchema {
  94 + private String schema;
  95 + private Long bytesSpeed;
  96 +
  97 + public String getSchema() {
  98 + return schema;
  99 + }
  100 +
  101 + public void setSchema(String schema) {
  102 + this.schema = schema;
  103 + }
  104 +
  105 + public Long getBytesSpeed() {
  106 + return bytesSpeed;
  107 + }
  108 +
  109 + public void setBytesSpeed(Long bytesSpeed) {
  110 + this.bytesSpeed = bytesSpeed;
  111 + }
  112 + }
  113 +
  114 +
  115 + public String getApp() {
  116 + return app;
  117 + }
  118 +
  119 + public void setApp(String app) {
  120 + this.app = app;
  121 + }
  122 +
  123 + public String getStream() {
  124 + return stream;
  125 + }
  126 +
  127 + public void setStream(String stream) {
  128 + this.stream = stream;
  129 + }
  130 +
  131 + public String getTotalReaderCount() {
  132 + return totalReaderCount;
  133 + }
  134 +
  135 + public void setTotalReaderCount(String totalReaderCount) {
  136 + this.totalReaderCount = totalReaderCount;
  137 + }
  138 +
  139 + public List<MediaSchema> getSchemas() {
  140 + return schemas;
  141 + }
  142 +
  143 + public void setSchemas(List<MediaSchema> schemas) {
  144 + this.schemas = schemas;
  145 + }
  146 +
  147 + public int getOriginType() {
  148 + return originType;
  149 + }
  150 +
  151 + public void setOriginType(int originType) {
  152 + this.originType = originType;
  153 + }
  154 +
  155 + public MediaItem.OriginSock getOriginSock() {
  156 + return originSock;
  157 + }
  158 +
  159 + public void setOriginSock(MediaItem.OriginSock originSock) {
  160 + this.originSock = originSock;
  161 + }
  162 +
  163 +
  164 + public String getOriginTypeStr() {
  165 + return originTypeStr;
  166 + }
  167 +
  168 + public void setOriginTypeStr(String originTypeStr) {
  169 + this.originTypeStr = originTypeStr;
  170 + }
  171 +
  172 + public String getOriginUrl() {
  173 + return originUrl;
  174 + }
  175 +
  176 + public void setOriginUrl(String originUrl) {
  177 + this.originUrl = originUrl;
  178 + }
  179 +
  180 + public Long getCreateStamp() {
  181 + return createStamp;
  182 + }
  183 +
  184 + public void setCreateStamp(Long createStamp) {
  185 + this.createStamp = createStamp;
  186 + }
  187 +
  188 + public Long getAliveSecond() {
  189 + return aliveSecond;
  190 + }
  191 +
  192 + public void setAliveSecond(Long aliveSecond) {
  193 + this.aliveSecond = aliveSecond;
  194 + }
  195 +
  196 + public List<MediaItem.MediaTrack> getTracks() {
  197 + return tracks;
  198 + }
  199 +
  200 + public void setTracks(List<MediaItem.MediaTrack> tracks) {
  201 + this.tracks = tracks;
  202 + }
  203 +
  204 +
  205 +}
  206 +
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -10,6 +10,8 @@ public class VideoManagerConstants { @@ -10,6 +10,8 @@ public class VideoManagerConstants {
10 10
11 public static final String MEDIA_SERVER_PREFIX = "VMP_media_server"; 11 public static final String MEDIA_SERVER_PREFIX = "VMP_media_server";
12 12
  13 + public static final String MEDIA_STREAM_PREFIX = "VMP_media_stream";
  14 +
13 public static final String DEVICE_PREFIX = "VMP_device_"; 15 public static final String DEVICE_PREFIX = "VMP_device_";
14 16
15 public static final String CACHEKEY_PREFIX = "VMP_channel_"; 17 public static final String CACHEKEY_PREFIX = "VMP_channel_";
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -51,8 +51,8 @@ public class ZLMHttpHookListener { @@ -51,8 +51,8 @@ public class ZLMHttpHookListener {
51 @Autowired 51 @Autowired
52 private IRedisCatchStorage redisCatchStorage; 52 private IRedisCatchStorage redisCatchStorage;
53 53
54 - // @Autowired  
55 - // private ZLMRESTfulUtils zlmresTfulUtils; 54 + @Autowired
  55 + private ZLMMediaListManager zlmMediaListManager;
56 56
57 @Autowired 57 @Autowired
58 private ZLMHttpHookSubscribe subscribe; 58 private ZLMHttpHookSubscribe subscribe;
@@ -237,6 +237,7 @@ public class ZLMHttpHookListener { @@ -237,6 +237,7 @@ public class ZLMHttpHookListener {
237 // 流消失移除redis play 237 // 流消失移除redis play
238 String app = json.getString("app"); 238 String app = json.getString("app");
239 String streamId = json.getString("stream"); 239 String streamId = json.getString("stream");
  240 + String schema = json.getString("schema");
240 boolean regist = json.getBoolean("regist"); 241 boolean regist = json.getBoolean("regist");
241 StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId); 242 StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
242 if ("rtp".equals(app) && !regist ) { 243 if ("rtp".equals(app) && !regist ) {
@@ -247,6 +248,10 @@ public class ZLMHttpHookListener { @@ -247,6 +248,10 @@ public class ZLMHttpHookListener {
247 streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId); 248 streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId);
248 redisCatchStorage.stopPlayback(streamInfo); 249 redisCatchStorage.stopPlayback(streamInfo);
249 } 250 }
  251 + }else {
  252 + if (!"rtp".equals(app) && "rtsp".equals(schema)){
  253 + zlmMediaListManager.updateMediaList();
  254 + }
250 } 255 }
251 JSONObject ret = new JSONObject(); 256 JSONObject ret = new JSONObject();
252 ret.put("code", 0); 257 ret.put("code", 0);
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java 0 → 100644
  1 +package com.genersoft.iot.vmp.media.zlm;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.JSONArray;
  5 +import com.alibaba.fastjson.JSONObject;
  6 +import com.alibaba.fastjson.TypeReference;
  7 +import com.genersoft.iot.vmp.common.RealVideo;
  8 +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
  9 +import com.genersoft.iot.vmp.gb28181.session.SsrcUtil;
  10 +import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
  11 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  12 +import com.genersoft.iot.vmp.storager.impl.RedisCatchStorageImpl;
  13 +import org.slf4j.Logger;
  14 +import org.slf4j.LoggerFactory;
  15 +import org.springframework.beans.factory.annotation.Autowired;
  16 +import org.springframework.beans.factory.annotation.Value;
  17 +import org.springframework.stereotype.Component;
  18 +
  19 +import java.util.*;
  20 +
  21 +@Component
  22 +public class ZLMMediaListManager {
  23 +
  24 + private Logger logger = LoggerFactory.getLogger("ZLMMediaListManager");
  25 +
  26 + @Autowired
  27 + private ZLMRESTfulUtils zlmresTfulUtils;
  28 +
  29 + @Autowired
  30 + private IRedisCatchStorage redisCatchStorage;
  31 +
  32 +
  33 + public void updateMediaList() {
  34 + JSONObject mediaList = zlmresTfulUtils.getMediaList();
  35 + String dataStr = mediaList.getString("data");
  36 +
  37 + Integer code = mediaList.getInteger("code");
  38 + Map<String, RealVideo> result = new HashMap<>();
  39 + if (code == 0 ) {
  40 + if (dataStr != null) {
  41 + List<MediaItem> mediaItems = JSON.parseObject(dataStr, new TypeReference<List<MediaItem>>() {});
  42 + for (MediaItem item : mediaItems) {
  43 + if ("rtp".equals(item.getApp())) {
  44 + continue;
  45 + }
  46 + String key = item.getApp() + "_" + item.getStream();
  47 + RealVideo realVideo = result.get(key);
  48 + if (realVideo == null) {
  49 + realVideo = new RealVideo();
  50 + realVideo.setApp(item.getApp());
  51 + realVideo.setStream(item.getStream());
  52 + realVideo.setAliveSecond(item.getAliveSecond());
  53 + realVideo.setCreateStamp(item.getCreateStamp());
  54 + realVideo.setOriginSock(item.getOriginSock());
  55 + realVideo.setTotalReaderCount(item.getTotalReaderCount());
  56 + realVideo.setOriginType(item.getOriginType());
  57 + realVideo.setOriginTypeStr(item.getOriginTypeStr());
  58 + realVideo.setOriginUrl(item.getOriginUrl());
  59 + realVideo.setCreateStamp(item.getCreateStamp());
  60 + realVideo.setAliveSecond(item.getAliveSecond());
  61 +
  62 + ArrayList<RealVideo.MediaSchema> mediaSchemas = new ArrayList<>();
  63 + realVideo.setSchemas(mediaSchemas);
  64 + realVideo.setTracks(item.getTracks());
  65 + realVideo.setVhost(item.getVhost());
  66 + result.put(key, realVideo);
  67 + }
  68 +
  69 + RealVideo.MediaSchema mediaSchema = new RealVideo.MediaSchema();
  70 + mediaSchema.setSchema(item.getSchema());
  71 + mediaSchema.setBytesSpeed(item.getBytesSpeed());
  72 + realVideo.getSchemas().add(mediaSchema);
  73 + }
  74 +
  75 + }
  76 + }else {
  77 + logger.warn("更新视频流失败,错误code: " + code);
  78 + }
  79 +
  80 + List<RealVideo> realVideos = new ArrayList<>(result.values());
  81 + Collections.sort(realVideos);
  82 + redisCatchStorage.updateMediaList(realVideos);
  83 + }
  84 +
  85 +
  86 +
  87 +}
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
@@ -73,6 +73,10 @@ public class ZLMRESTfulUtils { @@ -73,6 +73,10 @@ public class ZLMRESTfulUtils {
73 return sendPost("getMediaList",param); 73 return sendPost("getMediaList",param);
74 } 74 }
75 75
  76 + public JSONObject getMediaList(){
  77 + return sendPost("getMediaList",null);
  78 + }
  79 +
76 public JSONObject getMediaInfo(String app, String schema, String stream){ 80 public JSONObject getMediaInfo(String app, String schema, String stream){
77 Map<String, Object> param = new HashMap<>(); 81 Map<String, Object> param = new HashMap<>();
78 param.put("app",app); 82 param.put("app",app);
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
@@ -60,6 +60,9 @@ public class ZLMRunner implements CommandLineRunner { @@ -60,6 +60,9 @@ public class ZLMRunner implements CommandLineRunner {
60 @Autowired 60 @Autowired
61 private ZLMRESTfulUtils zlmresTfulUtils; 61 private ZLMRESTfulUtils zlmresTfulUtils;
62 62
  63 + @Autowired
  64 + private ZLMMediaListManager zlmMediaListManager;
  65 +
63 @Override 66 @Override
64 public void run(String... strings) throws Exception { 67 public void run(String... strings) throws Exception {
65 // 获取zlm信息 68 // 获取zlm信息
@@ -70,6 +73,8 @@ public class ZLMRunner implements CommandLineRunner { @@ -70,6 +73,8 @@ public class ZLMRunner implements CommandLineRunner {
70 if (autoConfig) saveZLMConfig(); 73 if (autoConfig) saveZLMConfig();
71 mediaServerConfig = getMediaServerConfig(); 74 mediaServerConfig = getMediaServerConfig();
72 redisCatchStorage.updateMediaInfo(mediaServerConfig); 75 redisCatchStorage.updateMediaInfo(mediaServerConfig);
  76 + // 更新流列表
  77 + zlmMediaListManager.updateMediaList();
73 } 78 }
74 } 79 }
75 80
@@ -130,4 +135,5 @@ public class ZLMRunner implements CommandLineRunner { @@ -130,4 +135,5 @@ public class ZLMRunner implements CommandLineRunner {
130 logger.info("设置zlm失败: " + responseJSON.getString("msg")); 135 logger.info("设置zlm失败: " + responseJSON.getString("msg"));
131 } 136 }
132 } 137 }
  138 +
133 } 139 }
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java 0 → 100644
  1 +package com.genersoft.iot.vmp.media.zlm.dto;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +
  5 +import java.util.List;
  6 +
  7 +public class MediaItem {
  8 +
  9 + /**
  10 + * 应用名
  11 + */
  12 + private String app;
  13 +
  14 + /**
  15 + * 流id
  16 + */
  17 + private String stream;
  18 +
  19 + /**
  20 + * 观看总人数,包括hls/rtsp/rtmp/http-flv/ws-flv
  21 + */
  22 + private String totalReaderCount;
  23 +
  24 + /**
  25 + * 协议 包括hls/rtsp/rtmp/http-flv/ws-flv
  26 + */
  27 + private String schema;
  28 +
  29 +
  30 + /**
  31 + * 产生源类型,
  32 + * unknown = 0,
  33 + * rtmp_push=1,
  34 + * rtsp_push=2,
  35 + * rtp_push=3,
  36 + * pull=4,
  37 + * ffmpeg_pull=5,
  38 + * mp4_vod=6,
  39 + * device_chn=7
  40 + */
  41 + private int originType;
  42 +
  43 + /**
  44 + * 客户端和服务器网络信息,可能为null类型
  45 + */
  46 + private OriginSock originSock;
  47 +
  48 + /**
  49 + * 产生源类型的字符串描述
  50 + */
  51 + private String originTypeStr;
  52 +
  53 + /**
  54 + * 产生源的url
  55 + */
  56 + private String originUrl;
  57 +
  58 + /**
  59 + * GMT unix系统时间戳,单位秒
  60 + */
  61 + private Long createStamp;
  62 +
  63 + /**
  64 + * 存活时间,单位秒
  65 + */
  66 + private Long aliveSecond;
  67 +
  68 + /**
  69 + * 数据产生速度,单位byte/s
  70 + */
  71 + private Long bytesSpeed;
  72 +
  73 + /**
  74 + * 音视频轨道
  75 + */
  76 + private List<MediaTrack> tracks;
  77 +
  78 + /**
  79 + * 音视频轨道
  80 + */
  81 + private String vhost;
  82 +
  83 +
  84 + public static class MediaTrack {
  85 + /**
  86 + * 音频通道数
  87 + */
  88 + private int channels;
  89 +
  90 + /**
  91 + * H264 = 0, H265 = 1, AAC = 2, G711A = 3, G711U = 4
  92 + */
  93 + private int codecId;
  94 +
  95 + /**
  96 + * 编码类型名称 CodecAAC CodecH264
  97 + */
  98 + private String codecIdName;
  99 +
  100 + /**
  101 + * Video = 0, Audio = 1
  102 + */
  103 + private int codecType;
  104 +
  105 + /**
  106 + * 轨道是否准备就绪
  107 + */
  108 + private boolean ready;
  109 +
  110 + /**
  111 + * 音频采样位数
  112 + */
  113 + private int sampleBit;
  114 +
  115 + /**
  116 + * 音频采样率
  117 + */
  118 + private int sampleRate;
  119 +
  120 + /**
  121 + * 视频fps
  122 + */
  123 + private int fps;
  124 +
  125 + /**
  126 + * 视频高
  127 + */
  128 + private int height;
  129 +
  130 + /**
  131 + * 视频宽
  132 + */
  133 + private int width;
  134 +
  135 + public int getChannels() {
  136 + return channels;
  137 + }
  138 +
  139 + public void setChannels(int channels) {
  140 + this.channels = channels;
  141 + }
  142 +
  143 + public int getCodecId() {
  144 + return codecId;
  145 + }
  146 +
  147 + public void setCodecId(int codecId) {
  148 + this.codecId = codecId;
  149 + }
  150 +
  151 + public String getCodecIdName() {
  152 + return codecIdName;
  153 + }
  154 +
  155 + public void setCodecIdName(String codecIdName) {
  156 + this.codecIdName = codecIdName;
  157 + }
  158 +
  159 + public int getCodecType() {
  160 + return codecType;
  161 + }
  162 +
  163 + public void setCodecType(int codecType) {
  164 + this.codecType = codecType;
  165 + }
  166 +
  167 + public boolean isReady() {
  168 + return ready;
  169 + }
  170 +
  171 + public void setReady(boolean ready) {
  172 + this.ready = ready;
  173 + }
  174 +
  175 + public int getSampleBit() {
  176 + return sampleBit;
  177 + }
  178 +
  179 + public void setSampleBit(int sampleBit) {
  180 + this.sampleBit = sampleBit;
  181 + }
  182 +
  183 + public int getSampleRate() {
  184 + return sampleRate;
  185 + }
  186 +
  187 + public void setSampleRate(int sampleRate) {
  188 + this.sampleRate = sampleRate;
  189 + }
  190 +
  191 + public int getFps() {
  192 + return fps;
  193 + }
  194 +
  195 + public void setFps(int fps) {
  196 + this.fps = fps;
  197 + }
  198 +
  199 + public int getHeight() {
  200 + return height;
  201 + }
  202 +
  203 + public void setHeight(int height) {
  204 + this.height = height;
  205 + }
  206 +
  207 + public int getWidth() {
  208 + return width;
  209 + }
  210 +
  211 + public void setWidth(int width) {
  212 + this.width = width;
  213 + }
  214 + }
  215 +
  216 + public static class OriginSock{
  217 + private String identifier;
  218 + private String local_ip;
  219 + private int local_port;
  220 + private String peer_ip;
  221 + private int peer_port;
  222 +
  223 + public String getIdentifier() {
  224 + return identifier;
  225 + }
  226 +
  227 + public void setIdentifier(String identifier) {
  228 + this.identifier = identifier;
  229 + }
  230 +
  231 + public String getLocal_ip() {
  232 + return local_ip;
  233 + }
  234 +
  235 + public void setLocal_ip(String local_ip) {
  236 + this.local_ip = local_ip;
  237 + }
  238 +
  239 + public int getLocal_port() {
  240 + return local_port;
  241 + }
  242 +
  243 + public void setLocal_port(int local_port) {
  244 + this.local_port = local_port;
  245 + }
  246 +
  247 + public String getPeer_ip() {
  248 + return peer_ip;
  249 + }
  250 +
  251 + public void setPeer_ip(String peer_ip) {
  252 + this.peer_ip = peer_ip;
  253 + }
  254 +
  255 + public int getPeer_port() {
  256 + return peer_port;
  257 + }
  258 +
  259 + public void setPeer_port(int peer_port) {
  260 + this.peer_port = peer_port;
  261 + }
  262 + }
  263 +
  264 + public String getApp() {
  265 + return app;
  266 + }
  267 +
  268 + public void setApp(String app) {
  269 + this.app = app;
  270 + }
  271 +
  272 + public String getStream() {
  273 + return stream;
  274 + }
  275 +
  276 + public void setStream(String stream) {
  277 + this.stream = stream;
  278 + }
  279 +
  280 + public String getTotalReaderCount() {
  281 + return totalReaderCount;
  282 + }
  283 +
  284 + public void setTotalReaderCount(String totalReaderCount) {
  285 + this.totalReaderCount = totalReaderCount;
  286 + }
  287 +
  288 +
  289 + public int getOriginType() {
  290 + return originType;
  291 + }
  292 +
  293 + public void setOriginType(int originType) {
  294 + this.originType = originType;
  295 + }
  296 +
  297 +
  298 + public String getOriginTypeStr() {
  299 + return originTypeStr;
  300 + }
  301 +
  302 + public void setOriginTypeStr(String originTypeStr) {
  303 + this.originTypeStr = originTypeStr;
  304 + }
  305 +
  306 + public String getOriginUrl() {
  307 + return originUrl;
  308 + }
  309 +
  310 + public void setOriginUrl(String originUrl) {
  311 + this.originUrl = originUrl;
  312 + }
  313 +
  314 + public Long getCreateStamp() {
  315 + return createStamp;
  316 + }
  317 +
  318 + public void setCreateStamp(Long createStamp) {
  319 + this.createStamp = createStamp;
  320 + }
  321 +
  322 + public Long getAliveSecond() {
  323 + return aliveSecond;
  324 + }
  325 +
  326 + public void setAliveSecond(Long aliveSecond) {
  327 + this.aliveSecond = aliveSecond;
  328 + }
  329 +
  330 + public List<MediaTrack> getTracks() {
  331 + return tracks;
  332 + }
  333 +
  334 + public void setTracks(List<MediaTrack> tracks) {
  335 + this.tracks = tracks;
  336 + }
  337 +
  338 + public String getSchema() {
  339 + return schema;
  340 + }
  341 +
  342 + public void setSchema(String schema) {
  343 + this.schema = schema;
  344 + }
  345 +
  346 + public void setOriginSock(OriginSock originSock) {
  347 + this.originSock = originSock;
  348 + }
  349 +
  350 + public Long getBytesSpeed() {
  351 + return bytesSpeed;
  352 + }
  353 +
  354 + public void setBytesSpeed(Long bytesSpeed) {
  355 + this.bytesSpeed = bytesSpeed;
  356 + }
  357 +
  358 + public String getVhost() {
  359 + return vhost;
  360 + }
  361 +
  362 + public void setVhost(String vhost) {
  363 + this.vhost = vhost;
  364 + }
  365 +
  366 + public OriginSock getOriginSock() {
  367 + return originSock;
  368 + }
  369 +}
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
1 package com.genersoft.iot.vmp.storager; 1 package com.genersoft.iot.vmp.storager;
2 2
  3 +import com.genersoft.iot.vmp.common.RealVideo;
3 import com.genersoft.iot.vmp.common.StreamInfo; 4 import com.genersoft.iot.vmp.common.StreamInfo;
4 import com.genersoft.iot.vmp.conf.MediaServerConfig; 5 import com.genersoft.iot.vmp.conf.MediaServerConfig;
5 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; 7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
7 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; 8 import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
8 9
  10 +import java.util.List;
9 import java.util.Map; 11 import java.util.Map;
10 12
11 public interface IRedisCatchStorage { 13 public interface IRedisCatchStorage {
@@ -102,4 +104,15 @@ public interface IRedisCatchStorage { @@ -102,4 +104,15 @@ public interface IRedisCatchStorage {
102 */ 104 */
103 boolean isChannelSendingRTP(String channelId); 105 boolean isChannelSendingRTP(String channelId);
104 106
  107 + /**
  108 + * 更新媒体流列表
  109 + * @param mediaList
  110 + */
  111 + void updateMediaList(List<RealVideo> mediaList);
  112 +
  113 + /**
  114 + * 获取当前媒体流列表
  115 + * @return List<RealVideo>
  116 + */
  117 + List<Object> getMediaList(int start, int end);
105 } 118 }
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
1 package com.genersoft.iot.vmp.storager.impl; 1 package com.genersoft.iot.vmp.storager.impl;
2 2
  3 +import com.genersoft.iot.vmp.common.RealVideo;
3 import com.genersoft.iot.vmp.common.StreamInfo; 4 import com.genersoft.iot.vmp.common.StreamInfo;
4 import com.genersoft.iot.vmp.common.VideoManagerConstants; 5 import com.genersoft.iot.vmp.common.VideoManagerConstants;
5 import com.genersoft.iot.vmp.conf.MediaServerConfig; 6 import com.genersoft.iot.vmp.conf.MediaServerConfig;
@@ -10,9 +11,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; @@ -10,9 +11,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil;
10 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.beans.factory.annotation.Autowired;
11 import org.springframework.stereotype.Component; 12 import org.springframework.stereotype.Component;
12 13
13 -import java.util.HashMap;  
14 -import java.util.List;  
15 -import java.util.Map; 14 +import java.util.*;
16 15
17 @Component 16 @Component
18 public class RedisCatchStorageImpl implements IRedisCatchStorage { 17 public class RedisCatchStorageImpl implements IRedisCatchStorage {
@@ -251,4 +250,30 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -251,4 +250,30 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
251 } 250 }
252 } 251 }
253 252
  253 +
  254 + /**
  255 + * 更新媒体流列表
  256 + * @param mediaList
  257 + */
  258 + @Override
  259 + public void updateMediaList(List<RealVideo> mediaList) {
  260 + String key = VideoManagerConstants.MEDIA_STREAM_PREFIX;
  261 + redis.del(key);
  262 + for (int i = 0; i < mediaList.size(); i++) {
  263 + RealVideo realVideo = mediaList.get(i);
  264 + redis.zAdd(key, realVideo, realVideo.getCreateStamp());
  265 + }
  266 + }
  267 +
  268 +
  269 + /**
  270 + * 获取当前媒体流列表
  271 + * @return List<RealVideo>
  272 + */
  273 + @Override
  274 + public List<Object> getMediaList(int start, int end) {
  275 + String key = VideoManagerConstants.MEDIA_STREAM_PREFIX;
  276 + Set<Object> realVideos = redis.ZRange(key, start, end);
  277 + return new ArrayList(realVideos);
  278 + }
254 } 279 }
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
@@ -396,7 +396,7 @@ public class RedisUtil { @@ -396,7 +396,7 @@ public class RedisUtil {
396 * @param value 396 * @param value
397 * @param score 397 * @param score
398 */ 398 */
399 - public void zAdd(String key, String value, double score) { 399 + public void zAdd(Object key, Object value, double score) {
400 redisTemplate.opsForZSet().add(key, value, score); 400 redisTemplate.opsForZSet().add(key, value, score);
401 } 401 }
402 402
@@ -406,7 +406,7 @@ public class RedisUtil { @@ -406,7 +406,7 @@ public class RedisUtil {
406 * @param key 406 * @param key
407 * @param value 407 * @param value
408 */ 408 */
409 - public void zRemove(String key, String value) { 409 + public void zRemove(Object key, Object value) {
410 redisTemplate.opsForZSet().remove(key, value); 410 redisTemplate.opsForZSet().remove(key, value);
411 } 411 }
412 412
@@ -417,7 +417,7 @@ public class RedisUtil { @@ -417,7 +417,7 @@ public class RedisUtil {
417 * @param value 417 * @param value
418 * @param score 418 * @param score
419 */ 419 */
420 - public Double zIncrScore(String key, String value, double score) { 420 + public Double zIncrScore(Object key, Object value, double score) {
421 return redisTemplate.opsForZSet().incrementScore(key, value, score); 421 return redisTemplate.opsForZSet().incrementScore(key, value, score);
422 } 422 }
423 423
@@ -428,7 +428,7 @@ public class RedisUtil { @@ -428,7 +428,7 @@ public class RedisUtil {
428 * @param value 428 * @param value
429 * @return 429 * @return
430 */ 430 */
431 - public Double zScore(String key, String value) { 431 + public Double zScore(Object key, Object value) {
432 return redisTemplate.opsForZSet().score(key, value); 432 return redisTemplate.opsForZSet().score(key, value);
433 } 433 }
434 434
@@ -439,7 +439,7 @@ public class RedisUtil { @@ -439,7 +439,7 @@ public class RedisUtil {
439 * @param value 439 * @param value
440 * @return 440 * @return
441 */ 441 */
442 - public Long zRank(String key, String value) { 442 + public Long zRank(Object key, Object value) {
443 return redisTemplate.opsForZSet().rank(key, value); 443 return redisTemplate.opsForZSet().rank(key, value);
444 } 444 }
445 445
@@ -449,7 +449,7 @@ public class RedisUtil { @@ -449,7 +449,7 @@ public class RedisUtil {
449 * @param key 449 * @param key
450 * @return 450 * @return
451 */ 451 */
452 - public Long zSize(String key) { 452 + public Long zSize(Object key) {
453 return redisTemplate.opsForZSet().zCard(key); 453 return redisTemplate.opsForZSet().zCard(key);
454 } 454 }
455 455
@@ -463,7 +463,7 @@ public class RedisUtil { @@ -463,7 +463,7 @@ public class RedisUtil {
463 * @param end 463 * @param end
464 * @return 464 * @return
465 */ 465 */
466 - public Set<String> ZRange(String key, int start, int end) { 466 + public Set<Object> ZRange(Object key, int start, int end) {
467 return redisTemplate.opsForZSet().range(key, start, end); 467 return redisTemplate.opsForZSet().range(key, start, end);
468 } 468 }
469 /** 469 /**
@@ -474,7 +474,7 @@ public class RedisUtil { @@ -474,7 +474,7 @@ public class RedisUtil {
474 * @param end 474 * @param end
475 * @return 475 * @return
476 */ 476 */
477 - public Set<ZSetOperations.TypedTuple<String>> zRangeWithScore(String key, int start, int end) { 477 + public Set<ZSetOperations.TypedTuple<String>> zRangeWithScore(Object key, int start, int end) {
478 return redisTemplate.opsForZSet().rangeWithScores(key, start, end); 478 return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
479 } 479 }
480 /** 480 /**
@@ -487,7 +487,7 @@ public class RedisUtil { @@ -487,7 +487,7 @@ public class RedisUtil {
487 * @param end 487 * @param end
488 * @return 488 * @return
489 */ 489 */
490 - public Set<String> zRevRange(String key, int start, int end) { 490 + public Set<String> zRevRange(Object key, int start, int end) {
491 return redisTemplate.opsForZSet().reverseRange(key, start, end); 491 return redisTemplate.opsForZSet().reverseRange(key, start, end);
492 } 492 }
493 /** 493 /**
@@ -498,7 +498,7 @@ public class RedisUtil { @@ -498,7 +498,7 @@ public class RedisUtil {
498 * @param max 498 * @param max
499 * @return 499 * @return
500 */ 500 */
501 - public Set<String> zSortRange(String key, int min, int max) { 501 + public Set<String> zSortRange(Object key, int min, int max) {
502 return redisTemplate.opsForZSet().rangeByScore(key, min, max); 502 return redisTemplate.opsForZSet().rangeByScore(key, min, max);
503 } 503 }
504 504
src/main/java/com/genersoft/iot/vmp/web/ApiMediaController.java 0 → 100644
  1 +package com.genersoft.iot.vmp.web;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.genersoft.iot.vmp.common.RealVideo;
  5 +import com.genersoft.iot.vmp.conf.SipConfig;
  6 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  7 +import org.slf4j.Logger;
  8 +import org.slf4j.LoggerFactory;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.stereotype.Controller;
  11 +import org.springframework.web.bind.annotation.CrossOrigin;
  12 +import org.springframework.web.bind.annotation.RequestMapping;
  13 +import org.springframework.web.bind.annotation.RequestParam;
  14 +import org.springframework.web.bind.annotation.ResponseBody;
  15 +
  16 +import java.util.List;
  17 +
  18 +/**
  19 + * 兼容LiveGBS的API:系统接口
  20 + */
  21 +@Controller
  22 +@CrossOrigin
  23 +@RequestMapping(value = "/api/v1/media")
  24 +public class ApiMediaController {
  25 +
  26 + private final static Logger logger = LoggerFactory.getLogger(ApiMediaController.class);
  27 +
  28 + @Autowired
  29 + private IRedisCatchStorage redisCatchStorage;
  30 +
  31 +
  32 + @RequestMapping(value = "/list")
  33 + @ResponseBody
  34 + public JSONObject list( @RequestParam(required = false)Integer start,
  35 + @RequestParam(required = false)Integer limit,
  36 + @RequestParam(required = false)String q,
  37 + @RequestParam(required = false)Boolean online ){
  38 +
  39 + List<Object> mediaList = redisCatchStorage.getMediaList(start - 1, start - 1 + limit);
  40 + JSONObject jsonObject = new JSONObject();
  41 + jsonObject.put("code", 0);
  42 + jsonObject.put("data", mediaList);
  43 + return jsonObject;
  44 + }
  45 +}
web_src/src/components/PushVideoList.vue 0 → 100644
  1 +<template>
  2 + <div id="app">
  3 + <el-container>
  4 + <el-header>
  5 + <uiHeader></uiHeader>
  6 + </el-header>
  7 + <el-main>
  8 + <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
  9 + <span style="font-size: 1rem; font-weight: bold;">推流列表</span>
  10 + <div style="position: absolute; right: 1rem; top: 0.3rem;">
  11 + <el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" @click="getDeviceList()"></el-button>
  12 + </div>
  13 + </div>
  14 + <!-- <devicePlayer ref="devicePlayer"></devicePlayer> -->
  15 + <el-table :data="deviceList" border style="width: 100%" :height="winHeight">
  16 + <el-table-column prop="schema" label="协议" width="180" align="center">
  17 + </el-table-column>
  18 + <el-table-column prop="streamUrl" label="流地址" width="240" align="center">
  19 + </el-table-column>
  20 + <el-table-column prop="online" label="在线人数" width="240" align="center">
  21 + </el-table-column>
  22 + <el-table-column prop="startTime" label="开始时间" align="center">
  23 + </el-table-column>
  24 +
  25 +
  26 + <el-table-column label="操作" width="360" align="center" fixed="right">
  27 + <template slot-scope="scope">
  28 + <el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button>
  29 + <el-button-group>
  30 + <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button>
  31 + <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopDevicePush(scope.row)">停止</el-button>
  32 + </el-button-group>
  33 + </template>
  34 + </el-table-column>
  35 + </el-table>
  36 + <el-pagination
  37 + style="float: right"
  38 + @size-change="handleSizeChange"
  39 + @current-change="currentChange"
  40 + :current-page="currentPage"
  41 + :page-size="count"
  42 + :page-sizes="[15, 25, 35, 50]"
  43 + layout="total, sizes, prev, pager, next"
  44 + :total="total">
  45 + </el-pagination>
  46 +
  47 + </el-main>
  48 + </el-container>
  49 + </div>
  50 +</template>
  51 +
  52 +<script>
  53 + import uiHeader from './UiHeader.vue'
  54 + export default {
  55 + name: 'app',
  56 + components: {
  57 + uiHeader
  58 + },
  59 + data() {
  60 + return {
  61 + deviceList: [], //设备列表
  62 + currentDevice: {}, //当前操作设备对象
  63 +
  64 + videoComponentList: [],
  65 + updateLooper: 0, //数据刷新轮训标志
  66 + currentDeviceChannelsLenth:0,
  67 + winHeight: window.innerHeight - 200,
  68 + currentPage:1,
  69 + count:15,
  70 + total:0,
  71 + getDeviceListLoading: false
  72 + };
  73 + },
  74 + computed: {
  75 + getcurrentDeviceChannels: function() {
  76 + let data = this.currentDevice['channelMap'];
  77 + let channels = null;
  78 + if (data) {
  79 + channels = Object.keys(data).map(key => {
  80 + return data[key];
  81 + });
  82 + this.currentDeviceChannelsLenth = channels.length;
  83 + }
  84 +
  85 + console.log("数据:" + JSON.stringify(channels));
  86 + return channels;
  87 + }
  88 + },
  89 + mounted() {
  90 + this.initData();
  91 + this.updateLooper = setInterval(this.initData, 10000);
  92 + },
  93 + destroyed() {
  94 + this.$destroy('videojs');
  95 + clearTimeout(this.updateLooper);
  96 + },
  97 + methods: {
  98 + initData: function() {
  99 + this.getDeviceList();
  100 + },
  101 + currentChange: function(val){
  102 + this.currentPage = val;
  103 + this.getDeviceList();
  104 + },
  105 + handleSizeChange: function(val){
  106 + this.count = val;
  107 + this.getDeviceList();
  108 + },
  109 + getDeviceList: function() {
  110 + let that = this;
  111 + this.getDeviceListLoading = true;
  112 + this.$axios.get(`/api/devices`,{
  113 + params: {
  114 + page: that.currentPage,
  115 + count: that.count
  116 + }
  117 + } )
  118 + .then(function (res) {
  119 + console.log(res);
  120 + console.log(res.data.list);
  121 + that.total = res.data.total;
  122 + that.deviceList = res.data.list;
  123 + that.getDeviceListLoading = false;
  124 + })
  125 + .catch(function (error) {
  126 + console.log(error);
  127 + that.getDeviceListLoading = false;
  128 + });
  129 +
  130 + },
  131 + showChannelList: function(row) {
  132 + console.log(JSON.stringify(row))
  133 + this.$router.push(`/channelList/${row.deviceId}/0/15/1`);
  134 + },
  135 + showDevicePosition: function(row) {
  136 + console.log(JSON.stringify(row))
  137 + this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`);
  138 + },
  139 +
  140 + //gb28181平台对接
  141 + //刷新设备信息
  142 + refDevice: function(itemData) {
  143 + ///api/devices/{deviceId}/sync
  144 + console.log("刷新对应设备:" + itemData.deviceId);
  145 + var that = this;
  146 + that.$refs[itemData.deviceId + 'refbtn' ].loading = true;
  147 + this.$axios({
  148 + method: 'post',
  149 + url: '/api/devices/' + itemData.deviceId + '/sync'
  150 + }).then(function(res) {
  151 + console.log("刷新设备结果:"+JSON.stringify(res));
  152 + if (!res.data.deviceId) {
  153 + that.$message({
  154 + showClose: true,
  155 + message: res.data,
  156 + type: 'error'
  157 + });
  158 + }else{
  159 + that.$message({
  160 + showClose: true,
  161 + message: '请求成功',
  162 + type: 'success'
  163 + });
  164 + }
  165 + that.initData()
  166 + that.$refs[itemData.deviceId + 'refbtn' ].loading = false;
  167 + }).catch(function(e) {
  168 + console.error(e)
  169 + that.$refs[itemData.deviceId + 'refbtn' ].loading = false;
  170 + });;
  171 + },
  172 + //通知设备上传媒体流
  173 + sendDevicePush: function(itemData) {
  174 + // let deviceId = this.currentDevice.deviceId;
  175 + // let channelId = itemData.channelId;
  176 + // console.log("通知设备推流1:" + deviceId + " : " + channelId);
  177 + // let that = this;
  178 + // this.$axios({
  179 + // method: 'get',
  180 + // url: '/api/play/' + deviceId + '/' + channelId
  181 + // }).then(function(res) {
  182 + // let ssrc = res.data.ssrc;
  183 + // that.$refs.devicePlayer.play(ssrc,deviceId,channelId);
  184 + // }).catch(function(e) {
  185 + // });
  186 + },
  187 + transportChange: function (row) {
  188 + console.log(row);
  189 + console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `);
  190 + let that = this;
  191 + this.$axios({
  192 + method: 'get',
  193 + url: '/api/devices/' + row.deviceId + '/transport/' + row.streamMode
  194 + }).then(function(res) {
  195 +
  196 + }).catch(function(e) {
  197 + });
  198 + }
  199 +
  200 + }
  201 + };
  202 +</script>
  203 +
  204 +<style>
  205 + .videoList {
  206 + display: flex;
  207 + flex-wrap: wrap;
  208 + align-content: flex-start;
  209 + }
  210 +
  211 + .video-item {
  212 + position: relative;
  213 + width: 15rem;
  214 + height: 10rem;
  215 + margin-right: 1rem;
  216 + background-color: #000000;
  217 + }
  218 +
  219 + .video-item-img {
  220 + position: absolute;
  221 + top: 0;
  222 + bottom: 0;
  223 + left: 0;
  224 + right: 0;
  225 + margin: auto;
  226 + width: 100%;
  227 + height: 100%;
  228 + }
  229 +
  230 + .video-item-img:after {
  231 + content: "";
  232 + display: inline-block;
  233 + position: absolute;
  234 + z-index: 2;
  235 + top: 0;
  236 + bottom: 0;
  237 + left: 0;
  238 + right: 0;
  239 + margin: auto;
  240 + width: 3rem;
  241 + height: 3rem;
  242 + background-image: url("../assets/loading.png");
  243 + background-size: cover;
  244 + background-color: #000000;
  245 + }
  246 +
  247 + .video-item-title {
  248 + position: absolute;
  249 + bottom: 0;
  250 + color: #000000;
  251 + background-color: #ffffff;
  252 + line-height: 1.5rem;
  253 + padding: 0.3rem;
  254 + width: 14.4rem;
  255 + }
  256 +</style>
web_src/src/components/UiHeader.vue
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 <el-menu router :default-active="this.$route.path" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" mode="horizontal"> 3 <el-menu router :default-active="this.$route.path" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" mode="horizontal">
4 <el-menu-item index="/">控制台</el-menu-item> 4 <el-menu-item index="/">控制台</el-menu-item>
5 <el-menu-item index="/deviceList">设备列表</el-menu-item> 5 <el-menu-item index="/deviceList">设备列表</el-menu-item>
  6 + <el-menu-item index="/pushVideoList">推流列表</el-menu-item>
6 <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item> 7 <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>
7 <el-switch v-model="alarmNotify" active-text="报警信息推送" style="display: block float: right" @change="sseControl"></el-switch> 8 <el-switch v-model="alarmNotify" active-text="报警信息推送" style="display: block float: right" @change="sseControl"></el-switch>
8 <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item> 9 <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>
web_src/src/router/index.js
@@ -4,6 +4,7 @@ import VueRouter from &#39;vue-router&#39; @@ -4,6 +4,7 @@ import VueRouter from &#39;vue-router&#39;
4 import control from '../components/control.vue' 4 import control from '../components/control.vue'
5 import deviceList from '../components/DeviceList.vue' 5 import deviceList from '../components/DeviceList.vue'
6 import channelList from '../components/channelList.vue' 6 import channelList from '../components/channelList.vue'
  7 +import pushVideoList from '../components/PushVideoList.vue'
7 import devicePosition from '../components/devicePosition.vue' 8 import devicePosition from '../components/devicePosition.vue'
8 import login from '../components/Login.vue' 9 import login from '../components/Login.vue'
9 import parentPlatformList from '../components/ParentPlatformList.vue' 10 import parentPlatformList from '../components/ParentPlatformList.vue'
@@ -28,6 +29,10 @@ export default new VueRouter({ @@ -28,6 +29,10 @@ export default new VueRouter({
28 component: deviceList, 29 component: deviceList,
29 }, 30 },
30 { 31 {
  32 + path: '/pushVideoList',
  33 + component: pushVideoList,
  34 + },
  35 + {
31 path: '/login', 36 path: '/login',
32 name: '登录', 37 name: '登录',
33 component: login, 38 component: login,