添加云端录像功能

This commit is contained in:
64850858
2021-06-01 17:05:07 +08:00
parent d881cd7eb3
commit ad93be12fb
34 changed files with 16251 additions and 690 deletions

View File

@@ -51,6 +51,9 @@ public class MediaConfig {
@Value("${media.rtp.portRange}")
private String rtpPortRange;
@Value("${media.recordAssistPort}")
private int recordAssistPort;
public String getIp() {
return ip;
}
@@ -174,4 +177,12 @@ public class MediaConfig {
public void setRtspSSLPort(String rtspSSLPort) {
this.rtspSSLPort = rtspSSLPort;
}
public int getRecordAssistPort() {
return recordAssistPort;
}
public void setRecordAssistPort(int recordAssistPort) {
this.recordAssistPort = recordAssistPort;
}
}

View File

@@ -0,0 +1,60 @@
package com.genersoft.iot.vmp.conf;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.mitre.dsmiley.httpproxy.ProxyServlet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import javax.servlet.ServletException;
import java.io.IOException;
import java.net.ConnectException;
import java.util.Locale;
@Configuration
public class ProxyServletConfig {
private final static Logger logger = LoggerFactory.getLogger(ProxyServletConfig.class);
@Autowired
private MediaConfig mediaConfig;
@Bean
public ServletRegistrationBean zlmServletRegistrationBean(){
String ip = StringUtils.isEmpty(mediaConfig.getWanIp())? mediaConfig.getIp(): mediaConfig.getWanIp();
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new ZLMProxySerlet(),"/zlm/*");
servletRegistrationBean.setName("zlm_Proxy");
servletRegistrationBean.addInitParameter("targetUri", String.format("http://%s:%s", ip, mediaConfig.getHttpPort()));
if (logger.isDebugEnabled()) {
servletRegistrationBean.addInitParameter("log", "true");
}
return servletRegistrationBean;
}
class ZLMProxySerlet extends ProxyServlet{
@Override
protected void handleRequestException(HttpRequest proxyRequest, HttpResponse proxyResonse, Exception e){
System.out.println(e.getMessage());
try {
super.handleRequestException(proxyRequest, proxyResonse, e);
} catch (ServletException servletException) {
logger.error("zlm 代理失败: ", e);
} catch (IOException ioException) {
if (ioException instanceof ConnectException) {
logger.error("zlm 连接失败");
}else {
logger.error("zlm 代理失败: ", e);
}
} catch (RuntimeException exception){
logger.error("zlm 代理失败: ", e);
}
}
}
}

View File

@@ -43,7 +43,6 @@ public class RedisConfig extends CachingConfigurerSupport {
* 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理
*
* @param connectionFactory
* @param listenerAdapter
* @return
*/
@Bean

View File

@@ -8,11 +8,53 @@ public class UserSetup {
@Value("${userSettings.savePositionHistory}")
boolean savePositionHistory;
@Value("${userSettings.autoApplyPlay}")
private boolean autoApplyPlay;
@Value("${userSettings.seniorSdp}")
private boolean seniorSdp;
@Value("${userSettings.playTimeout}")
private long playTimeout;
@Value("${userSettings.waitTrack}")
private boolean waitTrack;
@Value("${userSettings.interfaceAuthentication}")
private boolean interfaceAuthentication;
@Value("${userSettings.recordPushLive}")
private boolean recordPushLive;
public boolean getSavePositionHistory() {
return savePositionHistory;
}
public void setSavePositionHistory(boolean savePositionHistory) {
this.savePositionHistory = savePositionHistory;
public boolean isSavePositionHistory() {
return savePositionHistory;
}
public boolean isAutoApplyPlay() {
return autoApplyPlay;
}
public boolean isSeniorSdp() {
return seniorSdp;
}
public long getPlayTimeout() {
return playTimeout;
}
public boolean isWaitTrack() {
return waitTrack;
}
public boolean isInterfaceAuthentication() {
return interfaceAuthentication;
}
public boolean isRecordPushLive() {
return recordPushLive;
}
}

View File

@@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.conf.security;
import com.genersoft.iot.vmp.conf.UserSetup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
@@ -22,8 +23,8 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${userSettings.interfaceAuthentication}")
private boolean interfaceAuthentication;
@Autowired
private UserSetup userSetup;
@Autowired
private DefaultUserDetailsServiceImpl userDetailsService;
@@ -71,7 +72,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) {
if (!interfaceAuthentication) {
if (!userSetup.isInterfaceAuthentication()) {
web.ignoring().antMatchers("**");
}else {
// 可以直接访问的静态数据

View File

@@ -32,7 +32,7 @@ public class KeepaliveTimeoutListenerForPlatform extends KeyExpirationEventMessa
/**
* 监听失效的key
* @param message
* @param bytes
* @param pattern
*/
@Override
public void onMessage(Message message, byte[] pattern) {

View File

@@ -12,6 +12,7 @@ import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.MediaConfig;
import com.genersoft.iot.vmp.conf.UserSetup;
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
@@ -24,7 +25,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@@ -83,14 +83,8 @@ public class SIPCommander implements ISIPCommander {
@Autowired
private MediaConfig mediaConfig;
@Value("${userSettings.seniorSdp}")
private boolean seniorSdp;
@Value("${userSettings.autoApplyPlay}")
private boolean autoApplyPlay;
@Value("${userSettings.waitTrack}")
private boolean waitTrack;
@Autowired
private UserSetup userSetup;
@Autowired
private ZLMHttpHookSubscribe subscribe;
@@ -377,7 +371,7 @@ public class SIPCommander implements ISIPCommander {
subscribeKey.put("regist", true);
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, json->{
if (waitTrack && json.getJSONArray("tracks") == null) return;
if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
event.response(json);
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
});
@@ -390,7 +384,7 @@ public class SIPCommander implements ISIPCommander {
content.append("c=IN IP4 "+mediaInfo.getWanIp()+"\r\n");
content.append("t=0 0\r\n");
if (seniorSdp) {
if (userSetup.isSeniorSdp()) {
if("TCP-PASSIVE".equals(streamMode)) {
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
}else if ("TCP-ACTIVE".equals(streamMode)) {
@@ -478,7 +472,7 @@ public class SIPCommander implements ISIPCommander {
subscribeKey.put("regist", true);
logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, json->{
if (waitTrack && json.getJSONArray("tracks") == null) return;
if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
event.response(json);
subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
});
@@ -500,7 +494,7 @@ public class SIPCommander implements ISIPCommander {
}
String streamMode = device.getStreamMode().toUpperCase();
if (seniorSdp) {
if (userSetup.isSeniorSdp()) {
if("TCP-PASSIVE".equals(streamMode)) {
content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
}else if ("TCP-ACTIVE".equals(streamMode)) {

View File

@@ -1,54 +1,54 @@
package com.genersoft.iot.vmp.media.zlm;
import com.genersoft.iot.vmp.conf.MediaConfig;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("/zlm")
public class ZLMHTTPProxyController {
// private final static Logger logger = LoggerFactory.getLogger(ZLMHTTPProxyController.class);
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private MediaConfig mediaConfig;
@ResponseBody
@RequestMapping(value = "/**/**/**", produces = "application/json;charset=UTF-8")
public Object proxy(HttpServletRequest request, HttpServletResponse response){
if (redisCatchStorage.getMediaInfo() == null) {
return "未接入流媒体";
}
ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
String requestURI = String.format("http://%s:%s%s?%s&%s",
mediaInfo.getLocalIP(),
mediaConfig.getHttpPort(),
request.getRequestURI().replace("/zlm",""),
mediaInfo.getHookAdminParams(),
request.getQueryString()
);
// 发送请求
RestTemplate restTemplate = new RestTemplate();
//将指定的url返回的参数自动封装到自定义好的对应类对象中
Object result = null;
try {
result = restTemplate.getForObject(requestURI,Object.class);
}catch (HttpClientErrorException httpClientErrorException) {
response.setStatus(httpClientErrorException.getStatusCode().value());
}
return result;
}
}
//package com.genersoft.iot.vmp.media.zlm;
//
//import com.genersoft.iot.vmp.conf.MediaConfig;
//import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.web.bind.annotation.*;
//import org.springframework.web.client.HttpClientErrorException;
//import org.springframework.web.client.RestTemplate;
//
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//
//@RestController
//@RequestMapping("/zlm")
//public class ZLMHTTPProxyController {
//
//
// // private final static Logger logger = LoggerFactory.getLogger(ZLMHTTPProxyController.class);
//
// @Autowired
// private IRedisCatchStorage redisCatchStorage;
//
// @Autowired
// private MediaConfig mediaConfig;
//
// @ResponseBody
// @RequestMapping(value = "/**/**/**", produces = "application/json;charset=UTF-8")
// public Object proxy(HttpServletRequest request, HttpServletResponse response){
//
// if (redisCatchStorage.getMediaInfo() == null) {
// return "未接入流媒体";
// }
// ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
// String requestURI = String.format("http://%s:%s%s?%s&%s",
// mediaInfo.getLocalIP(),
// mediaConfig.getHttpPort(),
// request.getRequestURI().replace("/zlm",""),
// mediaInfo.getHookAdminParams(),
// request.getQueryString()
// );
// // 发送请求
// RestTemplate restTemplate = new RestTemplate();
// //将指定的url返回的参数自动封装到自定义好的对应类对象中
// Object result = null;
// try {
// result = restTemplate.getForObject(requestURI,Object.class);
//
// }catch (HttpClientErrorException httpClientErrorException) {
// response.setStatus(httpClientErrorException.getStatusCode().value());
// }
// return result;
// }
//}

View File

@@ -7,6 +7,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.MediaConfig;
import com.genersoft.iot.vmp.conf.UserSetup;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@@ -62,8 +63,8 @@ public class ZLMHttpHookListener {
@Autowired
private ZLMHttpHookSubscribe subscribe;
@Value("${userSettings.autoApplyPlay}")
private boolean autoApplyPlay;
@Autowired
private UserSetup userSetup;
@Autowired
private MediaConfig mediaConfig;
@@ -132,10 +133,8 @@ public class ZLMHttpHookListener {
@ResponseBody
@PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8")
public ResponseEntity<String> onPublish(@RequestBody JSONObject json){
if (logger.isDebugEnabled()) {
logger.debug("ZLM HOOK on_publish API调用参数" + json.toString());
}
logger.debug("ZLM HOOK on_publish API调用参数" + json.toString());
ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
if (subscribe != null) subscribe.response(json);
@@ -144,7 +143,7 @@ public class ZLMHttpHookListener {
ret.put("code", 0);
ret.put("msg", "success");
ret.put("enableHls", true);
ret.put("enableMP4", false);
ret.put("enableMP4", userSetup.isRecordPushLive());
ret.put("enableRtxp", true);
return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
}
@@ -333,7 +332,7 @@ public class ZLMHttpHookListener {
if (logger.isDebugEnabled()) {
logger.debug("ZLM HOOK on_stream_not_found API调用参数" + json.toString());
}
if (autoApplyPlay) {
if (userSetup.isAutoApplyPlay()) {
String app = json.getString("app");
String streamId = json.getString("stream");
StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);

View File

@@ -109,6 +109,10 @@ public class ZLMRunner implements CommandLineRunner {
if (StringUtils.isEmpty(mediaConfig.getHookIp())) mediaConfig.setHookIp(sipConfig.getSipIp());
String protocol = sslEnabled ? "https" : "http";
String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaConfig.getHookIp(), serverPort);
String recordHookPrex = null;
if (mediaConfig.getRecordAssistPort() != 0) {
recordHookPrex = String.format("http://127.0.0.1:%s/api/record", mediaConfig.getRecordAssistPort());
}
Map<String, Object> param = new HashMap<>();
param.put("api.secret",mediaConfig.getSecret()); // -profile:v Baseline
param.put("ffmpeg.cmd","%s -fflags nobuffer -rtsp_transport tcp -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s");
@@ -116,8 +120,8 @@ public class ZLMRunner implements CommandLineRunner {
param.put("hook.on_flow_report","");
param.put("hook.on_play",String.format("%s/on_play", hookPrex));
param.put("hook.on_http_access","");
param.put("hook.on_publish",String.format("%s/on_publish", hookPrex));
param.put("hook.on_record_mp4","");
param.put("hook.on_publish", String.format("%s/on_publish", hookPrex));
param.put("hook.on_record_mp4",recordHookPrex != null? String.format("%s/on_record_mp4", recordHookPrex): "");
param.put("hook.on_record_ts","");
param.put("hook.on_rtsp_auth","");
param.put("hook.on_rtsp_realm","");

View File

@@ -0,0 +1,8 @@
package com.genersoft.iot.vmp.service;
import com.genersoft.iot.vmp.storager.dao.dto.RecordInfo;
import com.github.pagehelper.PageInfo;
public interface IRecordInfoServer {
PageInfo<RecordInfo> getRecordList(int page, int count);
}

View File

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.conf.UserSetup;
import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
@@ -64,8 +65,8 @@ public class PlayServiceImpl implements IPlayService {
@Autowired
private VideoStreamSessionManager streamSession;
@Value("${userSettings.playTimeout}")
private long playTimeout;
@Autowired
private UserSetup userSetup;
@Override
@@ -76,7 +77,7 @@ public class PlayServiceImpl implements IPlayService {
playResult.setDevice(device);
UUID uuid = UUID.randomUUID();
playResult.setUuid(uuid.toString());
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(playTimeout);
DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(userSetup.getPlayTimeout());
playResult.setResult(result);
// 录像查询以channelId作为deviceId查询
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);

View File

@@ -0,0 +1,26 @@
package com.genersoft.iot.vmp.service.impl;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.service.IRecordInfoServer;
import com.genersoft.iot.vmp.storager.dao.RecordInfoDao;
import com.genersoft.iot.vmp.storager.dao.dto.RecordInfo;
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 RecordInfoServerImpl implements IRecordInfoServer {
@Autowired
private RecordInfoDao recordInfoDao;
@Override
public PageInfo<RecordInfo> getRecordList(int page, int count) {
PageHelper.startPage(page, count);
List<RecordInfo> all = recordInfoDao.selectAll();
return new PageInfo<>(all);
}
}

View File

@@ -0,0 +1,26 @@
package com.genersoft.iot.vmp.storager.dao;
import com.genersoft.iot.vmp.storager.dao.dto.RecordInfo;
import com.genersoft.iot.vmp.storager.dao.dto.User;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface RecordInfoDao {
@Insert("INSERT INTO recordInfo (app, stream, mediaServerId, createTime, type, deviceId, channelId, name) VALUES" +
"('${app}', '${stream}', '${mediaServerId}', datetime('now','localtime')), '${type}', '${deviceId}', '${channelId}', '${name}'")
int add(RecordInfo recordInfo);
@Delete("DELETE FROM user WHERE createTime < '${beforeTime}'")
int deleteBefore(String beforeTime);
@Select("select * FROM recordInfo")
List<RecordInfo> selectAll();
}

View File

@@ -0,0 +1,133 @@
package com.genersoft.iot.vmp.storager.dao.dto;
/**
* 录像记录
*/
public class RecordInfo {
/**
* ID
*/
private int id;
/**
* 应用名
*/
private String app;
/**
* 流ID
*/
private String stream;
/**
* 对应的zlm流媒体的ID
*/
private String mediaServerId;
/**
* 创建时间
*/
private String createTime;
/**
* 类型 对应zlm的 originType
* unknown = 0,
* rtmp_push=1,
* rtsp_push=2,
* rtp_push=3,
* pull=4,
* ffmpeg_pull=5,
* mp4_vod=6,
* device_chn=7,
* rtc_push=8
*/
private int type;
/**
* 国标录像时的设备ID
*/
private String deviceId;
/**
* 国标录像时的通道ID
*/
private String channelId;
/**
* 拉流代理录像时的名称
*/
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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 getMediaServerId() {
return mediaServerId;
}
public void setMediaServerId(String mediaServerId) {
this.mediaServerId = mediaServerId;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getChannelId() {
return channelId;
}
public void setChannelId(String channelId) {
this.channelId = channelId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -26,9 +26,9 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@CrossOrigin
@RestController
@RequestMapping("/api/gb_record")
public class RecordController {
public class GBRecordController {
private final static Logger logger = LoggerFactory.getLogger(RecordController.class);
private final static Logger logger = LoggerFactory.getLogger(GBRecordController.class);
@Autowired
private SIPCommander cmder;

View File

@@ -0,0 +1,68 @@
package com.genersoft.iot.vmp.vmanager.record;
import com.genersoft.iot.vmp.conf.MediaConfig;
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
@RestController
@RequestMapping("/record_proxy")
public class RecoderProxyController {
// private final static Logger logger = LoggerFactory.getLogger(ZLMHTTPProxyController.class);
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private MediaConfig mediaConfig;
@ResponseBody
@RequestMapping(value = "/**/**/**", produces = "application/json;charset=UTF-8")
public Object proxy(HttpServletRequest request, HttpServletResponse response){
String baseRequestURI = request.getRequestURI();
String[] split = baseRequestURI.split("/");
if (split.length <= 2) {
response.setStatus(HttpStatus.NOT_FOUND.value());
return null;
}
String mediaId = split[2];
if (StringUtils.isEmpty(mediaId)){
response.setStatus(HttpStatus.BAD_REQUEST.value());
return null;
}
// 后续改为根据Id获取对应的ZLM
ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
String requestURI = String.format("http://%s:%s%s?%s",
mediaInfo.getLocalIP(),
mediaConfig.getRecordAssistPort(),
baseRequestURI.substring(baseRequestURI.indexOf(mediaId) + mediaId.length()),
URLDecoder.decode(request.getQueryString())
);
// 发送请求
RestTemplate restTemplate = new RestTemplate();
//将指定的url返回的参数自动封装到自定义好的对应类对象中
Object result = null;
try {
result = restTemplate.getForObject(requestURI,Object.class);
}catch (HttpClientErrorException httpClientErrorException) {
response.setStatus(httpClientErrorException.getStatusCode().value());
}
return result;
}
}

View File

@@ -0,0 +1,51 @@
//package com.genersoft.iot.vmp.vmanager.record;
//
//import com.alibaba.fastjson.JSONObject;
//import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
//import com.genersoft.iot.vmp.service.IRecordInfoServer;
//import com.genersoft.iot.vmp.storager.dao.dto.RecordInfo;
//import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
//import com.github.pagehelper.PageInfo;
//import io.swagger.annotations.Api;
//import io.swagger.annotations.ApiImplicitParam;
//import io.swagger.annotations.ApiImplicitParams;
//import io.swagger.annotations.ApiOperation;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.web.bind.annotation.*;
//
//@Api(tags = "云端录像")
//@CrossOrigin
//@RestController
//@RequestMapping("/api/record")
//public class RecordController {
//
// @Autowired
// private IRecordInfoServer recordInfoServer;
//
// @ApiOperation("录像列表查询")
// @ApiImplicitParams({
// @ApiImplicitParam(name="page", value = "当前页", required = true, dataTypeClass = Integer.class),
// @ApiImplicitParam(name="count", value = "每页查询数量", required = true, dataTypeClass = Integer.class),
// @ApiImplicitParam(name="query", value = "查询内容", dataTypeClass = String.class),
// })
// @GetMapping(value = "/app/list")
// @ResponseBody
// public Object list(@RequestParam(required = false)Integer page,
// @RequestParam(required = false)Integer count ){
//
// PageInfo<RecordInfo> recordList = recordInfoServer.getRecordList(page - 1, page - 1 + count);
// return recordList;
// }
//
// @ApiOperation("获取录像详情")
// @ApiImplicitParams({
// @ApiImplicitParam(name="recordInfo", value = "录像记录", required = true, dataTypeClass = RecordInfo.class)
// })
// @GetMapping(value = "/detail")
// @ResponseBody
// public JSONObject list(RecordInfo recordInfo, String time ){
//
//
// return null;
// }
//}

View File

@@ -1,6 +1,9 @@
package com.genersoft.iot.vmp.vmanager.server;
import com.genersoft.iot.vmp.VManageBootstrap;
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.impl.RedisCatchStorageImpl;
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
import gov.nist.javax.sip.SipStackImpl;
import io.swagger.annotations.Api;
@@ -12,6 +15,7 @@ import org.springframework.web.bind.annotation.*;
import javax.sip.ListeningPoint;
import javax.sip.ObjectInUseException;
import javax.sip.SipProvider;
import java.util.ArrayList;
import java.util.Iterator;
@SuppressWarnings("rawtypes")
@@ -24,6 +28,20 @@ public class ServerController {
@Autowired
private ConfigurableApplicationContext context;
@Autowired
private IRedisCatchStorage redisCatchStorage;
@ApiOperation("流媒体服务列表")
@GetMapping(value = "/media_server/list")
@ResponseBody
public Object getMediaServerList(){
// TODO 为后续多个zlm支持准备
ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
ArrayList<ZLMServerConfig> result = new ArrayList<>();
result.add(mediaInfo);
return result;
}
@ApiOperation("重启服务")
@GetMapping(value = "/restart")