Commit ad93be12fb3705e995cf0dab933760edaef3dd7a
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) 提供这么棒的开源流媒体服务框架 |
pom.xml
| @@ -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
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