添加推流列表和拉流代理,下一步与国标关联
This commit is contained in:
parent
f8fe76add2
commit
56859d09df
@ -35,6 +35,8 @@ public class MediaServerConfig {
|
|||||||
|
|
||||||
private String wanIp;
|
private String wanIp;
|
||||||
|
|
||||||
|
private long updateTime;
|
||||||
|
|
||||||
@JSONField(name = "hls.fileBufSize")
|
@JSONField(name = "hls.fileBufSize")
|
||||||
private String hlsFileBufSize;
|
private String hlsFileBufSize;
|
||||||
|
|
||||||
@ -728,4 +730,12 @@ public class MediaServerConfig {
|
|||||||
public void setWanIp(String wanIp) {
|
public void setWanIp(String wanIp) {
|
||||||
this.wanIp = wanIp;
|
this.wanIp = wanIp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getUpdateTime() {
|
||||||
|
return updateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateTime(long updateTime) {
|
||||||
|
this.updateTime = updateTime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.genersoft.iot.vmp.media.zlm;
|
package com.genersoft.iot.vmp.media.zlm;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@ -272,26 +273,35 @@ public class ZLMHttpHookListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String streamId = json.getString("stream");
|
String streamId = json.getString("stream");
|
||||||
|
String app = json.getString("app");
|
||||||
StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
|
StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
|
||||||
|
|
||||||
JSONObject ret = new JSONObject();
|
|
||||||
ret.put("code", 0);
|
|
||||||
ret.put("close", true);
|
|
||||||
|
|
||||||
if (streamInfo != null) {
|
if ("rtp".equals(app)){
|
||||||
if (redisCatchStorage.isChannelSendingRTP(streamInfo.getChannelId())) {
|
JSONObject ret = new JSONObject();
|
||||||
ret.put("close", false);
|
ret.put("code", 0);
|
||||||
} else {
|
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);
|
cmder.streamByeCmd(streamId);
|
||||||
redisCatchStorage.stopPlay(streamInfo);
|
streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId);
|
||||||
storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
|
redisCatchStorage.stopPlayback(streamInfo);
|
||||||
}
|
}
|
||||||
}else{
|
return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
|
||||||
cmder.streamByeCmd(streamId);
|
}else {
|
||||||
streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId);
|
JSONObject ret = new JSONObject();
|
||||||
redisCatchStorage.stopPlayback(streamInfo);
|
ret.put("code", 0);
|
||||||
|
ret.put("close", false);
|
||||||
|
return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
|
||||||
}
|
}
|
||||||
return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -350,10 +360,21 @@ public class ZLMHttpHookListener {
|
|||||||
// String data = json.getString("data");
|
// String data = json.getString("data");
|
||||||
// List<MediaServerConfig> mediaServerConfigs = JSON.parseArray(JSON.toJSONString(json), MediaServerConfig.class);
|
// List<MediaServerConfig> mediaServerConfigs = JSON.parseArray(JSON.toJSONString(json), MediaServerConfig.class);
|
||||||
// MediaServerConfig mediaServerConfig = mediaServerConfigs.get(0);
|
// MediaServerConfig mediaServerConfig = mediaServerConfigs.get(0);
|
||||||
|
|
||||||
|
List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(ZLMHttpHookSubscribe.HookType.on_server_started);
|
||||||
|
if (subscribes != null && subscribes.size() > 0) {
|
||||||
|
for (ZLMHttpHookSubscribe.Event subscribe : subscribes) {
|
||||||
|
subscribe.response(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MediaServerConfig mediaServerConfig = JSON.toJavaObject(json, MediaServerConfig.class);
|
MediaServerConfig mediaServerConfig = JSON.toJavaObject(json, MediaServerConfig.class);
|
||||||
mediaServerConfig.setWanIp(StringUtils.isEmpty(mediaWanIp)? mediaIp: mediaWanIp);
|
mediaServerConfig.setWanIp(StringUtils.isEmpty(mediaWanIp)? mediaIp: mediaWanIp);
|
||||||
mediaServerConfig.setLocalIP(mediaIp);
|
mediaServerConfig.setLocalIP(mediaIp);
|
||||||
redisCatchStorage.updateMediaInfo(mediaServerConfig);
|
redisCatchStorage.updateMediaInfo(mediaServerConfig);
|
||||||
|
|
||||||
|
// 重新发起代理
|
||||||
|
|
||||||
JSONObject ret = new JSONObject();
|
JSONObject ret = new JSONObject();
|
||||||
ret.put("code", 0);
|
ret.put("code", 0);
|
||||||
ret.put("msg", "success");
|
ret.put("msg", "success");
|
||||||
|
@ -3,7 +3,9 @@ package com.genersoft.iot.vmp.media.zlm;
|
|||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@ -67,4 +69,19 @@ public class ZLMHttpHookSubscribe {
|
|||||||
}
|
}
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ZLMHttpHookSubscribe.Event> getSubscribes(HookType type) {
|
||||||
|
ZLMHttpHookSubscribe.Event event= null;
|
||||||
|
Map<JSONObject, Event> eventMap = allSubscribes.get(type);
|
||||||
|
if (eventMap == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
List<ZLMHttpHookSubscribe.Event> result = new ArrayList<>();
|
||||||
|
for (JSONObject key : eventMap.keySet()) {
|
||||||
|
result.add(eventMap.get(key));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ public class ZLMMediaListManager {
|
|||||||
|
|
||||||
public void updateMediaList() {
|
public void updateMediaList() {
|
||||||
JSONObject mediaList = zlmresTfulUtils.getMediaList();
|
JSONObject mediaList = zlmresTfulUtils.getMediaList();
|
||||||
|
if (mediaList == null) return;
|
||||||
String dataStr = mediaList.getString("data");
|
String dataStr = mediaList.getString("data");
|
||||||
|
|
||||||
Integer code = mediaList.getInteger("code");
|
Integer code = mediaList.getInteger("code");
|
||||||
|
@ -131,4 +131,25 @@ public class ZLMRESTfulUtils {
|
|||||||
public JSONObject stopSendRtp(Map<String, Object> param) {
|
public JSONObject stopSendRtp(Map<String, Object> param) {
|
||||||
return sendPost("stopSendRtp",param);
|
return sendPost("stopSendRtp",param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JSONObject addStreamProxy(String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) {
|
||||||
|
Map<String, Object> param = new HashMap<>();
|
||||||
|
param.put("vhost", "__defaultVhost__");
|
||||||
|
param.put("app", app);
|
||||||
|
param.put("stream", stream);
|
||||||
|
param.put("url", url);
|
||||||
|
param.put("enable_hls", enable_hls?1:0);
|
||||||
|
param.put("enable_mp4", enable_mp4?1:0);
|
||||||
|
param.put("rtp_type", rtp_type);
|
||||||
|
return sendPost("addStreamProxy",param);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject closeStreams(String app, String stream) {
|
||||||
|
Map<String, Object> param = new HashMap<>();
|
||||||
|
param.put("vhost", "__defaultVhost__");
|
||||||
|
param.put("app", app);
|
||||||
|
param.put("stream", stream);
|
||||||
|
param.put("force", 1);
|
||||||
|
return sendPost("close_streams",param);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,11 @@ import com.alibaba.fastjson.JSON;
|
|||||||
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONArray;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
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.IRedisCatchStorage;
|
||||||
//import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
//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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -16,6 +19,7 @@ import org.springframework.stereotype.Component;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@ -24,8 +28,8 @@ public class ZLMRunner implements CommandLineRunner {
|
|||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(ZLMRunner.class);
|
private final static Logger logger = LoggerFactory.getLogger(ZLMRunner.class);
|
||||||
|
|
||||||
// @Autowired
|
@Autowired
|
||||||
// private IVideoManagerStorager storager;
|
private IVideoManagerStorager storager;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IRedisCatchStorage redisCatchStorage;
|
private IRedisCatchStorage redisCatchStorage;
|
||||||
@ -63,18 +67,27 @@ public class ZLMRunner implements CommandLineRunner {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ZLMMediaListManager zlmMediaListManager;
|
private ZLMMediaListManager zlmMediaListManager;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ZLMHttpHookSubscribe hookSubscribe;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IStreamProxyService streamProxyService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(String... strings) throws Exception {
|
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信息
|
// 获取zlm信息
|
||||||
logger.info("等待zlm接入...");
|
logger.info("等待zlm接入...");
|
||||||
MediaServerConfig mediaServerConfig = getMediaServerConfig();
|
MediaServerConfig mediaServerConfig = getMediaServerConfig();
|
||||||
|
|
||||||
if (mediaServerConfig != null) {
|
if (mediaServerConfig != null) {
|
||||||
logger.info("zlm接入成功...");
|
zLmRunning(mediaServerConfig);
|
||||||
if (autoConfig) saveZLMConfig();
|
|
||||||
mediaServerConfig = getMediaServerConfig();
|
|
||||||
redisCatchStorage.updateMediaInfo(mediaServerConfig);
|
|
||||||
// 更新流列表
|
|
||||||
zlmMediaListManager.updateMediaList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,8 +98,7 @@ public class ZLMRunner implements CommandLineRunner {
|
|||||||
JSONArray data = responseJSON.getJSONArray("data");
|
JSONArray data = responseJSON.getJSONArray("data");
|
||||||
if (data != null && data.size() > 0) {
|
if (data != null && data.size() > 0) {
|
||||||
mediaServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), MediaServerConfig.class);
|
mediaServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), MediaServerConfig.class);
|
||||||
mediaServerConfig.setLocalIP(mediaIp);
|
|
||||||
mediaServerConfig.setWanIp(StringUtils.isEmpty(mediaWanIp)? mediaIp: mediaWanIp);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.error("getMediaServerConfig失败, 1s后重试");
|
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<StreamProxyDto> streamProxyListForEnable = storager.getStreamProxyListForEnable(true);
|
||||||
|
for (StreamProxyDto streamProxyDto : streamProxyListForEnable) {
|
||||||
|
logger.info("恢复流代理," + streamProxyDto.getApp() + "/" + streamProxyDto.getStream());
|
||||||
|
streamProxyService.addStreamProxyToZlm(streamProxyDto);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package com.genersoft.iot.vmp.storager;
|
package com.genersoft.iot.vmp.storager;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.genersoft.iot.vmp.common.RealVideo;
|
import com.genersoft.iot.vmp.common.RealVideo;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
import com.genersoft.iot.vmp.conf.MediaServerConfig;
|
||||||
@ -116,5 +117,5 @@ public interface IRedisCatchStorage {
|
|||||||
* 获取当前媒体流列表
|
* 获取当前媒体流列表
|
||||||
* @return List<RealVideo>
|
* @return List<RealVideo>
|
||||||
*/
|
*/
|
||||||
List<Object> getMediaList(int start, int end);
|
JSONObject getMediaList(int start, int end);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import java.util.List;
|
|||||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
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.vmanager.platform.bean.ChannelReduce;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
@ -261,4 +262,49 @@ public interface IVideoManagerStorager {
|
|||||||
* @param deviceId
|
* @param deviceId
|
||||||
*/
|
*/
|
||||||
public int clearMobilePositionsByDeviceId(String 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<StreamProxyDto> getStreamProxyListForEnable(boolean enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按照是app和stream获取代理流
|
||||||
|
* @param app
|
||||||
|
* @param stream
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public StreamProxyDto queryStreamProxy(String app, String stream);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取代理流
|
||||||
|
* @param page
|
||||||
|
* @param count
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
PageInfo<StreamProxyDto> queryStreamProxyList(Integer page, Integer count);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.genersoft.iot.vmp.storager.dao;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyDto;
|
||||||
|
import org.apache.ibatis.annotations.*;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
@Repository
|
||||||
|
public interface StreamProxyMapper {
|
||||||
|
|
||||||
|
@Insert("INSERT INTO stream_proxy (type, app, stream, url, src_url, dst_url, " +
|
||||||
|
"timeout_ms, ffmpeg_cmd_key, rtp_type, enable_hls, enable_mp4, enable) VALUES" +
|
||||||
|
"('${type}','${app}', '${stream}', '${url}', '${src_url}', '${dst_url}', " +
|
||||||
|
"'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_hls}, ${enable_mp4}, ${enable} )")
|
||||||
|
int add(StreamProxyDto streamProxyDto);
|
||||||
|
|
||||||
|
@Update("UPDATE stream_proxy " +
|
||||||
|
"SET type=#{type}, " +
|
||||||
|
"app=#{app}," +
|
||||||
|
"stream=#{stream}," +
|
||||||
|
"url=#{url}, " +
|
||||||
|
"src_url=#{src_url}," +
|
||||||
|
"dst_url=#{dst_url}, " +
|
||||||
|
"timeout_ms=#{timeout_ms}, " +
|
||||||
|
"ffmpeg_cmd_key=#{ffmpeg_cmd_key}, " +
|
||||||
|
"rtp_type=#{rtp_type}, " +
|
||||||
|
"enable_hls=#{enable_hls}, " +
|
||||||
|
"enable=#{enable}, " +
|
||||||
|
"enable_mp4=#{enable_mp4} " +
|
||||||
|
"WHERE app=#{app} AND stream=#{stream}")
|
||||||
|
int update(StreamProxyDto streamProxyDto);
|
||||||
|
|
||||||
|
@Delete("DELETE FROM stream_proxy WHERE app=#{app} AND stream=#{stream}")
|
||||||
|
int del(String app, String stream);
|
||||||
|
|
||||||
|
@Select("SELECT * FROM stream_proxy")
|
||||||
|
List<StreamProxyDto> selectAll();
|
||||||
|
|
||||||
|
@Select("SELECT * FROM stream_proxy WHERE enable=${enable}")
|
||||||
|
List<StreamProxyDto> selectForEnable(boolean enable);
|
||||||
|
|
||||||
|
@Select("SELECT * FROM stream_proxy WHERE app=#{app} AND stream=#{stream}")
|
||||||
|
StreamProxyDto selectOne(String app, String stream);
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package com.genersoft.iot.vmp.storager.impl;
|
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.RealVideo;
|
||||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||||
@ -92,6 +93,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean updateMediaInfo(MediaServerConfig mediaServerConfig) {
|
public boolean updateMediaInfo(MediaServerConfig mediaServerConfig) {
|
||||||
|
mediaServerConfig.setUpdateTime(System.currentTimeMillis());
|
||||||
return redis.set(VideoManagerConstants.MEDIA_SERVER_PREFIX,mediaServerConfig);
|
return redis.set(VideoManagerConstants.MEDIA_SERVER_PREFIX,mediaServerConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,9 +282,13 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
|
|||||||
* @return List<RealVideo>
|
* @return List<RealVideo>
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<Object> getMediaList(int start, int end) {
|
public JSONObject getMediaList(int start, int end) {
|
||||||
String key = VideoManagerConstants.MEDIA_STREAM_PREFIX;
|
String key = VideoManagerConstants.MEDIA_STREAM_PREFIX;
|
||||||
Set<Object> realVideos = redis.ZRange(key, start, end);
|
Set<Object> realVideos = redis.ZRange(key, start, end);
|
||||||
return new ArrayList(realVideos);
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("list", new ArrayList(realVideos));
|
||||||
|
jsonObject.put("total", redis.zSize(key));
|
||||||
|
|
||||||
|
return jsonObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,11 @@ import java.util.*;
|
|||||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
|
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.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
||||||
import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
|
import com.genersoft.iot.vmp.storager.dao.*;
|
||||||
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.vmanager.platform.bean.ChannelReduce;
|
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.PageHelper;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -49,6 +46,9 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PatformChannelMapper patformChannelMapper;
|
private PatformChannelMapper patformChannelMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private StreamProxyMapper streamProxyMapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -233,7 +233,7 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加Mobile Position设备移动位置
|
* 添加Mobile Position设备移动位置
|
||||||
* @param MobilePosition
|
* @param mobilePosition
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) {
|
public synchronized boolean insertMobilePosition(MobilePosition mobilePosition) {
|
||||||
@ -388,4 +388,68 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
|
|||||||
return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId);
|
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<StreamProxyDto> getStreamProxyListForEnable(boolean enable) {
|
||||||
|
return streamProxyMapper.selectForEnable(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询代理流列表
|
||||||
|
* @param page
|
||||||
|
* @param count
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public PageInfo<StreamProxyDto> queryStreamProxyList(Integer page, Integer count) {
|
||||||
|
PageHelper.startPage(page, count);
|
||||||
|
List<StreamProxyDto> all = streamProxyMapper.selectAll();
|
||||||
|
return new PageInfo<>(all);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按照是app和stream获取代理流
|
||||||
|
* @param app
|
||||||
|
* @param stream
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public StreamProxyDto queryStreamProxy(String app, String stream){
|
||||||
|
return streamProxyMapper.selectOne(app, stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -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.media.zlm.ZLMRESTfulUtils;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
|
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 com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -55,6 +56,9 @@ public class PlayController {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IPlayService playService;
|
private IPlayService playService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IMediaService mediaService;
|
||||||
|
|
||||||
@GetMapping("/play/{deviceId}/{channelId}")
|
@GetMapping("/play/{deviceId}/{channelId}")
|
||||||
public DeferredResult<ResponseEntity<String>> play(@PathVariable String deviceId,
|
public DeferredResult<ResponseEntity<String>> play(@PathVariable String deviceId,
|
||||||
@PathVariable String channelId) {
|
@PathVariable String channelId) {
|
||||||
@ -159,18 +163,20 @@ public class PlayController {
|
|||||||
JSONObject data = jsonObject.getJSONObject("data");
|
JSONObject data = jsonObject.getJSONObject("data");
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
result.put("key", data.getString("key"));
|
result.put("key", data.getString("key"));
|
||||||
StreamInfo streamInfoResult = new StreamInfo();
|
// StreamInfo streamInfoResult = new StreamInfo();
|
||||||
streamInfoResult.setRtmp(dstUrl);
|
// streamInfoResult.setRtmp(dstUrl);
|
||||||
streamInfoResult.setRtsp(String.format("rtsp://%s:%s/convert/%s", mediaInfo.getWanIp(), mediaInfo.getRtspPort(), streamId));
|
// 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.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);
|
result.put("data", streamInfoResult);
|
||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
|
@ -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);
|
||||||
|
}
|
@ -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<StreamProxyDto> 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);
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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.IRedisCatchStorage;
|
||||||
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
|
||||||
import com.genersoft.iot.vmp.vmanager.play.bean.PlayResult;
|
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 com.genersoft.iot.vmp.vmanager.service.IPlayService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -46,6 +47,9 @@ public class PlayServiceImpl implements IPlayService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ZLMRESTfulUtils zlmresTfulUtils;
|
private ZLMRESTfulUtils zlmresTfulUtils;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IMediaService mediaService;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PlayResult play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) {
|
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) {
|
public StreamInfo onPublishHandler(JSONObject resonse, String deviceId, String channelId, String uuid) {
|
||||||
String streamId = resonse.getString("id");
|
String streamId = resonse.getString("id");
|
||||||
StreamInfo streamInfo = new StreamInfo();
|
StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream("rtp", streamId);
|
||||||
|
// StreamInfo streamInfo = new StreamInfo();
|
||||||
streamInfo.setStreamId(streamId);
|
streamInfo.setStreamId(streamId);
|
||||||
streamInfo.setDeviceID(deviceId);
|
streamInfo.setDeviceID(deviceId);
|
||||||
streamInfo.setChannelId(channelId);
|
streamInfo.setChannelId(channelId);
|
||||||
MediaServerConfig mediaServerConfig = redisCatchStorage.getMediaInfo();
|
// MediaServerConfig mediaServerConfig = redisCatchStorage.getMediaInfo();
|
||||||
|
|
||||||
streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaServerConfig.getWanIp(), mediaServerConfig.getHttpPort(), streamId));
|
// streamInfo.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.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.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.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.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.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.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.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.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaServerConfig.getWanIp(), mediaServerConfig.getRtmpPort(), streamId));
|
||||||
streamInfo.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaServerConfig.getWanIp(), mediaServerConfig.getRtspPort(), streamId));
|
// streamInfo.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaServerConfig.getWanIp(), mediaServerConfig.getRtspPort(), streamId));
|
||||||
|
|
||||||
return streamInfo;
|
return streamInfo;
|
||||||
}
|
}
|
||||||
|
@ -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<StreamProxyDto> getAll(Integer page, Integer count) {
|
||||||
|
return videoManagerStorager.queryStreamProxyList(page, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void del(String app, String stream) {
|
||||||
|
StreamProxyDto streamProxyDto = new StreamProxyDto();
|
||||||
|
streamProxyDto.setApp(app);
|
||||||
|
streamProxyDto.setStream(stream);
|
||||||
|
JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto);
|
||||||
|
if (jsonObject.getInteger("code") == 0) {
|
||||||
|
videoManagerStorager.deleteStreamProxy(app, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean start(String app, String stream) {
|
||||||
|
boolean result = false;
|
||||||
|
StreamProxyDto streamProxyDto = videoManagerStorager.queryStreamProxy(app, stream);
|
||||||
|
if (!streamProxyDto.isEnable() && streamProxyDto != null) {
|
||||||
|
JSONObject jsonObject = addStreamProxyToZlm(streamProxyDto);
|
||||||
|
if (jsonObject.getInteger("code") == 0) {
|
||||||
|
result = true;
|
||||||
|
streamProxyDto.setEnable(true);
|
||||||
|
videoManagerStorager.updateStreamProxy(streamProxyDto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stop(String app, String stream) {
|
||||||
|
boolean result = false;
|
||||||
|
StreamProxyDto streamProxyDto = videoManagerStorager.queryStreamProxy(app, stream);
|
||||||
|
if (streamProxyDto.isEnable() && streamProxyDto != null) {
|
||||||
|
JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto);
|
||||||
|
if (jsonObject.getInteger("code") == 0) {
|
||||||
|
result = true;
|
||||||
|
streamProxyDto.setEnable(false);
|
||||||
|
videoManagerStorager.updateStreamProxy(streamProxyDto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -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<StreamProxyDto> list(@RequestParam(required = false)Integer page,
|
||||||
|
@RequestParam(required = false)Integer count,
|
||||||
|
@RequestParam(required = false)String q,
|
||||||
|
@RequestParam(required = false)Boolean online ){
|
||||||
|
|
||||||
|
return streamProxyService.getAll(page, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/save")
|
||||||
|
@ResponseBody
|
||||||
|
public Object save(@RequestBody StreamProxyDto param){
|
||||||
|
logger.info("添加代理: " + 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";
|
||||||
|
}
|
||||||
|
}
|
@ -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<Object> mediaList = redisCatchStorage.getMediaList(start - 1, start - 1 + limit);
|
|
||||||
JSONObject jsonObject = new JSONObject();
|
|
||||||
jsonObject.put("code", 0);
|
|
||||||
jsonObject.put("data", mediaList);
|
|
||||||
return jsonObject;
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
20
web_src/package-lock.json
generated
20
web_src/package-lock.json
generated
@ -10924,6 +10924,26 @@
|
|||||||
"clipboard": "^2.0.0"
|
"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": {
|
"vue-cookies": {
|
||||||
"version": "1.7.4",
|
"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",
|
"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",
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vue-baidu-map": "^0.21.22",
|
"vue-baidu-map": "^0.21.22",
|
||||||
"vue-clipboard2": "^0.3.1",
|
"vue-clipboard2": "^0.3.1",
|
||||||
|
"vue-clipboards": "^1.3.0",
|
||||||
"vue-cookies": "^1.7.4",
|
"vue-cookies": "^1.7.4",
|
||||||
"vue-router": "^3.1.6"
|
"vue-router": "^3.1.6"
|
||||||
},
|
},
|
||||||
|
@ -68,9 +68,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import platformEdit from './platformEdit.vue'
|
import platformEdit from './dialog/platformEdit.vue'
|
||||||
import uiHeader from './UiHeader.vue'
|
import uiHeader from './UiHeader.vue'
|
||||||
import chooseChannelDialog from './gb28181/chooseChannel.vue'
|
import chooseChannelDialog from './dialog/chooseChannel.vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'app',
|
name: 'app',
|
||||||
components: {
|
components: {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="pushVideoList">
|
||||||
<el-container>
|
<el-container>
|
||||||
<el-header>
|
<el-header>
|
||||||
<uiHeader></uiHeader>
|
<uiHeader></uiHeader>
|
||||||
@ -7,28 +7,27 @@
|
|||||||
<el-main>
|
<el-main>
|
||||||
<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
|
<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
|
||||||
<span style="font-size: 1rem; font-weight: bold;">推流列表</span>
|
<span style="font-size: 1rem; font-weight: bold;">推流列表</span>
|
||||||
<div style="position: absolute; right: 1rem; top: 0.3rem;">
|
|
||||||
<el-button icon="el-icon-refresh-right" circle size="mini" :loading="getDeviceListLoading" @click="getDeviceList()"></el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- <devicePlayer ref="devicePlayer"></devicePlayer> -->
|
<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
|
||||||
<el-table :data="deviceList" border style="width: 100%" :height="winHeight">
|
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">添加代理</el-button>
|
||||||
<el-table-column prop="schema" label="协议" width="180" align="center">
|
</div>
|
||||||
|
<devicePlayer ref="devicePlayer"></devicePlayer>
|
||||||
|
<el-table :data="pushList" border style="width: 100%" :height="winHeight">
|
||||||
|
<el-table-column prop="app" label="APP" width="180" align="center">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="streamUrl" label="流地址" width="240" align="center">
|
<el-table-column prop="stream" label="流ID" width="240" align="center">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="online" label="在线人数" width="240" align="center">
|
<el-table-column prop="totalReaderCount" label="在线人数" width="240" align="center">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="startTime" label="开始时间" align="center">
|
<el-table-column prop="createStamp" label="开始时间" align="center">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
|
|
||||||
<el-table-column label="操作" width="360" align="center" fixed="right">
|
<el-table-column label="操作" width="360" align="center" fixed="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button>
|
|
||||||
<el-button-group>
|
<el-button-group>
|
||||||
<el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">播放</el-button>
|
<el-button size="mini" icon="el-icon-video-play" @click="playPuhsh(scope.row)">播放</el-button>
|
||||||
<el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopDevicePush(scope.row)">停止</el-button>
|
<el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="!!scope.row.streamId" @click="stopPuhsh(scope.row)">停止</el-button>
|
||||||
</el-button-group>
|
</el-button-group>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -43,25 +42,27 @@
|
|||||||
layout="total, sizes, prev, pager, next"
|
layout="total, sizes, prev, pager, next"
|
||||||
:total="total">
|
:total="total">
|
||||||
</el-pagination>
|
</el-pagination>
|
||||||
|
<streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit>
|
||||||
</el-main>
|
</el-main>
|
||||||
</el-container>
|
</el-container>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import streamProxyEdit from './dialog/StreamProxyEdit.vue'
|
||||||
|
import devicePlayer from './dialog/devicePlayer.vue'
|
||||||
import uiHeader from './UiHeader.vue'
|
import uiHeader from './UiHeader.vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'app',
|
name: 'pushVideoList',
|
||||||
components: {
|
components: {
|
||||||
|
devicePlayer,
|
||||||
|
streamProxyEdit,
|
||||||
uiHeader
|
uiHeader
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
deviceList: [], //设备列表
|
pushList: [], //设备列表
|
||||||
currentDevice: {}, //当前操作设备对象
|
currentPusher: {}, //当前操作设备对象
|
||||||
|
|
||||||
videoComponentList: [],
|
|
||||||
updateLooper: 0, //数据刷新轮训标志
|
updateLooper: 0, //数据刷新轮训标志
|
||||||
currentDeviceChannelsLenth:0,
|
currentDeviceChannelsLenth:0,
|
||||||
winHeight: window.innerHeight - 200,
|
winHeight: window.innerHeight - 200,
|
||||||
@ -72,23 +73,10 @@
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
getcurrentDeviceChannels: function() {
|
|
||||||
let data = this.currentDevice['channelMap'];
|
|
||||||
let channels = null;
|
|
||||||
if (data) {
|
|
||||||
channels = Object.keys(data).map(key => {
|
|
||||||
return data[key];
|
|
||||||
});
|
|
||||||
this.currentDeviceChannelsLenth = channels.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("数据:" + JSON.stringify(channels));
|
|
||||||
return channels;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initData();
|
this.initData();
|
||||||
this.updateLooper = setInterval(this.initData, 10000);
|
// this.updateLooper = setInterval(this.initData, 10000);
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
this.$destroy('videojs');
|
this.$destroy('videojs');
|
||||||
@ -96,20 +84,20 @@
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initData: function() {
|
initData: function() {
|
||||||
this.getDeviceList();
|
this.getPushList();
|
||||||
},
|
},
|
||||||
currentChange: function(val){
|
currentChange: function(val){
|
||||||
this.currentPage = val;
|
this.currentPage = val;
|
||||||
this.getDeviceList();
|
this.getPushList();
|
||||||
},
|
},
|
||||||
handleSizeChange: function(val){
|
handleSizeChange: function(val){
|
||||||
this.count = val;
|
this.count = val;
|
||||||
this.getDeviceList();
|
this.getPushList();
|
||||||
},
|
},
|
||||||
getDeviceList: function() {
|
getPushList: function() {
|
||||||
let that = this;
|
let that = this;
|
||||||
this.getDeviceListLoading = true;
|
this.getDeviceListLoading = true;
|
||||||
this.$axios.get(`/api/devices`,{
|
this.$axios.get(`/api/media/list`,{
|
||||||
params: {
|
params: {
|
||||||
page: that.currentPage,
|
page: that.currentPage,
|
||||||
count: that.count
|
count: that.count
|
||||||
@ -119,83 +107,44 @@
|
|||||||
console.log(res);
|
console.log(res);
|
||||||
console.log(res.data.list);
|
console.log(res.data.list);
|
||||||
that.total = res.data.total;
|
that.total = res.data.total;
|
||||||
that.deviceList = res.data.list;
|
that.pushList = res.data.list;
|
||||||
that.getDeviceListLoading = false;
|
that.getDeviceListLoading = false;
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
that.getDeviceListLoading = false;
|
that.getDeviceListLoading = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
showChannelList: function(row) {
|
addStreamProxy: function(){
|
||||||
console.log(JSON.stringify(row))
|
console.log(2222)
|
||||||
this.$router.push(`/channelList/${row.deviceId}/0/15/1`);
|
this.$refs.streamProxyEdit.openDialog(null, this.initData)
|
||||||
},
|
},
|
||||||
showDevicePosition: function(row) {
|
saveStreamProxy: function(){
|
||||||
console.log(JSON.stringify(row))
|
|
||||||
this.$router.push(`/devicePosition/${row.deviceId}/0/15/1`);
|
|
||||||
},
|
},
|
||||||
|
playPuhsh: function(row){
|
||||||
//gb28181平台对接
|
let that = this;
|
||||||
//刷新设备信息
|
this.getListLoading = true;
|
||||||
refDevice: function(itemData) {
|
this.$axios.get(`/api/media/getStreamInfoByAppAndStream`,{
|
||||||
///api/devices/{deviceId}/sync
|
params: {
|
||||||
console.log("刷新对应设备:" + itemData.deviceId);
|
app: row.app,
|
||||||
var that = this;
|
stream: row.stream
|
||||||
that.$refs[itemData.deviceId + 'refbtn' ].loading = true;
|
|
||||||
this.$axios({
|
|
||||||
method: 'post',
|
|
||||||
url: '/api/devices/' + itemData.deviceId + '/sync'
|
|
||||||
}).then(function(res) {
|
|
||||||
console.log("刷新设备结果:"+JSON.stringify(res));
|
|
||||||
if (!res.data.deviceId) {
|
|
||||||
that.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: res.data,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
}else{
|
|
||||||
that.$message({
|
|
||||||
showClose: true,
|
|
||||||
message: '请求成功',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
that.initData()
|
})
|
||||||
that.$refs[itemData.deviceId + 'refbtn' ].loading = false;
|
.then(function (res) {
|
||||||
}).catch(function(e) {
|
that.getListLoading = false;
|
||||||
console.error(e)
|
that.$refs.devicePlayer.openDialog("streamPlay", null, null, {
|
||||||
that.$refs[itemData.deviceId + 'refbtn' ].loading = false;
|
streamInfo: res.data,
|
||||||
});;
|
hasAudio: true
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
that.getListLoading = false;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
//通知设备上传媒体流
|
stopPuhsh: function(row){
|
||||||
sendDevicePush: function(itemData) {
|
console.log(row)
|
||||||
// let deviceId = this.currentDevice.deviceId;
|
}
|
||||||
// let channelId = itemData.channelId;
|
|
||||||
// console.log("通知设备推流1:" + deviceId + " : " + channelId);
|
|
||||||
// let that = this;
|
|
||||||
// this.$axios({
|
|
||||||
// method: 'get',
|
|
||||||
// url: '/api/play/' + deviceId + '/' + channelId
|
|
||||||
// }).then(function(res) {
|
|
||||||
// let ssrc = res.data.ssrc;
|
|
||||||
// that.$refs.devicePlayer.play(ssrc,deviceId,channelId);
|
|
||||||
// }).catch(function(e) {
|
|
||||||
// });
|
|
||||||
},
|
|
||||||
transportChange: function (row) {
|
|
||||||
console.log(row);
|
|
||||||
console.log(`修改传输方式为 ${row.streamMode}:${row.deviceId} `);
|
|
||||||
let that = this;
|
|
||||||
this.$axios({
|
|
||||||
method: 'get',
|
|
||||||
url: '/api/devices/' + row.deviceId + '/transport/' + row.streamMode
|
|
||||||
}).then(function(res) {
|
|
||||||
|
|
||||||
}).catch(function(e) {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
297
web_src/src/components/StreamProxyList.vue
Normal file
297
web_src/src/components/StreamProxyList.vue
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
<template>
|
||||||
|
<div id="streamProxyList">
|
||||||
|
<el-container>
|
||||||
|
<el-header>
|
||||||
|
<uiHeader></uiHeader>
|
||||||
|
</el-header>
|
||||||
|
<el-main>
|
||||||
|
<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
|
||||||
|
<span style="font-size: 1rem; font-weight: bold;">拉流代理列表</span>
|
||||||
|
</div>
|
||||||
|
<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
|
||||||
|
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">添加代理</el-button>
|
||||||
|
</div>
|
||||||
|
<devicePlayer ref="devicePlayer"></devicePlayer>
|
||||||
|
<el-table :data="streamProxyList" border style="width: 100%" :height="winHeight">
|
||||||
|
<el-table-column prop="app" label="应用名" align="center" show-overflow-tooltip/>
|
||||||
|
<el-table-column prop="stream" label="流ID" align="center" show-overflow-tooltip/>
|
||||||
|
<el-table-column label="流地址" width="400" align="center" show-overflow-tooltip >
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div slot="reference" class="name-wrapper">
|
||||||
|
|
||||||
|
<el-tag size="medium" v-if="scope.row.type == 'default'">
|
||||||
|
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
|
||||||
|
{{scope.row.url}}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag size="medium" v-if="scope.row.type != 'default'">
|
||||||
|
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.src_url" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
|
||||||
|
{{scope.row.src_url}}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column label="转HLS" width="120" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div slot="reference" class="name-wrapper">
|
||||||
|
<el-tag size="medium" v-if="scope.row.enable_hls">已启用</el-tag>
|
||||||
|
<el-tag size="medium" type="info" v-if="!scope.row.enable_hls">未启用</el-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="MP4录制" width="120" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div slot="reference" class="name-wrapper">
|
||||||
|
<el-tag size="medium" v-if="scope.row.enable_mp4">已启用</el-tag>
|
||||||
|
<el-tag size="medium" type="info" v-if="!scope.row.enable_mp4">未启用</el-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="启用" width="120" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div slot="reference" class="name-wrapper">
|
||||||
|
<el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
|
||||||
|
<el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
|
||||||
|
<el-table-column label="操作" width="360" align="center" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button-group>
|
||||||
|
<el-button size="mini" icon="el-icon-video-play" v-if="scope.row.enable" @click="play(scope.row)">播放</el-button>
|
||||||
|
<el-button size="mini" icon="el-icon-close" type="success" v-if="scope.row.enable" @click="stop(scope.row)">停用</el-button>
|
||||||
|
<el-button size="mini" icon="el-icon-check" type="primary" v-if="!scope.row.enable" @click="start(scope.row)">启用</el-button>
|
||||||
|
<el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteStreamProxy(scope.row)">删除</el-button>
|
||||||
|
</el-button-group>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-pagination
|
||||||
|
style="float: right"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="currentChange"
|
||||||
|
:current-page="currentPage"
|
||||||
|
:page-size="count"
|
||||||
|
:page-sizes="[15, 25, 35, 50]"
|
||||||
|
layout="total, sizes, prev, pager, next"
|
||||||
|
:total="total">
|
||||||
|
</el-pagination>
|
||||||
|
<streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import streamProxyEdit from './dialog/StreamProxyEdit.vue'
|
||||||
|
import devicePlayer from './dialog/devicePlayer.vue'
|
||||||
|
import uiHeader from './UiHeader.vue'
|
||||||
|
export default {
|
||||||
|
name: 'streamProxyList',
|
||||||
|
components: {
|
||||||
|
devicePlayer,
|
||||||
|
streamProxyEdit,
|
||||||
|
uiHeader
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
streamProxyList: [],
|
||||||
|
currentPusher: {}, //当前操作设备对象
|
||||||
|
updateLooper: 0, //数据刷新轮训标志
|
||||||
|
currentDeviceChannelsLenth:0,
|
||||||
|
winHeight: window.innerHeight - 200,
|
||||||
|
currentPage:1,
|
||||||
|
count:15,
|
||||||
|
total:0,
|
||||||
|
getListLoading: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initData();
|
||||||
|
// this.updateLooper = setInterval(this.initData, 10000);
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.$destroy('videojs');
|
||||||
|
clearTimeout(this.updateLooper);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initData: function() {
|
||||||
|
this.getStreamProxyList();
|
||||||
|
},
|
||||||
|
currentChange: function(val){
|
||||||
|
this.currentPage = val;
|
||||||
|
this.getStreamProxyList();
|
||||||
|
},
|
||||||
|
handleSizeChange: function(val){
|
||||||
|
this.count = val;
|
||||||
|
this.getStreamProxyList();
|
||||||
|
},
|
||||||
|
getStreamProxyList: function() {
|
||||||
|
let that = this;
|
||||||
|
this.getListLoading = true;
|
||||||
|
this.$axios.get(`/api/proxy/list`,{
|
||||||
|
params: {
|
||||||
|
page: that.currentPage,
|
||||||
|
count: that.count
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
.then(function (res) {
|
||||||
|
console.log(res);
|
||||||
|
console.log(res.data.list);
|
||||||
|
that.total = res.data.total;
|
||||||
|
that.streamProxyList = res.data.list;
|
||||||
|
that.getListLoading = false;
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
that.getListLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
addStreamProxy: function(){
|
||||||
|
this.$refs.streamProxyEdit.openDialog(null, this.initData)
|
||||||
|
},
|
||||||
|
saveStreamProxy: function(){
|
||||||
|
},
|
||||||
|
play: function(row){
|
||||||
|
let that = this;
|
||||||
|
this.getListLoading = true;
|
||||||
|
this.$axios.get(`/api/media/getStreamInfoByAppAndStream`,{
|
||||||
|
params: {
|
||||||
|
app: row.app,
|
||||||
|
stream: row.stream
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function (res) {
|
||||||
|
that.getListLoading = false;
|
||||||
|
that.$refs.devicePlayer.openDialog("streamPlay", null, null, {
|
||||||
|
streamInfo: res.data,
|
||||||
|
hasAudio: true
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
that.getListLoading = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
deleteStreamProxy: function(row){
|
||||||
|
console.log(1111)
|
||||||
|
let that = this;
|
||||||
|
this.getListLoading = true;
|
||||||
|
this.$axios.get(`/api/proxy/del`,{
|
||||||
|
params: {
|
||||||
|
app: row.app,
|
||||||
|
stream: row.stream
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function (res) {
|
||||||
|
that.getListLoading = false;
|
||||||
|
that.initData()
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
that.getListLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
start: function(row){
|
||||||
|
let that = this;
|
||||||
|
this.getListLoading = true;
|
||||||
|
this.$axios.get(`/api/proxy/start`,{
|
||||||
|
params: {
|
||||||
|
app: row.app,
|
||||||
|
stream: row.stream
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function (res) {
|
||||||
|
that.getListLoading = false;
|
||||||
|
that.initData()
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
that.getListLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
stop: function(row){
|
||||||
|
let that = this;
|
||||||
|
this.getListLoading = true;
|
||||||
|
this.$axios.get(`/api/proxy/stop`,{
|
||||||
|
params: {
|
||||||
|
app: row.app,
|
||||||
|
stream: row.stream
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function (res) {
|
||||||
|
that.getListLoading = false;
|
||||||
|
that.initData()
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
that.getListLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.videoList {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-item {
|
||||||
|
position: relative;
|
||||||
|
width: 15rem;
|
||||||
|
height: 10rem;
|
||||||
|
margin-right: 1rem;
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-item-img {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: auto;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-item-img:after {
|
||||||
|
content: "";
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: auto;
|
||||||
|
width: 3rem;
|
||||||
|
height: 3rem;
|
||||||
|
background-image: url("../assets/loading.png");
|
||||||
|
background-size: cover;
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-item-title {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
color: #000000;
|
||||||
|
background-color: #ffffff;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
padding: 0.3rem;
|
||||||
|
width: 14.4rem;
|
||||||
|
}
|
||||||
|
.cpoy-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -4,6 +4,7 @@
|
|||||||
<el-menu-item index="/">控制台</el-menu-item>
|
<el-menu-item index="/">控制台</el-menu-item>
|
||||||
<el-menu-item index="/deviceList">设备列表</el-menu-item>
|
<el-menu-item index="/deviceList">设备列表</el-menu-item>
|
||||||
<el-menu-item index="/pushVideoList">推流列表</el-menu-item>
|
<el-menu-item index="/pushVideoList">推流列表</el-menu-item>
|
||||||
|
<el-menu-item index="/streamProxyList">拉流代理</el-menu-item>
|
||||||
<el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>
|
<el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>
|
||||||
<el-switch v-model="alarmNotify" active-text="报警信息推送" style="display: block float: right" @change="sseControl"></el-switch>
|
<el-switch v-model="alarmNotify" active-text="报警信息推送" style="display: block float: right" @change="sseControl"></el-switch>
|
||||||
<el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>
|
<el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import devicePlayer from './gb28181/devicePlayer.vue'
|
import devicePlayer from './dialog/devicePlayer.vue'
|
||||||
import uiHeader from './UiHeader.vue'
|
import uiHeader from './UiHeader.vue'
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
export default {
|
export default {
|
||||||
|
186
web_src/src/components/dialog/StreamProxyEdit.vue
Normal file
186
web_src/src/components/dialog/StreamProxyEdit.vue
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
<template>
|
||||||
|
<div id="addStreamProxy" v-loading="isLoging">
|
||||||
|
<el-dialog
|
||||||
|
title="添加代理"
|
||||||
|
width="40%"
|
||||||
|
top="2rem"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:visible.sync="showDialog"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
@close="close()"
|
||||||
|
>
|
||||||
|
<div id="shared" style="margin-top: 1rem;margin-right: 100px;">
|
||||||
|
<el-form ref="streamProxy" :rules="rules" :model="proxyParam" label-width="140px">
|
||||||
|
<el-form-item label="类型" prop="type">
|
||||||
|
<el-select
|
||||||
|
v-model="proxyParam.type"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请选择代理类型"
|
||||||
|
>
|
||||||
|
<el-option label="默认" value="default"></el-option>
|
||||||
|
<el-option label="FFmpeg" value="ffmpeg"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="应用名" prop="app">
|
||||||
|
<el-input v-model="proxyParam.app" clearable></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="流ID" prop="stream">
|
||||||
|
<el-input v-model="proxyParam.stream" clearable></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="拉流地址" prop="url" v-if="proxyParam.type=='default'">
|
||||||
|
<el-input v-model="proxyParam.url" clearable></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="拉流地址" prop="src_url" v-if="proxyParam.type=='ffmpeg'">
|
||||||
|
<el-input v-model="proxyParam.src_url" clearable></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="超时时间" prop="timeout_ms" v-if="proxyParam.type=='ffmpeg'">
|
||||||
|
<el-input v-model="proxyParam.timeout_ms" clearable></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="FFmpeg命令模板" prop="ffmpeg_cmd_key" v-if="proxyParam.type=='ffmpeg'">
|
||||||
|
<el-input v-model="proxyParam.ffmpeg_cmd_key" clearable></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="拉流方式" prop="rtp_type" v-if="proxyParam.type=='default'">
|
||||||
|
<el-select
|
||||||
|
v-model="proxyParam.rtp_type"
|
||||||
|
style="width: 100%"
|
||||||
|
placeholder="请选择拉流方式"
|
||||||
|
>
|
||||||
|
<el-option label="TCP" value="0"></el-option>
|
||||||
|
<el-option label="UDP" value="1"></el-option>
|
||||||
|
<el-option label="组播" value="2"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="其他选项">
|
||||||
|
<div style="float: left;">
|
||||||
|
<el-checkbox label="启用" v-model="proxyParam.enable" ></el-checkbox>
|
||||||
|
<el-checkbox label="转HLS" v-model="proxyParam.enable_hls" ></el-checkbox>
|
||||||
|
<el-checkbox label="MP4录制" v-model="proxyParam.enable_mp4" ></el-checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<div style="float: right;">
|
||||||
|
<el-button type="primary" @click="onSubmit">{{onSubmit_text}}</el-button>
|
||||||
|
<el-button @click="close">取消</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "streamProxyEdit",
|
||||||
|
props: {},
|
||||||
|
computed: {},
|
||||||
|
created() {},
|
||||||
|
data() {
|
||||||
|
// var deviceGBIdRules = async (rule, value, callback) => {
|
||||||
|
// console.log(value);
|
||||||
|
// if (value === "") {
|
||||||
|
// callback(new Error("请输入设备国标编号"));
|
||||||
|
// } else {
|
||||||
|
// var exit = await this.deviceGBIdExit(value);
|
||||||
|
// console.log(exit);
|
||||||
|
// console.log(exit == "true");
|
||||||
|
// console.log(exit === "true");
|
||||||
|
// if (exit) {
|
||||||
|
// callback(new Error("设备国标编号已存在"));
|
||||||
|
// } else {
|
||||||
|
// callback();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
return {
|
||||||
|
listChangeCallback: null,
|
||||||
|
showDialog: false,
|
||||||
|
isLoging: false,
|
||||||
|
onSubmit_text: "立即创建",
|
||||||
|
proxyParam: {
|
||||||
|
type: "default",
|
||||||
|
app: null,
|
||||||
|
stream: null,
|
||||||
|
url: "rtmp://58.200.131.2:1935/livetv/hunantv",
|
||||||
|
src_url: null,
|
||||||
|
timeout_ms: null,
|
||||||
|
ffmpeg_cmd_key: null,
|
||||||
|
rtp_type: null,
|
||||||
|
enable: true,
|
||||||
|
enable_hls: true,
|
||||||
|
enable_mp4: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
rules: {
|
||||||
|
app: [{ required: true, message: "请输入应用名", trigger: "blur" }],
|
||||||
|
stream: [{ required: true, message: "请输入流ID", trigger: "blur" }],
|
||||||
|
url: [{ required: true, message: "请输入要代理的流", trigger: "blur" }],
|
||||||
|
src_url: [{ required: true, message: "请输入要代理的流", trigger: "blur" }],
|
||||||
|
timeout_ms: [{ required: true, message: "请输入FFmpeg推流成功超时时间", trigger: "blur" }],
|
||||||
|
ffmpeg_cmd_key: [{ required: false, message: "请输入FFmpeg命令参数模板(可选)", trigger: "blur" }],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
openDialog: function (proxyParam, callback) {
|
||||||
|
this.showDialog = true;
|
||||||
|
this.listChangeCallback = callback;
|
||||||
|
if (proxyParam != null) {
|
||||||
|
this.proxyParam = proxyParam;
|
||||||
|
this.onSubmit_text = "保存";
|
||||||
|
} else {
|
||||||
|
this.onSubmit_text = "立即创建";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSubmit: function () {
|
||||||
|
console.log("onSubmit");
|
||||||
|
var that = this;
|
||||||
|
that.$axios
|
||||||
|
.post(`/api/proxy/save`, that.proxyParam)
|
||||||
|
.then(function (res) {
|
||||||
|
console.log(res);
|
||||||
|
console.log(res.data == "success");
|
||||||
|
if (res.data == "success") {
|
||||||
|
that.$message({
|
||||||
|
showClose: true,
|
||||||
|
message: "保存成功",
|
||||||
|
type: "success",
|
||||||
|
});
|
||||||
|
that.showDialog = false;
|
||||||
|
if (that.listChangeCallback != null) {
|
||||||
|
that.listChangeCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
console.log("关闭添加视频平台");
|
||||||
|
this.showDialog = false;
|
||||||
|
this.$refs.streamProxy.resetFields();
|
||||||
|
},
|
||||||
|
deviceGBIdExit: async function (deviceGbId) {
|
||||||
|
var result = false;
|
||||||
|
var that = this;
|
||||||
|
await that.$axios
|
||||||
|
.post(`/api/platforms/exit/${deviceGbId}`)
|
||||||
|
.then(function (res) {
|
||||||
|
result = res.data;
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
checkExpires: function() {
|
||||||
|
if (this.platform.enable && this.platform.expires == "0") {
|
||||||
|
this.platform.expires = "300";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
@ -21,7 +21,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import chooseChannelForGb from './chooseChannelForGb.vue'
|
import chooseChannelForGb from '../dialog/chooseChannelForGb.vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'chooseChannel',
|
name: 'chooseChannel',
|
||||||
props: {},
|
props: {},
|
@ -26,7 +26,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->
|
<!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->
|
||||||
<el-tab-pane label="录像查询" name="record">
|
<el-tab-pane label="录像查询" name="record" v-if="showRrecord">
|
||||||
<el-date-picker size="mini" v-model="videoHistory.date" type="date" value-format="yyyy-MM-dd" placeholder="日期" @change="queryRecords()"></el-date-picker>
|
<el-date-picker size="mini" v-model="videoHistory.date" type="date" value-format="yyyy-MM-dd" placeholder="日期" @change="queryRecords()"></el-date-picker>
|
||||||
<el-table :data="videoHistory.searchHistoryResult" height="150" v-loading="recordsLoading">
|
<el-table :data="videoHistory.searchHistoryResult" height="150" v-loading="recordsLoading">
|
||||||
<el-table-column label="名称" prop="name"></el-table-column>
|
<el-table-column label="名称" prop="name"></el-table-column>
|
||||||
@ -42,7 +42,7 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<!--遥控界面-->
|
<!--遥控界面-->
|
||||||
<el-tab-pane label="云台控制" name="control">
|
<el-tab-pane label="云台控制" name="control" v-if="showPtz">
|
||||||
<div style="display: flex; justify-content: left;">
|
<div style="display: flex; justify-content: left;">
|
||||||
<div class="control-wrapper">
|
<div class="control-wrapper">
|
||||||
<div class="control-btn control-top" @mousedown="ptzCamera(0, 2, 0)" @mouseup="ptzCamera(0, 0, 0)">
|
<div class="control-btn control-top" @mousedown="ptzCamera(0, 2, 0)" @mouseup="ptzCamera(0, 0, 0)">
|
||||||
@ -136,7 +136,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import player from './player.vue'
|
import player from '../dialog/player.vue'
|
||||||
export default {
|
export default {
|
||||||
name: 'devicePlayer',
|
name: 'devicePlayer',
|
||||||
props: {},
|
props: {},
|
||||||
@ -184,7 +184,9 @@ export default {
|
|||||||
tracks: [],
|
tracks: [],
|
||||||
coverPlaying:false,
|
coverPlaying:false,
|
||||||
tracksLoading: false,
|
tracksLoading: false,
|
||||||
recordPlay: ""
|
recordPlay: "",
|
||||||
|
showPtz: true,
|
||||||
|
showRrecord: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -230,6 +232,11 @@ export default {
|
|||||||
this.videoHistory.date = param.date;
|
this.videoHistory.date = param.date;
|
||||||
this.queryRecords()
|
this.queryRecords()
|
||||||
break;
|
break;
|
||||||
|
case "streamPlay":
|
||||||
|
this.showRrecord = false,
|
||||||
|
this.showPtz = false,
|
||||||
|
this.play(param.streamInfo, param.hasAudio)
|
||||||
|
break;
|
||||||
case "control":
|
case "control":
|
||||||
break;
|
break;
|
||||||
}
|
}
|
@ -11,6 +11,8 @@ import echarts from 'echarts';
|
|||||||
import VueClipboard from 'vue-clipboard2';
|
import VueClipboard from 'vue-clipboard2';
|
||||||
import { Notification } from 'element-ui';
|
import { Notification } from 'element-ui';
|
||||||
import Fingerprint2 from 'fingerprintjs2';
|
import Fingerprint2 from 'fingerprintjs2';
|
||||||
|
import VueClipboards from 'vue-clipboards';
|
||||||
|
|
||||||
|
|
||||||
// 生成唯一ID
|
// 生成唯一ID
|
||||||
Fingerprint2.get(function(components) {
|
Fingerprint2.get(function(components) {
|
||||||
@ -32,6 +34,7 @@ Fingerprint2.get(function(components) {
|
|||||||
Vue.use(VueClipboard);
|
Vue.use(VueClipboard);
|
||||||
Vue.use(ElementUI);
|
Vue.use(ElementUI);
|
||||||
Vue.use(VueCookies);
|
Vue.use(VueCookies);
|
||||||
|
Vue.use(VueClipboards);
|
||||||
Vue.prototype.$axios = axios;
|
Vue.prototype.$axios = axios;
|
||||||
Vue.prototype.$notify = Notification;
|
Vue.prototype.$notify = Notification;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import control from '../components/control.vue'
|
|||||||
import deviceList from '../components/DeviceList.vue'
|
import deviceList from '../components/DeviceList.vue'
|
||||||
import channelList from '../components/channelList.vue'
|
import channelList from '../components/channelList.vue'
|
||||||
import pushVideoList from '../components/PushVideoList.vue'
|
import pushVideoList from '../components/PushVideoList.vue'
|
||||||
|
import streamProxyList from '../components/StreamProxyList.vue'
|
||||||
import devicePosition from '../components/devicePosition.vue'
|
import devicePosition from '../components/devicePosition.vue'
|
||||||
import login from '../components/Login.vue'
|
import login from '../components/Login.vue'
|
||||||
import parentPlatformList from '../components/ParentPlatformList.vue'
|
import parentPlatformList from '../components/ParentPlatformList.vue'
|
||||||
@ -32,6 +33,10 @@ export default new VueRouter({
|
|||||||
path: '/pushVideoList',
|
path: '/pushVideoList',
|
||||||
component: pushVideoList,
|
component: pushVideoList,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/streamProxyList',
|
||||||
|
component: streamProxyList,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
name: '登录',
|
name: '登录',
|
||||||
|
Loading…
Reference in New Issue
Block a user