Commit ad93be12fb3705e995cf0dab933760edaef3dd7a

Authored by 64850858
1 parent d881cd7e

添加云端录像功能

Showing 23 changed files with 541 additions and 93 deletions

Too many changes to show.

To preserve performance only 23 of 34 files are displayed.

README.md
@@ -92,9 +92,6 @@ https://gitee.com/18010473990/wvp-GB28181.git @@ -92,9 +92,6 @@ https://gitee.com/18010473990/wvp-GB28181.git
92 - [ ] 添加系统配置 92 - [ ] 添加系统配置
93 - [ ] 添加用户管理 93 - [ ] 添加用户管理
94 94
95 -# 待实现:  
96 -web界面系统设置  
97 -  
98 95
99 # 项目部署 96 # 项目部署
100 参考:[WIKI](https://github.com/648540858/wvp-GB28181-pro/wiki) 97 参考:[WIKI](https://github.com/648540858/wvp-GB28181-pro/wiki)
@@ -104,7 +101,7 @@ https://gitee.com/18010473990/wvp-GB28181.git @@ -104,7 +101,7 @@ https://gitee.com/18010473990/wvp-GB28181.git
104 101
105 # 使用帮助 102 # 使用帮助
106 QQ群: 901799015, 542509000(ZLM大群) 103 QQ群: 901799015, 542509000(ZLM大群)
107 -QQ私信一般不回, 精力有限.欢迎大家在群里讨论. 104 +QQ私信一般不回, 精力有限.欢迎大家在群里讨论.觉得项目对你有帮助,欢迎star和提交pr。
108 105
109 # 致谢 106 # 致谢
110 感谢作者[夏楚](https://github.com/xia-chu) 提供这么棒的开源流媒体服务框架 107 感谢作者[夏楚](https://github.com/xia-chu) 提供这么棒的开源流媒体服务框架
@@ -184,6 +184,12 @@ @@ -184,6 +184,12 @@
184 <version>2.3.0</version> 184 <version>2.3.0</version>
185 </dependency> 185 </dependency>
186 186
  187 + <!--反向代理-->
  188 + <dependency>
  189 + <groupId>org.mitre.dsmiley.httpproxy</groupId>
  190 + <artifactId>smiley-http-proxy-servlet</artifactId>
  191 + <version>1.12</version>
  192 + </dependency>
187 193
188 <!-- onvif协议栈 --> 194 <!-- onvif协议栈 -->
189 <dependency> 195 <dependency>
src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java
@@ -51,6 +51,9 @@ public class MediaConfig { @@ -51,6 +51,9 @@ public class MediaConfig {
51 @Value("${media.rtp.portRange}") 51 @Value("${media.rtp.portRange}")
52 private String rtpPortRange; 52 private String rtpPortRange;
53 53
  54 + @Value("${media.recordAssistPort}")
  55 + private int recordAssistPort;
  56 +
54 public String getIp() { 57 public String getIp() {
55 return ip; 58 return ip;
56 } 59 }
@@ -174,4 +177,12 @@ public class MediaConfig { @@ -174,4 +177,12 @@ public class MediaConfig {
174 public void setRtspSSLPort(String rtspSSLPort) { 177 public void setRtspSSLPort(String rtspSSLPort) {
175 this.rtspSSLPort = rtspSSLPort; 178 this.rtspSSLPort = rtspSSLPort;
176 } 179 }
  180 +
  181 + public int getRecordAssistPort() {
  182 + return recordAssistPort;
  183 + }
  184 +
  185 + public void setRecordAssistPort(int recordAssistPort) {
  186 + this.recordAssistPort = recordAssistPort;
  187 + }
177 } 188 }
src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf;
  2 +
  3 +import org.apache.http.HttpRequest;
  4 +import org.apache.http.HttpResponse;
  5 +import org.mitre.dsmiley.httpproxy.ProxyServlet;
  6 +import org.slf4j.Logger;
  7 +import org.slf4j.LoggerFactory;
  8 +import org.springframework.beans.factory.annotation.Autowired;
  9 +import org.springframework.boot.web.servlet.ServletRegistrationBean;
  10 +import org.springframework.context.annotation.Bean;
  11 +import org.springframework.context.annotation.Configuration;
  12 +import org.springframework.util.StringUtils;
  13 +
  14 +import javax.servlet.ServletException;
  15 +import java.io.IOException;
  16 +import java.net.ConnectException;
  17 +import java.util.Locale;
  18 +
  19 +
  20 +@Configuration
  21 +public class ProxyServletConfig {
  22 +
  23 + private final static Logger logger = LoggerFactory.getLogger(ProxyServletConfig.class);
  24 +
  25 + @Autowired
  26 + private MediaConfig mediaConfig;
  27 +
  28 + @Bean
  29 + public ServletRegistrationBean zlmServletRegistrationBean(){
  30 + String ip = StringUtils.isEmpty(mediaConfig.getWanIp())? mediaConfig.getIp(): mediaConfig.getWanIp();
  31 + ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new ZLMProxySerlet(),"/zlm/*");
  32 + servletRegistrationBean.setName("zlm_Proxy");
  33 + servletRegistrationBean.addInitParameter("targetUri", String.format("http://%s:%s", ip, mediaConfig.getHttpPort()));
  34 + if (logger.isDebugEnabled()) {
  35 + servletRegistrationBean.addInitParameter("log", "true");
  36 + }
  37 + return servletRegistrationBean;
  38 + }
  39 +
  40 + class ZLMProxySerlet extends ProxyServlet{
  41 + @Override
  42 + protected void handleRequestException(HttpRequest proxyRequest, HttpResponse proxyResonse, Exception e){
  43 + System.out.println(e.getMessage());
  44 + try {
  45 + super.handleRequestException(proxyRequest, proxyResonse, e);
  46 + } catch (ServletException servletException) {
  47 + logger.error("zlm 代理失败: ", e);
  48 + } catch (IOException ioException) {
  49 + if (ioException instanceof ConnectException) {
  50 + logger.error("zlm 连接失败");
  51 + }else {
  52 + logger.error("zlm 代理失败: ", e);
  53 + }
  54 + } catch (RuntimeException exception){
  55 + logger.error("zlm 代理失败: ", e);
  56 + }
  57 + }
  58 + }
  59 +
  60 +}
src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
@@ -43,7 +43,6 @@ public class RedisConfig extends CachingConfigurerSupport { @@ -43,7 +43,6 @@ public class RedisConfig extends CachingConfigurerSupport {
43 * 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理 43 * 通过反射技术调用消息订阅处理器的相关方法进行一些业务处理
44 * 44 *
45 * @param connectionFactory 45 * @param connectionFactory
46 - * @param listenerAdapter  
47 * @return 46 * @return
48 */ 47 */
49 @Bean 48 @Bean
src/main/java/com/genersoft/iot/vmp/conf/UserSetup.java
@@ -8,11 +8,53 @@ public class UserSetup { @@ -8,11 +8,53 @@ public class UserSetup {
8 @Value("${userSettings.savePositionHistory}") 8 @Value("${userSettings.savePositionHistory}")
9 boolean savePositionHistory; 9 boolean savePositionHistory;
10 10
  11 + @Value("${userSettings.autoApplyPlay}")
  12 + private boolean autoApplyPlay;
  13 +
  14 + @Value("${userSettings.seniorSdp}")
  15 + private boolean seniorSdp;
  16 +
  17 + @Value("${userSettings.playTimeout}")
  18 + private long playTimeout;
  19 +
  20 + @Value("${userSettings.waitTrack}")
  21 + private boolean waitTrack;
  22 +
  23 + @Value("${userSettings.interfaceAuthentication}")
  24 + private boolean interfaceAuthentication;
  25 +
  26 + @Value("${userSettings.recordPushLive}")
  27 + private boolean recordPushLive;
  28 +
11 public boolean getSavePositionHistory() { 29 public boolean getSavePositionHistory() {
12 return savePositionHistory; 30 return savePositionHistory;
13 } 31 }
14 32
15 - public void setSavePositionHistory(boolean savePositionHistory) {  
16 - this.savePositionHistory = savePositionHistory; 33 + public boolean isSavePositionHistory() {
  34 + return savePositionHistory;
  35 + }
  36 +
  37 + public boolean isAutoApplyPlay() {
  38 + return autoApplyPlay;
  39 + }
  40 +
  41 + public boolean isSeniorSdp() {
  42 + return seniorSdp;
  43 + }
  44 +
  45 + public long getPlayTimeout() {
  46 + return playTimeout;
  47 + }
  48 +
  49 + public boolean isWaitTrack() {
  50 + return waitTrack;
  51 + }
  52 +
  53 + public boolean isInterfaceAuthentication() {
  54 + return interfaceAuthentication;
  55 + }
  56 +
  57 + public boolean isRecordPushLive() {
  58 + return recordPushLive;
17 } 59 }
18 } 60 }
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
1 package com.genersoft.iot.vmp.conf.security; 1 package com.genersoft.iot.vmp.conf.security;
2 2
  3 +import com.genersoft.iot.vmp.conf.UserSetup;
3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.beans.factory.annotation.Value; 5 import org.springframework.beans.factory.annotation.Value;
5 import org.springframework.context.annotation.Bean; 6 import org.springframework.context.annotation.Bean;
@@ -22,8 +23,8 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -22,8 +23,8 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
22 @EnableGlobalMethodSecurity(prePostEnabled = true) 23 @EnableGlobalMethodSecurity(prePostEnabled = true)
23 public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 24 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
24 25
25 - @Value("${userSettings.interfaceAuthentication}")  
26 - private boolean interfaceAuthentication; 26 + @Autowired
  27 + private UserSetup userSetup;
27 28
28 @Autowired 29 @Autowired
29 private DefaultUserDetailsServiceImpl userDetailsService; 30 private DefaultUserDetailsServiceImpl userDetailsService;
@@ -71,7 +72,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @@ -71,7 +72,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
71 @Override 72 @Override
72 public void configure(WebSecurity web) { 73 public void configure(WebSecurity web) {
73 74
74 - if (!interfaceAuthentication) { 75 + if (!userSetup.isInterfaceAuthentication()) {
75 web.ignoring().antMatchers("**"); 76 web.ignoring().antMatchers("**");
76 }else { 77 }else {
77 // 可以直接访问的静态数据 78 // 可以直接访问的静态数据
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java
@@ -32,7 +32,7 @@ public class KeepaliveTimeoutListenerForPlatform extends KeyExpirationEventMessa @@ -32,7 +32,7 @@ public class KeepaliveTimeoutListenerForPlatform extends KeyExpirationEventMessa
32 /** 32 /**
33 * 监听失效的key 33 * 监听失效的key
34 * @param message 34 * @param message
35 - * @param bytes 35 + * @param pattern
36 */ 36 */
37 @Override 37 @Override
38 public void onMessage(Message message, byte[] pattern) { 38 public void onMessage(Message message, byte[] pattern) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -12,6 +12,7 @@ import com.alibaba.fastjson.JSONArray; @@ -12,6 +12,7 @@ import com.alibaba.fastjson.JSONArray;
12 import com.alibaba.fastjson.JSONObject; 12 import com.alibaba.fastjson.JSONObject;
13 import com.genersoft.iot.vmp.common.StreamInfo; 13 import com.genersoft.iot.vmp.common.StreamInfo;
14 import com.genersoft.iot.vmp.conf.MediaConfig; 14 import com.genersoft.iot.vmp.conf.MediaConfig;
  15 +import com.genersoft.iot.vmp.conf.UserSetup;
15 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; 16 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
16 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 17 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
17 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; 18 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
@@ -24,7 +25,6 @@ import org.slf4j.Logger; @@ -24,7 +25,6 @@ import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory; 25 import org.slf4j.LoggerFactory;
25 import org.springframework.beans.factory.annotation.Autowired; 26 import org.springframework.beans.factory.annotation.Autowired;
26 import org.springframework.beans.factory.annotation.Qualifier; 27 import org.springframework.beans.factory.annotation.Qualifier;
27 -import org.springframework.beans.factory.annotation.Value;  
28 import org.springframework.context.annotation.DependsOn; 28 import org.springframework.context.annotation.DependsOn;
29 import org.springframework.context.annotation.Lazy; 29 import org.springframework.context.annotation.Lazy;
30 import org.springframework.stereotype.Component; 30 import org.springframework.stereotype.Component;
@@ -83,14 +83,8 @@ public class SIPCommander implements ISIPCommander { @@ -83,14 +83,8 @@ public class SIPCommander implements ISIPCommander {
83 @Autowired 83 @Autowired
84 private MediaConfig mediaConfig; 84 private MediaConfig mediaConfig;
85 85
86 - @Value("${userSettings.seniorSdp}")  
87 - private boolean seniorSdp;  
88 -  
89 - @Value("${userSettings.autoApplyPlay}")  
90 - private boolean autoApplyPlay;  
91 -  
92 - @Value("${userSettings.waitTrack}")  
93 - private boolean waitTrack; 86 + @Autowired
  87 + private UserSetup userSetup;
94 88
95 @Autowired 89 @Autowired
96 private ZLMHttpHookSubscribe subscribe; 90 private ZLMHttpHookSubscribe subscribe;
@@ -377,7 +371,7 @@ public class SIPCommander implements ISIPCommander { @@ -377,7 +371,7 @@ public class SIPCommander implements ISIPCommander {
377 subscribeKey.put("regist", true); 371 subscribeKey.put("regist", true);
378 372
379 subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, json->{ 373 subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, json->{
380 - if (waitTrack && json.getJSONArray("tracks") == null) return; 374 + if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
381 event.response(json); 375 event.response(json);
382 subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey); 376 subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
383 }); 377 });
@@ -390,7 +384,7 @@ public class SIPCommander implements ISIPCommander { @@ -390,7 +384,7 @@ public class SIPCommander implements ISIPCommander {
390 content.append("c=IN IP4 "+mediaInfo.getWanIp()+"\r\n"); 384 content.append("c=IN IP4 "+mediaInfo.getWanIp()+"\r\n");
391 content.append("t=0 0\r\n"); 385 content.append("t=0 0\r\n");
392 386
393 - if (seniorSdp) { 387 + if (userSetup.isSeniorSdp()) {
394 if("TCP-PASSIVE".equals(streamMode)) { 388 if("TCP-PASSIVE".equals(streamMode)) {
395 content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); 389 content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
396 }else if ("TCP-ACTIVE".equals(streamMode)) { 390 }else if ("TCP-ACTIVE".equals(streamMode)) {
@@ -478,7 +472,7 @@ public class SIPCommander implements ISIPCommander { @@ -478,7 +472,7 @@ public class SIPCommander implements ISIPCommander {
478 subscribeKey.put("regist", true); 472 subscribeKey.put("regist", true);
479 logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString()); 473 logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
480 subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, json->{ 474 subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, json->{
481 - if (waitTrack && json.getJSONArray("tracks") == null) return; 475 + if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return;
482 event.response(json); 476 event.response(json);
483 subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey); 477 subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);
484 }); 478 });
@@ -500,7 +494,7 @@ public class SIPCommander implements ISIPCommander { @@ -500,7 +494,7 @@ public class SIPCommander implements ISIPCommander {
500 } 494 }
501 String streamMode = device.getStreamMode().toUpperCase(); 495 String streamMode = device.getStreamMode().toUpperCase();
502 496
503 - if (seniorSdp) { 497 + if (userSetup.isSeniorSdp()) {
504 if("TCP-PASSIVE".equals(streamMode)) { 498 if("TCP-PASSIVE".equals(streamMode)) {
505 content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n"); 499 content.append("m=video "+ mediaPort +" TCP/RTP/AVP 96 126 125 99 34 98 97\r\n");
506 }else if ("TCP-ACTIVE".equals(streamMode)) { 500 }else if ("TCP-ACTIVE".equals(streamMode)) {
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHTTPProxyController.java
1 -package com.genersoft.iot.vmp.media.zlm;  
2 -  
3 -import com.genersoft.iot.vmp.conf.MediaConfig;  
4 -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;  
5 -import org.springframework.beans.factory.annotation.Autowired;  
6 -import org.springframework.beans.factory.annotation.Value;  
7 -import org.springframework.web.bind.annotation.*;  
8 -import org.springframework.web.client.HttpClientErrorException;  
9 -import org.springframework.web.client.RestTemplate;  
10 -  
11 -import javax.servlet.http.HttpServletRequest;  
12 -import javax.servlet.http.HttpServletResponse;  
13 -  
14 -@RestController  
15 -@RequestMapping("/zlm")  
16 -public class ZLMHTTPProxyController {  
17 -  
18 -  
19 - // private final static Logger logger = LoggerFactory.getLogger(ZLMHTTPProxyController.class);  
20 -  
21 - @Autowired  
22 - private IRedisCatchStorage redisCatchStorage;  
23 -  
24 - @Autowired  
25 - private MediaConfig mediaConfig;  
26 -  
27 - @ResponseBody  
28 - @RequestMapping(value = "/**/**/**", produces = "application/json;charset=UTF-8")  
29 - public Object proxy(HttpServletRequest request, HttpServletResponse response){  
30 -  
31 - if (redisCatchStorage.getMediaInfo() == null) {  
32 - return "未接入流媒体";  
33 - }  
34 - ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();  
35 - String requestURI = String.format("http://%s:%s%s?%s&%s",  
36 - mediaInfo.getLocalIP(),  
37 - mediaConfig.getHttpPort(),  
38 - request.getRequestURI().replace("/zlm",""),  
39 - mediaInfo.getHookAdminParams(),  
40 - request.getQueryString()  
41 - );  
42 - // 发送请求  
43 - RestTemplate restTemplate = new RestTemplate();  
44 - //将指定的url返回的参数自动封装到自定义好的对应类对象中  
45 - Object result = null;  
46 - try {  
47 - result = restTemplate.getForObject(requestURI,Object.class);  
48 -  
49 - }catch (HttpClientErrorException httpClientErrorException) {  
50 - response.setStatus(httpClientErrorException.getStatusCode().value());  
51 - }  
52 - return result;  
53 - }  
54 -} 1 +//package com.genersoft.iot.vmp.media.zlm;
  2 +//
  3 +//import com.genersoft.iot.vmp.conf.MediaConfig;
  4 +//import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  5 +//import org.springframework.beans.factory.annotation.Autowired;
  6 +//import org.springframework.beans.factory.annotation.Value;
  7 +//import org.springframework.web.bind.annotation.*;
  8 +//import org.springframework.web.client.HttpClientErrorException;
  9 +//import org.springframework.web.client.RestTemplate;
  10 +//
  11 +//import javax.servlet.http.HttpServletRequest;
  12 +//import javax.servlet.http.HttpServletResponse;
  13 +//
  14 +//@RestController
  15 +//@RequestMapping("/zlm")
  16 +//public class ZLMHTTPProxyController {
  17 +//
  18 +//
  19 +// // private final static Logger logger = LoggerFactory.getLogger(ZLMHTTPProxyController.class);
  20 +//
  21 +// @Autowired
  22 +// private IRedisCatchStorage redisCatchStorage;
  23 +//
  24 +// @Autowired
  25 +// private MediaConfig mediaConfig;
  26 +//
  27 +// @ResponseBody
  28 +// @RequestMapping(value = "/**/**/**", produces = "application/json;charset=UTF-8")
  29 +// public Object proxy(HttpServletRequest request, HttpServletResponse response){
  30 +//
  31 +// if (redisCatchStorage.getMediaInfo() == null) {
  32 +// return "未接入流媒体";
  33 +// }
  34 +// ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
  35 +// String requestURI = String.format("http://%s:%s%s?%s&%s",
  36 +// mediaInfo.getLocalIP(),
  37 +// mediaConfig.getHttpPort(),
  38 +// request.getRequestURI().replace("/zlm",""),
  39 +// mediaInfo.getHookAdminParams(),
  40 +// request.getQueryString()
  41 +// );
  42 +// // 发送请求
  43 +// RestTemplate restTemplate = new RestTemplate();
  44 +// //将指定的url返回的参数自动封装到自定义好的对应类对象中
  45 +// Object result = null;
  46 +// try {
  47 +// result = restTemplate.getForObject(requestURI,Object.class);
  48 +//
  49 +// }catch (HttpClientErrorException httpClientErrorException) {
  50 +// response.setStatus(httpClientErrorException.getStatusCode().value());
  51 +// }
  52 +// return result;
  53 +// }
  54 +//}
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -7,6 +7,7 @@ import com.alibaba.fastjson.JSON; @@ -7,6 +7,7 @@ import com.alibaba.fastjson.JSON;
7 import com.alibaba.fastjson.JSONArray; 7 import com.alibaba.fastjson.JSONArray;
8 import com.genersoft.iot.vmp.common.StreamInfo; 8 import com.genersoft.iot.vmp.common.StreamInfo;
9 import com.genersoft.iot.vmp.conf.MediaConfig; 9 import com.genersoft.iot.vmp.conf.MediaConfig;
  10 +import com.genersoft.iot.vmp.conf.UserSetup;
10 import com.genersoft.iot.vmp.gb28181.bean.Device; 11 import com.genersoft.iot.vmp.gb28181.bean.Device;
11 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 12 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
12 import com.genersoft.iot.vmp.storager.IVideoManagerStorager; 13 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@@ -62,8 +63,8 @@ public class ZLMHttpHookListener { @@ -62,8 +63,8 @@ public class ZLMHttpHookListener {
62 @Autowired 63 @Autowired
63 private ZLMHttpHookSubscribe subscribe; 64 private ZLMHttpHookSubscribe subscribe;
64 65
65 - @Value("${userSettings.autoApplyPlay}")  
66 - private boolean autoApplyPlay; 66 + @Autowired
  67 + private UserSetup userSetup;
67 68
68 @Autowired 69 @Autowired
69 private MediaConfig mediaConfig; 70 private MediaConfig mediaConfig;
@@ -132,10 +133,8 @@ public class ZLMHttpHookListener { @@ -132,10 +133,8 @@ public class ZLMHttpHookListener {
132 @ResponseBody 133 @ResponseBody
133 @PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8") 134 @PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8")
134 public ResponseEntity<String> onPublish(@RequestBody JSONObject json){ 135 public ResponseEntity<String> onPublish(@RequestBody JSONObject json){
135 -  
136 - if (logger.isDebugEnabled()) {  
137 - logger.debug("ZLM HOOK on_publish API调用,参数:" + json.toString());  
138 - } 136 +
  137 + logger.debug("ZLM HOOK on_publish API调用,参数:" + json.toString());
139 138
140 ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json); 139 ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json);
141 if (subscribe != null) subscribe.response(json); 140 if (subscribe != null) subscribe.response(json);
@@ -144,7 +143,7 @@ public class ZLMHttpHookListener { @@ -144,7 +143,7 @@ public class ZLMHttpHookListener {
144 ret.put("code", 0); 143 ret.put("code", 0);
145 ret.put("msg", "success"); 144 ret.put("msg", "success");
146 ret.put("enableHls", true); 145 ret.put("enableHls", true);
147 - ret.put("enableMP4", false); 146 + ret.put("enableMP4", userSetup.isRecordPushLive());
148 ret.put("enableRtxp", true); 147 ret.put("enableRtxp", true);
149 return new ResponseEntity<String>(ret.toString(),HttpStatus.OK); 148 return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
150 } 149 }
@@ -333,7 +332,7 @@ public class ZLMHttpHookListener { @@ -333,7 +332,7 @@ public class ZLMHttpHookListener {
333 if (logger.isDebugEnabled()) { 332 if (logger.isDebugEnabled()) {
334 logger.debug("ZLM HOOK on_stream_not_found API调用,参数:" + json.toString()); 333 logger.debug("ZLM HOOK on_stream_not_found API调用,参数:" + json.toString());
335 } 334 }
336 - if (autoApplyPlay) { 335 + if (userSetup.isAutoApplyPlay()) {
337 String app = json.getString("app"); 336 String app = json.getString("app");
338 String streamId = json.getString("stream"); 337 String streamId = json.getString("stream");
339 StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId); 338 StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId);
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
@@ -109,6 +109,10 @@ public class ZLMRunner implements CommandLineRunner { @@ -109,6 +109,10 @@ public class ZLMRunner implements CommandLineRunner {
109 if (StringUtils.isEmpty(mediaConfig.getHookIp())) mediaConfig.setHookIp(sipConfig.getSipIp()); 109 if (StringUtils.isEmpty(mediaConfig.getHookIp())) mediaConfig.setHookIp(sipConfig.getSipIp());
110 String protocol = sslEnabled ? "https" : "http"; 110 String protocol = sslEnabled ? "https" : "http";
111 String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaConfig.getHookIp(), serverPort); 111 String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaConfig.getHookIp(), serverPort);
  112 + String recordHookPrex = null;
  113 + if (mediaConfig.getRecordAssistPort() != 0) {
  114 + recordHookPrex = String.format("http://127.0.0.1:%s/api/record", mediaConfig.getRecordAssistPort());
  115 + }
112 Map<String, Object> param = new HashMap<>(); 116 Map<String, Object> param = new HashMap<>();
113 param.put("api.secret",mediaConfig.getSecret()); // -profile:v Baseline 117 param.put("api.secret",mediaConfig.getSecret()); // -profile:v Baseline
114 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"); 118 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 { @@ -116,8 +120,8 @@ public class ZLMRunner implements CommandLineRunner {
116 param.put("hook.on_flow_report",""); 120 param.put("hook.on_flow_report","");
117 param.put("hook.on_play",String.format("%s/on_play", hookPrex)); 121 param.put("hook.on_play",String.format("%s/on_play", hookPrex));
118 param.put("hook.on_http_access",""); 122 param.put("hook.on_http_access","");
119 - param.put("hook.on_publish",String.format("%s/on_publish", hookPrex));  
120 - param.put("hook.on_record_mp4",""); 123 + param.put("hook.on_publish", String.format("%s/on_publish", hookPrex));
  124 + param.put("hook.on_record_mp4",recordHookPrex != null? String.format("%s/on_record_mp4", recordHookPrex): "");
121 param.put("hook.on_record_ts",""); 125 param.put("hook.on_record_ts","");
122 param.put("hook.on_rtsp_auth",""); 126 param.put("hook.on_rtsp_auth","");
123 param.put("hook.on_rtsp_realm",""); 127 param.put("hook.on_rtsp_realm","");
src/main/java/com/genersoft/iot/vmp/service/IRecordInfoServer.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service;
  2 +
  3 +import com.genersoft.iot.vmp.storager.dao.dto.RecordInfo;
  4 +import com.github.pagehelper.PageInfo;
  5 +
  6 +public interface IRecordInfoServer {
  7 + PageInfo<RecordInfo> getRecordList(int page, int count);
  8 +}
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
4 import com.alibaba.fastjson.JSONArray; 4 import com.alibaba.fastjson.JSONArray;
5 import com.alibaba.fastjson.JSONObject; 5 import com.alibaba.fastjson.JSONObject;
6 import com.genersoft.iot.vmp.common.StreamInfo; 6 import com.genersoft.iot.vmp.common.StreamInfo;
  7 +import com.genersoft.iot.vmp.conf.UserSetup;
7 import com.genersoft.iot.vmp.gb28181.bean.Device; 8 import com.genersoft.iot.vmp.gb28181.bean.Device;
8 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 9 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
9 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 10 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
@@ -64,8 +65,8 @@ public class PlayServiceImpl implements IPlayService { @@ -64,8 +65,8 @@ public class PlayServiceImpl implements IPlayService {
64 @Autowired 65 @Autowired
65 private VideoStreamSessionManager streamSession; 66 private VideoStreamSessionManager streamSession;
66 67
67 - @Value("${userSettings.playTimeout}")  
68 - private long playTimeout; 68 + @Autowired
  69 + private UserSetup userSetup;
69 70
70 71
71 @Override 72 @Override
@@ -76,7 +77,7 @@ public class PlayServiceImpl implements IPlayService { @@ -76,7 +77,7 @@ public class PlayServiceImpl implements IPlayService {
76 playResult.setDevice(device); 77 playResult.setDevice(device);
77 UUID uuid = UUID.randomUUID(); 78 UUID uuid = UUID.randomUUID();
78 playResult.setUuid(uuid.toString()); 79 playResult.setUuid(uuid.toString());
79 - DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(playTimeout); 80 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(userSetup.getPlayTimeout());
80 playResult.setResult(result); 81 playResult.setResult(result);
81 // 录像查询以channelId作为deviceId查询 82 // 录像查询以channelId作为deviceId查询
82 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result); 83 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
src/main/java/com/genersoft/iot/vmp/service/impl/RecordInfoServerImpl.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service.impl;
  2 +
  3 +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
  4 +import com.genersoft.iot.vmp.service.IRecordInfoServer;
  5 +import com.genersoft.iot.vmp.storager.dao.RecordInfoDao;
  6 +import com.genersoft.iot.vmp.storager.dao.dto.RecordInfo;
  7 +import com.github.pagehelper.PageHelper;
  8 +import com.github.pagehelper.PageInfo;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.stereotype.Service;
  11 +
  12 +import java.util.List;
  13 +
  14 +@Service
  15 +public class RecordInfoServerImpl implements IRecordInfoServer {
  16 +
  17 + @Autowired
  18 + private RecordInfoDao recordInfoDao;
  19 +
  20 + @Override
  21 + public PageInfo<RecordInfo> getRecordList(int page, int count) {
  22 + PageHelper.startPage(page, count);
  23 + List<RecordInfo> all = recordInfoDao.selectAll();
  24 + return new PageInfo<>(all);
  25 + }
  26 +}
src/main/java/com/genersoft/iot/vmp/storager/dao/RecordInfoDao.java 0 → 100644
  1 +package com.genersoft.iot.vmp.storager.dao;
  2 +
  3 +import com.genersoft.iot.vmp.storager.dao.dto.RecordInfo;
  4 +import com.genersoft.iot.vmp.storager.dao.dto.User;
  5 +import org.apache.ibatis.annotations.Delete;
  6 +import org.apache.ibatis.annotations.Insert;
  7 +import org.apache.ibatis.annotations.Mapper;
  8 +import org.apache.ibatis.annotations.Select;
  9 +import org.springframework.stereotype.Repository;
  10 +
  11 +import java.util.List;
  12 +
  13 +@Mapper
  14 +@Repository
  15 +public interface RecordInfoDao {
  16 +
  17 + @Insert("INSERT INTO recordInfo (app, stream, mediaServerId, createTime, type, deviceId, channelId, name) VALUES" +
  18 + "('${app}', '${stream}', '${mediaServerId}', datetime('now','localtime')), '${type}', '${deviceId}', '${channelId}', '${name}'")
  19 + int add(RecordInfo recordInfo);
  20 +
  21 + @Delete("DELETE FROM user WHERE createTime < '${beforeTime}'")
  22 + int deleteBefore(String beforeTime);
  23 +
  24 + @Select("select * FROM recordInfo")
  25 + List<RecordInfo> selectAll();
  26 +}
src/main/java/com/genersoft/iot/vmp/storager/dao/dto/RecordInfo.java 0 → 100644
  1 +package com.genersoft.iot.vmp.storager.dao.dto;
  2 +
  3 +/**
  4 + * 录像记录
  5 + */
  6 +public class RecordInfo {
  7 +
  8 + /**
  9 + * ID
  10 + */
  11 + private int id;
  12 +
  13 + /**
  14 + * 应用名
  15 + */
  16 + private String app;
  17 +
  18 + /**
  19 + * 流ID
  20 + */
  21 + private String stream;
  22 +
  23 + /**
  24 + * 对应的zlm流媒体的ID
  25 + */
  26 + private String mediaServerId;
  27 +
  28 + /**
  29 + * 创建时间
  30 + */
  31 + private String createTime;
  32 +
  33 + /**
  34 + * 类型 对应zlm的 originType
  35 + * unknown = 0,
  36 + * rtmp_push=1,
  37 + * rtsp_push=2,
  38 + * rtp_push=3,
  39 + * pull=4,
  40 + * ffmpeg_pull=5,
  41 + * mp4_vod=6,
  42 + * device_chn=7,
  43 + * rtc_push=8
  44 + */
  45 + private int type;
  46 +
  47 + /**
  48 + * 国标录像时的设备ID
  49 + */
  50 + private String deviceId;
  51 +
  52 + /**
  53 + * 国标录像时的通道ID
  54 + */
  55 + private String channelId;
  56 +
  57 + /**
  58 + * 拉流代理录像时的名称
  59 + */
  60 + private String name;
  61 +
  62 + public int getId() {
  63 + return id;
  64 + }
  65 +
  66 + public void setId(int id) {
  67 + this.id = id;
  68 + }
  69 +
  70 + public String getApp() {
  71 + return app;
  72 + }
  73 +
  74 + public void setApp(String app) {
  75 + this.app = app;
  76 + }
  77 +
  78 + public String getStream() {
  79 + return stream;
  80 + }
  81 +
  82 + public void setStream(String stream) {
  83 + this.stream = stream;
  84 + }
  85 +
  86 + public String getMediaServerId() {
  87 + return mediaServerId;
  88 + }
  89 +
  90 + public void setMediaServerId(String mediaServerId) {
  91 + this.mediaServerId = mediaServerId;
  92 + }
  93 +
  94 + public String getCreateTime() {
  95 + return createTime;
  96 + }
  97 +
  98 + public void setCreateTime(String createTime) {
  99 + this.createTime = createTime;
  100 + }
  101 +
  102 + public int getType() {
  103 + return type;
  104 + }
  105 +
  106 + public void setType(int type) {
  107 + this.type = type;
  108 + }
  109 +
  110 + public String getDeviceId() {
  111 + return deviceId;
  112 + }
  113 +
  114 + public void setDeviceId(String deviceId) {
  115 + this.deviceId = deviceId;
  116 + }
  117 +
  118 + public String getChannelId() {
  119 + return channelId;
  120 + }
  121 +
  122 + public void setChannelId(String channelId) {
  123 + this.channelId = channelId;
  124 + }
  125 +
  126 + public String getName() {
  127 + return name;
  128 + }
  129 +
  130 + public void setName(String name) {
  131 + this.name = name;
  132 + }
  133 +}
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/RecordController.java renamed to src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
@@ -26,9 +26,9 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager; @@ -26,9 +26,9 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
26 @CrossOrigin 26 @CrossOrigin
27 @RestController 27 @RestController
28 @RequestMapping("/api/gb_record") 28 @RequestMapping("/api/gb_record")
29 -public class RecordController { 29 +public class GBRecordController {
30 30
31 - private final static Logger logger = LoggerFactory.getLogger(RecordController.class); 31 + private final static Logger logger = LoggerFactory.getLogger(GBRecordController.class);
32 32
33 @Autowired 33 @Autowired
34 private SIPCommander cmder; 34 private SIPCommander cmder;
src/main/java/com/genersoft/iot/vmp/vmanager/record/RecoderProxyController.java 0 → 100644
  1 +package com.genersoft.iot.vmp.vmanager.record;
  2 +
  3 +import com.genersoft.iot.vmp.conf.MediaConfig;
  4 +import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
  5 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.http.HttpStatus;
  8 +import org.springframework.util.StringUtils;
  9 +import org.springframework.web.bind.annotation.RequestMapping;
  10 +import org.springframework.web.bind.annotation.ResponseBody;
  11 +import org.springframework.web.bind.annotation.RestController;
  12 +import org.springframework.web.client.HttpClientErrorException;
  13 +import org.springframework.web.client.RestTemplate;
  14 +
  15 +import javax.servlet.http.HttpServletRequest;
  16 +import javax.servlet.http.HttpServletResponse;
  17 +import java.net.URLDecoder;
  18 +
  19 +@RestController
  20 +@RequestMapping("/record_proxy")
  21 +public class RecoderProxyController {
  22 +
  23 +
  24 + // private final static Logger logger = LoggerFactory.getLogger(ZLMHTTPProxyController.class);
  25 +
  26 + @Autowired
  27 + private IRedisCatchStorage redisCatchStorage;
  28 +
  29 + @Autowired
  30 + private MediaConfig mediaConfig;
  31 +
  32 + @ResponseBody
  33 + @RequestMapping(value = "/**/**/**", produces = "application/json;charset=UTF-8")
  34 + public Object proxy(HttpServletRequest request, HttpServletResponse response){
  35 +
  36 +
  37 + String baseRequestURI = request.getRequestURI();
  38 + String[] split = baseRequestURI.split("/");
  39 + if (split.length <= 2) {
  40 + response.setStatus(HttpStatus.NOT_FOUND.value());
  41 + return null;
  42 + }
  43 + String mediaId = split[2];
  44 + if (StringUtils.isEmpty(mediaId)){
  45 + response.setStatus(HttpStatus.BAD_REQUEST.value());
  46 + return null;
  47 + }
  48 + // 后续改为根据Id获取对应的ZLM
  49 + ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
  50 + String requestURI = String.format("http://%s:%s%s?%s",
  51 + mediaInfo.getLocalIP(),
  52 + mediaConfig.getRecordAssistPort(),
  53 + baseRequestURI.substring(baseRequestURI.indexOf(mediaId) + mediaId.length()),
  54 + URLDecoder.decode(request.getQueryString())
  55 + );
  56 + // 发送请求
  57 + RestTemplate restTemplate = new RestTemplate();
  58 + //将指定的url返回的参数自动封装到自定义好的对应类对象中
  59 + Object result = null;
  60 + try {
  61 + result = restTemplate.getForObject(requestURI,Object.class);
  62 +
  63 + }catch (HttpClientErrorException httpClientErrorException) {
  64 + response.setStatus(httpClientErrorException.getStatusCode().value());
  65 + }
  66 + return result;
  67 + }
  68 +}
src/main/java/com/genersoft/iot/vmp/vmanager/record/RecordController.java 0 → 100644
  1 +//package com.genersoft.iot.vmp.vmanager.record;
  2 +//
  3 +//import com.alibaba.fastjson.JSONObject;
  4 +//import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
  5 +//import com.genersoft.iot.vmp.service.IRecordInfoServer;
  6 +//import com.genersoft.iot.vmp.storager.dao.dto.RecordInfo;
  7 +//import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
  8 +//import com.github.pagehelper.PageInfo;
  9 +//import io.swagger.annotations.Api;
  10 +//import io.swagger.annotations.ApiImplicitParam;
  11 +//import io.swagger.annotations.ApiImplicitParams;
  12 +//import io.swagger.annotations.ApiOperation;
  13 +//import org.springframework.beans.factory.annotation.Autowired;
  14 +//import org.springframework.web.bind.annotation.*;
  15 +//
  16 +//@Api(tags = "云端录像")
  17 +//@CrossOrigin
  18 +//@RestController
  19 +//@RequestMapping("/api/record")
  20 +//public class RecordController {
  21 +//
  22 +// @Autowired
  23 +// private IRecordInfoServer recordInfoServer;
  24 +//
  25 +// @ApiOperation("录像列表查询")
  26 +// @ApiImplicitParams({
  27 +// @ApiImplicitParam(name="page", value = "当前页", required = true, dataTypeClass = Integer.class),
  28 +// @ApiImplicitParam(name="count", value = "每页查询数量", required = true, dataTypeClass = Integer.class),
  29 +// @ApiImplicitParam(name="query", value = "查询内容", dataTypeClass = String.class),
  30 +// })
  31 +// @GetMapping(value = "/app/list")
  32 +// @ResponseBody
  33 +// public Object list(@RequestParam(required = false)Integer page,
  34 +// @RequestParam(required = false)Integer count ){
  35 +//
  36 +// PageInfo<RecordInfo> recordList = recordInfoServer.getRecordList(page - 1, page - 1 + count);
  37 +// return recordList;
  38 +// }
  39 +//
  40 +// @ApiOperation("获取录像详情")
  41 +// @ApiImplicitParams({
  42 +// @ApiImplicitParam(name="recordInfo", value = "录像记录", required = true, dataTypeClass = RecordInfo.class)
  43 +// })
  44 +// @GetMapping(value = "/detail")
  45 +// @ResponseBody
  46 +// public JSONObject list(RecordInfo recordInfo, String time ){
  47 +//
  48 +//
  49 +// return null;
  50 +// }
  51 +//}
src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
1 package com.genersoft.iot.vmp.vmanager.server; 1 package com.genersoft.iot.vmp.vmanager.server;
2 2
3 import com.genersoft.iot.vmp.VManageBootstrap; 3 import com.genersoft.iot.vmp.VManageBootstrap;
  4 +import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
  5 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  6 +import com.genersoft.iot.vmp.storager.impl.RedisCatchStorageImpl;
4 import com.genersoft.iot.vmp.utils.SpringBeanFactory; 7 import com.genersoft.iot.vmp.utils.SpringBeanFactory;
5 import gov.nist.javax.sip.SipStackImpl; 8 import gov.nist.javax.sip.SipStackImpl;
6 import io.swagger.annotations.Api; 9 import io.swagger.annotations.Api;
@@ -12,6 +15,7 @@ import org.springframework.web.bind.annotation.*; @@ -12,6 +15,7 @@ import org.springframework.web.bind.annotation.*;
12 import javax.sip.ListeningPoint; 15 import javax.sip.ListeningPoint;
13 import javax.sip.ObjectInUseException; 16 import javax.sip.ObjectInUseException;
14 import javax.sip.SipProvider; 17 import javax.sip.SipProvider;
  18 +import java.util.ArrayList;
15 import java.util.Iterator; 19 import java.util.Iterator;
16 20
17 @SuppressWarnings("rawtypes") 21 @SuppressWarnings("rawtypes")
@@ -24,6 +28,20 @@ public class ServerController { @@ -24,6 +28,20 @@ public class ServerController {
24 @Autowired 28 @Autowired
25 private ConfigurableApplicationContext context; 29 private ConfigurableApplicationContext context;
26 30
  31 + @Autowired
  32 + private IRedisCatchStorage redisCatchStorage;
  33 +
  34 +
  35 + @ApiOperation("流媒体服务列表")
  36 + @GetMapping(value = "/media_server/list")
  37 + @ResponseBody
  38 + public Object getMediaServerList(){
  39 + // TODO 为后续多个zlm支持准备
  40 + ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();
  41 + ArrayList<ZLMServerConfig> result = new ArrayList<>();
  42 + result.add(mediaInfo);
  43 + return result;
  44 + }
27 45
28 @ApiOperation("重启服务") 46 @ApiOperation("重启服务")
29 @GetMapping(value = "/restart") 47 @GetMapping(value = "/restart")
src/main/resources/application-dev.yml
@@ -92,6 +92,8 @@ media: @@ -92,6 +92,8 @@ media:
92 enable: true 92 enable: true
93 # [可选] 在此范围内选择端口用于媒体流传输, 93 # [可选] 在此范围内选择端口用于媒体流传输,
94 portRange: 30000,30500 # 端口范围 94 portRange: 30000,30500 # 端口范围
  95 + # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载
  96 + recordAssistPort: 18081
95 97
96 # [可选] 日志配置, 一般不需要改 98 # [可选] 日志配置, 一般不需要改
97 logging: 99 logging:
@@ -118,6 +120,8 @@ userSettings: @@ -118,6 +120,8 @@ userSettings:
118 waitTrack: false 120 waitTrack: false
119 # 是否开启接口鉴权 121 # 是否开启接口鉴权
120 interfaceAuthentication: true 122 interfaceAuthentication: true
  123 + # 推流直播是否录制
  124 + recordPushLive: true
121 125
122 # 在线文档: swagger-ui(生产环境建议关闭) 126 # 在线文档: swagger-ui(生产环境建议关闭)
123 springfox: 127 springfox:
src/main/resources/wvp.sqlite
No preview for this file type