Commit b4048fbe80dba8e7756ae557a15ab60b4f80a44b

Authored by 648540858
2 parents 786c76ba 053cd130

合并开源主线

Showing 165 changed files with 3011 additions and 1000 deletions
README.md
@@ -99,15 +99,16 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git @@ -99,15 +99,16 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
99 - [X] 支持接口鉴权 99 - [X] 支持接口鉴权
100 - [X] 云端录像,推流/代理/国标视频均可以录制在云端服务器,支持预览和下载 100 - [X] 云端录像,推流/代理/国标视频均可以录制在云端服务器,支持预览和下载
101 - [X] 支持打包可执行jar和war 101 - [X] 支持打包可执行jar和war
  102 +- [X] 支持跨域请求,支持前后端分离部署
102 103
103 104
104 # 遇到问题如何解决 105 # 遇到问题如何解决
105 国标最麻烦的地方在于设备的兼容性,所以需要大量的设备来测试,目前作者手里的设备有限,再加上作者水平有限,所以遇到问题在所难免; 106 国标最麻烦的地方在于设备的兼容性,所以需要大量的设备来测试,目前作者手里的设备有限,再加上作者水平有限,所以遇到问题在所难免;
106 -1. 查看wiki,仔细的阅读可以帮你避免几乎所有的问题 107 +1. 查看文档网站,仔细的阅读可以帮你避免几乎所有的问题
107 2. 搜索issues,这里有大部分的答案 108 2. 搜索issues,这里有大部分的答案
108 3. 加QQ群(901799015),这里有大量热心的小伙伴,但是前提新希望你已经仔细阅读了wiki和搜索了issues。 109 3. 加QQ群(901799015),这里有大量热心的小伙伴,但是前提新希望你已经仔细阅读了wiki和搜索了issues。
109 4. 你可以请作者为你解答,但是我不是免费的。 110 4. 你可以请作者为你解答,但是我不是免费的。
110 -5. 你可以把遇到问题的设备寄给我,可以更容易的复现问题。 111 +5. 你可以把遇到问题的设备寄给我,可以更容易的兼容设备和解决问题。
111 112
112 # 使用帮助 113 # 使用帮助
113 QQ群: 901799015, ZLM使用文档[https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit) 114 QQ群: 901799015, ZLM使用文档[https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit)
doc/_content/ability/gis.md
@@ -14,7 +14,7 @@ WVP提供了简单的电子地图用于设备的定位以及移动设备的轨 @@ -14,7 +14,7 @@ WVP提供了简单的电子地图用于设备的定位以及移动设备的轨
14 PS: 目前的底图仅用用作演示和学习,商用情况请自行购买授权使用。 14 PS: 目前的底图仅用用作演示和学习,商用情况请自行购买授权使用。
15 15
16 ### 更换底图以及底图配置 16 ### 更换底图以及底图配置
17 -目前WVP支持使用了更换底图,配置文件在web_src/static/js/mapConfig.js,请修改后重新编译前端文件。 17 +目前WVP支持使用了更换底图,配置文件在web_src/static/js/config.js,请修改后重新编译前端文件。
18 ```javascript 18 ```javascript
19 window.mapParam = { 19 window.mapParam = {
20 // 开启/关闭地图功能 20 // 开启/关闭地图功能
doc/_content/introduction/deployment.md
@@ -27,13 +27,32 @@ @@ -27,13 +27,32 @@
27 ```shell 27 ```shell
28 nohup java -jar wvp-pro-*.jar & 28 nohup java -jar wvp-pro-*.jar &
29 ``` 29 ```
30 -war包: 30 +**war包:**
31 下载Tomcat后将war包放入webapps中,启动Tomcat以解压war包,停止Tomcat后,删除ROOT目录以及war包,将解压后的war包目录重命名为ROOT,将配置文件中的Server.port配置为与Tomcat端口一致 31 下载Tomcat后将war包放入webapps中,启动Tomcat以解压war包,停止Tomcat后,删除ROOT目录以及war包,将解压后的war包目录重命名为ROOT,将配置文件中的Server.port配置为与Tomcat端口一致
32 然后启动Tomcat。 32 然后启动Tomcat。
33 **启动ZLM** 33 **启动ZLM**
34 ```shell 34 ```shell
35 nohup ./MediaServer -d -m 3 & 35 nohup ./MediaServer -d -m 3 &
36 ``` 36 ```
37 - 37 +### 前后端分离部署
  38 +前后端部署目前在最新的版本已经支持,请使用3月15日之后的版本部署
  39 +前端编译后的文件在`src/main/resources/static`中,将此目录下的文件部署。
  40 +前后端分离部署最大的问题是跨域的解决,之前版本使用cookie完成登录流程,而cookie是不可以在复杂跨域中使用的。所以当前版本使用JWT生成的TOKEN作为认证凭据,
  41 +部署前端后需要在wvp中配置前端访问的地址以完成跨域流程。
  42 +**配置前端服务器**
  43 +1. 假如你的服务有公网域名为xxx.com,公网IP为11.11.11.11, 那么你可以在wvp中这样配置:
  44 +```yaml
  45 +user-settings:
  46 + # 跨域配置,配置你访问前端页面的地址即可, 可以配置多个
  47 + allowed-origins:
  48 + - http://xxx.com:8008
  49 + - http://11.11.11.11:8008
  50 +```
  51 +配置不是必须的,你使用哪个ip/域名访问就配置哪个即可。修改配置后重启wvp以使配置生效。
  52 +2. 在`src/main/resources/static/static/js/config.js`下配置服务器的地址,也就是wvp服务的地址
  53 +```javascript
  54 +window.baseUrl = "http://xxx.com:18080"
  55 +```
  56 +`这里的地址是需要客户电脑能访问到的,因为请求是客户端电脑发起,与代理不同`
38 [接入设备](./_content/ability/device.md) 57 [接入设备](./_content/ability/device.md)
39 58
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 11
12 <groupId>com.genersoft</groupId> 12 <groupId>com.genersoft</groupId>
13 <artifactId>wvp-pro</artifactId> 13 <artifactId>wvp-pro</artifactId>
14 - <version>2.6.7</version> 14 + <version>2.6.8</version>
15 <name>web video platform</name> 15 <name>web video platform</name>
16 <description>国标28181视频平台</description> 16 <description>国标28181视频平台</description>
17 <packaging>${project.packaging}</packaging> 17 <packaging>${project.packaging}</packaging>
@@ -123,11 +123,9 @@ @@ -123,11 +123,9 @@
123 <artifactId>spring-boot-starter-security</artifactId> 123 <artifactId>spring-boot-starter-security</artifactId>
124 </dependency> 124 </dependency>
125 125
126 - <!-- druid数据库连接池 -->  
127 <dependency> 126 <dependency>
128 - <groupId>com.alibaba</groupId>  
129 - <artifactId>druid-spring-boot-starter</artifactId>  
130 - <version>1.2.11</version> 127 + <groupId>org.springframework.boot</groupId>
  128 + <artifactId>spring-boot-starter-jdbc</artifactId>
131 </dependency> 129 </dependency>
132 130
133 <!-- mysql数据库 --> 131 <!-- mysql数据库 -->
@@ -216,8 +214,6 @@ @@ -216,8 +214,6 @@
216 <version>4.10.0</version> 214 <version>4.10.0</version>
217 </dependency> 215 </dependency>
218 216
219 -  
220 -  
221 <!-- okhttp-digest --> 217 <!-- okhttp-digest -->
222 <dependency> 218 <dependency>
223 <groupId>io.github.rburgst</groupId> 219 <groupId>io.github.rburgst</groupId>
@@ -226,10 +222,17 @@ @@ -226,10 +222,17 @@
226 </dependency> 222 </dependency>
227 223
228 <!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 --> 224 <!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 -->
  225 +<!-- <dependency>-->
  226 +<!-- <groupId>net.sf.kxml</groupId>-->
  227 +<!-- <artifactId>kxml2</artifactId>-->
  228 +<!-- <version>2.3.0</version>-->
  229 +<!-- </dependency>-->
  230 +
  231 + <!-- jwt实现 -->
229 <dependency> 232 <dependency>
230 - <groupId>net.sf.kxml</groupId>  
231 - <artifactId>kxml2</artifactId>  
232 - <version>2.3.0</version> 233 + <groupId>org.bitbucket.b_c</groupId>
  234 + <artifactId>jose4j</artifactId>
  235 + <version>0.9.3</version>
233 </dependency> 236 </dependency>
234 237
235 <!--反向代理--> 238 <!--反向代理-->
@@ -289,7 +292,7 @@ @@ -289,7 +292,7 @@
289 <plugin> 292 <plugin>
290 <groupId>org.springframework.boot</groupId> 293 <groupId>org.springframework.boot</groupId>
291 <artifactId>spring-boot-maven-plugin</artifactId> 294 <artifactId>spring-boot-maven-plugin</artifactId>
292 - <version>2.3.5.RELEASE</version> 295 + <version>2.7.2</version>
293 <configuration> 296 <configuration>
294 <includeSystemScope>true</includeSystemScope> 297 <includeSystemScope>true</includeSystemScope>
295 </configuration> 298 </configuration>
sql/2.6.6-2.6.7更新.sql 0 → 100755
  1 +alter table device
  2 + add asMessageChannel int default 0;
  3 +
  4 +alter table parent_platform
  5 + add asMessageChannel int default 0;
  6 +
  7 +alter table device
  8 + add mediaServerId varchar(50) default null;
  9 +
  10 +
  11 +
  12 +
src/main/resources/db/migration/V2.6.7_20230201__初始化.sql renamed to sql/初始化.sql
@@ -32,6 +32,7 @@ CREATE TABLE `device` ( @@ -32,6 +32,7 @@ CREATE TABLE `device` (
32 `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, 32 `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
33 `streamMode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, 33 `streamMode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
34 `online` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, 34 `online` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  35 + `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
35 `registerTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, 36 `registerTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
36 `keepaliveTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, 37 `keepaliveTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
37 `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, 38 `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
@@ -47,6 +48,7 @@ CREATE TABLE `device` ( @@ -47,6 +48,7 @@ CREATE TABLE `device` (
47 `mobilePositionSubmissionInterval` int DEFAULT '5', 48 `mobilePositionSubmissionInterval` int DEFAULT '5',
48 `subscribeCycleForAlarm` int DEFAULT NULL, 49 `subscribeCycleForAlarm` int DEFAULT NULL,
49 `ssrcCheck` int DEFAULT '0', 50 `ssrcCheck` int DEFAULT '0',
  51 + `asMessageChannel` int DEFAULT '0',
50 `geoCoordSys` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, 52 `geoCoordSys` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
51 `treeType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, 53 `treeType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
52 `custom_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, 54 `custom_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
@@ -329,6 +331,7 @@ CREATE TABLE `parent_platform` ( @@ -329,6 +331,7 @@ CREATE TABLE `parent_platform` (
329 `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, 331 `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
330 `ptz` int DEFAULT NULL, 332 `ptz` int DEFAULT NULL,
331 `rtcp` int DEFAULT NULL, 333 `rtcp` int DEFAULT NULL,
  334 + `asMessageChannel` int DEFAULT '0',
332 `status` bit(1) DEFAULT NULL, 335 `status` bit(1) DEFAULT NULL,
333 `startOfflinePush` int DEFAULT '0', 336 `startOfflinePush` int DEFAULT '0',
334 `administrativeDivision` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, 337 `administrativeDivision` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
1 package com.genersoft.iot.vmp; 1 package com.genersoft.iot.vmp;
2 2
3 -import com.genersoft.iot.vmp.conf.druid.EnableDruidSupport;  
4 import com.genersoft.iot.vmp.utils.GitUtil; 3 import com.genersoft.iot.vmp.utils.GitUtil;
5 import com.genersoft.iot.vmp.utils.SpringBeanFactory; 4 import com.genersoft.iot.vmp.utils.SpringBeanFactory;
6 import org.slf4j.Logger; 5 import org.slf4j.Logger;
@@ -25,7 +24,6 @@ import java.util.Collections; @@ -25,7 +24,6 @@ import java.util.Collections;
25 @ServletComponentScan("com.genersoft.iot.vmp.conf") 24 @ServletComponentScan("com.genersoft.iot.vmp.conf")
26 @SpringBootApplication 25 @SpringBootApplication
27 @EnableScheduling 26 @EnableScheduling
28 -@EnableDruidSupport  
29 public class VManageBootstrap extends SpringBootServletInitializer { 27 public class VManageBootstrap extends SpringBootServletInitializer {
30 28
31 private final static Logger logger = LoggerFactory.getLogger(VManageBootstrap.class); 29 private final static Logger logger = LoggerFactory.getLogger(VManageBootstrap.class);
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
@@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.common; @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.common;
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4
5 import java.io.Serializable; 5 import java.io.Serializable;
  6 +import java.util.Objects;
6 7
7 @Schema(description = "流信息") 8 @Schema(description = "流信息")
8 public class StreamInfo implements Serializable, Cloneable{ 9 public class StreamInfo implements Serializable, Cloneable{
@@ -168,7 +169,7 @@ public class StreamInfo implements Serializable, Cloneable{ @@ -168,7 +169,7 @@ public class StreamInfo implements Serializable, Cloneable{
168 } 169 }
169 170
170 public void setRtmp(String host, int port, int sslPort, String app, String stream, String callIdParam) { 171 public void setRtmp(String host, int port, int sslPort, String app, String stream, String callIdParam) {
171 - String file = String.format("%s/%s/%s", app, stream, callIdParam); 172 + String file = String.format("%s/%s%s", app, stream, callIdParam);
172 if (port > 0) { 173 if (port > 0) {
173 this.rtmp = new StreamURL("rtmp", host, port, file); 174 this.rtmp = new StreamURL("rtmp", host, port, file);
174 } 175 }
@@ -178,7 +179,7 @@ public class StreamInfo implements Serializable, Cloneable{ @@ -178,7 +179,7 @@ public class StreamInfo implements Serializable, Cloneable{
178 } 179 }
179 180
180 public void setRtsp(String host, int port, int sslPort, String app, String stream, String callIdParam) { 181 public void setRtsp(String host, int port, int sslPort, String app, String stream, String callIdParam) {
181 - String file = String.format("%s/%s/%s", app, stream, callIdParam); 182 + String file = String.format("%s/%s%s", app, stream, callIdParam);
182 if (port > 0) { 183 if (port > 0) {
183 this.rtsp = new StreamURL("rtsp", host, port, file); 184 this.rtsp = new StreamURL("rtsp", host, port, file);
184 } 185 }
@@ -236,8 +237,11 @@ public class StreamInfo implements Serializable, Cloneable{ @@ -236,8 +237,11 @@ public class StreamInfo implements Serializable, Cloneable{
236 } 237 }
237 } 238 }
238 239
239 - public void setRtc(String host, int port, int sslPort, String app, String stream, String callIdParam, boolean isPlay) {  
240 - String file = String.format("index/api/webrtc?app=%s&stream=%s&type=%s%s", app, stream, isPlay?"play":"push", callIdParam); 240 + public void setRtc(String host, int port, int sslPort, String app, String stream, String callIdParam) {
  241 + if (callIdParam != null) {
  242 + callIdParam = Objects.equals(callIdParam, "") ? callIdParam : callIdParam.replace("?", "&");
  243 + }
  244 + String file = String.format("index/api/webrtc?app=%s&stream=%s&type=play%s", app, stream, callIdParam);
241 if (port > 0) { 245 if (port > 0) {
242 this.rtc = new StreamURL("http", host, port, file); 246 this.rtc = new StreamURL("http", host, port, file);
243 } 247 }
src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java
@@ -66,9 +66,7 @@ public class ApiAccessFilter extends OncePerRequestFilter { @@ -66,9 +66,7 @@ public class ApiAccessFilter extends OncePerRequestFilter {
66 logDto.setUri(servletRequest.getRequestURI()); 66 logDto.setUri(servletRequest.getRequestURI());
67 logDto.setCreateTime(DateUtil.getNow()); 67 logDto.setCreateTime(DateUtil.getNow());
68 logService.add(logDto); 68 logService.add(logDto);
69 -// logger.warn("[Api Access] [{}] [{}] [{}] [{}] [{}] {}ms",  
70 -// uriName, servletRequest.getMethod(), servletRequest.getRequestURI(), servletRequest.getRemoteAddr(), HttpStatus.valueOf(servletResponse.getStatus()),  
71 -// System.currentTimeMillis() - start); 69 +
72 70
73 } 71 }
74 } 72 }
src/main/java/com/genersoft/iot/vmp/conf/GlobalExceptionHandler.java
@@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory; @@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory;
8 import org.springframework.http.HttpStatus; 8 import org.springframework.http.HttpStatus;
9 import org.springframework.http.ResponseEntity; 9 import org.springframework.http.ResponseEntity;
10 import org.springframework.security.authentication.BadCredentialsException; 10 import org.springframework.security.authentication.BadCredentialsException;
  11 +import org.springframework.web.HttpRequestMethodNotSupportedException;
11 import org.springframework.web.bind.annotation.ExceptionHandler; 12 import org.springframework.web.bind.annotation.ExceptionHandler;
12 import org.springframework.web.bind.annotation.ResponseStatus; 13 import org.springframework.web.bind.annotation.ResponseStatus;
13 import org.springframework.web.bind.annotation.RestControllerAdvice; 14 import org.springframework.web.bind.annotation.RestControllerAdvice;
@@ -32,6 +33,28 @@ public class GlobalExceptionHandler { @@ -32,6 +33,28 @@ public class GlobalExceptionHandler {
32 return WVPResult.fail(ErrorCode.ERROR500.getCode(), e.getMessage()); 33 return WVPResult.fail(ErrorCode.ERROR500.getCode(), e.getMessage());
33 } 34 }
34 35
  36 + /**
  37 + * 默认异常处理
  38 + * @param e 异常
  39 + * @return 统一返回结果
  40 + */
  41 + @ExceptionHandler(IllegalStateException.class)
  42 + @ResponseStatus(HttpStatus.BAD_REQUEST)
  43 + public WVPResult<String> exceptionHandler(IllegalStateException e) {
  44 + return WVPResult.fail(ErrorCode.ERROR400);
  45 + }
  46 +
  47 + /**
  48 + * 默认异常处理
  49 + * @param e 异常
  50 + * @return 统一返回结果
  51 + */
  52 + @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
  53 + @ResponseStatus(HttpStatus.BAD_REQUEST)
  54 + public WVPResult<String> exceptionHandler(HttpRequestMethodNotSupportedException e) {
  55 + return WVPResult.fail(ErrorCode.ERROR400);
  56 + }
  57 +
35 58
36 /** 59 /**
37 * 自定义异常处理, 处理controller中返回的错误 60 * 自定义异常处理, 处理controller中返回的错误
src/main/java/com/genersoft/iot/vmp/conf/GlobalResponseAdvice.java
@@ -10,14 +10,11 @@ import org.springframework.context.annotation.Bean; @@ -10,14 +10,11 @@ import org.springframework.context.annotation.Bean;
10 import org.springframework.core.MethodParameter; 10 import org.springframework.core.MethodParameter;
11 import org.springframework.http.MediaType; 11 import org.springframework.http.MediaType;
12 import org.springframework.http.converter.HttpMessageConverter; 12 import org.springframework.http.converter.HttpMessageConverter;
13 -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;  
14 import org.springframework.http.server.ServerHttpRequest; 13 import org.springframework.http.server.ServerHttpRequest;
15 import org.springframework.http.server.ServerHttpResponse; 14 import org.springframework.http.server.ServerHttpResponse;
16 import org.springframework.web.bind.annotation.RestControllerAdvice; 15 import org.springframework.web.bind.annotation.RestControllerAdvice;
17 import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; 16 import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
18 17
19 -import java.util.List;  
20 -  
21 /** 18 /**
22 * 全局统一返回结果 19 * 全局统一返回结果
23 * @author lin 20 * @author lin
src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.conf; @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.conf;
2 2
3 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 3 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
4 import com.genersoft.iot.vmp.service.IMediaServerService; 4 import com.genersoft.iot.vmp.service.IMediaServerService;
  5 +import org.apache.catalina.connector.ClientAbortException;
5 import org.apache.http.HttpHost; 6 import org.apache.http.HttpHost;
6 import org.apache.http.HttpRequest; 7 import org.apache.http.HttpRequest;
7 import org.apache.http.HttpResponse; 8 import org.apache.http.HttpResponse;
@@ -169,13 +170,14 @@ public class ProxyServletConfig { @@ -169,13 +170,14 @@ public class ProxyServletConfig {
169 protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) { 170 protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
170 String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString); 171 String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
171 MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI()); 172 MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
172 - String remoteHost = String.format("http://%s:%s", mediaInfo.getIp(), mediaInfo.getHttpPort());  
173 - if (mediaInfo != null) {  
174 - if (!ObjectUtils.isEmpty(queryStr)) {  
175 - queryStr += "&remoteHost=" + remoteHost;  
176 - }else {  
177 - queryStr = "remoteHost=" + remoteHost;  
178 - } 173 + if (mediaInfo == null) {
  174 + return null;
  175 + }
  176 + String remoteHost = String.format("http://%s:%s", mediaInfo.getStreamIp(), mediaInfo.getRecordAssistPort());
  177 + if (!ObjectUtils.isEmpty(queryStr)) {
  178 + queryStr += "&remoteHost=" + remoteHost;
  179 + }else {
  180 + queryStr = "remoteHost=" + remoteHost;
179 } 181 }
180 return queryStr; 182 return queryStr;
181 } 183 }
@@ -192,6 +194,12 @@ public class ProxyServletConfig { @@ -192,6 +194,12 @@ public class ProxyServletConfig {
192 } catch (IOException ioException) { 194 } catch (IOException ioException) {
193 if (ioException instanceof ConnectException) { 195 if (ioException instanceof ConnectException) {
194 logger.error("录像服务 连接失败"); 196 logger.error("录像服务 连接失败");
  197 + }else if (ioException instanceof ClientAbortException) {
  198 + /**
  199 + * TODO 使用这个代理库实现代理在遇到代理视频文件时,如果是206结果,会遇到报错蛋市目前功能正常,
  200 + * TODO 暂时去除异常处理。后续使用其他代理框架修改测试
  201 + */
  202 +
195 }else { 203 }else {
196 logger.error("录像服务 代理失败: ", e); 204 logger.error("录像服务 代理失败: ", e);
197 } 205 }
src/main/java/com/genersoft/iot/vmp/conf/SipConfig.java
@@ -4,7 +4,6 @@ package com.genersoft.iot.vmp.conf; @@ -4,7 +4,6 @@ package com.genersoft.iot.vmp.conf;
4 import org.junit.jupiter.api.Order; 4 import org.junit.jupiter.api.Order;
5 import org.springframework.boot.context.properties.ConfigurationProperties; 5 import org.springframework.boot.context.properties.ConfigurationProperties;
6 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
7 -import org.springframework.util.ObjectUtils;  
8 7
9 @Component 8 @Component
10 @ConfigurationProperties(prefix = "sip", ignoreInvalidFields = true) 9 @ConfigurationProperties(prefix = "sip", ignoreInvalidFields = true)
@@ -13,6 +12,8 @@ public class SipConfig { @@ -13,6 +12,8 @@ public class SipConfig {
13 12
14 private String ip; 13 private String ip;
15 14
  15 + private String showIp;
  16 +
16 private Integer port; 17 private Integer port;
17 18
18 private String domain; 19 private String domain;
@@ -96,4 +97,14 @@ public class SipConfig { @@ -96,4 +97,14 @@ public class SipConfig {
96 this.alarm = alarm; 97 this.alarm = alarm;
97 } 98 }
98 99
  100 + public String getShowIp() {
  101 + if (this.showIp == null) {
  102 + return this.ip;
  103 + }
  104 + return showIp;
  105 + }
  106 +
  107 + public void setShowIp(String showIp) {
  108 + this.showIp = showIp;
  109 + }
99 } 110 }
src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
@@ -40,17 +40,20 @@ public class SipPlatformRunner implements CommandLineRunner { @@ -40,17 +40,20 @@ public class SipPlatformRunner implements CommandLineRunner {
40 List<ParentPlatform> parentPlatforms = storager.queryEnableParentPlatformList(true); 40 List<ParentPlatform> parentPlatforms = storager.queryEnableParentPlatformList(true);
41 41
42 for (ParentPlatform parentPlatform : parentPlatforms) { 42 for (ParentPlatform parentPlatform : parentPlatforms) {
  43 +
  44 + ParentPlatformCatch parentPlatformCatchOld = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
  45 +
43 // 更新缓存 46 // 更新缓存
44 ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch(); 47 ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch();
45 parentPlatformCatch.setParentPlatform(parentPlatform); 48 parentPlatformCatch.setParentPlatform(parentPlatform);
46 parentPlatformCatch.setId(parentPlatform.getServerGBId()); 49 parentPlatformCatch.setId(parentPlatform.getServerGBId());
47 redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); 50 redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
48 - // 设置所有平台离线  
49 - platformService.offline(parentPlatform, true);  
50 // 取消订阅 51 // 取消订阅
51 - sipCommanderForPlatform.unregister(parentPlatform, null, (eventResult)->{ 52 + sipCommanderForPlatform.unregister(parentPlatform, parentPlatformCatchOld.getSipTransactionInfo(), null, (eventResult)->{
52 platformService.login(parentPlatform); 53 platformService.login(parentPlatform);
53 }); 54 });
  55 + // 设置所有平台离线
  56 + platformService.offline(parentPlatform, true);
54 } 57 }
55 } 58 }
56 } 59 }
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
@@ -50,15 +50,22 @@ public class UserSetting { @@ -50,15 +50,22 @@ public class UserSetting {
50 private Boolean pushStreamAfterAck = Boolean.FALSE; 50 private Boolean pushStreamAfterAck = Boolean.FALSE;
51 51
52 private Boolean sipLog = Boolean.FALSE; 52 private Boolean sipLog = Boolean.FALSE;
  53 + private Boolean sendToPlatformsWhenIdLost = Boolean.FALSE;
  54 +
  55 + private Boolean refuseChannelStatusChannelFormNotify = Boolean.FALSE;
53 56
54 private String serverId = "000000"; 57 private String serverId = "000000";
55 58
  59 + private String recordPath = null;
  60 +
56 private String thirdPartyGBIdReg = "[\\s\\S]*"; 61 private String thirdPartyGBIdReg = "[\\s\\S]*";
57 62
58 private String broadcastForPlatform = "UDP"; 63 private String broadcastForPlatform = "UDP";
59 64
60 private List<String> interfaceAuthenticationExcludes = new ArrayList<>(); 65 private List<String> interfaceAuthenticationExcludes = new ArrayList<>();
61 66
  67 + private List<String> allowedOrigins = new ArrayList<>();
  68 +
62 public Boolean getSavePositionHistory() { 69 public Boolean getSavePositionHistory() {
63 return savePositionHistory; 70 return savePositionHistory;
64 } 71 }
@@ -238,4 +245,36 @@ public class UserSetting { @@ -238,4 +245,36 @@ public class UserSetting {
238 public void setSipLog(Boolean sipLog) { 245 public void setSipLog(Boolean sipLog) {
239 this.sipLog = sipLog; 246 this.sipLog = sipLog;
240 } 247 }
  248 +
  249 + public List<String> getAllowedOrigins() {
  250 + return allowedOrigins;
  251 + }
  252 +
  253 + public void setAllowedOrigins(List<String> allowedOrigins) {
  254 + this.allowedOrigins = allowedOrigins;
  255 + }
  256 +
  257 + public Boolean getSendToPlatformsWhenIdLost() {
  258 + return sendToPlatformsWhenIdLost;
  259 + }
  260 +
  261 + public void setSendToPlatformsWhenIdLost(Boolean sendToPlatformsWhenIdLost) {
  262 + this.sendToPlatformsWhenIdLost = sendToPlatformsWhenIdLost;
  263 + }
  264 +
  265 + public Boolean getRefuseChannelStatusChannelFormNotify() {
  266 + return refuseChannelStatusChannelFormNotify;
  267 + }
  268 +
  269 + public void setRefuseChannelStatusChannelFormNotify(Boolean refuseChannelStatusChannelFormNotify) {
  270 + this.refuseChannelStatusChannelFormNotify = refuseChannelStatusChannelFormNotify;
  271 + }
  272 +
  273 + public String getRecordPath() {
  274 + return recordPath;
  275 + }
  276 +
  277 + public void setRecordPath(String recordPath) {
  278 + this.recordPath = recordPath;
  279 + }
241 } 280 }
src/main/java/com/genersoft/iot/vmp/conf/druid/DruidConfiguration.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.conf.druid;  
2 -  
3 -import com.alibaba.druid.support.http.StatViewServlet;  
4 -import com.alibaba.druid.support.http.WebStatFilter;  
5 -import org.springframework.beans.factory.annotation.Value;  
6 -import org.springframework.boot.web.servlet.FilterRegistrationBean;  
7 -import org.springframework.boot.web.servlet.ServletRegistrationBean;  
8 -import org.springframework.context.annotation.Bean;  
9 -  
10 -import javax.servlet.Filter;  
11 -import javax.servlet.Servlet;  
12 -  
13 -/**  
14 - * druid监控配置  
15 - * @author  
16 - */  
17 -public class DruidConfiguration {  
18 -  
19 - @Value("${rj-druid-manage.allow:127.0.0.1}")  
20 - private String allow;  
21 -  
22 - @Value("${rj-druid-manage.deny:}")  
23 - private String deny;  
24 -  
25 - @Value("${rj-druid-manage.loginUsername:admin}")  
26 - private String loginUsername;  
27 -  
28 - @Value("${rj-druid-manage.loginPassword:admin}")  
29 - private String loginPassword;  
30 -  
31 - @Value("${rj-druid-manage.resetEnable:false}")  
32 - private String resetEnable;  
33 -  
34 - /**  
35 - * druid监控页面开启  
36 - */  
37 - @Bean  
38 - public ServletRegistrationBean druidServlet() {  
39 - ServletRegistrationBean<Servlet> servletRegistrationBean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");  
40 - // IP白名单  
41 - servletRegistrationBean.addInitParameter("allow", allow);  
42 - // IP黑名单(共同存在时,deny优先于allow)  
43 - servletRegistrationBean.addInitParameter("deny", deny);  
44 - //控制台管理用户  
45 - servletRegistrationBean.addInitParameter("loginUsername", loginUsername);  
46 - servletRegistrationBean.addInitParameter("loginPassword", loginPassword);  
47 - //是否能够重置数据 禁用HTML页面上的“Reset All”功能  
48 - servletRegistrationBean.addInitParameter("resetEnable", resetEnable);  
49 - return servletRegistrationBean;  
50 - }  
51 -  
52 - /**  
53 - * druid url监控配置  
54 - */  
55 - @Bean  
56 - public FilterRegistrationBean filterRegistrationBean() {  
57 - FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(new WebStatFilter());  
58 - filterRegistrationBean.addUrlPatterns("/*");  
59 - filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");  
60 - return filterRegistrationBean;  
61 - }  
62 -  
63 -  
64 -}  
65 \ No newline at end of file 0 \ No newline at end of file
src/main/java/com/genersoft/iot/vmp/conf/druid/EnableDruidSupport.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.conf.druid;  
2 -  
3 -import org.springframework.boot.web.servlet.ServletComponentScan;  
4 -import org.springframework.context.annotation.Import;  
5 -  
6 -import java.lang.annotation.*;  
7 -  
8 -/**  
9 - * druid监控支持注解  
10 - *  
11 - * @author  
12 - * {@link DruidConfiguration} druid监控页面安全配置支持  
13 - * {@link ServletComponentScan} druid监控页面需要扫描servlet  
14 - */  
15 -@Target(ElementType.TYPE)  
16 -@Retention(RetentionPolicy.RUNTIME)  
17 -@Documented  
18 -@Inherited  
19 -@Import({  
20 - DruidConfiguration.class,  
21 -})  
22 -@ServletComponentScan  
23 -public @interface EnableDruidSupport {  
24 -}  
src/main/java/com/genersoft/iot/vmp/conf/security/AnonymousAuthenticationEntryPoint.java
1 package com.genersoft.iot.vmp.conf.security; 1 package com.genersoft.iot.vmp.conf.security;
2 2
3 import com.alibaba.fastjson2.JSONObject; 3 import com.alibaba.fastjson2.JSONObject;
  4 +import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
4 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 5 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
5 -import org.apache.poi.hssf.eventmodel.ERFListener;  
6 -import org.slf4j.Logger;  
7 -import org.slf4j.LoggerFactory; 6 +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
8 import org.springframework.security.core.AuthenticationException; 7 import org.springframework.security.core.AuthenticationException;
  8 +import org.springframework.security.core.context.SecurityContextHolder;
9 import org.springframework.security.web.AuthenticationEntryPoint; 9 import org.springframework.security.web.AuthenticationEntryPoint;
10 import org.springframework.stereotype.Component; 10 import org.springframework.stereotype.Component;
11 11
@@ -18,17 +18,15 @@ import java.io.IOException; @@ -18,17 +18,15 @@ import java.io.IOException;
18 * @author lin 18 * @author lin
19 */ 19 */
20 @Component 20 @Component
21 -public class AnonymousAuthenticationEntryPoint implements AuthenticationEntryPoint {  
22 -  
23 - private final static Logger logger = LoggerFactory.getLogger(DefaultUserDetailsServiceImpl.class); 21 +public class AnonymousAuthenticationEntryPoint implements AuthenticationEntryPoint {
24 22
25 @Override 23 @Override
26 public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) { 24 public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) {
27 - // 允许跨域  
28 - response.setHeader("Access-Control-Allow-Origin", "*");  
29 - // 允许自定义请求头token(允许head跨域)  
30 - response.setHeader("Access-Control-Allow-Headers", "token, Accept, Origin, X-Requested-With, Content-Type, Last-Modified");  
31 - response.setHeader("Content-type", "application/json;charset=UTF-8"); 25 + String jwt = request.getHeader(JwtUtils.getHeader());
  26 + JwtUser jwtUser = JwtUtils.verifyToken(jwt);
  27 + String username = jwtUser.getUserName();
  28 + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtUser.getPassword() );
  29 + SecurityContextHolder.getContext().setAuthentication(token);
32 JSONObject jsonObject = new JSONObject(); 30 JSONObject jsonObject = new JSONObject();
33 jsonObject.put("code", ErrorCode.ERROR401.getCode()); 31 jsonObject.put("code", ErrorCode.ERROR401.getCode());
34 jsonObject.put("msg", ErrorCode.ERROR401.getMsg()); 32 jsonObject.put("msg", ErrorCode.ERROR401.getMsg());
src/main/java/com/genersoft/iot/vmp/conf/security/DefaultUserDetailsServiceImpl.java
1 package com.genersoft.iot.vmp.conf.security; 1 package com.genersoft.iot.vmp.conf.security;
2 2
3 -import java.time.LocalDateTime;  
4 - 3 +import com.alibaba.excel.util.StringUtils;
  4 +import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
  5 +import com.genersoft.iot.vmp.service.IUserService;
  6 +import com.genersoft.iot.vmp.storager.dao.dto.User;
5 import org.slf4j.Logger; 7 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory; 8 import org.slf4j.LoggerFactory;
7 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.beans.factory.annotation.Autowired;
@@ -10,10 +12,7 @@ import org.springframework.security.core.userdetails.UserDetailsService; @@ -10,10 +12,7 @@ import org.springframework.security.core.userdetails.UserDetailsService;
10 import org.springframework.security.core.userdetails.UsernameNotFoundException; 12 import org.springframework.security.core.userdetails.UsernameNotFoundException;
11 import org.springframework.stereotype.Component; 13 import org.springframework.stereotype.Component;
12 14
13 -import com.alibaba.excel.util.StringUtils;  
14 -import com.genersoft.iot.vmp.conf.security.dto.LoginUser;  
15 -import com.genersoft.iot.vmp.service.IUserService;  
16 -import com.genersoft.iot.vmp.storager.dao.dto.User; 15 +import java.time.LocalDateTime;
17 16
18 /** 17 /**
19 * 用户登录认证逻辑 18 * 用户登录认证逻辑
@@ -45,4 +44,8 @@ public class DefaultUserDetailsServiceImpl implements UserDetailsService { @@ -45,4 +44,8 @@ public class DefaultUserDetailsServiceImpl implements UserDetailsService {
45 } 44 }
46 45
47 46
  47 +
  48 +
  49 +
  50 +
48 } 51 }
src/main/java/com/genersoft/iot/vmp/conf/security/InvalidSessionHandler.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.conf.security;  
2 -  
3 -import org.slf4j.Logger;  
4 -import org.slf4j.LoggerFactory;  
5 -import org.springframework.security.web.session.InvalidSessionStrategy;  
6 -  
7 -import javax.servlet.ServletException;  
8 -import javax.servlet.http.HttpServletRequest;  
9 -import javax.servlet.http.HttpServletResponse;  
10 -import java.io.IOException;  
11 -  
12 -/**  
13 - * 登录超时的处理  
14 - */  
15 -public class InvalidSessionHandler implements InvalidSessionStrategy {  
16 -  
17 - private final static Logger logger = LoggerFactory.getLogger(InvalidSessionHandler.class);  
18 -  
19 - @Override  
20 - public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse httpServletResponse) throws IOException, ServletException {  
21 - String username = request.getParameter("username");  
22 - logger.info("[登录超时] - [{}]", username);  
23 - }  
24 -}  
src/main/java/com/genersoft/iot/vmp/conf/security/JwtAuthenticationFilter.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf.security;
  2 +
  3 +import com.genersoft.iot.vmp.conf.UserSetting;
  4 +import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
  5 +import org.apache.commons.lang3.StringUtils;
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  8 +import org.springframework.security.core.context.SecurityContextHolder;
  9 +import org.springframework.stereotype.Component;
  10 +import org.springframework.web.filter.OncePerRequestFilter;
  11 +
  12 +import javax.servlet.FilterChain;
  13 +import javax.servlet.ServletException;
  14 +import javax.servlet.http.HttpServletRequest;
  15 +import javax.servlet.http.HttpServletResponse;
  16 +import java.io.IOException;
  17 +import java.util.ArrayList;
  18 +
  19 +/**
  20 + * jwt token 过滤器
  21 + */
  22 +
  23 +@Component
  24 +public class JwtAuthenticationFilter extends OncePerRequestFilter {
  25 +
  26 +
  27 + @Autowired
  28 + private UserSetting userSetting;
  29 +
  30 +
  31 + @Override
  32 + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
  33 +
  34 + // 忽略登录请求的token验证
  35 + String requestURI = request.getRequestURI();
  36 + if (requestURI.equalsIgnoreCase("/api/user/login")) {
  37 + chain.doFilter(request, response);
  38 + return;
  39 + }
  40 + if (!userSetting.isInterfaceAuthentication()) {
  41 + // 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录
  42 + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>() );
  43 + SecurityContextHolder.getContext().setAuthentication(token);
  44 + chain.doFilter(request, response);
  45 + return;
  46 + }
  47 + String jwt = request.getHeader(JwtUtils.getHeader());
  48 + // 这里如果没有jwt,继续往后走,因为后面还有鉴权管理器等去判断是否拥有身份凭证,所以是可以放行的
  49 + // 没有jwt相当于匿名访问,若有一些接口是需要权限的,则不能访问这些接口
  50 + if (StringUtils.isBlank(jwt)) {
  51 + jwt = request.getParameter(JwtUtils.getHeader());
  52 + if (StringUtils.isBlank(jwt)) {
  53 + chain.doFilter(request, response);
  54 + return;
  55 + }
  56 + }
  57 +
  58 + JwtUser jwtUser = JwtUtils.verifyToken(jwt);
  59 + String username = jwtUser.getUserName();
  60 + // TODO 处理各个状态
  61 + switch (jwtUser.getStatus()){
  62 + case EXPIRED:
  63 + response.setStatus(400);
  64 + chain.doFilter(request, response);
  65 + // 异常
  66 + return;
  67 + case EXCEPTION:
  68 + // 过期
  69 + response.setStatus(400);
  70 + chain.doFilter(request, response);
  71 + return;
  72 + case EXPIRING_SOON:
  73 + // 即将过期
  74 +// return;
  75 + default:
  76 + }
  77 +
  78 + // 构建UsernamePasswordAuthenticationToken,这里密码为null,是因为提供了正确的JWT,实现自动登录
  79 + UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, jwtUser.getPassword(), new ArrayList<>() );
  80 + SecurityContextHolder.getContext().setAuthentication(token);
  81 + chain.doFilter(request, response);
  82 + }
  83 +
  84 +}
src/main/java/com/genersoft/iot/vmp/conf/security/JwtUtils.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf.security;
  2 +
  3 +import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
  4 +import org.jose4j.json.JsonUtil;
  5 +import org.jose4j.jwk.RsaJsonWebKey;
  6 +import org.jose4j.jws.AlgorithmIdentifiers;
  7 +import org.jose4j.jws.JsonWebSignature;
  8 +import org.jose4j.jwt.JwtClaims;
  9 +import org.jose4j.jwt.NumericDate;
  10 +import org.jose4j.jwt.consumer.ErrorCodes;
  11 +import org.jose4j.jwt.consumer.InvalidJwtException;
  12 +import org.jose4j.jwt.consumer.JwtConsumer;
  13 +import org.jose4j.jwt.consumer.JwtConsumerBuilder;
  14 +import org.jose4j.lang.JoseException;
  15 +import org.slf4j.Logger;
  16 +import org.slf4j.LoggerFactory;
  17 +
  18 +import java.security.PrivateKey;
  19 +import java.time.LocalDateTime;
  20 +import java.time.ZoneOffset;
  21 +
  22 +public class JwtUtils {
  23 +
  24 + private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
  25 +
  26 + private static final String HEADER = "access-token";
  27 + private static final String AUDIENCE = "Audience";
  28 +
  29 + private static final long EXPIRED_THRESHOLD = 10 * 60;
  30 +
  31 + private static final String keyId = "3e79646c4dbc408383a9eed09f2b85ae";
  32 + private static final String privateKeyStr = "{\"kty\":\"RSA\",\"kid\":\"3e79646c4dbc408383a9eed09f2b85ae\",\"alg\":\"RS256\",\"n\":\"gndmVdiOTSJ5et2HIeTM5f1m61x5ojLUi5HDfvr-jRrESQ5kbKuySGHVwR4QhwinpY1wQqBnwc80tx7cb_6SSqsTOoGln6T_l3k2Pb54ClVnGWiW_u1kmX78V2TZOsVmZmwtdZCMi-2zWIyAdIEXE-gncIehoAgEoq2VAhaCURbJWro_EwzzQwNmCTkDodLAx4npXRd_qSu0Ayp0txym9OFovBXBULRvk4DPiy3i_bPUmCDxzC46pTtFOe9p82uybTehZfULZtXXqRm85FL9n5zkrsTllPNAyEGhgb0RK9sE5nK1m_wNNysDyfLC4EFf1VXTrKm14XNVjc2vqLb7Mw\",\"e\":\"AQAB\",\"d\":\"ed7U_k3rJ4yTk70JtRSIfjKGiEb67BO1TabcymnljKO7RU8nage84zZYuSu_XpQsHk6P1f0Gzxkicghm_Er-FrfVn2pp70Xu52z3yRd6BJUgWLDFk97ngScIyw5OiULKU9SrZk2frDpftNCSUcIgb50F8m0QAnBa_CdPsQKbuuhLv8V8tBAV7F_lAwvSBgu56wRo3hPz5dWH8YeXM7XBfQ9viFMNEKd21sP_j5C7ueUnXT66nBxe3ZJEU3iuMYM6D6dB_KW2GfZC6WmTgvGhhxJD0h7aYmfjkD99MDleB7SkpbvoODOqiQ5Epb7Nyh6kv5u4KUv2CJYtATLZkUeMkQ\",\"p\":\"uBUjWPWtlGksmOqsqCNWksfqJvMcnP_8TDYN7e4-WnHL4N-9HjRuPDnp6kHvCIEi9SEfxm7gNxlRcWegvNQr3IZCz7TnCTexXc5NOklB9OavWFla6u-s3Thn6Tz45-EUjpJr0VJMxhO-KxGmuTwUXBBp4vN6K2qV6rQNFmgkWzk\",\"q\":\"tW_i7cCec56bHkhITL_79dXHz_PLC_f7xlynmlZJGU_d6mqOKmLBNBbTMLnYW8uAFiFzWxDeDHh1o5uF0mSQR-Z1Fg35OftnpbWpy0Cbc2la5WgXQjOwtG1eLYIY2BD3-wQ1VYDBCvowr4FDi-sngxwLqvwmrJ0xjhi99O-Gzcs\",\"dp\":\"q1d5jE85Hz_6M-eTh_lEluEf0NtPEc-vvhw-QO4V-cecNpbrCBdTWBmr4dE3NdpFeJc5ZVFEv-SACyei1MBEh0ItI_pFZi4BmMfy2ELh8ptaMMkTOESYyVy8U7veDq9RnBcr5i1Nqr0rsBkA77-9T6gzdvycBZdzLYAkAmwzEvk\",\"dq\":\"q29A2K08Crs-jmp2Bi8Q_8QzvIX6wSBbwZ4ir24AO-5_HNP56IrPS0yV2GCB0pqCOGb6_Hz_koDvhtuYoqdqvMVAtMoXR3YJBUaVXPt65p4RyNmFwIPe31zHs_BNUTsXVRMw4c16mci03-Af1sEm4HdLfxAp6sfM3xr5wcnhcek\",\"qi\":\"rHPgVTyHUHuYzcxfouyBfb1XAY8nshwn0ddo81o1BccD4Z7zo5It6SefDHjxCAbcmbiCcXBSooLcY-NF5FMv3fg19UE21VyLQltHcVjRRp2tRs4OHcM8yaXIU2x6N6Z6BP2tOksHb9MOBY1wAQzFOAKg_G4Sxev6-_6ud6RISuc\"}";
  33 + private static final String publicKeyStr = "{\"kty\":\"RSA\",\"kid\":\"3e79646c4dbc408383a9eed09f2b85ae\",\"alg\":\"RS256\",\"n\":\"gndmVdiOTSJ5et2HIeTM5f1m61x5ojLUi5HDfvr-jRrESQ5kbKuySGHVwR4QhwinpY1wQqBnwc80tx7cb_6SSqsTOoGln6T_l3k2Pb54ClVnGWiW_u1kmX78V2TZOsVmZmwtdZCMi-2zWIyAdIEXE-gncIehoAgEoq2VAhaCURbJWro_EwzzQwNmCTkDodLAx4npXRd_qSu0Ayp0txym9OFovBXBULRvk4DPiy3i_bPUmCDxzC46pTtFOe9p82uybTehZfULZtXXqRm85FL9n5zkrsTllPNAyEGhgb0RK9sE5nK1m_wNNysDyfLC4EFf1VXTrKm14XNVjc2vqLb7Mw\",\"e\":\"AQAB\"}";
  34 +
  35 + /**
  36 + * token过期时间(分钟)
  37 + */
  38 + public static final long expirationTime = 30;
  39 +
  40 + public static String createToken(String username, String password) {
  41 + try {
  42 + /**
  43 + * “iss” (issuer) 发行人
  44 + *
  45 + * “sub” (subject) 主题
  46 + *
  47 + * “aud” (audience) 接收方 用户
  48 + *
  49 + * “exp” (expiration time) 到期时间
  50 + *
  51 + * “nbf” (not before) 在此之前不可用
  52 + *
  53 + * “iat” (issued at) jwt的签发时间
  54 + */
  55 + //Payload
  56 + JwtClaims claims = new JwtClaims();
  57 + claims.setGeneratedJwtId();
  58 + claims.setIssuedAtToNow();
  59 + // 令牌将过期的时间 分钟
  60 + claims.setExpirationTimeMinutesInTheFuture(expirationTime);
  61 + claims.setNotBeforeMinutesInThePast(0);
  62 + claims.setSubject("login");
  63 + claims.setAudience(AUDIENCE);
  64 + //添加自定义参数,必须是字符串类型
  65 + claims.setClaim("username", username);
  66 + claims.setClaim("password", password);
  67 +
  68 + //jws
  69 + JsonWebSignature jws = new JsonWebSignature();
  70 + //签名算法RS256
  71 + jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
  72 + jws.setKeyIdHeaderValue(keyId);
  73 + jws.setPayload(claims.toJson());
  74 +
  75 + PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyStr)).getPrivateKey();
  76 + jws.setKey(privateKey);
  77 +
  78 + //get token
  79 + String idToken = jws.getCompactSerialization();
  80 + return idToken;
  81 + } catch (JoseException e) {
  82 + logger.error("[Token生成失败]: {}", e.getMessage());
  83 + }
  84 +
  85 + return null;
  86 + }
  87 +
  88 + public static String getHeader() {
  89 + return HEADER;
  90 + }
  91 +
  92 +
  93 + public static JwtUser verifyToken(String token) {
  94 +
  95 + JwtUser jwtUser = new JwtUser();
  96 +
  97 + try {
  98 + JwtConsumer consumer = new JwtConsumerBuilder()
  99 + .setRequireExpirationTime()
  100 + .setMaxFutureValidityInMinutes(5256000)
  101 + .setAllowedClockSkewInSeconds(30)
  102 + .setRequireSubject()
  103 + //.setExpectedIssuer("")
  104 + .setExpectedAudience(AUDIENCE)
  105 + .setVerificationKey(new RsaJsonWebKey(JsonUtil.parseJson(publicKeyStr)).getPublicKey())
  106 + .build();
  107 +
  108 + JwtClaims claims = consumer.processToClaims(token);
  109 + NumericDate expirationTime = claims.getExpirationTime();
  110 + // 判断是否即将过期, 默认剩余时间小于5分钟未即将过期
  111 + // 剩余时间 (秒)
  112 + long timeRemaining = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8)) - expirationTime.getValue();
  113 + if (timeRemaining < 5 * 60) {
  114 + jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON);
  115 + }else {
  116 + jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
  117 + }
  118 +
  119 + String username = (String) claims.getClaimValue("username");
  120 + String password = (String) claims.getClaimValue("password");
  121 + jwtUser.setUserName(username);
  122 + jwtUser.setPassword(password);
  123 +
  124 + return jwtUser;
  125 + } catch (InvalidJwtException e) {
  126 + if (e.hasErrorCode(ErrorCodes.EXPIRED)) {
  127 + jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED);
  128 + }else {
  129 + jwtUser.setStatus(JwtUser.TokenStatus.EXCEPTION);
  130 + }
  131 + return jwtUser;
  132 + }catch (Exception e) {
  133 + logger.error("[Token解析失败]: {}", e.getMessage());
  134 + jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED);
  135 + return jwtUser;
  136 + }
  137 + }
  138 +}
src/main/java/com/genersoft/iot/vmp/conf/security/LoginSuccessHandler.java
@@ -21,7 +21,16 @@ public class LoginSuccessHandler implements AuthenticationSuccessHandler { @@ -21,7 +21,16 @@ public class LoginSuccessHandler implements AuthenticationSuccessHandler {
21 21
22 @Override 22 @Override
23 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { 23 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
24 - String username = request.getParameter("username");  
25 - logger.info("[登录成功] - [{}]", username); 24 +// String username = request.getParameter("username");
  25 +// httpServletResponse.setContentType("application/json;charset=UTF-8");
  26 +// // 生成JWT,并放置到请求头中
  27 +// String jwt = JwtUtils.createToken(authentication.getName(), );
  28 +// httpServletResponse.setHeader(JwtUtils.getHeader(), jwt);
  29 +// ServletOutputStream outputStream = httpServletResponse.getOutputStream();
  30 +// outputStream.write(JSON.toJSONString(ErrorCode.SUCCESS).getBytes(StandardCharsets.UTF_8));
  31 +// outputStream.flush();
  32 +// outputStream.close();
  33 +
  34 +// logger.info("[登录成功] - [{}]", username);
26 } 35 }
27 } 36 }
src/main/java/com/genersoft/iot/vmp/conf/security/SecurityUtils.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.security.dto.LoginUser; 3 import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
  4 +import com.genersoft.iot.vmp.storager.dao.dto.User;
4 import org.springframework.security.authentication.AuthenticationManager; 5 import org.springframework.security.authentication.AuthenticationManager;
5 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 6 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
6 import org.springframework.security.core.Authentication; 7 import org.springframework.security.core.Authentication;
@@ -9,6 +10,7 @@ import org.springframework.security.core.context.SecurityContextHolder; @@ -9,6 +10,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
9 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 10 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
10 11
11 import javax.security.sasl.AuthenticationException; 12 import javax.security.sasl.AuthenticationException;
  13 +import java.time.LocalDateTime;
12 14
13 public class SecurityUtils { 15 public class SecurityUtils {
14 16
@@ -25,9 +27,12 @@ public class SecurityUtils { @@ -25,9 +27,12 @@ public class SecurityUtils {
25 public static LoginUser login(String username, String password, AuthenticationManager authenticationManager) throws AuthenticationException { 27 public static LoginUser login(String username, String password, AuthenticationManager authenticationManager) throws AuthenticationException {
26 //使用security框架自带的验证token生成器 也可以自定义。 28 //使用security框架自带的验证token生成器 也可以自定义。
27 UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(username,password); 29 UsernamePasswordAuthenticationToken token =new UsernamePasswordAuthenticationToken(username,password);
  30 + //认证 如果失败,这里会自动异常后返回,所以这里不需要判断返回值是否为空,确定是否登录成功
28 Authentication authenticate = authenticationManager.authenticate(token); 31 Authentication authenticate = authenticationManager.authenticate(token);
29 - SecurityContextHolder.getContext().setAuthentication(authenticate);  
30 LoginUser user = (LoginUser) authenticate.getPrincipal(); 32 LoginUser user = (LoginUser) authenticate.getPrincipal();
  33 +
  34 + SecurityContextHolder.getContext().setAuthentication(token);
  35 +
31 return user; 36 return user;
32 } 37 }
33 38
@@ -49,8 +54,13 @@ public class SecurityUtils { @@ -49,8 +54,13 @@ public class SecurityUtils {
49 if(authentication!=null){ 54 if(authentication!=null){
50 Object principal = authentication.getPrincipal(); 55 Object principal = authentication.getPrincipal();
51 if(principal!=null && !"anonymousUser".equals(principal)){ 56 if(principal!=null && !"anonymousUser".equals(principal)){
52 - LoginUser user = (LoginUser) authentication.getPrincipal();  
53 - return user; 57 +// LoginUser user = (LoginUser) authentication.getPrincipal();
  58 +
  59 + String username = (String) principal;
  60 + User user = new User();
  61 + user.setUsername(username);
  62 + LoginUser loginUser = new LoginUser(user, LocalDateTime.now());
  63 + return loginUser;
54 } 64 }
55 } 65 }
56 return null; 66 return null;
src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java
@@ -15,9 +15,16 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -15,9 +15,16 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
15 import org.springframework.security.config.annotation.web.builders.WebSecurity; 15 import org.springframework.security.config.annotation.web.builders.WebSecurity;
16 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 16 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
17 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 17 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  18 +import org.springframework.security.config.http.SessionCreationPolicy;
18 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 19 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  20 +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
  21 +import org.springframework.web.cors.CorsConfiguration;
  22 +import org.springframework.web.cors.CorsConfigurationSource;
  23 +import org.springframework.web.cors.CorsUtils;
  24 +import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
19 25
20 -import java.util.List; 26 +import java.util.ArrayList;
  27 +import java.util.Arrays;
21 28
22 /** 29 /**
23 * 配置Spring Security 30 * 配置Spring Security
@@ -56,22 +63,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @@ -56,22 +63,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
56 */ 63 */
57 @Autowired 64 @Autowired
58 private AnonymousAuthenticationEntryPoint anonymousAuthenticationEntryPoint; 65 private AnonymousAuthenticationEntryPoint anonymousAuthenticationEntryPoint;
59 -// /**  
60 -// * 超时处理  
61 -// */  
62 -// @Autowired  
63 -// private InvalidSessionHandler invalidSessionHandler;  
64 -  
65 -// /**  
66 -// * 顶号处理  
67 -// */  
68 -// @Autowired  
69 -// private SessionInformationExpiredHandler sessionInformationExpiredHandler;  
70 -// /**  
71 -// * 登录用户没有权限访问资源  
72 -// */  
73 -// @Autowired  
74 -// private LoginUserAccessDeniedHandler accessDeniedHandler; 66 + @Autowired
  67 + private JwtAuthenticationFilter jwtAuthenticationFilter;
75 68
76 69
77 /** 70 /**
@@ -80,31 +73,21 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @@ -80,31 +73,21 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
80 @Override 73 @Override
81 public void configure(WebSecurity web) { 74 public void configure(WebSecurity web) {
82 75
83 - if (!userSetting.isInterfaceAuthentication()) {  
84 - web.ignoring().antMatchers("**");  
85 - }else {  
86 - // 可以直接访问的静态数据  
87 - web.ignoring()  
88 - .antMatchers("/")  
89 - .antMatchers("/#/**")  
90 - .antMatchers("/static/**")  
91 - .antMatchers("/index.html")  
92 - .antMatchers("/doc.html") // "/webjars/**", "/swagger-resources/**", "/v3/api-docs/**"  
93 - .antMatchers("/webjars/**")  
94 - .antMatchers("/swagger-resources/**")  
95 - .antMatchers("/v3/api-docs/**")  
96 - .antMatchers("/favicon.ico")  
97 - .antMatchers("/js/**");  
98 - List<String> interfaceAuthenticationExcludes = userSetting.getInterfaceAuthenticationExcludes();  
99 - for (String interfaceAuthenticationExclude : interfaceAuthenticationExcludes) {  
100 - if (interfaceAuthenticationExclude.split("/").length < 4 ) {  
101 - logger.warn("{}不满足两级目录,已忽略", interfaceAuthenticationExclude);  
102 - }else {  
103 - web.ignoring().antMatchers(interfaceAuthenticationExclude);  
104 - }  
105 -  
106 - }  
107 - } 76 + ArrayList<String> matchers = new ArrayList<>();
  77 + matchers.add("/");
  78 + matchers.add("/#/**");
  79 + matchers.add("/static/**");
  80 + matchers.add("/index.html");
  81 + matchers.add("/doc.html");
  82 + matchers.add("/webjars/**");
  83 + matchers.add("/swagger-resources/**");
  84 + matchers.add("/v3/api-docs/**");
  85 + matchers.add("/js/**");
  86 + matchers.add("/api/device/query/snap/**");
  87 + matchers.add("/record_proxy/*/**");
  88 + matchers.addAll(userSetting.getInterfaceAuthenticationExcludes());
  89 + // 可以直接访问的静态数据
  90 + web.ignoring().antMatchers(matchers.toArray(new String[0]));
108 } 91 }
109 92
110 /** 93 /**
@@ -126,36 +109,43 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @@ -126,36 +109,43 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
126 109
127 @Override 110 @Override
128 protected void configure(HttpSecurity http) throws Exception { 111 protected void configure(HttpSecurity http) throws Exception {
129 - http.cors().and().csrf().disable();  
130 - // 设置允许添加静态文件  
131 - http.headers().contentTypeOptions().disable();  
132 - http.authorizeRequests()  
133 - // 放行接口  
134 - .antMatchers("/api/user/login","/index/hook/**").permitAll()  
135 - // 除上面外的所有请求全部需要鉴权认证 112 + http.headers().contentTypeOptions().disable()
  113 + .and().cors().configurationSource(configurationSource())
  114 + .and().csrf().disable()
  115 + .sessionManagement()
  116 + .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  117 +
  118 + // 配置拦截规则
  119 + .and()
  120 + .authorizeRequests()
  121 + .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
  122 + .antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll()
  123 + .antMatchers("/api/user/login","/index/hook/**","/zlm_Proxy/FhTuMYqB2HeCuNOb/record/t/1/2023-03-25/16:35:07-16:35:16-9353.mp4").permitAll()
136 .anyRequest().authenticated() 124 .anyRequest().authenticated()
137 - // 异常处理(权限拒绝、登录失效等)  
138 - .and().exceptionHandling()  
139 - //匿名用户访问无权限资源时的异常处理 125 + // 异常处理器
  126 + .and()
  127 + .exceptionHandling()
140 .authenticationEntryPoint(anonymousAuthenticationEntryPoint) 128 .authenticationEntryPoint(anonymousAuthenticationEntryPoint)
141 -// .accessDeniedHandler(accessDeniedHandler)//登录用户没有权限访问资源  
142 - // 登入 允许所有用户  
143 - .and().formLogin().permitAll()  
144 - //登录成功处理逻辑  
145 - .successHandler(loginSuccessHandler)  
146 - //登录失败处理逻辑  
147 - .failureHandler(loginFailureHandler)  
148 - // 登出  
149 .and().logout().logoutUrl("/api/user/logout").permitAll() 129 .and().logout().logoutUrl("/api/user/logout").permitAll()
150 - //登出成功处理逻辑  
151 .logoutSuccessHandler(logoutHandler) 130 .logoutSuccessHandler(logoutHandler)
152 - .deleteCookies("JSESSIONID")  
153 - // 会话管理  
154 -// .and().sessionManagement().invalidSessionStrategy(invalidSessionHandler) // 超时处理  
155 -// .maximumSessions(1)//同一账号同时登录最大用户数  
156 -// .expiredSessionStrategy(sessionInformationExpiredHandler) // 顶号处理  
157 ; 131 ;
  132 + http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
  133 +
  134 + }
158 135
  136 + CorsConfigurationSource configurationSource(){
  137 + // 配置跨域
  138 + CorsConfiguration corsConfiguration = new CorsConfiguration();
  139 + corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
  140 + corsConfiguration.setAllowedMethods(Arrays.asList("*"));
  141 + corsConfiguration.setMaxAge(3600L);
  142 + corsConfiguration.setAllowCredentials(true);
  143 + corsConfiguration.setAllowedOrigins(userSetting.getAllowedOrigins());
  144 + corsConfiguration.setExposedHeaders(Arrays.asList(JwtUtils.getHeader()));
  145 +
  146 + UrlBasedCorsConfigurationSource url = new UrlBasedCorsConfigurationSource();
  147 + url.registerCorsConfiguration("/**",corsConfiguration);
  148 + return url;
159 } 149 }
160 150
161 /** 151 /**
src/main/java/com/genersoft/iot/vmp/conf/security/dto/JwtUser.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf.security.dto;
  2 +
  3 +public class JwtUser {
  4 +
  5 + public enum TokenStatus{
  6 + /**
  7 + * 正常的使用状态
  8 + */
  9 + NORMAL,
  10 + /**
  11 + * 过期而失效
  12 + */
  13 + EXPIRED,
  14 + /**
  15 + * 即将过期
  16 + */
  17 + EXPIRING_SOON,
  18 + /**
  19 + * 异常
  20 + */
  21 + EXCEPTION
  22 + }
  23 +
  24 + private String userName;
  25 +
  26 + private String password;
  27 +
  28 + private TokenStatus status;
  29 +
  30 + public String getUserName() {
  31 + return userName;
  32 + }
  33 +
  34 + public void setUserName(String userName) {
  35 + this.userName = userName;
  36 + }
  37 +
  38 + public TokenStatus getStatus() {
  39 + return status;
  40 + }
  41 +
  42 + public void setStatus(TokenStatus status) {
  43 + this.status = status;
  44 + }
  45 +
  46 + public String getPassword() {
  47 + return password;
  48 + }
  49 +
  50 + public void setPassword(String password) {
  51 + this.password = password;
  52 + }
  53 +}
src/main/java/com/genersoft/iot/vmp/conf/security/dto/LoginUser.java
@@ -19,6 +19,8 @@ public class LoginUser implements UserDetails, CredentialsContainer { @@ -19,6 +19,8 @@ public class LoginUser implements UserDetails, CredentialsContainer {
19 */ 19 */
20 private User user; 20 private User user;
21 21
  22 + private String accessToken;
  23 +
22 24
23 /** 25 /**
24 * 登录时间 26 * 登录时间
@@ -102,4 +104,11 @@ public class LoginUser implements UserDetails, CredentialsContainer { @@ -102,4 +104,11 @@ public class LoginUser implements UserDetails, CredentialsContainer {
102 return user.getPushKey(); 104 return user.getPushKey();
103 } 105 }
104 106
  107 + public String getAccessToken() {
  108 + return accessToken;
  109 + }
  110 +
  111 + public void setAccessToken(String accessToken) {
  112 + this.accessToken = accessToken;
  113 + }
105 } 114 }
src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java
@@ -171,7 +171,7 @@ public class DigestServerAuthenticationHelper { @@ -171,7 +171,7 @@ public class DigestServerAuthenticationHelper {
171 */ 171 */
172 public boolean doAuthenticatePlainTextPassword(Request request, String pass) { 172 public boolean doAuthenticatePlainTextPassword(Request request, String pass) {
173 AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); 173 AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
174 - if ( authHeader == null ) { 174 + if ( authHeader == null || authHeader.getRealm() == null) {
175 return false; 175 return false;
176 } 176 }
177 String realm = authHeader.getRealm().trim(); 177 String realm = authHeader.getRealm().trim();
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java
@@ -188,6 +188,13 @@ public class Device { @@ -188,6 +188,13 @@ public class Device {
188 @Schema(description = "SIP交互IP(设备访问平台的IP)") 188 @Schema(description = "SIP交互IP(设备访问平台的IP)")
189 private String localIp; 189 private String localIp;
190 190
  191 + @Schema(description = "是否作为消息通道")
  192 + private boolean asMessageChannel;
  193 +
  194 + @Schema(description = "设备注册的事务信息")
  195 + private SipTransactionInfo sipTransactionInfo;
  196 +
  197 +
191 public String getDeviceId() { 198 public String getDeviceId() {
192 return deviceId; 199 return deviceId;
193 } 200 }
@@ -428,4 +435,20 @@ public class Device { @@ -428,4 +435,20 @@ public class Device {
428 public void setKeepaliveIntervalTime(int keepaliveIntervalTime) { 435 public void setKeepaliveIntervalTime(int keepaliveIntervalTime) {
429 this.keepaliveIntervalTime = keepaliveIntervalTime; 436 this.keepaliveIntervalTime = keepaliveIntervalTime;
430 } 437 }
  438 +
  439 + public boolean isAsMessageChannel() {
  440 + return asMessageChannel;
  441 + }
  442 +
  443 + public void setAsMessageChannel(boolean asMessageChannel) {
  444 + this.asMessageChannel = asMessageChannel;
  445 + }
  446 +
  447 + public SipTransactionInfo getSipTransactionInfo() {
  448 + return sipTransactionInfo;
  449 + }
  450 +
  451 + public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) {
  452 + this.sipTransactionInfo = sipTransactionInfo;
  453 + }
431 } 454 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
@@ -189,6 +189,9 @@ public class ParentPlatform { @@ -189,6 +189,9 @@ public class ParentPlatform {
189 @Schema(description = "树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGrou") 189 @Schema(description = "树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGrou")
190 private String treeType; 190 private String treeType;
191 191
  192 + @Schema(description = "是否作为消息通道")
  193 + private boolean asMessageChannel;
  194 +
192 public Integer getId() { 195 public Integer getId() {
193 return id; 196 return id;
194 } 197 }
@@ -428,4 +431,12 @@ public class ParentPlatform { @@ -428,4 +431,12 @@ public class ParentPlatform {
428 public void setTreeType(String treeType) { 431 public void setTreeType(String treeType) {
429 this.treeType = treeType; 432 this.treeType = treeType;
430 } 433 }
  434 +
  435 + public boolean isAsMessageChannel() {
  436 + return asMessageChannel;
  437 + }
  438 +
  439 + public void setAsMessageChannel(boolean asMessageChannel) {
  440 + this.asMessageChannel = asMessageChannel;
  441 + }
431 } 442 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatformCatch.java
@@ -16,6 +16,8 @@ public class ParentPlatformCatch { @@ -16,6 +16,8 @@ public class ParentPlatformCatch {
16 16
17 private ParentPlatform parentPlatform; 17 private ParentPlatform parentPlatform;
18 18
  19 + private SipTransactionInfo sipTransactionInfo;
  20 +
19 public String getId() { 21 public String getId() {
20 return id; 22 return id;
21 } 23 }
@@ -55,4 +57,12 @@ public class ParentPlatformCatch { @@ -55,4 +57,12 @@ public class ParentPlatformCatch {
55 public void setCallId(String callId) { 57 public void setCallId(String callId) {
56 this.callId = callId; 58 this.callId = callId;
57 } 59 }
  60 +
  61 + public SipTransactionInfo getSipTransactionInfo() {
  62 + return sipTransactionInfo;
  63 + }
  64 +
  65 + public void setSipTransactionInfo(SipTransactionInfo sipTransactionInfo) {
  66 + this.sipTransactionInfo = sipTransactionInfo;
  67 + }
58 } 68 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
1 package com.genersoft.iot.vmp.gb28181.bean; 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2
3 3
  4 +import io.swagger.v3.oas.annotations.media.Schema;
  5 +
4 import java.time.Instant; 6 import java.time.Instant;
5 import java.util.List; 7 import java.util.List;
6 8
@@ -9,22 +11,29 @@ import java.util.List; @@ -9,22 +11,29 @@ import java.util.List;
9 * @author: swwheihei 11 * @author: swwheihei
10 * @date: 2020年5月8日 下午2:05:56 12 * @date: 2020年5月8日 下午2:05:56
11 */ 13 */
  14 +@Schema(description = "设备录像查询结果信息")
12 public class RecordInfo { 15 public class RecordInfo {
13 16
  17 + @Schema(description = "设备编号")
14 private String deviceId; 18 private String deviceId;
15 19
  20 + @Schema(description = "通道编号")
16 private String channelId; 21 private String channelId;
17 22
  23 + @Schema(description = "命令序列号")
18 private String sn; 24 private String sn;
19 25
  26 + @Schema(description = "设备名称")
20 private String name; 27 private String name;
21 - 28 +
  29 + @Schema(description = "列表总数")
22 private int sumNum; 30 private int sumNum;
23 31
24 private int count; 32 private int count;
25 33
26 private Instant lastTime; 34 private Instant lastTime;
27 - 35 +
  36 + @Schema(description = "")
28 private List<RecordItem> recordList; 37 private List<RecordItem> recordList;
29 38
30 public String getDeviceId() { 39 public String getDeviceId() {
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java
@@ -2,9 +2,9 @@ package com.genersoft.iot.vmp.gb28181.bean; @@ -2,9 +2,9 @@ package com.genersoft.iot.vmp.gb28181.bean;
2 2
3 3
4 import com.genersoft.iot.vmp.utils.DateUtil; 4 import com.genersoft.iot.vmp.utils.DateUtil;
  5 +import io.swagger.v3.oas.annotations.media.Schema;
5 import org.jetbrains.annotations.NotNull; 6 import org.jetbrains.annotations.NotNull;
6 7
7 -import java.text.ParseException;  
8 import java.time.Instant; 8 import java.time.Instant;
9 import java.time.temporal.TemporalAccessor; 9 import java.time.temporal.TemporalAccessor;
10 10
@@ -13,26 +13,37 @@ import java.time.temporal.TemporalAccessor; @@ -13,26 +13,37 @@ import java.time.temporal.TemporalAccessor;
13 * @author: swwheihei 13 * @author: swwheihei
14 * @date: 2020年5月8日 下午2:06:54 14 * @date: 2020年5月8日 下午2:06:54
15 */ 15 */
  16 +@Schema(description = "设备录像详情")
16 public class RecordItem implements Comparable<RecordItem>{ 17 public class RecordItem implements Comparable<RecordItem>{
17 18
  19 + @Schema(description = "设备编号")
18 private String deviceId; 20 private String deviceId;
19 - 21 +
  22 + @Schema(description = "名称")
20 private String name; 23 private String name;
21 - 24 +
  25 + @Schema(description = "文件路径名 (可选)")
22 private String filePath; 26 private String filePath;
23 27
  28 + @Schema(description = "录像文件大小,单位:Byte(可选)")
24 private String fileSize; 29 private String fileSize;
25 30
  31 + @Schema(description = "录像地址(可选)")
26 private String address; 32 private String address;
27 - 33 +
  34 + @Schema(description = "录像开始时间(可选)")
28 private String startTime; 35 private String startTime;
29 - 36 +
  37 + @Schema(description = "录像结束时间(可选)")
30 private String endTime; 38 private String endTime;
31 - 39 +
  40 + @Schema(description = "保密属性(必选)缺省为0;0:不涉密,1:涉密")
32 private int secrecy; 41 private int secrecy;
33 - 42 +
  43 + @Schema(description = "录像产生类型(可选)time或alarm 或 manua")
34 private String type; 44 private String type;
35 - 45 +
  46 + @Schema(description = "录像触发者ID(可选)")
36 private String recorderId; 47 private String recorderId;
37 48
38 public String getDeviceId() { 49 public String getDeviceId() {
src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEventImpl.java
1 package com.genersoft.iot.vmp.gb28181.event.device; 1 package com.genersoft.iot.vmp.gb28181.event.device;
2 2
3 import com.genersoft.iot.vmp.gb28181.bean.Device; 3 import com.genersoft.iot.vmp.gb28181.bean.Device;
4 -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;  
5 import com.genersoft.iot.vmp.service.IDeviceService; 4 import com.genersoft.iot.vmp.service.IDeviceService;
6 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.context.ApplicationListener; 6 import org.springframework.context.ApplicationListener;
@@ -9,8 +8,6 @@ import org.springframework.stereotype.Component; @@ -9,8 +8,6 @@ import org.springframework.stereotype.Component;
9 8
10 import javax.sip.ClientTransaction; 9 import javax.sip.ClientTransaction;
11 import javax.sip.address.SipURI; 10 import javax.sip.address.SipURI;
12 -import javax.sip.header.CallIdHeader;  
13 -import javax.sip.header.ToHeader;  
14 import javax.sip.message.Request; 11 import javax.sip.message.Request;
15 12
16 /** 13 /**
@@ -34,7 +31,7 @@ public class RequestTimeoutEventImpl implements ApplicationListener&lt;RequestTimeo @@ -34,7 +31,7 @@ public class RequestTimeoutEventImpl implements ApplicationListener&lt;RequestTimeo
34 if (device == null) { 31 if (device == null) {
35 return; 32 return;
36 } 33 }
37 - deviceService.offline(device.getDeviceId()); 34 + deviceService.offline(device.getDeviceId(), "等待消息超时");
38 } 35 }
39 36
40 } 37 }
src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java
@@ -61,9 +61,9 @@ public class SipRunner implements CommandLineRunner { @@ -61,9 +61,9 @@ public class SipRunner implements CommandLineRunner {
61 61
62 for (Device device : deviceList) { 62 for (Device device : deviceList) {
63 if (deviceService.expire(device)){ 63 if (deviceService.expire(device)){
64 - deviceService.offline(device.getDeviceId()); 64 + deviceService.offline(device.getDeviceId(), "注册已过期");
65 }else { 65 }else {
66 - deviceService.online(device); 66 + deviceService.online(device, null);
67 } 67 }
68 } 68 }
69 // 重置cseq计数 69 // 重置cseq计数
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -120,7 +120,7 @@ public interface ISIPCommander { @@ -120,7 +120,7 @@ public interface ISIPCommander {
120 */ 120 */
121 void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, 121 void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
122 String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, 122 String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
123 - SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; 123 + SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
124 124
125 125
126 /** 126 /**
@@ -217,7 +217,6 @@ public interface ISIPCommander { @@ -217,7 +217,6 @@ public interface ISIPCommander {
217 * 217 *
218 * @param device 视频设备 218 * @param device 视频设备
219 * @param channelId 通道id,非通道则是设备本身 219 * @param channelId 通道id,非通道则是设备本身
220 - * @param frontCmd 上级平台的指令,如果存在则直接下发  
221 * @param enabled 看守位使能:1 = 开启,0 = 关闭 220 * @param enabled 看守位使能:1 = 开启,0 = 关闭
222 * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) 221 * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
223 * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 222 * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
@@ -22,12 +22,10 @@ public interface ISIPCommanderForPlatform { @@ -22,12 +22,10 @@ public interface ISIPCommanderForPlatform {
22 * @param parentPlatform 22 * @param parentPlatform
23 * @return 23 * @return
24 */ 24 */
25 - void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent)  
26 - throws InvalidArgumentException, ParseException, SipException; 25 + void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException;
27 26
28 - void register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www,  
29 - SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister)  
30 - throws SipException, InvalidArgumentException, ParseException; 27 + void register(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException;
  28 + void register(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException;
31 29
32 /** 30 /**
33 * 向上级平台注销 31 * 向上级平台注销
@@ -35,8 +33,7 @@ public interface ISIPCommanderForPlatform { @@ -35,8 +33,7 @@ public interface ISIPCommanderForPlatform {
35 * @param parentPlatform 33 * @param parentPlatform
36 * @return 34 * @return
37 */ 35 */
38 - void unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent)  
39 - throws InvalidArgumentException, ParseException, SipException; 36 + void unregister(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException;
40 37
41 38
42 /** 39 /**
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
@@ -46,7 +46,7 @@ public class SIPRequestHeaderPlarformProvider { @@ -46,7 +46,7 @@ public class SIPRequestHeaderPlarformProvider {
46 @Autowired 46 @Autowired
47 private IRedisCatchStorage redisCatchStorage; 47 private IRedisCatchStorage redisCatchStorage;
48 48
49 - public Request createRegisterRequest(@NotNull ParentPlatform parentPlatform, long CSeq, String fromTag, String viaTag, CallIdHeader callIdHeader, boolean isRegister) throws ParseException, InvalidArgumentException, PeerUnavailableException { 49 + public Request createRegisterRequest(@NotNull ParentPlatform parentPlatform, long CSeq, String fromTag, String toTag, CallIdHeader callIdHeader, boolean isRegister) throws ParseException, InvalidArgumentException, PeerUnavailableException {
50 Request request = null; 50 Request request = null;
51 String sipAddress = parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort(); 51 String sipAddress = parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort();
52 //请求行 52 //请求行
@@ -54,7 +54,8 @@ public class SIPRequestHeaderPlarformProvider { @@ -54,7 +54,8 @@ public class SIPRequestHeaderPlarformProvider {
54 parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); 54 parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
55 //via 55 //via
56 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); 56 ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
57 - ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(parentPlatform.getServerIP(), parentPlatform.getServerPort(), parentPlatform.getTransport(), viaTag); 57 + ViaHeader viaHeader = sipLayer.getSipFactory().createHeaderFactory().createViaHeader(parentPlatform.getServerIP(),
  58 + parentPlatform.getServerPort(), parentPlatform.getTransport(), SipUtils.getNewViaTag());
58 viaHeader.setRPort(); 59 viaHeader.setRPort();
59 viaHeaders.add(viaHeader); 60 viaHeaders.add(viaHeader);
60 //from 61 //from
@@ -64,7 +65,7 @@ public class SIPRequestHeaderPlarformProvider { @@ -64,7 +65,7 @@ public class SIPRequestHeaderPlarformProvider {
64 //to 65 //to
65 SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain()); 66 SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), sipConfig.getDomain());
66 Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); 67 Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
67 - ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,null); 68 + ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,toTag);
68 69
69 //Forwards 70 //Forwards
70 MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); 71 MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
@@ -86,15 +87,21 @@ public class SIPRequestHeaderPlarformProvider { @@ -86,15 +87,21 @@ public class SIPRequestHeaderPlarformProvider {
86 return request; 87 return request;
87 } 88 }
88 89
89 - public Request createRegisterRequest(@NotNull ParentPlatform parentPlatform, String fromTag, String viaTag,  
90 - String callId, WWWAuthenticateHeader www , CallIdHeader callIdHeader, boolean isRegister) throws ParseException, PeerUnavailableException, InvalidArgumentException { 90 + public Request createRegisterRequest(@NotNull ParentPlatform parentPlatform, String fromTag, String toTag,
  91 + WWWAuthenticateHeader www , CallIdHeader callIdHeader, boolean isRegister) throws ParseException, PeerUnavailableException, InvalidArgumentException {
91 92
92 93
93 - Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), fromTag, viaTag, callIdHeader, isRegister); 94 + Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), fromTag, toTag, callIdHeader, isRegister);
94 SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort()); 95 SipURI requestURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
95 if (www == null) { 96 if (www == null) {
96 AuthorizationHeader authorizationHeader = sipLayer.getSipFactory().createHeaderFactory().createAuthorizationHeader("Digest"); 97 AuthorizationHeader authorizationHeader = sipLayer.getSipFactory().createHeaderFactory().createAuthorizationHeader("Digest");
97 - authorizationHeader.setUsername(parentPlatform.getDeviceGBId()); 98 + String username = parentPlatform.getUsername();
  99 + if ( username == null || username == "" )
  100 + {
  101 + authorizationHeader.setUsername(parentPlatform.getDeviceGBId());
  102 + } else {
  103 + authorizationHeader.setUsername(username);
  104 + }
98 authorizationHeader.setURI(requestURI); 105 authorizationHeader.setURI(requestURI);
99 authorizationHeader.setAlgorithm("MD5"); 106 authorizationHeader.setAlgorithm("MD5");
100 registerRequest.addHeader(authorizationHeader); 107 registerRequest.addHeader(authorizationHeader);
@@ -108,8 +115,6 @@ public class SIPRequestHeaderPlarformProvider { @@ -108,8 +115,6 @@ public class SIPRequestHeaderPlarformProvider {
108 // qop 保护质量 包含auth(默认的)和auth-int(增加了报文完整性检测)两种策略 115 // qop 保护质量 包含auth(默认的)和auth-int(增加了报文完整性检测)两种策略
109 String qop = www.getQop(); 116 String qop = www.getQop();
110 117
111 - callIdHeader.setCallId(callId);  
112 -  
113 String cNonce = null; 118 String cNonce = null;
114 String nc = "00000001"; 119 String nc = "00000001";
115 if (qop != null) { 120 if (qop != null) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -276,7 +276,7 @@ public class SIPCommander implements ISIPCommander { @@ -276,7 +276,7 @@ public class SIPCommander implements ISIPCommander {
276 return; 276 return;
277 } 277 }
278 278
279 - logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); 279 + logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort());
280 HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId()); 280 HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId());
281 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { 281 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
282 if (event != null) { 282 if (event != null) {
@@ -377,7 +377,7 @@ public class SIPCommander implements ISIPCommander { @@ -377,7 +377,7 @@ public class SIPCommander implements ISIPCommander {
377 SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { 377 SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
378 378
379 379
380 - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); 380 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getSdpIp(), mediaServerItem.getIp(), ssrcInfo.getPort());
381 String sdpIp; 381 String sdpIp;
382 if (!ObjectUtils.isEmpty(device.getSdpIp())) { 382 if (!ObjectUtils.isEmpty(device.getSdpIp())) {
383 sdpIp = device.getSdpIp(); 383 sdpIp = device.getSdpIp();
@@ -479,10 +479,11 @@ public class SIPCommander implements ISIPCommander { @@ -479,10 +479,11 @@ public class SIPCommander implements ISIPCommander {
479 */ 479 */
480 @Override 480 @Override
481 public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, 481 public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
482 - String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,  
483 - SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { 482 + String startTime, String endTime, int downloadSpeed,
  483 + InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent,
  484 + SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
484 485
485 - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); 486 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getSdpIp(), mediaServerItem.getIp(), ssrcInfo.getPort());
486 String sdpIp; 487 String sdpIp;
487 if (!ObjectUtils.isEmpty(device.getSdpIp())) { 488 if (!ObjectUtils.isEmpty(device.getSdpIp())) {
488 sdpIp = device.getSdpIp(); 489 sdpIp = device.getSdpIp();
@@ -549,11 +550,14 @@ public class SIPCommander implements ISIPCommander { @@ -549,11 +550,14 @@ public class SIPCommander implements ISIPCommander {
549 content.append("a=downloadspeed:" + downloadSpeed + "\r\n"); 550 content.append("a=downloadspeed:" + downloadSpeed + "\r\n");
550 551
551 content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc 552 content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
552 - 553 + logger.debug("此时请求下载信令的ssrc===>{}",ssrcInfo.getSsrc());
553 HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId()); 554 HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId());
554 // 添加订阅 555 // 添加订阅
  556 + CallIdHeader newCallIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()), device.getTransport());
  557 + String callId=newCallIdHeader.getCallId();
555 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { 558 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
556 - hookEvent.call(new InviteStreamInfo(mediaServerItem, json,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream())); 559 + logger.debug("sipc 添加订阅===callId {}",callId);
  560 + hookEvent.call(new InviteStreamInfo(mediaServerItem, json,callId, "rtp", ssrcInfo.getStream()));
557 subscribe.removeSubscribe(hookSubscribe); 561 subscribe.removeSubscribe(hookSubscribe);
558 hookSubscribe.getContent().put("regist", false); 562 hookSubscribe.getContent().put("regist", false);
559 hookSubscribe.getContent().put("schema", "rtsp"); 563 hookSubscribe.getContent().put("schema", "rtsp");
@@ -562,7 +566,7 @@ public class SIPCommander implements ISIPCommander { @@ -562,7 +566,7 @@ public class SIPCommander implements ISIPCommander {
562 (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd) -> { 566 (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd) -> {
563 logger.info("[录像]下载结束, 发送BYE"); 567 logger.info("[录像]下载结束, 发送BYE");
564 try { 568 try {
565 - streamByeCmd(device, channelId, ssrcInfo.getStream(),sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId()); 569 + streamByeCmd(device, channelId, ssrcInfo.getStream(),callId);
566 } catch (InvalidArgumentException | ParseException | SipException | 570 } catch (InvalidArgumentException | ParseException | SipException |
567 SsrcTransactionNotFoundException e) { 571 SsrcTransactionNotFoundException e) {
568 logger.error("[录像]下载结束, 发送BYE失败 {}", e.getMessage()); 572 logger.error("[录像]下载结束, 发送BYE失败 {}", e.getMessage());
@@ -570,15 +574,24 @@ public class SIPCommander implements ISIPCommander { @@ -570,15 +574,24 @@ public class SIPCommander implements ISIPCommander {
570 }); 574 });
571 }); 575 });
572 576
573 - Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()), ssrcInfo.getSsrc()); 577 + Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null,newCallIdHeader, ssrcInfo.getSsrc());
574 if (inviteStreamCallback != null) { 578 if (inviteStreamCallback != null) {
575 - inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream())); 579 + inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,callId, "rtp", ssrcInfo.getStream()));
576 } 580 }
577 581
578 - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent -> {  
579 - ResponseEvent responseEvent = (ResponseEvent) okEvent.event; 582 + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> {
  583 + ResponseEvent responseEvent = (ResponseEvent) event.event;
580 SIPResponse response = (SIPResponse) responseEvent.getResponse(); 584 SIPResponse response = (SIPResponse) responseEvent.getResponse();
581 - streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download); 585 + String contentString =new String(response.getRawContent());
  586 + int ssrcIndex = contentString.indexOf("y=");
  587 + String ssrc=ssrcInfo.getSsrc();
  588 + if (ssrcIndex >= 0) {
  589 + ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
  590 + }
  591 + logger.debug("接收到的下载响应ssrc====>{}",ssrcInfo.getSsrc());
  592 + logger.debug("接收到的下载响应ssrc====>{}",ssrc);
  593 + streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrc, mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download);
  594 + okEvent.response(event);
582 }); 595 });
583 } 596 }
584 597
@@ -778,7 +791,7 @@ public class SIPCommander implements ISIPCommander { @@ -778,7 +791,7 @@ public class SIPCommander implements ISIPCommander {
778 cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n"); 791 cmdXml.append("<GuardCmd>" + guardCmdStr + "</GuardCmd>\r\n");
779 cmdXml.append("</Control>\r\n"); 792 cmdXml.append("</Control>\r\n");
780 793
781 - 794 +
782 795
783 Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); 796 Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
784 sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); 797 sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent);
@@ -854,7 +867,6 @@ public class SIPCommander implements ISIPCommander { @@ -854,7 +867,6 @@ public class SIPCommander implements ISIPCommander {
854 * 867 *
855 * @param device 视频设备 868 * @param device 视频设备
856 * @param channelId 通道id,非通道则是设备本身 869 * @param channelId 通道id,非通道则是设备本身
857 - * @param frontCmd 上级平台的指令,如果存在则直接下发  
858 * @param enabled 看守位使能:1 = 开启,0 = 关闭 870 * @param enabled 看守位使能:1 = 开启,0 = 关闭
859 * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) 871 * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
860 * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 872 * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
@@ -978,7 +990,7 @@ public class SIPCommander implements ISIPCommander { @@ -978,7 +990,7 @@ public class SIPCommander implements ISIPCommander {
978 catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); 990 catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");
979 catalogXml.append("</Query>\r\n"); 991 catalogXml.append("</Query>\r\n");
980 992
981 - 993 +
982 994
983 Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); 995 Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
984 996
@@ -1181,7 +1193,6 @@ public class SIPCommander implements ISIPCommander { @@ -1181,7 +1193,6 @@ public class SIPCommander implements ISIPCommander {
1181 cmdXml.append("</Query>\r\n"); 1193 cmdXml.append("</Query>\r\n");
1182 1194
1183 1195
1184 -  
1185 Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); 1196 Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
1186 sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); 1197 sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent);
1187 } 1198 }
@@ -1427,7 +1438,7 @@ public class SIPCommander implements ISIPCommander { @@ -1427,7 +1438,7 @@ public class SIPCommander implements ISIPCommander {
1427 if (device == null) { 1438 if (device == null) {
1428 return; 1439 return;
1429 } 1440 }
1430 - logger.info("[发送 报警通知] {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(), 1441 + logger.info("[发送报警通知]设备: {}/{}->{},{}", device.getDeviceId(), deviceAlarm.getChannelId(),
1431 deviceAlarm.getLongitude(), deviceAlarm.getLatitude()); 1442 deviceAlarm.getLongitude(), deviceAlarm.getLatitude());
1432 1443
1433 String characterSet = device.getCharset(); 1444 String characterSet = device.getCharset();
@@ -1439,7 +1450,7 @@ public class SIPCommander implements ISIPCommander { @@ -1439,7 +1450,7 @@ public class SIPCommander implements ISIPCommander {
1439 deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n"); 1450 deviceStatusXml.append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n");
1440 deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n"); 1451 deviceStatusXml.append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n");
1441 deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n"); 1452 deviceStatusXml.append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n");
1442 - deviceStatusXml.append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n"); 1453 + deviceStatusXml.append("<AlarmTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(deviceAlarm.getAlarmTime()) + "</AlarmTime>\r\n");
1443 deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n"); 1454 deviceStatusXml.append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n");
1444 deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n"); 1455 deviceStatusXml.append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n");
1445 deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n"); 1456 deviceStatusXml.append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n");
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -24,6 +24,7 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo; @@ -24,6 +24,7 @@ import com.genersoft.iot.vmp.service.bean.SSRCInfo;
24 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 24 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
25 import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; 25 import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo;
26 import com.genersoft.iot.vmp.utils.DateUtil; 26 import com.genersoft.iot.vmp.utils.DateUtil;
  27 +import com.genersoft.iot.vmp.utils.GitUtil;
27 import gov.nist.javax.sip.message.MessageFactoryImpl; 28 import gov.nist.javax.sip.message.MessageFactoryImpl;
28 import gov.nist.javax.sip.message.SIPRequest; 29 import gov.nist.javax.sip.message.SIPRequest;
29 import gov.nist.javax.sip.message.SIPResponse; 30 import gov.nist.javax.sip.message.SIPResponse;
@@ -85,26 +86,49 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -85,26 +86,49 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
85 @Autowired 86 @Autowired
86 private DynamicTask dynamicTask; 87 private DynamicTask dynamicTask;
87 88
  89 + @Autowired
  90 + private GitUtil gitUtil;
  91 +
88 @Override 92 @Override
89 public void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException { 93 public void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
90 register(parentPlatform, null, null, errorEvent, okEvent, false, true); 94 register(parentPlatform, null, null, errorEvent, okEvent, false, true);
91 } 95 }
92 96
93 @Override 97 @Override
94 - public void unregister(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {  
95 - register(parentPlatform, null, null, errorEvent, okEvent, false, false); 98 + public void register(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
  99 +
  100 + register(parentPlatform, sipTransactionInfo, null, errorEvent, okEvent, false, true);
96 } 101 }
97 102
98 @Override 103 @Override
99 - public void register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www, 104 + public void unregister(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException {
  105 + register(parentPlatform, sipTransactionInfo, null, errorEvent, okEvent, false, false);
  106 + }
  107 +
  108 + @Override
  109 + public void register(ParentPlatform parentPlatform, @Nullable SipTransactionInfo sipTransactionInfo, @Nullable WWWAuthenticateHeader www,
100 SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException { 110 SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain, boolean isRegister) throws SipException, InvalidArgumentException, ParseException {
101 Request request; 111 Request request;
102 - if (!registerAgain ) {  
103 - CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());  
104 112
  113 + CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());
  114 + String fromTag = SipUtils.getNewFromTag();
  115 + String toTag = null;
  116 + if (sipTransactionInfo != null ) {
  117 + if (sipTransactionInfo.getCallId() != null) {
  118 + callIdHeader.setCallId(sipTransactionInfo.getCallId());
  119 + }
  120 + if (sipTransactionInfo.getFromTag() != null) {
  121 + fromTag = sipTransactionInfo.getFromTag();
  122 + }
  123 + if (sipTransactionInfo.getToTag() != null) {
  124 + toTag = sipTransactionInfo.getToTag();
  125 + }
  126 + }
  127 +
  128 + if (!registerAgain ) {
105 request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, 129 request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform,
106 - redisCatchStorage.getCSEQ(), SipUtils.getNewFromTag(),  
107 - SipUtils.getNewViaTag(), callIdHeader, isRegister); 130 + redisCatchStorage.getCSEQ(), fromTag,
  131 + toTag, callIdHeader, isRegister);
108 // 将 callid 写入缓存, 等注册成功可以更新状态 132 // 将 callid 写入缓存, 等注册成功可以更新状态
109 String callIdFromHeader = callIdHeader.getCallId(); 133 String callIdFromHeader = callIdHeader.getCallId();
110 redisCatchStorage.updatePlatformRegisterInfo(callIdFromHeader, PlatformRegisterInfo.getInstance(parentPlatform.getServerGBId(), isRegister)); 134 redisCatchStorage.updatePlatformRegisterInfo(callIdFromHeader, PlatformRegisterInfo.getInstance(parentPlatform.getServerGBId(), isRegister));
@@ -122,8 +146,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -122,8 +146,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
122 }); 146 });
123 147
124 }else { 148 }else {
125 - CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(parentPlatform.getDeviceIp(),parentPlatform.getTransport());  
126 - request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, SipUtils.getNewFromTag(), null, callId, www, callIdHeader, isRegister); 149 + request = headerProviderPlatformProvider.createRegisterRequest(parentPlatform, fromTag, toTag, www, callIdHeader, isRegister);
127 } 150 }
128 151
129 sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, null, okEvent); 152 sipSender.transmitRequest(parentPlatform.getDeviceIp(), request, null, okEvent);
@@ -245,6 +268,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -245,6 +268,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
245 catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n"); 268 catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");
246 catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n"); 269 catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");
247 catalogXml.append("<Password>" + channel.getPort() + "</Password>\r\n"); 270 catalogXml.append("<Password>" + channel.getPort() + "</Password>\r\n");
  271 + catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");
248 catalogXml.append("<Status>" + (channel.getStatus() == 1?"ON":"OFF") + "</Status>\r\n"); 272 catalogXml.append("<Status>" + (channel.getStatus() == 1?"ON":"OFF") + "</Status>\r\n");
249 catalogXml.append("<Longitude>" + 273 catalogXml.append("<Longitude>" +
250 (channel.getLongitudeWgs84() != 0? channel.getLongitudeWgs84():channel.getLongitude()) 274 (channel.getLongitudeWgs84() != 0? channel.getLongitudeWgs84():channel.getLongitude())
@@ -285,6 +309,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -285,6 +309,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
285 309
286 String callId = request.getCallIdHeader().getCallId(); 310 String callId = request.getCallIdHeader().getCallId();
287 311
  312 + logger.info("[命令发送] 国标级联{} 目录查询回复: 共{}条,已发送{}条", parentPlatform.getServerGBId(),
  313 + channels.size(), Math.min(index + parentPlatform.getCatalogGroup(), channels.size()));
  314 + logger.debug(catalogXml);
288 if (sendAfterResponse) { 315 if (sendAfterResponse) {
289 // 默认按照收到200回复后发送下一条, 如果超时收不到回复,就以30毫秒的间隔直接发送。 316 // 默认按照收到200回复后发送下一条, 如果超时收不到回复,就以30毫秒的间隔直接发送。
290 dynamicTask.startDelay(timeoutTaskKey, ()->{ 317 dynamicTask.startDelay(timeoutTaskKey, ()->{
@@ -336,17 +363,22 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -336,17 +363,22 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
336 if (parentPlatform == null) { 363 if (parentPlatform == null) {
337 return; 364 return;
338 } 365 }
  366 + String deviceId = device == null ? parentPlatform.getDeviceGBId() : device.getDeviceId();
  367 + String deviceName = device == null ? parentPlatform.getName() : device.getName();
  368 + String manufacturer = device == null ? "WVP-28181-PRO" : device.getManufacturer();
  369 + String model = device == null ? "platform" : device.getModel();
  370 + String firmware = device == null ? gitUtil.getBuildVersion() : device.getFirmware();
339 String characterSet = parentPlatform.getCharacterSet(); 371 String characterSet = parentPlatform.getCharacterSet();
340 StringBuffer deviceInfoXml = new StringBuffer(600); 372 StringBuffer deviceInfoXml = new StringBuffer(600);
341 deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); 373 deviceInfoXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
342 deviceInfoXml.append("<Response>\r\n"); 374 deviceInfoXml.append("<Response>\r\n");
343 deviceInfoXml.append("<CmdType>DeviceInfo</CmdType>\r\n"); 375 deviceInfoXml.append("<CmdType>DeviceInfo</CmdType>\r\n");
344 deviceInfoXml.append("<SN>" +sn + "</SN>\r\n"); 376 deviceInfoXml.append("<SN>" +sn + "</SN>\r\n");
345 - deviceInfoXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n");  
346 - deviceInfoXml.append("<DeviceName>" + device.getName() + "</DeviceName>\r\n");  
347 - deviceInfoXml.append("<Manufacturer>" + device.getManufacturer() + "</Manufacturer>\r\n");  
348 - deviceInfoXml.append("<Model>" + device.getModel() + "</Model>\r\n");  
349 - deviceInfoXml.append("<Firmware>" + device.getFirmware() + "</Firmware>\r\n"); 377 + deviceInfoXml.append("<DeviceID>" + deviceId + "</DeviceID>\r\n");
  378 + deviceInfoXml.append("<DeviceName>" + deviceName + "</DeviceName>\r\n");
  379 + deviceInfoXml.append("<Manufacturer>" + manufacturer + "</Manufacturer>\r\n");
  380 + deviceInfoXml.append("<Model>" + model + "</Model>\r\n");
  381 + deviceInfoXml.append("<Firmware>" + firmware + "</Firmware>\r\n");
350 deviceInfoXml.append("<Result>OK</Result>\r\n"); 382 deviceInfoXml.append("<Result>OK</Result>\r\n");
351 deviceInfoXml.append("</Response>\r\n"); 383 deviceInfoXml.append("</Response>\r\n");
352 384
@@ -423,7 +455,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -423,7 +455,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
423 if (parentPlatform == null) { 455 if (parentPlatform == null) {
424 return; 456 return;
425 } 457 }
426 - logger.info("[发送报警通知] {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(), 458 + logger.info("[发送报警通知]平台: {}/{}->{},{}: {}", parentPlatform.getServerGBId(), deviceAlarm.getChannelId(),
427 deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSON.toJSONString(deviceAlarm)); 459 deviceAlarm.getLongitude(), deviceAlarm.getLatitude(), JSON.toJSONString(deviceAlarm));
428 String characterSet = parentPlatform.getCharacterSet(); 460 String characterSet = parentPlatform.getCharacterSet();
429 StringBuffer deviceStatusXml = new StringBuffer(600); 461 StringBuffer deviceStatusXml = new StringBuffer(600);
@@ -434,7 +466,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -434,7 +466,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
434 .append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n") 466 .append("<DeviceID>" + deviceAlarm.getChannelId() + "</DeviceID>\r\n")
435 .append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n") 467 .append("<AlarmPriority>" + deviceAlarm.getAlarmPriority() + "</AlarmPriority>\r\n")
436 .append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n") 468 .append("<AlarmMethod>" + deviceAlarm.getAlarmMethod() + "</AlarmMethod>\r\n")
437 - .append("<AlarmTime>" + deviceAlarm.getAlarmTime() + "</AlarmTime>\r\n") 469 + .append("<AlarmTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(deviceAlarm.getAlarmTime()) + "</AlarmTime>\r\n")
438 .append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n") 470 .append("<AlarmDescription>" + deviceAlarm.getAlarmDescription() + "</AlarmDescription>\r\n")
439 .append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n") 471 .append("<Longitude>" + deviceAlarm.getLongitude() + "</Longitude>\r\n")
440 .append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n") 472 .append("<Latitude>" + deviceAlarm.getLatitude() + "</Latitude>\r\n")
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
@@ -45,7 +45,7 @@ public abstract class SIPRequestProcessorParent { @@ -45,7 +45,7 @@ public abstract class SIPRequestProcessorParent {
45 try { 45 try {
46 return SipFactory.getInstance().createHeaderFactory(); 46 return SipFactory.getInstance().createHeaderFactory();
47 } catch (PeerUnavailableException e) { 47 } catch (PeerUnavailableException e) {
48 - e.printStackTrace(); 48 + logger.error("未处理的异常 ", e);
49 } 49 }
50 return null; 50 return null;
51 } 51 }
@@ -54,7 +54,7 @@ public abstract class SIPRequestProcessorParent { @@ -54,7 +54,7 @@ public abstract class SIPRequestProcessorParent {
54 try { 54 try {
55 return SipFactory.getInstance().createMessageFactory(); 55 return SipFactory.getInstance().createMessageFactory();
56 } catch (PeerUnavailableException e) { 56 } catch (PeerUnavailableException e) {
57 - e.printStackTrace(); 57 + logger.error("未处理的异常 ", e);
58 } 58 }
59 return null; 59 return null;
60 } 60 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.conf.UserSetting; @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.conf.UserSetting;
8 import com.genersoft.iot.vmp.gb28181.bean.*; 8 import com.genersoft.iot.vmp.gb28181.bean.*;
9 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 9 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
10 import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; 10 import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
  11 +import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
11 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 12 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
12 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; 13 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
13 import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; 14 import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
@@ -457,12 +458,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -457,12 +458,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
457 if (!userSetting.getPushStreamAfterAck()) { 458 if (!userSetting.getPushStreamAfterAck()) {
458 playService.startPushStream(sendRtpItem, sipResponse, platform, request.getCallIdHeader()); 459 playService.startPushStream(sendRtpItem, sipResponse, platform, request.getCallIdHeader());
459 } 460 }
460 - } catch (SipException e) {  
461 - e.printStackTrace();  
462 - } catch (InvalidArgumentException e) {  
463 - e.printStackTrace();  
464 - } catch (ParseException e) {  
465 - e.printStackTrace(); 461 + } catch (SipException | InvalidArgumentException | ParseException e) {
  462 + logger.error("[命令发送失败] 国标级联 回复SdpAck", e);
466 } 463 }
467 }; 464 };
468 SipSubscribe.Event errorEvent = ((event) -> { 465 SipSubscribe.Event errorEvent = ((event) -> {
@@ -471,7 +468,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -471,7 +468,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
471 Response response = getMessageFactory().createResponse(event.statusCode, evt.getRequest()); 468 Response response = getMessageFactory().createResponse(event.statusCode, evt.getRequest());
472 sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); 469 sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
473 } catch (ParseException | SipException e) { 470 } catch (ParseException | SipException e) {
474 - e.printStackTrace(); 471 + logger.error("未处理的异常 ", e);
475 } 472 }
476 }); 473 });
477 sendRtpItem.setApp("rtp"); 474 sendRtpItem.setApp("rtp");
@@ -543,6 +540,15 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -543,6 +540,15 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
543 } 540 }
544 } 541 }
545 } else if (gbStream != null) { 542 } else if (gbStream != null) {
  543 + if(ssrc.equals(ssrcDefault))
  544 + {
  545 + SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
  546 + if(ssrcConfig != null)
  547 + {
  548 + ssrc = ssrcConfig.getPlaySsrc();
  549 + ssrcConfig.releaseSsrc(ssrc);
  550 + }
  551 + }
546 if("push".equals(gbStream.getStreamType())) { 552 if("push".equals(gbStream.getStreamType())) {
547 if (streamPushItem != null && streamPushItem.isPushIng()) { 553 if (streamPushItem != null && streamPushItem.isPushIng()) {
548 // 推流状态 554 // 推流状态
@@ -572,7 +578,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -572,7 +578,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
572 } catch (SdpParseException e) { 578 } catch (SdpParseException e) {
573 logger.error("sdp解析错误", e); 579 logger.error("sdp解析错误", e);
574 } catch (SdpException e) { 580 } catch (SdpException e) {
575 - e.printStackTrace(); 581 + logger.error("未处理的异常 ", e);
576 } 582 }
577 } 583 }
578 584
@@ -727,11 +733,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -727,11 +733,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
727 mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream()); 733 mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
728 responseAck(request, Response.REQUEST_TIMEOUT); // 超时 734 responseAck(request, Response.REQUEST_TIMEOUT); // 超时
729 } catch (SipException e) { 735 } catch (SipException e) {
730 - e.printStackTrace(); 736 + logger.error("未处理的异常 ", e);
731 } catch (InvalidArgumentException e) { 737 } catch (InvalidArgumentException e) {
732 - e.printStackTrace(); 738 + logger.error("未处理的异常 ", e);
733 } catch (ParseException e) { 739 } catch (ParseException e) {
734 - e.printStackTrace(); 740 + logger.error("未处理的异常 ", e);
735 } 741 }
736 }, userSetting.getPlatformPlayTimeout()); 742 }, userSetting.getPlatformPlayTimeout());
737 // 添加监听 743 // 添加监听
@@ -750,11 +756,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -750,11 +756,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
750 try { 756 try {
751 responseAck(request, Response.BUSY_HERE); 757 responseAck(request, Response.BUSY_HERE);
752 } catch (SipException e) { 758 } catch (SipException e) {
753 - e.printStackTrace(); 759 + logger.error("未处理的异常 ", e);
754 } catch (InvalidArgumentException e) { 760 } catch (InvalidArgumentException e) {
755 - e.printStackTrace(); 761 + logger.error("未处理的异常 ", e);
756 } catch (ParseException e) { 762 } catch (ParseException e) {
757 - e.printStackTrace(); 763 + logger.error("未处理的异常 ", e);
758 } 764 }
759 return; 765 return;
760 } 766 }
@@ -812,11 +818,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -812,11 +818,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
812 try { 818 try {
813 responseAck(request, Response.BUSY_HERE); 819 responseAck(request, Response.BUSY_HERE);
814 } catch (SipException e) { 820 } catch (SipException e) {
815 - e.printStackTrace(); 821 + logger.error("未处理的异常 ", e);
816 } catch (InvalidArgumentException e) { 822 } catch (InvalidArgumentException e) {
817 - e.printStackTrace(); 823 + logger.error("未处理的异常 ", e);
818 } catch (ParseException e) { 824 } catch (ParseException e) {
819 - e.printStackTrace(); 825 + logger.error("未处理的异常 ", e);
820 } 826 }
821 return; 827 return;
822 } 828 }
@@ -869,7 +875,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -869,7 +875,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
869 content.append("s=Play\r\n"); 875 content.append("s=Play\r\n");
870 content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); 876 content.append("c=IN IP4 " + mediaServerItem.getSdpIp() + "\r\n");
871 content.append("t=0 0\r\n"); 877 content.append("t=0 0\r\n");
872 - content.append("m=video " + sendRtpItem.getLocalPort() + " RTP/AVP 96\r\n"); 878 + // 非严格模式端口不统一, 增加兼容性,修改为一个不为0的端口
  879 + int localPort = sendRtpItem.getLocalPort();
  880 + if(localPort == 0)
  881 + {
  882 + localPort = new Random().nextInt(65535) + 1;
  883 + }
  884 + content.append("m=video " + localPort + " RTP/AVP 96\r\n");
873 content.append("a=sendonly\r\n"); 885 content.append("a=sendonly\r\n");
874 content.append("a=rtpmap:96 PS/90000\r\n"); 886 content.append("a=rtpmap:96 PS/90000\r\n");
875 if (sendRtpItem.isTcp()) { 887 if (sendRtpItem.isTcp()) {
@@ -890,11 +902,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -890,11 +902,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
890 } 902 }
891 return sipResponse; 903 return sipResponse;
892 } catch (SipException e) { 904 } catch (SipException e) {
893 - e.printStackTrace(); 905 + logger.error("未处理的异常 ", e);
894 } catch (InvalidArgumentException e) { 906 } catch (InvalidArgumentException e) {
895 - e.printStackTrace(); 907 + logger.error("未处理的异常 ", e);
896 } catch (ParseException e) { 908 } catch (ParseException e) {
897 - e.printStackTrace(); 909 + logger.error("未处理的异常 ", e);
898 } 910 }
899 return null; 911 return null;
900 } 912 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
@@ -93,7 +93,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -93,7 +93,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
93 try { 93 try {
94 responseAck((SIPRequest) evt.getRequest(), Response.OK, null, null); 94 responseAck((SIPRequest) evt.getRequest(), Response.OK, null, null);
95 }catch (SipException | InvalidArgumentException | ParseException e) { 95 }catch (SipException | InvalidArgumentException | ParseException e) {
96 - e.printStackTrace(); 96 + logger.error("未处理的异常 ", e);
97 } 97 }
98 boolean runed = !taskQueue.isEmpty(); 98 boolean runed = !taskQueue.isEmpty();
99 taskQueue.offer(new HandlerCatchData(evt, null, null)); 99 taskQueue.offer(new HandlerCatchData(evt, null, null));
@@ -229,7 +229,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -229,7 +229,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
229 jsonObject.put("speed", mobilePosition.getSpeed()); 229 jsonObject.put("speed", mobilePosition.getSpeed());
230 redisCatchStorage.sendMobilePositionMsg(jsonObject); 230 redisCatchStorage.sendMobilePositionMsg(jsonObject);
231 } catch (DocumentException e) { 231 } catch (DocumentException e) {
232 - e.printStackTrace(); 232 + logger.error("未处理的异常 ", e);
233 } 233 }
234 } 234 }
235 235
@@ -339,7 +339,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -339,7 +339,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
339 publisher.deviceAlarmEventPublish(deviceAlarm); 339 publisher.deviceAlarmEventPublish(deviceAlarm);
340 } 340 }
341 } catch (DocumentException e) { 341 } catch (DocumentException e) {
342 - e.printStackTrace(); 342 + logger.error("未处理的异常 ", e);
343 } 343 }
344 } 344 }
345 345
@@ -397,12 +397,20 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -397,12 +397,20 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
397 case CatalogEvent.OFF : 397 case CatalogEvent.OFF :
398 // 离线 398 // 离线
399 logger.info("[收到通道离线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); 399 logger.info("[收到通道离线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
400 - storager.deviceChannelOffline(deviceId, channel.getChannelId()); 400 + if (userSetting.getRefuseChannelStatusChannelFormNotify()) {
  401 + storager.deviceChannelOffline(deviceId, channel.getChannelId());
  402 + }else {
  403 + logger.info("[收到通道离线通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  404 + }
401 break; 405 break;
402 case CatalogEvent.VLOST: 406 case CatalogEvent.VLOST:
403 // 视频丢失 407 // 视频丢失
404 logger.info("[收到通道视频丢失通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); 408 logger.info("[收到通道视频丢失通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
405 - storager.deviceChannelOffline(deviceId, channel.getChannelId()); 409 + if (userSetting.getRefuseChannelStatusChannelFormNotify()) {
  410 + storager.deviceChannelOffline(deviceId, channel.getChannelId());
  411 + }else {
  412 + logger.info("[收到通道视频丢失通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  413 + }
406 break; 414 break;
407 case CatalogEvent.DEFECT: 415 case CatalogEvent.DEFECT:
408 // 故障 416 // 故障
@@ -432,7 +440,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -432,7 +440,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
432 } 440 }
433 } 441 }
434 } catch (DocumentException e) { 442 } catch (DocumentException e) {
435 - e.printStackTrace(); 443 + logger.error("未处理的异常 ", e);
436 } 444 }
437 } 445 }
438 446
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.UserSetting; @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.UserSetting;
5 import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper; 5 import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper;
6 import com.genersoft.iot.vmp.gb28181.bean.Device; 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
7 import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo; 7 import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
  8 +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
8 import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate; 9 import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate;
9 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; 10 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
10 import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; 11 import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
@@ -18,6 +19,7 @@ import gov.nist.javax.sip.address.AddressImpl; @@ -18,6 +19,7 @@ import gov.nist.javax.sip.address.AddressImpl;
18 import gov.nist.javax.sip.address.SipUri; 19 import gov.nist.javax.sip.address.SipUri;
19 import gov.nist.javax.sip.header.SIPDateHeader; 20 import gov.nist.javax.sip.header.SIPDateHeader;
20 import gov.nist.javax.sip.message.SIPRequest; 21 import gov.nist.javax.sip.message.SIPRequest;
  22 +import gov.nist.javax.sip.message.SIPResponse;
21 import org.slf4j.Logger; 23 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory; 24 import org.slf4j.LoggerFactory;
23 import org.springframework.beans.factory.InitializingBean; 25 import org.springframework.beans.factory.InitializingBean;
@@ -34,6 +36,7 @@ import javax.sip.header.AuthorizationHeader; @@ -34,6 +36,7 @@ import javax.sip.header.AuthorizationHeader;
34 import javax.sip.header.ContactHeader; 36 import javax.sip.header.ContactHeader;
35 import javax.sip.header.FromHeader; 37 import javax.sip.header.FromHeader;
36 import javax.sip.header.ViaHeader; 38 import javax.sip.header.ViaHeader;
  39 +import javax.sip.message.Request;
37 import javax.sip.message.Response; 40 import javax.sip.message.Response;
38 import java.security.NoSuchAlgorithmException; 41 import java.security.NoSuchAlgorithmException;
39 import java.text.ParseException; 42 import java.text.ParseException;
@@ -105,6 +108,30 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -105,6 +108,30 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
105 SipUri uri = (SipUri) address.getURI(); 108 SipUri uri = (SipUri) address.getURI();
106 String deviceId = uri.getUser(); 109 String deviceId = uri.getUser();
107 Device device = deviceService.getDevice(deviceId); 110 Device device = deviceService.getDevice(deviceId);
  111 +
  112 + RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request,
  113 + userSetting.getSipUseSourceIpAsRemoteAddress());
  114 +
  115 + if (device != null &&
  116 + device.getSipTransactionInfo() != null &&
  117 + request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) {
  118 + logger.info("[注册请求] 注册续订: {}", device.getDeviceId());
  119 + device.setExpires(request.getExpires().getExpires());
  120 + device.setIp(remoteAddressInfo.getIp());
  121 + device.setPort(remoteAddressInfo.getPort());
  122 + device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));
  123 + device.setLocalIp(request.getLocalAddress().getHostAddress());
  124 + Response registerOkResponse = getRegisterOkResponse(request);
  125 + // 判断TCP还是UDP
  126 + ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
  127 + String transport = reqViaHeader.getTransport();
  128 + device.setTransport("TCP".equalsIgnoreCase(transport) ? "TCP" : "UDP");
  129 + sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), registerOkResponse);
  130 + device.setRegisterTime(DateUtil.getNow());
  131 + SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)registerOkResponse);
  132 + deviceService.online(device, sipTransactionInfo);
  133 + return;
  134 + }
108 String password = (device != null && !ObjectUtils.isEmpty(device.getPassword()))? device.getPassword() : sipConfig.getPassword(); 135 String password = (device != null && !ObjectUtils.isEmpty(device.getPassword()))? device.getPassword() : sipConfig.getPassword();
109 AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); 136 AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME);
110 if (authHead == null && !ObjectUtils.isEmpty(password)) { 137 if (authHead == null && !ObjectUtils.isEmpty(password)) {
@@ -147,9 +174,6 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -147,9 +174,6 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
147 // 添加Expires头 174 // 添加Expires头
148 response.addHeader(request.getExpires()); 175 response.addHeader(request.getExpires());
149 176
150 - RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request,  
151 - userSetting.getSipUseSourceIpAsRemoteAddress());  
152 -  
153 if (device == null) { 177 if (device == null) {
154 device = new Device(); 178 device = new Device();
155 device.setStreamMode("UDP"); 179 device.setStreamMode("UDP");
@@ -182,13 +206,33 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -182,13 +206,33 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
182 if (registerFlag) { 206 if (registerFlag) {
183 logger.info("[注册成功] deviceId: {}->{}", deviceId, requestAddress); 207 logger.info("[注册成功] deviceId: {}->{}", deviceId, requestAddress);
184 device.setRegisterTime(DateUtil.getNow()); 208 device.setRegisterTime(DateUtil.getNow());
185 - deviceService.online(device); 209 + SipTransactionInfo sipTransactionInfo = new SipTransactionInfo((SIPResponse)response);
  210 + deviceService.online(device, sipTransactionInfo);
186 } else { 211 } else {
187 logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress); 212 logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress);
188 - deviceService.offline(deviceId); 213 + deviceService.offline(deviceId, "主动注销");
189 } 214 }
190 } catch (SipException | NoSuchAlgorithmException | ParseException e) { 215 } catch (SipException | NoSuchAlgorithmException | ParseException e) {
191 - e.printStackTrace(); 216 + logger.error("未处理的异常 ", e);
192 } 217 }
193 } 218 }
  219 +
  220 + private Response getRegisterOkResponse(Request request) throws ParseException {
  221 + // 携带授权头并且密码正确
  222 + Response response = getMessageFactory().createResponse(Response.OK, request);
  223 + // 添加date头
  224 + SIPDateHeader dateHeader = new SIPDateHeader();
  225 + // 使用自己修改的
  226 + WvpSipDate wvpSipDate = new WvpSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis());
  227 + dateHeader.setDate(wvpSipDate);
  228 + response.addHeader(dateHeader);
  229 +
  230 + // 添加Contact头
  231 + response.addHeader(request.getHeader(ContactHeader.NAME));
  232 + // 添加Expires头
  233 + response.addHeader(request.getExpires());
  234 +
  235 + return response;
  236 +
  237 + }
194 } 238 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
2 2
  3 +import com.genersoft.iot.vmp.common.VideoManagerConstants;
3 import com.genersoft.iot.vmp.conf.DynamicTask; 4 import com.genersoft.iot.vmp.conf.DynamicTask;
4 import com.genersoft.iot.vmp.conf.UserSetting; 5 import com.genersoft.iot.vmp.conf.UserSetting;
5 import com.genersoft.iot.vmp.gb28181.bean.CmdType; 6 import com.genersoft.iot.vmp.gb28181.bean.CmdType;
@@ -8,14 +9,11 @@ import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; @@ -8,14 +9,11 @@ import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
8 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; 9 import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo;
9 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; 10 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
10 import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; 11 import com.genersoft.iot.vmp.gb28181.transmit.SIPSender;
11 -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;  
12 -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;  
13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; 12 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
14 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 13 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
15 import com.genersoft.iot.vmp.gb28181.utils.SipUtils; 14 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
16 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; 15 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
17 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 16 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
18 -import gov.nist.javax.sip.SipProviderImpl;  
19 import gov.nist.javax.sip.message.SIPRequest; 17 import gov.nist.javax.sip.message.SIPRequest;
20 import gov.nist.javax.sip.message.SIPResponse; 18 import gov.nist.javax.sip.message.SIPResponse;
21 import org.dom4j.DocumentException; 19 import org.dom4j.DocumentException;
@@ -26,7 +24,9 @@ import org.springframework.beans.factory.InitializingBean; @@ -26,7 +24,9 @@ import org.springframework.beans.factory.InitializingBean;
26 import org.springframework.beans.factory.annotation.Autowired; 24 import org.springframework.beans.factory.annotation.Autowired;
27 import org.springframework.stereotype.Component; 25 import org.springframework.stereotype.Component;
28 26
29 -import javax.sip.*; 27 +import javax.sip.InvalidArgumentException;
  28 +import javax.sip.RequestEvent;
  29 +import javax.sip.SipException;
30 import javax.sip.header.ExpiresHeader; 30 import javax.sip.header.ExpiresHeader;
31 import javax.sip.message.Response; 31 import javax.sip.message.Response;
32 import java.text.ParseException; 32 import java.text.ParseException;
@@ -93,7 +93,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -93,7 +93,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
93 sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); 93 sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response);
94 } 94 }
95 } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { 95 } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
96 - e.printStackTrace(); 96 + logger.error("未处理的异常 ", e);
97 } 97 }
98 98
99 } 99 }
@@ -146,7 +146,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -146,7 +146,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
146 } 146 }
147 147
148 } catch (SipException | InvalidArgumentException | ParseException e) { 148 } catch (SipException | InvalidArgumentException | ParseException e) {
149 - e.printStackTrace(); 149 + logger.error("未处理的异常 ", e);
150 } 150 }
151 } 151 }
152 152
@@ -192,7 +192,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme @@ -192,7 +192,7 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme
192 subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo); 192 subscribeHolder.putCatalogSubscribe(platformId, subscribeInfo);
193 } 193 }
194 } catch (SipException | InvalidArgumentException | ParseException e) { 194 } catch (SipException | InvalidArgumentException | ParseException e) {
195 - e.printStackTrace(); 195 + logger.error("未处理的异常 ", e);
196 } 196 }
197 } 197 }
198 } 198 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java
@@ -73,35 +73,38 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent @@ -73,35 +73,38 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
73 String channelId = getText(rootElement, "DeviceID"); 73 String channelId = getText(rootElement, "DeviceID");
74 // 远程启动功能 74 // 远程启动功能
75 if (!ObjectUtils.isEmpty(getText(rootElement, "TeleBoot"))) { 75 if (!ObjectUtils.isEmpty(getText(rootElement, "TeleBoot"))) {
76 - if (parentPlatform.getServerGBId().equals(targetGBId)) {  
77 - // 远程启动本平台:需要在重新启动程序后先对SipStack解绑  
78 - logger.info("执行远程启动本平台命令");  
79 - try {  
80 - cmderFroPlatform.unregister(parentPlatform, null, null);  
81 - } catch (InvalidArgumentException | ParseException | SipException e) {  
82 - logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());  
83 - }  
84 - taskExecutor.execute(() -> {  
85 - // 远程启动  
86 -// try {  
87 -// Thread.sleep(3000);  
88 -// SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider");  
89 -// SipStackImpl stack = (SipStackImpl)up.getSipStack();  
90 -// stack.stop();  
91 -// Iterator listener = stack.getListeningPoints();  
92 -// while (listener.hasNext()) {  
93 -// stack.deleteListeningPoint((ListeningPoint) listener.next());  
94 -// }  
95 -// Iterator providers = stack.getSipProviders();  
96 -// while (providers.hasNext()) {  
97 -// stack.deleteSipProvider((SipProvider) providers.next());  
98 -// }  
99 -// VManageBootstrap.restart();  
100 -// } catch (InterruptedException | ObjectInUseException e) {  
101 -// logger.error("[任务执行失败] 服务重启: {}", e.getMessage());  
102 -// }  
103 - });  
104 - } 76 + // TODO 拒绝远程启动命令
  77 + logger.warn("[国标级联]收到平台的远程启动命令, 不处理");
  78 +
  79 +// if (parentPlatform.getServerGBId().equals(targetGBId)) {
  80 +// // 远程启动本平台:需要在重新启动程序后先对SipStack解绑
  81 +// logger.info("执行远程启动本平台命令");
  82 +// try {
  83 +// cmderFroPlatform.unregister(parentPlatform, null, null);
  84 +// } catch (InvalidArgumentException | ParseException | SipException e) {
  85 +// logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
  86 +// }
  87 +// taskExecutor.execute(() -> {
  88 +// // 远程启动
  89 +//// try {
  90 +//// Thread.sleep(3000);
  91 +//// SipProvider up = (SipProvider) SpringBeanFactory.getBean("udpSipProvider");
  92 +//// SipStackImpl stack = (SipStackImpl)up.getSipStack();
  93 +//// stack.stop();
  94 +//// Iterator listener = stack.getListeningPoints();
  95 +//// while (listener.hasNext()) {
  96 +//// stack.deleteListeningPoint((ListeningPoint) listener.next());
  97 +//// }
  98 +//// Iterator providers = stack.getSipProviders();
  99 +//// while (providers.hasNext()) {
  100 +//// stack.deleteSipProvider((SipProvider) providers.next());
  101 +//// }
  102 +//// VManageBootstrap.restart();
  103 +//// } catch (InterruptedException | ObjectInUseException e) {
  104 +//// logger.error("[任务执行失败] 服务重启: {}", e.getMessage());
  105 +//// }
  106 +// });
  107 +// }
105 } 108 }
106 DeviceControlType deviceControlType = DeviceControlType.typeOf(rootElement); 109 DeviceControlType deviceControlType = DeviceControlType.typeOf(rootElement);
107 logger.info("[接受deviceControl命令] 命令: {}", deviceControlType); 110 logger.info("[接受deviceControl命令] 命令: {}", deviceControlType);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
@@ -186,9 +186,13 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @@ -186,9 +186,13 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
186 // 发送给平台的报警信息。 发送redis通知 186 // 发送给平台的报警信息。 发送redis通知
187 logger.info("[发送给平台的报警信息]内容:{}", JSONObject.toJSONString(deviceAlarm)); 187 logger.info("[发送给平台的报警信息]内容:{}", JSONObject.toJSONString(deviceAlarm));
188 AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); 188 AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage();
189 - alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); 189 + if (deviceAlarm.getAlarmMethod() != null) {
  190 + alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod()));
  191 + }
190 alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); 192 alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription());
191 - alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType())); 193 + if (deviceAlarm.getAlarmType() != null) {
  194 + alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType()));
  195 + }
192 alarmChannelMessage.setGbId(channelId); 196 alarmChannelMessage.setGbId(channelId);
193 redisCatchStorage.sendAlarmMsg(alarmChannelMessage); 197 redisCatchStorage.sendAlarmMsg(alarmChannelMessage);
194 continue; 198 continue;
@@ -204,6 +208,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @@ -204,6 +208,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
204 publisher.deviceAlarmEventPublish(deviceAlarm); 208 publisher.deviceAlarmEventPublish(deviceAlarm);
205 } 209 }
206 }catch (Exception e) { 210 }catch (Exception e) {
  211 + logger.error("未处理的异常 ", e);
207 logger.warn("[收到报警通知] 发现未处理的异常, {}\r\n{}",e.getMessage(), evt.getRequest()); 212 logger.warn("[收到报警通知] 发现未处理的异常, {}\r\n{}",e.getMessage(), evt.getRequest());
208 } 213 }
209 } 214 }
@@ -264,12 +269,15 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @@ -264,12 +269,15 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
264 if (channelId.equals(parentPlatform.getDeviceGBId())) { 269 if (channelId.equals(parentPlatform.getDeviceGBId())) {
265 // 发送给平台的报警信息。 发送redis通知 270 // 发送给平台的报警信息。 发送redis通知
266 AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); 271 AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage();
267 - alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); 272 + if (deviceAlarm.getAlarmMethod() != null) {
  273 + alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod()));
  274 + }
268 alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); 275 alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription());
269 alarmChannelMessage.setGbId(channelId); 276 alarmChannelMessage.setGbId(channelId);
270 - alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType())); 277 + if (deviceAlarm.getAlarmType() != null) {
  278 + alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType()));
  279 + }
271 redisCatchStorage.sendAlarmMsg(alarmChannelMessage); 280 redisCatchStorage.sendAlarmMsg(alarmChannelMessage);
272 - return;  
273 } 281 }
274 } 282 }
275 } 283 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -88,13 +88,13 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp @@ -88,13 +88,13 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
88 // 对于已经离线的设备判断他的注册是否已经过期 88 // 对于已经离线的设备判断他的注册是否已经过期
89 if (!deviceService.expire(device)){ 89 if (!deviceService.expire(device)){
90 device.setOnline(0); 90 device.setOnline(0);
91 - deviceService.online(device); 91 + deviceService.online(device, null);
92 } 92 }
93 } 93 }
94 // 刷新过期任务 94 // 刷新过期任务
95 String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); 95 String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId();
96 // 如果三次心跳失败,则设置设备离线 96 // 如果三次心跳失败,则设置设备离线
97 - dynamicTask.startDelay(registerExpireTaskKey, ()-> deviceService.offline(device.getDeviceId()), device.getKeepaliveIntervalTime()*1000*3); 97 + dynamicTask.startDelay(registerExpireTaskKey, ()-> deviceService.offline(device.getDeviceId(), "三次心跳失败"), device.getKeepaliveIntervalTime()*1000*3);
98 98
99 } 99 }
100 100
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java
@@ -149,9 +149,10 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen @@ -149,9 +149,10 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
149 redisCatchStorage.sendMobilePositionMsg(jsonObject); 149 redisCatchStorage.sendMobilePositionMsg(jsonObject);
150 150
151 } catch (DocumentException e) { 151 } catch (DocumentException e) {
152 - e.printStackTrace(); 152 + logger.error("未处理的异常 ", e);
153 } catch (Exception e) { 153 } catch (Exception e) {
154 - logger.warn("[移动位置通知] 发现未处理的异常, {}\r\n{}",e.getMessage(), evt.getRequest()); 154 + logger.warn("[移动位置通知] 发现未处理的异常, \r\n{}", evt.getRequest());
  155 + logger.error("[移动位置通知] 异常内容: ", e);
155 } 156 }
156 } 157 }
157 }); 158 });
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java
@@ -60,17 +60,24 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp @@ -60,17 +60,24 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp
60 return; 60 return;
61 } 61 }
62 String sn = rootElement.element("SN").getText(); 62 String sn = rootElement.element("SN").getText();
  63 +
63 /*根据WVP原有的数据结构,设备和通道是分开放置,设备信息都是存放在设备表里,通道表里的设备信息不可作为真实信息处理 64 /*根据WVP原有的数据结构,设备和通道是分开放置,设备信息都是存放在设备表里,通道表里的设备信息不可作为真实信息处理
64 大部分NVR/IPC设备对他的通道信息实现都是返回默认的值没有什么参考价值。NVR/IPC通道我们统一使用设备表的设备信息来作为返回。 65 大部分NVR/IPC设备对他的通道信息实现都是返回默认的值没有什么参考价值。NVR/IPC通道我们统一使用设备表的设备信息来作为返回。
65 我们这里使用查询数据库的方式来实现这个设备信息查询的功能,在其他地方对设备信息更新达到正确的目的。*/ 66 我们这里使用查询数据库的方式来实现这个设备信息查询的功能,在其他地方对设备信息更新达到正确的目的。*/
  67 +
66 String channelId = getText(rootElement, "DeviceID"); 68 String channelId = getText(rootElement, "DeviceID");
67 - Device device = storager.queryDeviceInfoByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);  
68 - if (device ==null){  
69 - logger.error("[平台没有该通道的使用权限]:platformId"+parentPlatform.getServerGBId()+" deviceID:"+channelId);  
70 - return; 69 + // 查询这是通道id还是设备id
  70 + Device device = null;
  71 + // 如果id指向平台的国标编号,那么就是查询平台的信息
  72 + if (!parentPlatform.getDeviceGBId().equals(channelId)) {
  73 + device = storager.queryDeviceInfoByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
  74 + if (device ==null){
  75 + logger.error("[平台没有该通道的使用权限]:platformId"+parentPlatform.getServerGBId()+" deviceID:"+channelId);
  76 + return;
  77 + }
71 } 78 }
72 try { 79 try {
73 - cmderFroPlatform.deviceInfoResponse(parentPlatform,device, sn, fromHeader.getTag()); 80 + cmderFroPlatform.deviceInfoResponse(parentPlatform, device, sn, fromHeader.getTag());
74 } catch (SipException | InvalidArgumentException | ParseException e) { 81 } catch (SipException | InvalidArgumentException | ParseException e) {
75 logger.error("[命令发送失败] 国标级联 DeviceInfo查询回复: {}", e.getMessage()); 82 logger.error("[命令发送失败] 国标级联 DeviceInfo查询回复: {}", e.getMessage());
76 } 83 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
@@ -132,7 +132,8 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -132,7 +132,8 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
132 132
133 } 133 }
134 }catch (Exception e) { 134 }catch (Exception e) {
135 - logger.warn("[收到通道] 发现未处理的异常, {}\r\n{}",e.getMessage(), evt.getRequest()); 135 + logger.warn("[收到通道] 发现未处理的异常, \r\n{}", evt.getRequest());
  136 + logger.error("[收到通道] 异常内容: ", e);
136 } 137 }
137 } 138 }
138 }); 139 });
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd;
2 2
3 import com.alibaba.fastjson2.JSONObject; 3 import com.alibaba.fastjson2.JSONObject;
4 -import com.genersoft.iot.vmp.common.VideoManagerConstants;  
5 import com.genersoft.iot.vmp.gb28181.bean.Device; 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 5 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
7 -import com.genersoft.iot.vmp.gb28181.event.EventPublisher;  
8 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 6 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
9 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 7 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
10 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 8 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
@@ -26,7 +24,6 @@ import javax.sip.RequestEvent; @@ -26,7 +24,6 @@ import javax.sip.RequestEvent;
26 import javax.sip.SipException; 24 import javax.sip.SipException;
27 import javax.sip.message.Response; 25 import javax.sip.message.Response;
28 import java.text.ParseException; 26 import java.text.ParseException;
29 -import java.util.Objects;  
30 27
31 @Component 28 @Component
32 public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { 29 public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
@@ -74,9 +71,9 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen @@ -74,9 +71,9 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen
74 } 71 }
75 String text = onlineElement.getText(); 72 String text = onlineElement.getText();
76 if ("ONLINE".equalsIgnoreCase(text.trim())) { 73 if ("ONLINE".equalsIgnoreCase(text.trim())) {
77 - deviceService.online(device); 74 + deviceService.online(device, null);
78 }else { 75 }else {
79 - deviceService.offline(device.getDeviceId()); 76 + deviceService.offline(device.getDeviceId(), "设备状态查询结果:" + text.trim());
80 } 77 }
81 RequestMessage msg = new RequestMessage(); 78 RequestMessage msg = new RequestMessage();
82 msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + device.getDeviceId()); 79 msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + device.getDeviceId());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java
@@ -142,7 +142,7 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar @@ -142,7 +142,7 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
142 } 142 }
143 143
144 } catch (DocumentException e) { 144 } catch (DocumentException e) {
145 - e.printStackTrace(); 145 + logger.error("未处理的异常 ", e);
146 } 146 }
147 } 147 }
148 148
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java
@@ -150,7 +150,8 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -150,7 +150,8 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
150 } 150 }
151 } 151 }
152 } catch (Exception e) { 152 } catch (Exception e) {
153 - logger.error("[国标录像] 发现未处理的异常, "+e.getMessage(), e); 153 + logger.error("[国标录像] 发现未处理的异常, \r\n{}", evt.getRequest());
  154 + logger.error("[国标录像] 异常内容: ", e);
154 } 155 }
155 }); 156 });
156 } 157 }
@@ -163,7 +164,11 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -163,7 +164,11 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
163 public void releaseRequest(String deviceId, String sn,RecordInfo recordInfo){ 164 public void releaseRequest(String deviceId, String sn,RecordInfo recordInfo){
164 String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn; 165 String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn;
165 // 对数据进行排序 166 // 对数据进行排序
166 - Collections.sort(recordInfo.getRecordList()); 167 + if(recordInfo!=null && recordInfo.getRecordList()!=null) {
  168 + Collections.sort(recordInfo.getRecordList());
  169 + }else{
  170 + recordInfo.setRecordList(new ArrayList<>());
  171 + }
167 172
168 RequestMessage msg = new RequestMessage(); 173 RequestMessage msg = new RequestMessage();
169 msg.setKey(key); 174 msg.setKey(key);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl; @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.response.impl;
2 2
3 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 3 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; 4 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
  5 +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
5 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; 6 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
6 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; 7 import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
@@ -10,6 +11,7 @@ import com.genersoft.iot.vmp.service.IPlatformService; @@ -10,6 +11,7 @@ import com.genersoft.iot.vmp.service.IPlatformService;
10 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 11 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
11 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 12 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
12 import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; 13 import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo;
  14 +import gov.nist.javax.sip.message.SIPResponse;
13 import org.slf4j.Logger; 15 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory; 16 import org.slf4j.LoggerFactory;
15 import org.springframework.beans.factory.annotation.Autowired; 17 import org.springframework.beans.factory.annotation.Autowired;
@@ -18,7 +20,6 @@ import org.springframework.stereotype.Component; @@ -18,7 +20,6 @@ import org.springframework.stereotype.Component;
18 import javax.sip.InvalidArgumentException; 20 import javax.sip.InvalidArgumentException;
19 import javax.sip.ResponseEvent; 21 import javax.sip.ResponseEvent;
20 import javax.sip.SipException; 22 import javax.sip.SipException;
21 -import javax.sip.header.CallIdHeader;  
22 import javax.sip.header.WWWAuthenticateHeader; 23 import javax.sip.header.WWWAuthenticateHeader;
23 import javax.sip.message.Response; 24 import javax.sip.message.Response;
24 import java.text.ParseException; 25 import java.text.ParseException;
@@ -65,9 +66,8 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { @@ -65,9 +66,8 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
65 */ 66 */
66 @Override 67 @Override
67 public void process(ResponseEvent evt) { 68 public void process(ResponseEvent evt) {
68 - Response response = evt.getResponse();  
69 - CallIdHeader callIdHeader = (CallIdHeader) response.getHeader(CallIdHeader.NAME);  
70 - String callId = callIdHeader.getCallId(); 69 + SIPResponse response = (SIPResponse)evt.getResponse();
  70 + String callId = response.getCallIdHeader().getCallId();
71 PlatformRegisterInfo platformRegisterInfo = redisCatchStorage.queryPlatformRegisterInfo(callId); 71 PlatformRegisterInfo platformRegisterInfo = redisCatchStorage.queryPlatformRegisterInfo(callId);
72 if (platformRegisterInfo == null) { 72 if (platformRegisterInfo == null) {
73 logger.info(String.format("[国标级联]未找到callId: %s 的注册/注销平台id", callId )); 73 logger.info(String.format("[国标级联]未找到callId: %s 的注册/注销平台id", callId ));
@@ -90,15 +90,17 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { @@ -90,15 +90,17 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
90 90
91 if (response.getStatusCode() == Response.UNAUTHORIZED) { 91 if (response.getStatusCode() == Response.UNAUTHORIZED) {
92 WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME); 92 WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
  93 + SipTransactionInfo sipTransactionInfo = new SipTransactionInfo(response);
93 try { 94 try {
94 - sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true, platformRegisterInfo.isRegister()); 95 + sipCommanderForPlatform.register(parentPlatform, sipTransactionInfo, www, null, null, true, platformRegisterInfo.isRegister());
95 } catch (SipException | InvalidArgumentException | ParseException e) { 96 } catch (SipException | InvalidArgumentException | ParseException e) {
96 logger.error("[命令发送失败] 国标级联 再次注册: {}", e.getMessage()); 97 logger.error("[命令发送失败] 国标级联 再次注册: {}", e.getMessage());
97 } 98 }
98 }else if (response.getStatusCode() == Response.OK){ 99 }else if (response.getStatusCode() == Response.OK){
99 100
100 if (platformRegisterInfo.isRegister()) { 101 if (platformRegisterInfo.isRegister()) {
101 - platformService.online(parentPlatform); 102 + SipTransactionInfo sipTransactionInfo = new SipTransactionInfo(response);
  103 + platformService.online(parentPlatform, sipTransactionInfo);
102 }else { 104 }else {
103 platformService.offline(parentPlatform, false); 105 platformService.offline(parentPlatform, false);
104 } 106 }
src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
@@ -9,17 +9,12 @@ import org.jetbrains.annotations.NotNull; @@ -9,17 +9,12 @@ import org.jetbrains.annotations.NotNull;
9 import org.slf4j.Logger; 9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory; 10 import org.slf4j.LoggerFactory;
11 import org.springframework.stereotype.Component; 11 import org.springframework.stereotype.Component;
12 -import org.springframework.util.ObjectUtils;  
13 -import org.springframework.util.StringUtils;  
14 12
15 -import java.io.File;  
16 -import java.io.FileOutputStream;  
17 import java.io.IOException; 13 import java.io.IOException;
18 import java.net.ConnectException; 14 import java.net.ConnectException;
19 import java.util.HashMap; 15 import java.util.HashMap;
20 import java.util.Map; 16 import java.util.Map;
21 import java.util.Objects; 17 import java.util.Objects;
22 -import java.util.concurrent.TimeUnit;  
23 18
24 @Component 19 @Component
25 public class AssistRESTfulUtils { 20 public class AssistRESTfulUtils {
@@ -137,6 +132,11 @@ public class AssistRESTfulUtils { @@ -137,6 +132,11 @@ public class AssistRESTfulUtils {
137 return sendGet(mediaServerItem, "api/record/file/duration",param, callback); 132 return sendGet(mediaServerItem, "api/record/file/duration",param, callback);
138 } 133 }
139 134
  135 + public JSONObject getInfo(MediaServerItem mediaServerItem, RequestCallback callback){
  136 + Map<String, Object> param = new HashMap<>();
  137 + return sendGet(mediaServerItem, "api/record/info",param, callback);
  138 + }
  139 +
140 public JSONObject addStreamCallInfo(MediaServerItem mediaServerItem, String app, String stream, String callId, RequestCallback callback){ 140 public JSONObject addStreamCallInfo(MediaServerItem mediaServerItem, String app, String stream, String callId, RequestCallback callback){
141 Map<String, Object> param = new HashMap<>(); 141 Map<String, Object> param = new HashMap<>();
142 param.put("app",app); 142 param.put("app",app);
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -119,10 +119,11 @@ public class ZLMHttpHookListener { @@ -119,10 +119,11 @@ public class ZLMHttpHookListener {
119 * 服务器定时上报时间,上报间隔可配置,默认10s上报一次 119 * 服务器定时上报时间,上报间隔可配置,默认10s上报一次
120 */ 120 */
121 @ResponseBody 121 @ResponseBody
  122 +
122 @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8") 123 @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8")
123 public HookResult onServerKeepalive(@RequestBody OnServerKeepaliveHookParam param) { 124 public HookResult onServerKeepalive(@RequestBody OnServerKeepaliveHookParam param) {
124 125
125 - logger.info("[ZLM HOOK] 收到zlm心跳:" + param.getMediaServerId()); 126 +// logger.info("[ZLM HOOK] 收到zlm心跳:" + param.getMediaServerId());
126 127
127 taskExecutor.execute(() -> { 128 taskExecutor.execute(() -> {
128 List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive); 129 List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive);
@@ -142,6 +143,7 @@ public class ZLMHttpHookListener { @@ -142,6 +143,7 @@ public class ZLMHttpHookListener {
142 * 播放器鉴权事件,rtsp/rtmp/http-flv/ws-flv/hls的播放都将触发此鉴权事件。 143 * 播放器鉴权事件,rtsp/rtmp/http-flv/ws-flv/hls的播放都将触发此鉴权事件。
143 */ 144 */
144 @ResponseBody 145 @ResponseBody
  146 +
145 @PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8") 147 @PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8")
146 public HookResult onPlay(@RequestBody OnPlayHookParam param) { 148 public HookResult onPlay(@RequestBody OnPlayHookParam param) {
147 if (logger.isDebugEnabled()) { 149 if (logger.isDebugEnabled()) {
@@ -264,9 +266,28 @@ public class ZLMHttpHookListener { @@ -264,9 +266,28 @@ public class ZLMHttpHookListener {
264 } 266 }
265 267
266 } 268 }
  269 + if (mediaInfo.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) {
  270 + logger.info("推流时发现尚未设置录像路径,从assist服务中读取");
  271 + JSONObject info = assistRESTfulUtils.getInfo(mediaInfo, null);
  272 + if (info != null && info.getInteger("code") != null && info.getInteger("code") == 0 ) {
  273 + JSONObject dataJson = info.getJSONObject("data");
  274 + if (dataJson != null) {
  275 + String recordPath = dataJson.getString("record");
  276 + userSetting.setRecordPath(recordPath);
  277 + result.setMp4_save_path(recordPath);
  278 + // 修改zlm中的录像路径
  279 + if (mediaInfo.isAutoConfig()) {
  280 + taskExecutor.execute(() -> {
  281 + mediaServerService.setZLMConfig(mediaInfo, false);
  282 + });
  283 + }
  284 + }
  285 + }
  286 + }
267 return result; 287 return result;
268 } 288 }
269 289
  290 +
270 /** 291 /**
271 * rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。 292 * rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。
272 */ 293 */
@@ -293,8 +314,12 @@ public class ZLMHttpHookListener { @@ -293,8 +314,12 @@ public class ZLMHttpHookListener {
293 subscribe.response(mediaInfo, json); 314 subscribe.response(mediaInfo, json);
294 } 315 }
295 } 316 }
296 - // 流消失移除redis play 317 +
  318 + List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks();
  319 + // TODO 重构此处逻辑
  320 +
297 if (param.isRegist()) { 321 if (param.isRegist()) {
  322 + // 处理流注册的鉴权信息
298 if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal() 323 if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal()
299 || param.getOriginType() == OriginType.RTSP_PUSH.ordinal() 324 || param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
300 || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) { 325 || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
@@ -334,9 +334,9 @@ public class ZLMRESTfulUtils { @@ -334,9 +334,9 @@ public class ZLMRESTfulUtils {
334 sendPost(mediaServerItem, "kick_sessions",param, null); 334 sendPost(mediaServerItem, "kick_sessions",param, null);
335 } 335 }
336 336
337 - public void getSnap(MediaServerItem mediaServerItem, String flvUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) { 337 + public void getSnap(MediaServerItem mediaServerItem, String streamUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) {
338 Map<String, Object> param = new HashMap<>(3); 338 Map<String, Object> param = new HashMap<>(3);
339 - param.put("url", flvUrl); 339 + param.put("url", streamUrl);
340 param.put("timeout_sec", timeout_sec); 340 param.put("timeout_sec", timeout_sec);
341 param.put("expire_sec", expire_sec); 341 param.put("expire_sec", expire_sec);
342 sendGetForImg(mediaServerItem, "getSnap", param, targetPath, fileName); 342 sendGetForImg(mediaServerItem, "getSnap", param, targetPath, fileName);
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
@@ -262,8 +262,11 @@ public class ZLMRTPServerFactory { @@ -262,8 +262,11 @@ public class ZLMRTPServerFactory {
262 logger.info("[保持端口] {}->监听端口到期继续保持监听", ssrc); 262 logger.info("[保持端口] {}->监听端口到期继续保持监听", ssrc);
263 keepPort(serverItem, ssrc); 263 keepPort(serverItem, ssrc);
264 }); 264 });
265 - }  
266 logger.info("[保持端口] {}->监听端口: {}", ssrc, localPort); 265 logger.info("[保持端口] {}->监听端口: {}", ssrc, localPort);
  266 + logger.info("[保持端口] {}->监听端口: {}", ssrc, localPort);
  267 + }else {
  268 + logger.info("[保持端口] 监听端口失败: {}", ssrc);
  269 + }
267 return localPort; 270 return localPort;
268 } 271 }
269 272
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java
@@ -10,21 +10,87 @@ public class ZLMServerConfig { @@ -10,21 +10,87 @@ public class ZLMServerConfig {
10 @JSONField(name = "api.secret") 10 @JSONField(name = "api.secret")
11 private String apiSecret; 11 private String apiSecret;
12 12
  13 + @JSONField(name = "api.snapRoot")
  14 + private String apiSnapRoot;
  15 +
  16 + @JSONField(name = "api.defaultSnap")
  17 + private String apiDefaultSnap;
  18 +
13 @JSONField(name = "ffmpeg.bin") 19 @JSONField(name = "ffmpeg.bin")
14 private String ffmpegBin; 20 private String ffmpegBin;
15 21
16 @JSONField(name = "ffmpeg.cmd") 22 @JSONField(name = "ffmpeg.cmd")
17 private String ffmpegCmd; 23 private String ffmpegCmd;
18 24
  25 + @JSONField(name = "ffmpeg.snap")
  26 + private String ffmpegSnap;
  27 +
19 @JSONField(name = "ffmpeg.log") 28 @JSONField(name = "ffmpeg.log")
20 private String ffmpegLog; 29 private String ffmpegLog;
21 30
  31 + @JSONField(name = "ffmpeg.restart_sec")
  32 + private String ffmpegRestartSec;
  33 +
  34 + @JSONField(name = "protocol.modify_stamp")
  35 + private String protocolModifyStamp;
  36 +
  37 + @JSONField(name = "protocol.enable_audio")
  38 + private String protocolEnableAudio;
  39 +
  40 + @JSONField(name = "protocol.add_mute_audio")
  41 + private String protocolAddMuteAudio;
  42 +
  43 + @JSONField(name = "protocol.continue_push_ms")
  44 + private String protocolContinuePushMs;
  45 +
  46 + @JSONField(name = "protocol.enable_hls")
  47 + private String protocolEnableHls;
  48 +
  49 + @JSONField(name = "protocol.enable_mp4")
  50 + private String protocolEnableMp4;
  51 +
  52 + @JSONField(name = "protocol.enable_rtsp")
  53 + private String protocolEnableRtsp;
  54 +
  55 + @JSONField(name = "protocol.enable_rtmp")
  56 + private String protocolEnableRtmp;
  57 +
  58 + @JSONField(name = "protocol.enable_ts")
  59 + private String protocolEnableTs;
  60 +
  61 + @JSONField(name = "protocol.enable_fmp4")
  62 + private String protocolEnableFmp4;
  63 +
  64 + @JSONField(name = "protocol.mp4_as_player")
  65 + private String protocolMp4AsPlayer;
  66 +
  67 + @JSONField(name = "protocol.mp4_max_second")
  68 + private String protocolMp4MaxSecond;
  69 +
  70 + @JSONField(name = "protocol.mp4_save_path")
  71 + private String protocolMp4SavePath;
  72 +
  73 + @JSONField(name = "protocol.hls_save_path")
  74 + private String protocolHlsSavePath;
  75 +
  76 + @JSONField(name = "protocol.hls_demand")
  77 + private String protocolHlsDemand;
  78 +
  79 + @JSONField(name = "protocol.rtsp_demand")
  80 + private String protocolRtspDemand;
  81 +
  82 + @JSONField(name = "protocol.rtmp_demand")
  83 + private String protocolRtmpDemand;
  84 +
  85 + @JSONField(name = "protocol.ts_demand")
  86 + private String protocolTsDemand;
  87 +
  88 + @JSONField(name = "protocol.fmp4_demand")
  89 + private String protocolFmp4Demand;
  90 +
22 @JSONField(name = "general.enableVhost") 91 @JSONField(name = "general.enableVhost")
23 private String generalEnableVhost; 92 private String generalEnableVhost;
24 93
25 - @JSONField(name = "general.mediaServerId")  
26 - private String generalMediaServerId;  
27 -  
28 @JSONField(name = "general.flowThreshold") 94 @JSONField(name = "general.flowThreshold")
29 private String generalFlowThreshold; 95 private String generalFlowThreshold;
30 96
@@ -34,6 +100,25 @@ public class ZLMServerConfig { @@ -34,6 +100,25 @@ public class ZLMServerConfig {
34 @JSONField(name = "general.streamNoneReaderDelayMS") 100 @JSONField(name = "general.streamNoneReaderDelayMS")
35 private int generalStreamNoneReaderDelayMS; 101 private int generalStreamNoneReaderDelayMS;
36 102
  103 + @JSONField(name = "general.resetWhenRePlay")
  104 + private String generalResetWhenRePlay;
  105 +
  106 + @JSONField(name = "general.mergeWriteMS")
  107 + private String generalMergeWriteMS;
  108 +
  109 + @JSONField(name = "general.mediaServerId")
  110 + private String generalMediaServerId;
  111 +
  112 + @JSONField(name = "general.wait_track_ready_ms")
  113 + private String generalWaitTrackReadyMs;
  114 +
  115 + @JSONField(name = "general.wait_add_track_ms")
  116 + private String generalWaitAddTrackMs;
  117 +
  118 + @JSONField(name = "general.unready_frame_cache")
  119 + private String generalUnreadyFrameCache;
  120 +
  121 +
37 @JSONField(name = "ip") 122 @JSONField(name = "ip")
38 private String ip; 123 private String ip;
39 124
@@ -59,6 +144,18 @@ public class ZLMServerConfig { @@ -59,6 +144,18 @@ public class ZLMServerConfig {
59 @JSONField(name = "hls.segNum") 144 @JSONField(name = "hls.segNum")
60 private String hlsSegNum; 145 private String hlsSegNum;
61 146
  147 + @JSONField(name = "hls.segRetain")
  148 + private String hlsSegRetain;
  149 +
  150 + @JSONField(name = "hls.broadcastRecordTs")
  151 + private String hlsBroadcastRecordTs;
  152 +
  153 + @JSONField(name = "hls.deleteDelaySec")
  154 + private String hlsDeleteDelaySec;
  155 +
  156 + @JSONField(name = "hls.segKeep")
  157 + private String hlsSegKeep;
  158 +
62 @JSONField(name = "hook.access_file_except_hls") 159 @JSONField(name = "hook.access_file_except_hls")
63 private String hookAccessFileExceptHLS; 160 private String hookAccessFileExceptHLS;
64 161
@@ -104,6 +201,18 @@ public class ZLMServerConfig { @@ -104,6 +201,18 @@ public class ZLMServerConfig {
104 @JSONField(name = "hook.on_stream_not_found") 201 @JSONField(name = "hook.on_stream_not_found")
105 private String hookOnStreamNotFound; 202 private String hookOnStreamNotFound;
106 203
  204 + @JSONField(name = "hook.on_server_started")
  205 + private String hookOnServerStarted;
  206 +
  207 + @JSONField(name = "hook.on_server_keepalive")
  208 + private String hookOnServerKeepalive;
  209 +
  210 + @JSONField(name = "hook.on_send_rtp_stopped")
  211 + private String hookOnSendRtpStopped;
  212 +
  213 + @JSONField(name = "hook.on_rtp_server_timeout")
  214 + private String hookOnRtpServerTimeout;
  215 +
107 @JSONField(name = "hook.timeoutSec") 216 @JSONField(name = "hook.timeoutSec")
108 private String hookTimeoutSec; 217 private String hookTimeoutSec;
109 218
@@ -813,4 +922,292 @@ public class ZLMServerConfig { @@ -813,4 +922,292 @@ public class ZLMServerConfig {
813 public void setPortRange(String portRange) { 922 public void setPortRange(String portRange) {
814 this.portRange = portRange; 923 this.portRange = portRange;
815 } 924 }
  925 +
  926 + public String getApiSnapRoot() {
  927 + return apiSnapRoot;
  928 + }
  929 +
  930 + public void setApiSnapRoot(String apiSnapRoot) {
  931 + this.apiSnapRoot = apiSnapRoot;
  932 + }
  933 +
  934 + public String getApiDefaultSnap() {
  935 + return apiDefaultSnap;
  936 + }
  937 +
  938 + public void setApiDefaultSnap(String apiDefaultSnap) {
  939 + this.apiDefaultSnap = apiDefaultSnap;
  940 + }
  941 +
  942 + public String getFfmpegSnap() {
  943 + return ffmpegSnap;
  944 + }
  945 +
  946 + public void setFfmpegSnap(String ffmpegSnap) {
  947 + this.ffmpegSnap = ffmpegSnap;
  948 + }
  949 +
  950 + public String getFfmpegRestartSec() {
  951 + return ffmpegRestartSec;
  952 + }
  953 +
  954 + public void setFfmpegRestartSec(String ffmpegRestartSec) {
  955 + this.ffmpegRestartSec = ffmpegRestartSec;
  956 + }
  957 +
  958 + public String getProtocolModifyStamp() {
  959 + return protocolModifyStamp;
  960 + }
  961 +
  962 + public void setProtocolModifyStamp(String protocolModifyStamp) {
  963 + this.protocolModifyStamp = protocolModifyStamp;
  964 + }
  965 +
  966 + public String getProtocolEnableAudio() {
  967 + return protocolEnableAudio;
  968 + }
  969 +
  970 + public void setProtocolEnableAudio(String protocolEnableAudio) {
  971 + this.protocolEnableAudio = protocolEnableAudio;
  972 + }
  973 +
  974 + public String getProtocolAddMuteAudio() {
  975 + return protocolAddMuteAudio;
  976 + }
  977 +
  978 + public void setProtocolAddMuteAudio(String protocolAddMuteAudio) {
  979 + this.protocolAddMuteAudio = protocolAddMuteAudio;
  980 + }
  981 +
  982 + public String getProtocolContinuePushMs() {
  983 + return protocolContinuePushMs;
  984 + }
  985 +
  986 + public void setProtocolContinuePushMs(String protocolContinuePushMs) {
  987 + this.protocolContinuePushMs = protocolContinuePushMs;
  988 + }
  989 +
  990 + public String getProtocolEnableHls() {
  991 + return protocolEnableHls;
  992 + }
  993 +
  994 + public void setProtocolEnableHls(String protocolEnableHls) {
  995 + this.protocolEnableHls = protocolEnableHls;
  996 + }
  997 +
  998 + public String getProtocolEnableMp4() {
  999 + return protocolEnableMp4;
  1000 + }
  1001 +
  1002 + public void setProtocolEnableMp4(String protocolEnableMp4) {
  1003 + this.protocolEnableMp4 = protocolEnableMp4;
  1004 + }
  1005 +
  1006 + public String getProtocolEnableRtsp() {
  1007 + return protocolEnableRtsp;
  1008 + }
  1009 +
  1010 + public void setProtocolEnableRtsp(String protocolEnableRtsp) {
  1011 + this.protocolEnableRtsp = protocolEnableRtsp;
  1012 + }
  1013 +
  1014 + public String getProtocolEnableRtmp() {
  1015 + return protocolEnableRtmp;
  1016 + }
  1017 +
  1018 + public void setProtocolEnableRtmp(String protocolEnableRtmp) {
  1019 + this.protocolEnableRtmp = protocolEnableRtmp;
  1020 + }
  1021 +
  1022 + public String getProtocolEnableTs() {
  1023 + return protocolEnableTs;
  1024 + }
  1025 +
  1026 + public void setProtocolEnableTs(String protocolEnableTs) {
  1027 + this.protocolEnableTs = protocolEnableTs;
  1028 + }
  1029 +
  1030 + public String getProtocolEnableFmp4() {
  1031 + return protocolEnableFmp4;
  1032 + }
  1033 +
  1034 + public void setProtocolEnableFmp4(String protocolEnableFmp4) {
  1035 + this.protocolEnableFmp4 = protocolEnableFmp4;
  1036 + }
  1037 +
  1038 + public String getProtocolMp4AsPlayer() {
  1039 + return protocolMp4AsPlayer;
  1040 + }
  1041 +
  1042 + public void setProtocolMp4AsPlayer(String protocolMp4AsPlayer) {
  1043 + this.protocolMp4AsPlayer = protocolMp4AsPlayer;
  1044 + }
  1045 +
  1046 + public String getProtocolMp4MaxSecond() {
  1047 + return protocolMp4MaxSecond;
  1048 + }
  1049 +
  1050 + public void setProtocolMp4MaxSecond(String protocolMp4MaxSecond) {
  1051 + this.protocolMp4MaxSecond = protocolMp4MaxSecond;
  1052 + }
  1053 +
  1054 + public String getProtocolMp4SavePath() {
  1055 + return protocolMp4SavePath;
  1056 + }
  1057 +
  1058 + public void setProtocolMp4SavePath(String protocolMp4SavePath) {
  1059 + this.protocolMp4SavePath = protocolMp4SavePath;
  1060 + }
  1061 +
  1062 + public String getProtocolHlsSavePath() {
  1063 + return protocolHlsSavePath;
  1064 + }
  1065 +
  1066 + public void setProtocolHlsSavePath(String protocolHlsSavePath) {
  1067 + this.protocolHlsSavePath = protocolHlsSavePath;
  1068 + }
  1069 +
  1070 + public String getProtocolHlsDemand() {
  1071 + return protocolHlsDemand;
  1072 + }
  1073 +
  1074 + public void setProtocolHlsDemand(String protocolHlsDemand) {
  1075 + this.protocolHlsDemand = protocolHlsDemand;
  1076 + }
  1077 +
  1078 + public String getProtocolRtspDemand() {
  1079 + return protocolRtspDemand;
  1080 + }
  1081 +
  1082 + public void setProtocolRtspDemand(String protocolRtspDemand) {
  1083 + this.protocolRtspDemand = protocolRtspDemand;
  1084 + }
  1085 +
  1086 + public String getProtocolRtmpDemand() {
  1087 + return protocolRtmpDemand;
  1088 + }
  1089 +
  1090 + public void setProtocolRtmpDemand(String protocolRtmpDemand) {
  1091 + this.protocolRtmpDemand = protocolRtmpDemand;
  1092 + }
  1093 +
  1094 + public String getProtocolTsDemand() {
  1095 + return protocolTsDemand;
  1096 + }
  1097 +
  1098 + public void setProtocolTsDemand(String protocolTsDemand) {
  1099 + this.protocolTsDemand = protocolTsDemand;
  1100 + }
  1101 +
  1102 + public String getProtocolFmp4Demand() {
  1103 + return protocolFmp4Demand;
  1104 + }
  1105 +
  1106 + public void setProtocolFmp4Demand(String protocolFmp4Demand) {
  1107 + this.protocolFmp4Demand = protocolFmp4Demand;
  1108 + }
  1109 +
  1110 + public String getGeneralResetWhenRePlay() {
  1111 + return generalResetWhenRePlay;
  1112 + }
  1113 +
  1114 + public void setGeneralResetWhenRePlay(String generalResetWhenRePlay) {
  1115 + this.generalResetWhenRePlay = generalResetWhenRePlay;
  1116 + }
  1117 +
  1118 + public String getGeneralMergeWriteMS() {
  1119 + return generalMergeWriteMS;
  1120 + }
  1121 +
  1122 + public void setGeneralMergeWriteMS(String generalMergeWriteMS) {
  1123 + this.generalMergeWriteMS = generalMergeWriteMS;
  1124 + }
  1125 +
  1126 + public String getGeneralWaitTrackReadyMs() {
  1127 + return generalWaitTrackReadyMs;
  1128 + }
  1129 +
  1130 + public void setGeneralWaitTrackReadyMs(String generalWaitTrackReadyMs) {
  1131 + this.generalWaitTrackReadyMs = generalWaitTrackReadyMs;
  1132 + }
  1133 +
  1134 + public String getGeneralWaitAddTrackMs() {
  1135 + return generalWaitAddTrackMs;
  1136 + }
  1137 +
  1138 + public void setGeneralWaitAddTrackMs(String generalWaitAddTrackMs) {
  1139 + this.generalWaitAddTrackMs = generalWaitAddTrackMs;
  1140 + }
  1141 +
  1142 + public String getGeneralUnreadyFrameCache() {
  1143 + return generalUnreadyFrameCache;
  1144 + }
  1145 +
  1146 + public void setGeneralUnreadyFrameCache(String generalUnreadyFrameCache) {
  1147 + this.generalUnreadyFrameCache = generalUnreadyFrameCache;
  1148 + }
  1149 +
  1150 + public String getHlsSegRetain() {
  1151 + return hlsSegRetain;
  1152 + }
  1153 +
  1154 + public void setHlsSegRetain(String hlsSegRetain) {
  1155 + this.hlsSegRetain = hlsSegRetain;
  1156 + }
  1157 +
  1158 + public String getHlsBroadcastRecordTs() {
  1159 + return hlsBroadcastRecordTs;
  1160 + }
  1161 +
  1162 + public void setHlsBroadcastRecordTs(String hlsBroadcastRecordTs) {
  1163 + this.hlsBroadcastRecordTs = hlsBroadcastRecordTs;
  1164 + }
  1165 +
  1166 + public String getHlsDeleteDelaySec() {
  1167 + return hlsDeleteDelaySec;
  1168 + }
  1169 +
  1170 + public void setHlsDeleteDelaySec(String hlsDeleteDelaySec) {
  1171 + this.hlsDeleteDelaySec = hlsDeleteDelaySec;
  1172 + }
  1173 +
  1174 + public String getHlsSegKeep() {
  1175 + return hlsSegKeep;
  1176 + }
  1177 +
  1178 + public void setHlsSegKeep(String hlsSegKeep) {
  1179 + this.hlsSegKeep = hlsSegKeep;
  1180 + }
  1181 +
  1182 + public String getHookOnServerStarted() {
  1183 + return hookOnServerStarted;
  1184 + }
  1185 +
  1186 + public void setHookOnServerStarted(String hookOnServerStarted) {
  1187 + this.hookOnServerStarted = hookOnServerStarted;
  1188 + }
  1189 +
  1190 + public String getHookOnServerKeepalive() {
  1191 + return hookOnServerKeepalive;
  1192 + }
  1193 +
  1194 + public void setHookOnServerKeepalive(String hookOnServerKeepalive) {
  1195 + this.hookOnServerKeepalive = hookOnServerKeepalive;
  1196 + }
  1197 +
  1198 + public String getHookOnSendRtpStopped() {
  1199 + return hookOnSendRtpStopped;
  1200 + }
  1201 +
  1202 + public void setHookOnSendRtpStopped(String hookOnSendRtpStopped) {
  1203 + this.hookOnSendRtpStopped = hookOnSendRtpStopped;
  1204 + }
  1205 +
  1206 + public String getHookOnRtpServerTimeout() {
  1207 + return hookOnRtpServerTimeout;
  1208 + }
  1209 +
  1210 + public void setHookOnRtpServerTimeout(String hookOnRtpServerTimeout) {
  1211 + this.hookOnRtpServerTimeout = hookOnRtpServerTimeout;
  1212 + }
816 } 1213 }
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResultForOnPublish.java
@@ -5,6 +5,7 @@ public class HookResultForOnPublish extends HookResult{ @@ -5,6 +5,7 @@ public class HookResultForOnPublish extends HookResult{
5 private boolean enable_audio; 5 private boolean enable_audio;
6 private boolean enable_mp4; 6 private boolean enable_mp4;
7 private int mp4_max_second; 7 private int mp4_max_second;
  8 + private String mp4_save_path;
8 9
9 public HookResultForOnPublish() { 10 public HookResultForOnPublish() {
10 } 11 }
@@ -41,4 +42,12 @@ public class HookResultForOnPublish extends HookResult{ @@ -41,4 +42,12 @@ public class HookResultForOnPublish extends HookResult{
41 public void setMp4_max_second(int mp4_max_second) { 42 public void setMp4_max_second(int mp4_max_second) {
42 this.mp4_max_second = mp4_max_second; 43 this.mp4_max_second = mp4_max_second;
43 } 44 }
  45 +
  46 + public String getMp4_save_path() {
  47 + return mp4_save_path;
  48 + }
  49 +
  50 + public void setMp4_save_path(String mp4_save_path) {
  51 + this.mp4_save_path = mp4_save_path;
  52 + }
44 } 53 }
src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.service; @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.service;
2 2
3 import com.genersoft.iot.vmp.gb28181.bean.Device; 3 import com.genersoft.iot.vmp.gb28181.bean.Device;
4 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 4 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  5 +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
5 import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; 6 import com.genersoft.iot.vmp.gb28181.bean.SyncStatus;
6 import com.genersoft.iot.vmp.vmanager.bean.BaseTree; 7 import com.genersoft.iot.vmp.vmanager.bean.BaseTree;
7 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo; 8 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
@@ -18,13 +19,13 @@ public interface IDeviceService { @@ -18,13 +19,13 @@ public interface IDeviceService {
18 * 设备上线 19 * 设备上线
19 * @param device 设备信息 20 * @param device 设备信息
20 */ 21 */
21 - void online(Device device); 22 + void online(Device device, SipTransactionInfo sipTransactionInfo);
22 23
23 /** 24 /**
24 * 设备下线 25 * 设备下线
25 * @param deviceId 设备编号 26 * @param deviceId 设备编号
26 */ 27 */
27 - void offline(String deviceId); 28 + void offline(String deviceId, String reason);
28 29
29 /** 30 /**
30 * 添加目录订阅 31 * 添加目录订阅
src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java
@@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
6 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; 6 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
8 import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; 8 import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback;
  9 +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
9 import com.github.pagehelper.PageInfo; 10 import com.github.pagehelper.PageInfo;
10 11
11 import javax.sip.InvalidArgumentException; 12 import javax.sip.InvalidArgumentException;
@@ -35,10 +36,16 @@ public interface IPlatformService { @@ -35,10 +36,16 @@ public interface IPlatformService {
35 boolean add(ParentPlatform parentPlatform); 36 boolean add(ParentPlatform parentPlatform);
36 37
37 /** 38 /**
  39 + * 添加级联平台
  40 + * @param parentPlatform 级联平台
  41 + */
  42 + boolean update(ParentPlatform parentPlatform);
  43 +
  44 + /**
38 * 平台上线 45 * 平台上线
39 * @param parentPlatform 平台信息 46 * @param parentPlatform 平台信息
40 */ 47 */
41 - void online(ParentPlatform parentPlatform); 48 + void online(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo);
42 49
43 /** 50 /**
44 * 平台离线 51 * 平台离线
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -96,7 +96,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -96,7 +96,7 @@ public class DeviceServiceImpl implements IDeviceService {
96 private ZLMRESTfulUtils zlmresTfulUtils; 96 private ZLMRESTfulUtils zlmresTfulUtils;
97 97
98 @Override 98 @Override
99 - public void online(Device device) { 99 + public void online(Device device, SipTransactionInfo sipTransactionInfo) {
100 logger.info("[设备上线] deviceId:{}->{}:{}", device.getDeviceId(), device.getIp(), device.getPort()); 100 logger.info("[设备上线] deviceId:{}->{}:{}", device.getDeviceId(), device.getIp(), device.getPort());
101 Device deviceInRedis = redisCatchStorage.getDevice(device.getDeviceId()); 101 Device deviceInRedis = redisCatchStorage.getDevice(device.getDeviceId());
102 Device deviceInDb = deviceMapper.getDeviceByDeviceId(device.getDeviceId()); 102 Device deviceInDb = deviceMapper.getDeviceByDeviceId(device.getDeviceId());
@@ -111,6 +111,14 @@ public class DeviceServiceImpl implements IDeviceService { @@ -111,6 +111,14 @@ public class DeviceServiceImpl implements IDeviceService {
111 // 默认心跳间隔60 111 // 默认心跳间隔60
112 device.setKeepaliveIntervalTime(60); 112 device.setKeepaliveIntervalTime(60);
113 } 113 }
  114 + if (sipTransactionInfo != null) {
  115 + device.setSipTransactionInfo(sipTransactionInfo);
  116 + }else {
  117 + if (deviceInRedis != null) {
  118 + device.setSipTransactionInfo(deviceInRedis.getSipTransactionInfo());
  119 + }
  120 + }
  121 +
114 // 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询 122 // 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询
115 if (device.getCreateTime() == null) { 123 if (device.getCreateTime() == null) {
116 device.setOnline(1); 124 device.setOnline(1);
@@ -163,12 +171,12 @@ public class DeviceServiceImpl implements IDeviceService { @@ -163,12 +171,12 @@ public class DeviceServiceImpl implements IDeviceService {
163 // 刷新过期任务 171 // 刷新过期任务
164 String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); 172 String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId();
165 // 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线 173 // 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线
166 - dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getKeepaliveIntervalTime() * 1000 * 3); 174 + dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId(), "首次注册后未能收到心跳"), device.getKeepaliveIntervalTime() * 1000 * 3);
167 } 175 }
168 176
169 @Override 177 @Override
170 - public void offline(String deviceId) {  
171 - logger.error("[设备离线], device:{}", deviceId); 178 + public void offline(String deviceId, String reason) {
  179 + logger.error("[设备离线],{}, device:{}", reason, deviceId);
172 Device device = deviceMapper.getDeviceByDeviceId(deviceId); 180 Device device = deviceMapper.getDeviceByDeviceId(deviceId);
173 if (device == null) { 181 if (device == null) {
174 return; 182 return;
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
@@ -41,6 +41,9 @@ public class GbStreamServiceImpl implements IGbStreamService { @@ -41,6 +41,9 @@ public class GbStreamServiceImpl implements IGbStreamService {
41 private PlatformGbStreamMapper platformGbStreamMapper; 41 private PlatformGbStreamMapper platformGbStreamMapper;
42 42
43 @Autowired 43 @Autowired
  44 + private SubscribeHolder subscribeHolder;
  45 +
  46 + @Autowired
44 private ParentPlatformMapper platformMapper; 47 private ParentPlatformMapper platformMapper;
45 48
46 @Autowired 49 @Autowired
@@ -73,16 +76,23 @@ public class GbStreamServiceImpl implements IGbStreamService { @@ -73,16 +76,23 @@ public class GbStreamServiceImpl implements IGbStreamService {
73 } 76 }
74 try { 77 try {
75 List<DeviceChannel> deviceChannelList = new ArrayList<>(); 78 List<DeviceChannel> deviceChannelList = new ArrayList<>();
76 - for (GbStream gbStream : gbStreams) { 79 +
  80 +
  81 + for (int i = 0; i < gbStreams.size(); i++) {
  82 + GbStream gbStream = gbStreams.get(i);
77 gbStream.setCatalogId(catalogId); 83 gbStream.setCatalogId(catalogId);
78 gbStream.setPlatformId(platformId); 84 gbStream.setPlatformId(platformId);
79 // TODO 修改为批量提交 85 // TODO 修改为批量提交
80 platformGbStreamMapper.add(gbStream); 86 platformGbStreamMapper.add(gbStream);
  87 + logger.info("[关联通道]直播流通道 平台:{}, 共需关联通道数:{}, 已关联:{}", platformId, gbStreams.size(), i + 1);
81 DeviceChannel deviceChannelListByStream = getDeviceChannelListByStreamWithStatus(gbStream, catalogId, parentPlatform); 88 DeviceChannel deviceChannelListByStream = getDeviceChannelListByStreamWithStatus(gbStream, catalogId, parentPlatform);
82 deviceChannelList.add(deviceChannelListByStream); 89 deviceChannelList.add(deviceChannelListByStream);
83 } 90 }
84 dataSourceTransactionManager.commit(transactionStatus); //手动提交 91 dataSourceTransactionManager.commit(transactionStatus); //手动提交
85 - eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD); 92 + if (subscribeHolder.getCatalogSubscribe(platformId) != null) {
  93 + eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);
  94 + }
  95 +
86 result = true; 96 result = true;
87 }catch (Exception e) { 97 }catch (Exception e) {
88 logger.error("批量保存流与平台的关系时错误", e); 98 logger.error("批量保存流与平台的关系时错误", e);
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
@@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.conf.exception.ControllerException; @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.conf.exception.ControllerException;
11 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 11 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
12 import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; 12 import com.genersoft.iot.vmp.gb28181.session.SsrcConfig;
13 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 13 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
  14 +import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
14 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; 15 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
15 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; 16 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
16 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; 17 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
@@ -38,6 +39,7 @@ import org.springframework.transaction.TransactionDefinition; @@ -38,6 +39,7 @@ import org.springframework.transaction.TransactionDefinition;
38 import org.springframework.transaction.TransactionStatus; 39 import org.springframework.transaction.TransactionStatus;
39 import org.springframework.util.ObjectUtils; 40 import org.springframework.util.ObjectUtils;
40 41
  42 +import java.io.File;
41 import java.time.LocalDateTime; 43 import java.time.LocalDateTime;
42 import java.util.*; 44 import java.util.*;
43 45
@@ -64,6 +66,9 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -64,6 +66,9 @@ public class MediaServerServiceImpl implements IMediaServerService {
64 private UserSetting userSetting; 66 private UserSetting userSetting;
65 67
66 @Autowired 68 @Autowired
  69 + private AssistRESTfulUtils assistRESTfulUtils;
  70 +
  71 + @Autowired
67 private ZLMRESTfulUtils zlmresTfulUtils; 72 private ZLMRESTfulUtils zlmresTfulUtils;
68 73
69 @Autowired 74 @Autowired
@@ -409,13 +414,27 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -409,13 +414,27 @@ public class MediaServerServiceImpl implements IMediaServerService {
409 } 414 }
410 RedisUtil.set(key, serverItem); 415 RedisUtil.set(key, serverItem);
411 resetOnlineServerItem(serverItem); 416 resetOnlineServerItem(serverItem);
  417 +
  418 +
412 if (serverItem.isAutoConfig()) { 419 if (serverItem.isAutoConfig()) {
  420 + // 查看assist服务的录像路径配置
  421 + if (serverItem.getRecordAssistPort() > 0 && userSetting.getRecordPath() == null) {
  422 + JSONObject info = assistRESTfulUtils.getInfo(serverItem, null);
  423 + if (info != null && info.getInteger("code") != null && info.getInteger("code") == 0 ) {
  424 + JSONObject dataJson = info.getJSONObject("data");
  425 + if (dataJson != null) {
  426 + String recordPath = dataJson.getString("record");
  427 + userSetting.setRecordPath(recordPath);
  428 + }
  429 + }
  430 + }
413 setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); 431 setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable()));
414 } 432 }
415 final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId(); 433 final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId();
416 dynamicTask.stop(zlmKeepaliveKey); 434 dynamicTask.stop(zlmKeepaliveKey);
417 dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(serverItem), (Math.getExponent(serverItem.getHookAliveInterval()) + 5) * 1000); 435 dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(serverItem), (Math.getExponent(serverItem.getHookAliveInterval()) + 5) * 1000);
418 publisher.zlmOnlineEventPublish(serverItem.getId()); 436 publisher.zlmOnlineEventPublish(serverItem.getId());
  437 +
419 logger.info("[ZLM] 连接成功 {} - {}:{} ", 438 logger.info("[ZLM] 连接成功 {} - {}:{} ",
420 zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); 439 zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
421 } 440 }
@@ -549,6 +568,9 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -549,6 +568,9 @@ public class MediaServerServiceImpl implements IMediaServerService {
549 568
550 Map<String, Object> param = new HashMap<>(); 569 Map<String, Object> param = new HashMap<>();
551 param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline 570 param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline
  571 + if (mediaServerItem.getRtspPort() != 0) {
  572 + param.put("ffmpeg.snap", "%s -rtsp_transport tcp -i %s -y -f mjpeg -t 0.001 %s");
  573 + }
552 param.put("hook.enable","1"); 574 param.put("hook.enable","1");
553 param.put("hook.on_flow_report",""); 575 param.put("hook.on_flow_report","");
554 param.put("hook.on_play",String.format("%s/on_play", hookPrex)); 576 param.put("hook.on_play",String.format("%s/on_play", hookPrex));
@@ -583,6 +605,13 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -583,6 +605,13 @@ public class MediaServerServiceImpl implements IMediaServerService {
583 param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-")); 605 param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-"));
584 } 606 }
585 607
  608 + if (userSetting.getRecordPath() != null) {
  609 + File recordPathFile = new File(userSetting.getRecordPath());
  610 + File mp4SavePathFile = recordPathFile.getParentFile().getAbsoluteFile();
  611 + param.put("protocol.mp4_save_path", mp4SavePathFile.getAbsoluteFile());
  612 + param.put("record.appName", recordPathFile.getName());
  613 + }
  614 +
586 JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param); 615 JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param);
587 616
588 if (responseJSON != null && responseJSON.getInteger("code") == 0) { 617 if (responseJSON != null && responseJSON.getInteger("code") == 0) {
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java
1 package com.genersoft.iot.vmp.service.impl; 1 package com.genersoft.iot.vmp.service.impl;
2 2
3 -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;  
4 -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;  
5 -import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;  
6 -import com.genersoft.iot.vmp.gb28181.bean.TreeType; 3 +import com.genersoft.iot.vmp.gb28181.bean.*;
7 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 4 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
8 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; 5 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
9 import com.genersoft.iot.vmp.service.IPlatformChannelService; 6 import com.genersoft.iot.vmp.service.IPlatformChannelService;
@@ -15,7 +12,10 @@ import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; @@ -15,7 +12,10 @@ import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
15 import org.slf4j.Logger; 12 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory; 13 import org.slf4j.LoggerFactory;
17 import org.springframework.beans.factory.annotation.Autowired; 14 import org.springframework.beans.factory.annotation.Autowired;
  15 +import org.springframework.jdbc.datasource.DataSourceTransactionManager;
18 import org.springframework.stereotype.Service; 16 import org.springframework.stereotype.Service;
  17 +import org.springframework.transaction.TransactionDefinition;
  18 +import org.springframework.transaction.TransactionStatus;
19 import org.springframework.util.ObjectUtils; 19 import org.springframework.util.ObjectUtils;
20 20
21 import java.util.ArrayList; 21 import java.util.ArrayList;
@@ -35,6 +35,16 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService { @@ -35,6 +35,16 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
35 private PlatformChannelMapper platformChannelMapper; 35 private PlatformChannelMapper platformChannelMapper;
36 36
37 @Autowired 37 @Autowired
  38 + TransactionDefinition transactionDefinition;
  39 +
  40 + @Autowired
  41 + DataSourceTransactionManager dataSourceTransactionManager;
  42 +
  43 + @Autowired
  44 + private SubscribeHolder subscribeHolder;
  45 +
  46 +
  47 + @Autowired
38 private DeviceChannelMapper deviceChannelMapper; 48 private DeviceChannelMapper deviceChannelMapper;
39 49
40 @Autowired 50 @Autowired
@@ -69,17 +79,47 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService { @@ -69,17 +79,47 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
69 } 79 }
70 List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values()); 80 List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values());
71 // 对剩下的数据进行存储 81 // 对剩下的数据进行存储
72 - int result = 0; 82 + int allCount = 0;
  83 + boolean result = false;
  84 + TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
  85 + int limitCount = 300;
73 if (channelReducesToAdd.size() > 0) { 86 if (channelReducesToAdd.size() > 0) {
74 - result = platformChannelMapper.addChannels(platformId, channelReducesToAdd);  
75 - // TODO 后续给平台增加控制开关以控制是否响应目录订阅  
76 - List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId, platform);  
77 - if (deviceChannelList != null) {  
78 - eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD); 87 + if (channelReducesToAdd.size() > limitCount) {
  88 + for (int i = 0; i < channelReducesToAdd.size(); i += limitCount) {
  89 + int toIndex = i + limitCount;
  90 + if (i + limitCount > channelReducesToAdd.size()) {
  91 + toIndex = channelReducesToAdd.size();
  92 + }
  93 + int count = platformChannelMapper.addChannels(platformId, channelReducesToAdd.subList(i, toIndex));
  94 + result = result || count < 0;
  95 + allCount += count;
  96 + logger.info("[关联通道]国标通道 平台:{}, 共需关联通道数:{}, 已关联:{}", platformId, channelReducesToAdd.size(), toIndex);
  97 + }
  98 + }else {
  99 + allCount = platformChannelMapper.addChannels(platformId, channelReducesToAdd);
  100 + result = result || allCount < 0;
  101 + logger.info("[关联通道]国标通道 平台:{}, 关联通道数:{}", platformId, channelReducesToAdd.size());
79 } 102 }
80 - }  
81 103
82 - return result; 104 + if (result) {
  105 + //事务回滚
  106 + dataSourceTransactionManager.rollback(transactionStatus);
  107 + allCount = 0;
  108 + }else {
  109 + logger.info("[关联通道]国标通道 平台:{}, 正在存入数据库", platformId);
  110 + dataSourceTransactionManager.commit(transactionStatus);
  111 +
  112 + }
  113 + SubscribeInfo catalogSubscribe = subscribeHolder.getCatalogSubscribe(platformId);
  114 + if (catalogSubscribe != null) {
  115 + List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId, platform);
  116 + if (deviceChannelList != null) {
  117 + eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);
  118 + }
  119 + }
  120 + logger.info("[关联通道]国标通道 平台:{}, 存入数据库成功", platformId);
  121 + }
  122 + return allCount;
83 } 123 }
84 124
85 private List<DeviceChannel> getDeviceChannelListByChannelReduceList(List<ChannelReduce> channelReduces, String catalogId, ParentPlatform platform) { 125 private List<DeviceChannel> getDeviceChannelListByChannelReduceList(List<ChannelReduce> channelReduces, String catalogId, ParentPlatform platform) {
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
@@ -21,8 +21,8 @@ import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; @@ -21,8 +21,8 @@ import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
21 import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; 21 import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback;
22 import com.genersoft.iot.vmp.service.bean.SSRCInfo; 22 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
23 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 23 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
24 -import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;  
25 -import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper; 24 +import com.genersoft.iot.vmp.storager.dao.*;
  25 +import com.genersoft.iot.vmp.utils.DateUtil;
26 import com.github.pagehelper.PageHelper; 26 import com.github.pagehelper.PageHelper;
27 import com.github.pagehelper.PageInfo; 27 import com.github.pagehelper.PageInfo;
28 import org.slf4j.Logger; 28 import org.slf4j.Logger;
@@ -54,6 +54,15 @@ public class PlatformServiceImpl implements IPlatformService { @@ -54,6 +54,15 @@ public class PlatformServiceImpl implements IPlatformService {
54 private ParentPlatformMapper platformMapper; 54 private ParentPlatformMapper platformMapper;
55 55
56 @Autowired 56 @Autowired
  57 + private PlatformCatalogMapper catalogMapper;
  58 +
  59 + @Autowired
  60 + private PlatformChannelMapper platformChannelMapper;
  61 +
  62 + @Autowired
  63 + private PlatformGbStreamMapper platformGbStreamMapper;
  64 +
  65 + @Autowired
57 private IRedisCatchStorage redisCatchStorage; 66 private IRedisCatchStorage redisCatchStorage;
58 67
59 @Autowired 68 @Autowired
@@ -135,36 +144,106 @@ public class PlatformServiceImpl implements IPlatformService { @@ -135,36 +144,106 @@ public class PlatformServiceImpl implements IPlatformService {
135 } 144 }
136 145
137 @Override 146 @Override
138 - public void online(ParentPlatform parentPlatform) {  
139 - logger.info("[国标级联]:{}, 平台上线/更新注册", parentPlatform.getServerGBId()); 147 + public boolean update(ParentPlatform parentPlatform) {
  148 + logger.info("[国标级联]更新平台 {}", parentPlatform.getDeviceGBId());
  149 + parentPlatform.setCharacterSet(parentPlatform.getCharacterSet().toUpperCase());
  150 + ParentPlatform parentPlatformOld = platformMapper.getParentPlatById(parentPlatform.getId());
  151 + ParentPlatformCatch parentPlatformCatchOld = redisCatchStorage.queryPlatformCatchInfo(parentPlatformOld.getServerGBId());
  152 + parentPlatform.setUpdateTime(DateUtil.getNow());
  153 + if (!parentPlatformOld.getTreeType().equals(parentPlatform.getTreeType())) {
  154 + // 目录结构发生变化,清空之前的关联关系
  155 + logger.info("保存平台{}时发现目录结构变化,清空关联关系", parentPlatform.getDeviceGBId());
  156 + catalogMapper.delByPlatformId(parentPlatformOld.getServerGBId());
  157 + platformChannelMapper.delByPlatformId(parentPlatformOld.getServerGBId());
  158 + platformGbStreamMapper.delByPlatformId(parentPlatformOld.getServerGBId());
  159 + }
  160 +
  161 +
  162 + // 停止心跳定时
  163 + final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatformOld.getServerGBId();
  164 + dynamicTask.stop(keepaliveTaskKey);
  165 + // 停止注册定时
  166 + final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatformOld.getServerGBId();
  167 + dynamicTask.stop(registerTaskKey);
  168 + // 注销旧的
  169 + try {
  170 + if (parentPlatformOld.isStatus()) {
  171 + logger.info("保存平台{}时发现救平台在线,发送注销命令", parentPlatform.getDeviceGBId());
  172 + commanderForPlatform.unregister(parentPlatformOld, parentPlatformCatchOld.getSipTransactionInfo(), null, eventResult -> {
  173 + logger.info("[国标级联] 注销成功, 平台:{}", parentPlatformOld.getServerGBId());
  174 + });
  175 + }
  176 +
  177 + } catch (InvalidArgumentException | ParseException | SipException e) {
  178 + logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
  179 + }
  180 +
  181 + // 更新数据库
  182 + if (parentPlatform.getCatalogGroup() == 0) {
  183 + parentPlatform.setCatalogGroup(1);
  184 + }
  185 + if (parentPlatform.getAdministrativeDivision() == null) {
  186 + parentPlatform.setAdministrativeDivision(parentPlatform.getAdministrativeDivision());
  187 + }
  188 +
  189 + platformMapper.updateParentPlatform(parentPlatform);
  190 + // 更新redis
  191 + redisCatchStorage.delPlatformCatchInfo(parentPlatformOld.getServerGBId());
  192 + ParentPlatformCatch parentPlatformCatch = new ParentPlatformCatch();
  193 + parentPlatformCatch.setParentPlatform(parentPlatform);
  194 + parentPlatformCatch.setId(parentPlatform.getServerGBId());
  195 + redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
  196 + // 注册
  197 + if (parentPlatform.isEnable()) {
  198 + // 保存时启用就发送注册
  199 + // 注册成功时由程序直接调用了online方法
  200 + try {
  201 + commanderForPlatform.register(parentPlatform, eventResult -> {
  202 + logger.info("[国标级联] {},添加向上级注册失败,请确定上级平台可用时重新保存", parentPlatform.getServerGBId());
  203 + }, null);
  204 + } catch (InvalidArgumentException | ParseException | SipException e) {
  205 + logger.error("[命令发送失败] 国标级联: {}", e.getMessage());
  206 + }
  207 + }
  208 + // 重新开启定时注册, 使用续订消息
  209 + // 重新开始心跳保活
  210 +
  211 +
  212 + return false;
  213 + }
  214 +
  215 +
  216 + @Override
  217 + public void online(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo) {
  218 + logger.info("[国标级联]:{}, 平台上线", parentPlatform.getServerGBId());
140 platformMapper.updateParentPlatformStatus(parentPlatform.getServerGBId(), true); 219 platformMapper.updateParentPlatformStatus(parentPlatform.getServerGBId(), true);
141 ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId()); 220 ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(parentPlatform.getServerGBId());
142 - if (parentPlatformCatch != null) {  
143 - parentPlatformCatch.getParentPlatform().setStatus(true);  
144 - redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);  
145 - }else { 221 + if (parentPlatformCatch == null) {
146 parentPlatformCatch = new ParentPlatformCatch(); 222 parentPlatformCatch = new ParentPlatformCatch();
147 parentPlatformCatch.setParentPlatform(parentPlatform); 223 parentPlatformCatch.setParentPlatform(parentPlatform);
148 parentPlatformCatch.setId(parentPlatform.getServerGBId()); 224 parentPlatformCatch.setId(parentPlatform.getServerGBId());
149 parentPlatform.setStatus(true); 225 parentPlatform.setStatus(true);
150 parentPlatformCatch.setParentPlatform(parentPlatform); 226 parentPlatformCatch.setParentPlatform(parentPlatform);
151 - redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);  
152 } 227 }
153 228
  229 + parentPlatformCatch.getParentPlatform().setStatus(true);
  230 + parentPlatformCatch.setSipTransactionInfo(sipTransactionInfo);
  231 + redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
  232 +
154 final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId(); 233 final String registerTaskKey = REGISTER_KEY_PREFIX + parentPlatform.getServerGBId();
155 if (!dynamicTask.isAlive(registerTaskKey)) { 234 if (!dynamicTask.isAlive(registerTaskKey)) {
  235 + logger.info("[国标级联]:{}, 添加定时注册任务", parentPlatform.getServerGBId());
156 // 添加注册任务 236 // 添加注册任务
157 dynamicTask.startCron(registerTaskKey, 237 dynamicTask.startCron(registerTaskKey,
158 // 注册失败(注册成功时由程序直接调用了online方法) 238 // 注册失败(注册成功时由程序直接调用了online方法)
159 - ()-> {  
160 - registerTask(parentPlatform);  
161 - },  
162 - (parentPlatform.getExpires() - 10) *1000); 239 + ()-> registerTask(parentPlatform, sipTransactionInfo),
  240 + parentPlatform.getExpires() * 1000);
163 } 241 }
164 242
165 243
166 final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId(); 244 final String keepaliveTaskKey = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId();
167 if (!dynamicTask.contains(keepaliveTaskKey)) { 245 if (!dynamicTask.contains(keepaliveTaskKey)) {
  246 + logger.info("[国标级联]:{}, 添加定时心跳任务", parentPlatform.getServerGBId());
168 // 添加心跳任务 247 // 添加心跳任务
169 dynamicTask.startCron(keepaliveTaskKey, 248 dynamicTask.startCron(keepaliveTaskKey,
170 ()-> { 249 ()-> {
@@ -205,11 +284,11 @@ public class PlatformServiceImpl implements IPlatformService { @@ -205,11 +284,11 @@ public class PlatformServiceImpl implements IPlatformService {
205 logger.error("[命令发送失败] 国标级联 发送心跳: {}", e.getMessage()); 284 logger.error("[命令发送失败] 国标级联 发送心跳: {}", e.getMessage());
206 } 285 }
207 }, 286 },
208 - (parentPlatform.getKeepTimeout() - 10)*1000); 287 + (parentPlatform.getKeepTimeout())*1000);
209 } 288 }
210 } 289 }
211 290
212 - private void registerTask(ParentPlatform parentPlatform){ 291 + private void registerTask(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo){
213 try { 292 try {
214 // 设置超时重发, 后续从底层支持消息重发 293 // 设置超时重发, 后续从底层支持消息重发
215 String key = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId() + "_timeout"; 294 String key = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId() + "_timeout";
@@ -217,10 +296,10 @@ public class PlatformServiceImpl implements IPlatformService { @@ -217,10 +296,10 @@ public class PlatformServiceImpl implements IPlatformService {
217 return; 296 return;
218 } 297 }
219 dynamicTask.startDelay(key, ()->{ 298 dynamicTask.startDelay(key, ()->{
220 - registerTask(parentPlatform); 299 + registerTask(parentPlatform, sipTransactionInfo);
221 }, 1000); 300 }, 1000);
222 - logger.info("[国标级联] 平台:{}注册即将到期,重新注册", parentPlatform.getServerGBId());  
223 - commanderForPlatform.register(parentPlatform, eventResult -> { 301 + logger.info("[国标级联] 平台:{}注册即将到期,开始续订", parentPlatform.getServerGBId());
  302 + commanderForPlatform.register(parentPlatform, sipTransactionInfo, eventResult -> {
224 dynamicTask.stop(key); 303 dynamicTask.stop(key);
225 offline(parentPlatform, false); 304 offline(parentPlatform, false);
226 },eventResult -> { 305 },eventResult -> {
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -438,7 +438,12 @@ public class PlayServiceImpl implements IPlayService { @@ -438,7 +438,12 @@ public class PlayServiceImpl implements IPlayService {
438 onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId); 438 onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId);
439 hookEvent.response(mediaServerItemInuse, response); 439 hookEvent.response(mediaServerItemInuse, response);
440 logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); 440 logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId);
441 - String streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.flv", mediaServerItemInuse.getHttpPort(), "rtp", ssrcInfo.getStream()); 441 + String streamUrl;
  442 + if (mediaServerItemInuse.getRtspPort() != 0) {
  443 + streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", ssrcInfo.getStream());
  444 + }else {
  445 + streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.mp4", mediaServerItemInuse.getHttpPort(), "rtp", ssrcInfo.getStream());
  446 + }
442 String path = "snap"; 447 String path = "snap";
443 String fileName = device.getDeviceId() + "_" + channelId + ".jpg"; 448 String fileName = device.getDeviceId() + "_" + channelId + ".jpg";
444 // 请求截图 449 // 请求截图
@@ -806,23 +811,75 @@ public class PlayServiceImpl implements IPlayService { @@ -806,23 +811,75 @@ public class PlayServiceImpl implements IPlayService {
806 hookCallBack.call(downloadResult); 811 hookCallBack.call(downloadResult);
807 streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); 812 streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
808 }; 813 };
809 - 814 + InviteStreamCallback hookEvent = (InviteStreamInfo inviteStreamInfo) -> {
  815 + logger.info("收到订阅消息: " + inviteStreamInfo.getCallId());
  816 + dynamicTask.stop(downLoadTimeOutTaskKey);
  817 + StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);
  818 + streamInfo.setStartTime(startTime);
  819 + streamInfo.setEndTime(endTime);
  820 + redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());
  821 + downloadResult.setCode(ErrorCode.SUCCESS.getCode());
  822 + downloadResult.setMsg(ErrorCode.SUCCESS.getMsg());
  823 + downloadResult.setData(streamInfo);
  824 + downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
  825 + downloadResult.setResponse(inviteStreamInfo.getResponse());
  826 + hookCallBack.call(downloadResult);
  827 + };
810 try { 828 try {
811 cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack, 829 cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack,
812 - inviteStreamInfo -> {  
813 - logger.info("收到订阅消息: " + inviteStreamInfo.getResponse().toJSONString());  
814 - dynamicTask.stop(downLoadTimeOutTaskKey);  
815 - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);  
816 - streamInfo.setStartTime(startTime);  
817 - streamInfo.setEndTime(endTime);  
818 - redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());  
819 - downloadResult.setCode(ErrorCode.SUCCESS.getCode());  
820 - downloadResult.setMsg(ErrorCode.SUCCESS.getMsg());  
821 - downloadResult.setData(streamInfo);  
822 - downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());  
823 - downloadResult.setResponse(inviteStreamInfo.getResponse());  
824 - hookCallBack.call(downloadResult);  
825 - }, errorEvent); 830 + hookEvent, errorEvent, eventResult ->
  831 + {
  832 + if (eventResult.type == SipSubscribe.EventResultType.response) {
  833 + ResponseEvent responseEvent = (ResponseEvent) eventResult.event;
  834 + String contentString = new String(responseEvent.getResponse().getRawContent());
  835 + // 获取ssrc
  836 + int ssrcIndex = contentString.indexOf("y=");
  837 + // 检查是否有y字段
  838 + if (ssrcIndex >= 0) {
  839 + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容
  840 + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
  841 + // 查询到ssrc不一致且开启了ssrc校验则需要针对处理
  842 + if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {
  843 + return;
  844 + }
  845 + logger.info("[回放消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse);
  846 + if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
  847 + logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
  848 +
  849 + if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) {
  850 + // ssrc 不可用
  851 + // 释放ssrc
  852 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
  853 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  854 + eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用";
  855 + eventResult.statusCode = 400;
  856 + errorEvent.response(eventResult);
  857 + return;
  858 + }
  859 +
  860 + // 单端口模式streamId也有变化,需要重新设置监听
  861 + if (!mediaServerItem.isRtpEnable()) {
  862 + // 添加订阅
  863 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
  864 + subscribe.removeSubscribe(hookSubscribe);
  865 + hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
  866 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> {
  867 + logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());
  868 + dynamicTask.stop(downLoadTimeOutTaskKey);
  869 + // hook响应
  870 + onPublishHandlerForPlayback(mediaServerItemInUse, response, device.getDeviceId(), channelId, hookCallBack);
  871 + hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream()));
  872 + });
  873 + }
  874 + // 关闭rtp server
  875 + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
  876 + // 重新开启ssrc server
  877 + mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort());
  878 + }
  879 + }
  880 + }
  881 +
  882 + });
826 } catch (InvalidArgumentException | SipException | ParseException e) { 883 } catch (InvalidArgumentException | SipException | ParseException e) {
827 logger.error("[命令发送失败] 录像下载: {}", e.getMessage()); 884 logger.error("[命令发送失败] 录像下载: {}", e.getMessage());
828 885
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
@@ -201,7 +201,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -201,7 +201,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
201 dataSourceTransactionManager.commit(transactionStatus); //手动提交 201 dataSourceTransactionManager.commit(transactionStatus); //手动提交
202 result = true; 202 result = true;
203 }catch (Exception e) { 203 }catch (Exception e) {
204 - e.printStackTrace(); 204 + logger.error("未处理的异常 ", e);
205 dataSourceTransactionManager.rollback(transactionStatus); 205 dataSourceTransactionManager.rollback(transactionStatus);
206 } 206 }
207 return result; 207 return result;
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java
1 package com.genersoft.iot.vmp.service.redisMsg; 1 package com.genersoft.iot.vmp.service.redisMsg;
2 2
3 import com.alibaba.fastjson2.JSON; 3 import com.alibaba.fastjson2.JSON;
  4 +import com.genersoft.iot.vmp.conf.UserSetting;
4 import com.genersoft.iot.vmp.gb28181.bean.*; 5 import com.genersoft.iot.vmp.gb28181.bean.*;
5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
@@ -44,13 +45,17 @@ public class RedisAlarmMsgListener implements MessageListener { @@ -44,13 +45,17 @@ public class RedisAlarmMsgListener implements MessageListener {
44 @Autowired 45 @Autowired
45 private ThreadPoolTaskExecutor taskExecutor; 46 private ThreadPoolTaskExecutor taskExecutor;
46 47
  48 + @Autowired
  49 + private UserSetting userSetting;
  50 +
47 @Override 51 @Override
48 public void onMessage(@NotNull Message message, byte[] bytes) { 52 public void onMessage(@NotNull Message message, byte[] bytes) {
  53 + // 消息示例: PUBLISH alarm_receive '{ "gbId": "", "alarmSn": 1, "alarmType": "111", "alarmDescription": "222", }'
49 logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody())); 54 logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody()));
50 boolean isEmpty = taskQueue.isEmpty(); 55 boolean isEmpty = taskQueue.isEmpty();
51 taskQueue.offer(message); 56 taskQueue.offer(message);
52 if (isEmpty) { 57 if (isEmpty) {
53 - logger.info("[线程池信息]活动线程数:{}, 最大线程数: {}", taskExecutor.getActiveCount(), taskExecutor.getMaxPoolSize()); 58 +// logger.info("[线程池信息]活动线程数:{}, 最大线程数: {}", taskExecutor.getActiveCount(), taskExecutor.getMaxPoolSize());
54 taskExecutor.execute(() -> { 59 taskExecutor.execute(() -> {
55 while (!taskQueue.isEmpty()) { 60 while (!taskQueue.isEmpty()) {
56 Message msg = taskQueue.poll(); 61 Message msg = taskQueue.poll();
@@ -69,22 +74,52 @@ public class RedisAlarmMsgListener implements MessageListener { @@ -69,22 +74,52 @@ public class RedisAlarmMsgListener implements MessageListener {
69 deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn()); 74 deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn());
70 deviceAlarm.setAlarmType("" + alarmChannelMessage.getAlarmType()); 75 deviceAlarm.setAlarmType("" + alarmChannelMessage.getAlarmType());
71 deviceAlarm.setAlarmPriority("1"); 76 deviceAlarm.setAlarmPriority("1");
72 - deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601()); 77 + deviceAlarm.setAlarmTime(DateUtil.getNow());
73 deviceAlarm.setLongitude(0); 78 deviceAlarm.setLongitude(0);
74 deviceAlarm.setLatitude(0); 79 deviceAlarm.setLatitude(0);
75 80
76 if (ObjectUtils.isEmpty(gbId)) { 81 if (ObjectUtils.isEmpty(gbId)) {
77 - // 发送给所有的上级  
78 - List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true);  
79 - if (parentPlatforms.size() > 0) {  
80 - for (ParentPlatform parentPlatform : parentPlatforms) { 82 + if (userSetting.getSendToPlatformsWhenIdLost()) {
  83 + // 发送给所有的上级
  84 + List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true);
  85 + if (parentPlatforms.size() > 0) {
  86 + for (ParentPlatform parentPlatform : parentPlatforms) {
  87 + try {
  88 + deviceAlarm.setChannelId(parentPlatform.getDeviceGBId());
  89 + commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);
  90 + } catch (SipException | InvalidArgumentException | ParseException e) {
  91 + logger.error("[命令发送失败] 国标级联 发送报警: {}", e.getMessage());
  92 + }
  93 + }
  94 + }
  95 + }else {
  96 + // 获取开启了消息推送的设备和平台
  97 + List<ParentPlatform> parentPlatforms = storage.queryEnablePlatformListWithAsMessageChannel();
  98 + if (parentPlatforms.size() > 0) {
  99 + for (ParentPlatform parentPlatform : parentPlatforms) {
  100 + try {
  101 + deviceAlarm.setChannelId(parentPlatform.getDeviceGBId());
  102 + commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);
  103 + } catch (SipException | InvalidArgumentException | ParseException e) {
  104 + logger.error("[命令发送失败] 国标级联 发送报警: {}", e.getMessage());
  105 + }
  106 + }
  107 + }
  108 +
  109 + }
  110 + // 获取开启了消息推送的设备和平台
  111 + List<Device> devices = storage.queryDeviceWithAsMessageChannel();
  112 + if (devices.size() > 0) {
  113 + for (Device device : devices) {
81 try { 114 try {
82 - commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm);  
83 - } catch (SipException | InvalidArgumentException | ParseException e) {  
84 - logger.error("[命令发送失败] 国标级联 发送报警: {}", e.getMessage()); 115 + deviceAlarm.setChannelId(device.getDeviceId());
  116 + commander.sendAlarmMessage(device, deviceAlarm);
  117 + } catch (InvalidArgumentException | SipException | ParseException e) {
  118 + logger.error("[命令发送失败] 发送报警: {}", e.getMessage());
85 } 119 }
86 } 120 }
87 } 121 }
  122 +
88 }else { 123 }else {
89 Device device = storage.queryVideoDevice(gbId); 124 Device device = storage.queryVideoDevice(gbId);
90 ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId); 125 ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId);
@@ -105,6 +140,7 @@ public class RedisAlarmMsgListener implements MessageListener { @@ -105,6 +140,7 @@ public class RedisAlarmMsgListener implements MessageListener {
105 } 140 }
106 } 141 }
107 }catch (Exception e) { 142 }catch (Exception e) {
  143 + logger.error("未处理的异常 ", e);
108 logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage()); 144 logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage());
109 } 145 }
110 } 146 }
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java
@@ -202,7 +202,8 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -202,7 +202,8 @@ public class RedisGbPlayMsgListener implements MessageListener {
202 202
203 } 203 }
204 }catch (Exception e) { 204 }catch (Exception e) {
205 - logger.warn("[RedisGbPlayMsg] 发现未处理的异常, {}",e.getMessage()); 205 + logger.warn("[RedisGbPlayMsg] 发现未处理的异常, \r\n{}", JSON.toJSONString(message));
  206 + logger.error("[RedisGbPlayMsg] 异常内容: ", e);
206 } 207 }
207 } 208 }
208 }); 209 });
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java
@@ -53,7 +53,8 @@ public class RedisGpsMsgListener implements MessageListener { @@ -53,7 +53,8 @@ public class RedisGpsMsgListener implements MessageListener {
53 // 只是放入redis缓存起来 53 // 只是放入redis缓存起来
54 redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo); 54 redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo);
55 }catch (Exception e) { 55 }catch (Exception e) {
56 - logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage()); 56 + logger.warn("[REDIS的ALARM通知] 发现未处理的异常, \r\n{}", JSON.toJSONString(message));
  57 + logger.error("[REDIS的ALARM通知] 异常内容: ", e);
57 } 58 }
58 } 59 }
59 }); 60 });
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java
@@ -58,7 +58,8 @@ public class RedisPushStreamResponseListener implements MessageListener { @@ -58,7 +58,8 @@ public class RedisPushStreamResponseListener implements MessageListener {
58 responseEvents.get(response.getApp() + response.getStream()).run(response); 58 responseEvents.get(response.getApp() + response.getStream()).run(response);
59 } 59 }
60 }catch (Exception e) { 60 }catch (Exception e) {
61 - logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage()); 61 + logger.warn("[REDIS消息-请求推流结果] 发现未处理的异常, \r\n{}", JSON.toJSONString(message));
  62 + logger.error("[REDIS消息-请求推流结果] 异常内容: ", e);
62 } 63 }
63 } 64 }
64 }); 65 });
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java
@@ -95,7 +95,8 @@ public class RedisPushStreamStatusListMsgListener implements MessageListener { @@ -95,7 +95,8 @@ public class RedisPushStreamStatusListMsgListener implements MessageListener {
95 gbStreamService.updateGbIdOrName(streamPushItemForUpdate); 95 gbStreamService.updateGbIdOrName(streamPushItemForUpdate);
96 } 96 }
97 }catch (Exception e) { 97 }catch (Exception e) {
98 - logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage()); 98 + logger.warn("[REDIS消息-推流设备列表更新] 发现未处理的异常, \r\n{}", JSON.toJSONString(message));
  99 + logger.error("[REDIS消息-推流设备列表更新] 异常内容: ", e);
99 } 100 }
100 } 101 }
101 }); 102 });
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java
@@ -79,7 +79,8 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic @@ -79,7 +79,8 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic
79 streamPushService.online(statusChangeFromPushStream.getOnlineStreams()); 79 streamPushService.online(statusChangeFromPushStream.getOnlineStreams());
80 } 80 }
81 }catch (Exception e) { 81 }catch (Exception e) {
82 - logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage()); 82 + logger.warn("[REDIS消息-推流设备状态变化] 发现未处理的异常, \r\n{}", JSON.toJSONString(message));
  83 + logger.error("[REDIS消息-推流设备状态变化] 异常内容: ", e);
83 } 84 }
84 } 85 }
85 }); 86 });
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java
@@ -82,7 +82,8 @@ public class RedisStreamMsgListener implements MessageListener { @@ -82,7 +82,8 @@ public class RedisStreamMsgListener implements MessageListener {
82 zlmMediaListManager.removeMedia(app, stream); 82 zlmMediaListManager.removeMedia(app, stream);
83 } 83 }
84 }catch (Exception e) { 84 }catch (Exception e) {
85 - logger.warn("[REDIS的ALARM通知] 发现未处理的异常, {}",e.getMessage()); 85 + logger.warn("[REDIS消息-流变化] 发现未处理的异常, \r\n{}", JSON.toJSONString(message));
  86 + logger.error("[REDIS消息-流变化] 异常内容: ", e);
86 } 87 }
87 } 88 }
88 }); 89 });
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java
@@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
5 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 5 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
6 import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; 6 import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo;
7 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; 7 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
  8 +import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend;
8 import com.github.pagehelper.PageInfo; 9 import com.github.pagehelper.PageInfo;
9 10
10 import java.util.List; 11 import java.util.List;
@@ -58,7 +59,7 @@ public interface IVideoManagerStorage { @@ -58,7 +59,7 @@ public interface IVideoManagerStorage {
58 */ 59 */
59 public PageInfo<DeviceChannel> queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, Boolean catalogUnderDevice, int page, int count); 60 public PageInfo<DeviceChannel> queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, Boolean catalogUnderDevice, int page, int count);
60 61
61 - public List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit,List<String> channelIds); 62 + public List<DeviceChannelExtend> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, List<String> channelIds, String query, Boolean hasSubChannel, Boolean online, int start, int limit);
62 63
63 64
64 /** 65 /**
@@ -374,4 +375,10 @@ public interface IVideoManagerStorage { @@ -374,4 +375,10 @@ public interface IVideoManagerStorage {
374 void cleanContentForPlatform(String serverGBId); 375 void cleanContentForPlatform(String serverGBId);
375 376
376 List<DeviceChannel> queryChannelWithCatalog(String serverGBId); 377 List<DeviceChannel> queryChannelWithCatalog(String serverGBId);
  378 +
  379 + List<DeviceChannelExtend> queryChannelsByDeviceId(String serial, List<String> channelIds, Boolean online);
  380 +
  381 + List<ParentPlatform> queryEnablePlatformListWithAsMessageChannel();
  382 +
  383 + List<Device> queryDeviceWithAsMessageChannel();
377 } 384 }
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
@@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
5 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannelInPlatform; 5 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannelInPlatform;
6 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo; 6 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
7 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; 7 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
  8 +import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend;
8 import org.apache.ibatis.annotations.*; 9 import org.apache.ibatis.annotations.*;
9 import org.springframework.stereotype.Repository; 10 import org.springframework.stereotype.Repository;
10 11
@@ -82,7 +83,56 @@ public interface DeviceChannelMapper { @@ -82,7 +83,56 @@ public interface DeviceChannelMapper {
82 "</foreach> </if>" + 83 "</foreach> </if>" +
83 "ORDER BY dc.channelId " + 84 "ORDER BY dc.channelId " +
84 " </script>"}) 85 " </script>"})
85 - List<DeviceChannel> queryChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online,List<String> channelIds); 86 + List<DeviceChannel> queryChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online, List<String> channelIds);
  87 +
  88 + @Select(value = {" <script>" +
  89 + "SELECT " +
  90 + "dc.*, " +
  91 + "de.name as deviceName, " +
  92 + "de.online as deviceOnline " +
  93 + "from " +
  94 + "device_channel dc " +
  95 + "LEFT JOIN device de ON dc.deviceId = de.deviceId " +
  96 + "WHERE 1=1" +
  97 + " <if test='deviceId != null'> AND dc.deviceId = #{deviceId} </if> " +
  98 + " <if test='query != null'> AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%')</if> " +
  99 + " <if test='parentChannelId != null'> AND dc.parentId=#{parentChannelId} </if> " +
  100 + " <if test='online == true' > AND dc.status=1</if>" +
  101 + " <if test='online == false' > AND dc.status=0</if>" +
  102 + " <if test='hasSubChannel == true' > AND dc.subCount > 0 </if>" +
  103 + " <if test='hasSubChannel == false' > AND dc.subCount = 0 </if>" +
  104 + "<if test='channelIds != null'> AND dc.channelId in <foreach item='item' index='index' collection='channelIds' open='(' separator=',' close=')'>" +
  105 + "#{item} " +
  106 + "</foreach> </if>" +
  107 + "ORDER BY dc.channelId ASC" +
  108 + " </script>"})
  109 + List<DeviceChannelExtend> queryChannelsWithDeviceInfo(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online, List<String> channelIds);
  110 +
  111 +
  112 + @Select(value = {" <script>" +
  113 + "SELECT " +
  114 + "dc.*, " +
  115 + "de.name as deviceName, " +
  116 + "de.online as deviceOnline " +
  117 + "from " +
  118 + "device_channel dc " +
  119 + "LEFT JOIN device de ON dc.deviceId = de.deviceId " +
  120 + "WHERE 1=1" +
  121 + " <if test='deviceId != null'> AND dc.deviceId = #{deviceId} </if> " +
  122 + " <if test='query != null'> AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%')</if> " +
  123 + " <if test='parentChannelId != null'> AND dc.parentId=#{parentChannelId} </if> " +
  124 + " <if test='online == true' > AND dc.status=1</if>" +
  125 + " <if test='online == false' > AND dc.status=0</if>" +
  126 + " <if test='hasSubChannel == true' > AND dc.subCount > 0 </if>" +
  127 + " <if test='hasSubChannel == false' > AND dc.subCount = 0 </if>" +
  128 + "<if test='channelIds != null'> AND dc.channelId in <foreach item='item' index='index' collection='channelIds' open='(' separator=',' close=')'>" +
  129 + "#{item} " +
  130 + "</foreach> </if>" +
  131 + "ORDER BY dc.channelId ASC " +
  132 + "Limit #{limit} OFFSET #{start}" +
  133 + " </script>"})
  134 + List<DeviceChannelExtend> queryChannelsByDeviceIdWithStartAndLimit(String deviceId,List<String> channelIds, String parentChannelId, String query,
  135 + Boolean hasSubChannel, Boolean online, int start, int limit);
86 136
87 @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND channelId=#{channelId}") 137 @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND channelId=#{channelId}")
88 DeviceChannel queryChannel(String deviceId, String channelId); 138 DeviceChannel queryChannel(String deviceId, String channelId);
@@ -245,28 +295,6 @@ public interface DeviceChannelMapper { @@ -245,28 +295,6 @@ public interface DeviceChannelMapper {
245 int batchUpdate(List<DeviceChannel> updateChannels); 295 int batchUpdate(List<DeviceChannel> updateChannels);
246 296
247 297
248 - @Select(value = {" <script>" +  
249 - "SELECT " +  
250 - "dc1.* " +  
251 - "from " +  
252 - "device_channel dc1 " +  
253 - "WHERE " +  
254 - "dc1.deviceId = #{deviceId} " +  
255 - " <if test='query != null'> AND (dc1.channelId LIKE concat('%',#{query},'%') OR dc1.name LIKE concat('%',#{query},'%') OR dc1.name LIKE concat('%',#{query},'%'))</if> " +  
256 - " <if test='parentChannelId != null'> AND dc1.parentId=#{parentChannelId} </if> " +  
257 - " <if test='online == true' > AND dc1.status=1</if>" +  
258 - " <if test='online == false' > AND dc1.status=0</if>" +  
259 - " <if test='hasSubChannel == true' > AND dc1.subCount >0</if>" +  
260 - " <if test='hasSubChannel == false' > AND dc1.subCount=0</if>" +  
261 - "<if test='channelIds != null'> AND dc1.channelId in <foreach item='item' index='index' collection='channelIds' open='(' separator=',' close=')'>" +  
262 - "#{item} " +  
263 - "</foreach> </if>" +  
264 - "ORDER BY dc1.channelId ASC " +  
265 - "Limit #{limit} OFFSET #{start}" +  
266 - " </script>"})  
267 - List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String parentChannelId, String query,  
268 - Boolean hasSubChannel, Boolean online, int start, int limit,List<String> channelIds);  
269 -  
270 @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND status=1") 298 @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND status=1")
271 List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId); 299 List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId);
272 300
@@ -316,10 +344,10 @@ public interface DeviceChannelMapper { @@ -316,10 +344,10 @@ public interface DeviceChannelMapper {
316 "select * " + 344 "select * " +
317 "from device_channel " + 345 "from device_channel " +
318 "where deviceId=#{deviceId}" + 346 "where deviceId=#{deviceId}" +
319 - " <if test='parentId != null and length != null' > and parentId = #{parentId} or left(channelId, #{parentId.length()}) = #{parentId} and length(channelId)=#{length} </if>" + 347 + " <if test='parentId != null and length != null' > and parentId = #{parentId} or left(channelId, LENGTH(#{parentId})) = #{parentId} and length(channelId)=#{length} </if>" +
320 " <if test='parentId == null and length != null' > and parentId = #{parentId} or length(channelId)=#{length} </if>" + 348 " <if test='parentId == null and length != null' > and parentId = #{parentId} or length(channelId)=#{length} </if>" +
321 " <if test='parentId == null and length == null' > and parentId = #{parentId} </if>" + 349 " <if test='parentId == null and length == null' > and parentId = #{parentId} </if>" +
322 - " <if test='parentId != null and length == null' > and parentId = #{parentId} or left(channelId, #{parentId.length()}) = #{parentId} </if>" + 350 + " <if test='parentId != null and length == null' > and parentId = #{parentId} or left(channelId, LENGTH(#{parentId})) = #{parentId} </if>" +
323 " </script>"}) 351 " </script>"})
324 List<DeviceChannel> getChannelsWithCivilCodeAndLength(String deviceId, String parentId, Integer length); 352 List<DeviceChannel> getChannelsWithCivilCodeAndLength(String deviceId, String parentId, Integer length);
325 353
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
@@ -39,9 +39,12 @@ public interface DeviceMapper { @@ -39,9 +39,12 @@ public interface DeviceMapper {
39 "mobilePositionSubmissionInterval," + 39 "mobilePositionSubmissionInterval," +
40 "subscribeCycleForAlarm," + 40 "subscribeCycleForAlarm," +
41 "ssrcCheck," + 41 "ssrcCheck," +
  42 + "asMessageChannel," +
42 "geoCoordSys," + 43 "geoCoordSys," +
43 "treeType," + 44 "treeType," +
44 - "online" + 45 + "online," +
  46 + "mediaServerId," +
  47 + "(SELECT count(0) FROM device_channel WHERE deviceId=device.deviceId) as channelCount "+
45 " FROM device WHERE deviceId = #{deviceId}") 48 " FROM device WHERE deviceId = #{deviceId}")
46 Device getDeviceByDeviceId(String deviceId); 49 Device getDeviceByDeviceId(String deviceId);
47 50
@@ -70,6 +73,7 @@ public interface DeviceMapper { @@ -70,6 +73,7 @@ public interface DeviceMapper {
70 "mobilePositionSubmissionInterval," + 73 "mobilePositionSubmissionInterval," +
71 "subscribeCycleForAlarm," + 74 "subscribeCycleForAlarm," +
72 "ssrcCheck," + 75 "ssrcCheck," +
  76 + "asMessageChannel," +
73 "geoCoordSys," + 77 "geoCoordSys," +
74 "treeType," + 78 "treeType," +
75 "online" + 79 "online" +
@@ -98,6 +102,7 @@ public interface DeviceMapper { @@ -98,6 +102,7 @@ public interface DeviceMapper {
98 "#{mobilePositionSubmissionInterval}," + 102 "#{mobilePositionSubmissionInterval}," +
99 "#{subscribeCycleForAlarm}," + 103 "#{subscribeCycleForAlarm}," +
100 "#{ssrcCheck}," + 104 "#{ssrcCheck}," +
  105 + "#{asMessageChannel}," +
101 "#{geoCoordSys}," + 106 "#{geoCoordSys}," +
102 "#{treeType}," + 107 "#{treeType}," +
103 "#{online}" + 108 "#{online}" +
@@ -152,9 +157,11 @@ public interface DeviceMapper { @@ -152,9 +157,11 @@ public interface DeviceMapper {
152 "mobilePositionSubmissionInterval," + 157 "mobilePositionSubmissionInterval," +
153 "subscribeCycleForAlarm," + 158 "subscribeCycleForAlarm," +
154 "ssrcCheck," + 159 "ssrcCheck," +
  160 + "asMessageChannel," +
155 "geoCoordSys," + 161 "geoCoordSys," +
156 "treeType," + 162 "treeType," +
157 "online," + 163 "online," +
  164 + "mediaServerId," +
158 "(SELECT count(0) FROM device_channel WHERE deviceId=de.deviceId) as channelCount FROM device de" + 165 "(SELECT count(0) FROM device_channel WHERE deviceId=de.deviceId) as channelCount FROM device de" +
159 "<if test=\"online != null\"> where online=${online}</if>"+ 166 "<if test=\"online != null\"> where online=${online}</if>"+
160 " </script>" 167 " </script>"
@@ -164,9 +171,6 @@ public interface DeviceMapper { @@ -164,9 +171,6 @@ public interface DeviceMapper {
164 @Delete("DELETE FROM device WHERE deviceId=#{deviceId}") 171 @Delete("DELETE FROM device WHERE deviceId=#{deviceId}")
165 int del(String deviceId); 172 int del(String deviceId);
166 173
167 - @Update("UPDATE device SET online=0")  
168 - int outlineForAll();  
169 -  
170 @Select("SELECT " + 174 @Select("SELECT " +
171 "deviceId, " + 175 "deviceId, " +
172 "coalesce(custom_name, name) as name, " + 176 "coalesce(custom_name, name) as name, " +
@@ -192,6 +196,7 @@ public interface DeviceMapper { @@ -192,6 +196,7 @@ public interface DeviceMapper {
192 "mobilePositionSubmissionInterval," + 196 "mobilePositionSubmissionInterval," +
193 "subscribeCycleForAlarm," + 197 "subscribeCycleForAlarm," +
194 "ssrcCheck," + 198 "ssrcCheck," +
  199 + "asMessageChannel," +
195 "geoCoordSys," + 200 "geoCoordSys," +
196 "treeType," + 201 "treeType," +
197 "online " + 202 "online " +
@@ -222,6 +227,7 @@ public interface DeviceMapper { @@ -222,6 +227,7 @@ public interface DeviceMapper {
222 "mobilePositionSubmissionInterval," + 227 "mobilePositionSubmissionInterval," +
223 "subscribeCycleForAlarm," + 228 "subscribeCycleForAlarm," +
224 "ssrcCheck," + 229 "ssrcCheck," +
  230 + "asMessageChannel," +
225 "geoCoordSys," + 231 "geoCoordSys," +
226 "treeType," + 232 "treeType," +
227 "online" + 233 "online" +
@@ -243,12 +249,13 @@ public interface DeviceMapper { @@ -243,12 +249,13 @@ public interface DeviceMapper {
243 "<if test=\"mobilePositionSubmissionInterval != null\">, mobilePositionSubmissionInterval=#{mobilePositionSubmissionInterval}</if>" + 249 "<if test=\"mobilePositionSubmissionInterval != null\">, mobilePositionSubmissionInterval=#{mobilePositionSubmissionInterval}</if>" +
244 "<if test=\"subscribeCycleForAlarm != null\">, subscribeCycleForAlarm=#{subscribeCycleForAlarm}</if>" + 250 "<if test=\"subscribeCycleForAlarm != null\">, subscribeCycleForAlarm=#{subscribeCycleForAlarm}</if>" +
245 "<if test=\"ssrcCheck != null\">, ssrcCheck=#{ssrcCheck}</if>" + 251 "<if test=\"ssrcCheck != null\">, ssrcCheck=#{ssrcCheck}</if>" +
  252 + "<if test=\"asMessageChannel != null\">, asMessageChannel=#{asMessageChannel}</if>" +
246 "<if test=\"geoCoordSys != null\">, geoCoordSys=#{geoCoordSys}</if>" + 253 "<if test=\"geoCoordSys != null\">, geoCoordSys=#{geoCoordSys}</if>" +
247 "<if test=\"treeType != null\">, treeType=#{treeType}</if>" + 254 "<if test=\"treeType != null\">, treeType=#{treeType}</if>" +
248 "<if test=\"mediaServerId != null\">, mediaServerId=#{mediaServerId}</if>" + 255 "<if test=\"mediaServerId != null\">, mediaServerId=#{mediaServerId}</if>" +
249 "WHERE deviceId=#{deviceId}"+ 256 "WHERE deviceId=#{deviceId}"+
250 " </script>"}) 257 " </script>"})
251 - int updateCustom(Device device); 258 + void updateCustom(Device device);
252 259
253 @Insert("INSERT INTO device (" + 260 @Insert("INSERT INTO device (" +
254 "deviceId, " + 261 "deviceId, " +
@@ -259,9 +266,11 @@ public interface DeviceMapper { @@ -259,9 +266,11 @@ public interface DeviceMapper {
259 "updateTime," + 266 "updateTime," +
260 "charset," + 267 "charset," +
261 "ssrcCheck," + 268 "ssrcCheck," +
  269 + "asMessageChannel," +
262 "geoCoordSys," + 270 "geoCoordSys," +
263 "treeType," + 271 "treeType," +
264 - "online" + 272 + "online," +
  273 + "mediaServerId" +
265 ") VALUES (" + 274 ") VALUES (" +
266 "#{deviceId}," + 275 "#{deviceId}," +
267 "#{name}," + 276 "#{name}," +
@@ -271,9 +280,11 @@ public interface DeviceMapper { @@ -271,9 +280,11 @@ public interface DeviceMapper {
271 "#{updateTime}," + 280 "#{updateTime}," +
272 "#{charset}," + 281 "#{charset}," +
273 "#{ssrcCheck}," + 282 "#{ssrcCheck}," +
  283 + "#{asMessageChannel}," +
274 "#{geoCoordSys}," + 284 "#{geoCoordSys}," +
275 "#{treeType}," + 285 "#{treeType}," +
276 - "#{online}" + 286 + "#{online}," +
  287 + "#{mediaServerId}" +
277 ")") 288 ")")
278 void addCustomDevice(Device device); 289 void addCustomDevice(Device device);
279 290
@@ -282,4 +293,7 @@ public interface DeviceMapper { @@ -282,4 +293,7 @@ public interface DeviceMapper {
282 293
283 @Select("select * from device") 294 @Select("select * from device")
284 List<Device> getAll(); 295 List<Device> getAll();
  296 +
  297 + @Select("select * from device where asMessageChannel = 1")
  298 + List<Device> queryDeviceWithAsMessageChannel();
285 } 299 }
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
@@ -15,10 +15,10 @@ import java.util.List; @@ -15,10 +15,10 @@ import java.util.List;
15 public interface ParentPlatformMapper { 15 public interface ParentPlatformMapper {
16 16
17 @Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp, " + 17 @Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp, " +
18 - " devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, " + 18 + " devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, asMessageChannel, " +
19 " status, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime, treeType) " + 19 " status, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime, treeType) " +
20 " VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIP}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " + 20 " VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIP}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " +
21 - " #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, " + 21 + " #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, #{asMessageChannel}, " +
22 " #{status}, #{startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{treeType})") 22 " #{status}, #{startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{treeType})")
23 int addParentPlatform(ParentPlatform parentPlatform); 23 int addParentPlatform(ParentPlatform parentPlatform);
24 24
@@ -40,6 +40,7 @@ public interface ParentPlatformMapper { @@ -40,6 +40,7 @@ public interface ParentPlatformMapper {
40 "characterSet=#{characterSet}, " + 40 "characterSet=#{characterSet}, " +
41 "ptz=#{ptz}, " + 41 "ptz=#{ptz}, " +
42 "rtcp=#{rtcp}, " + 42 "rtcp=#{rtcp}, " +
  43 + "asMessageChannel=#{asMessageChannel}, " +
43 "status=#{status}, " + 44 "status=#{status}, " +
44 "startOfflinePush=#{startOfflinePush}, " + 45 "startOfflinePush=#{startOfflinePush}, " +
45 "catalogGroup=#{catalogGroup}, " + 46 "catalogGroup=#{catalogGroup}, " +
@@ -68,9 +69,12 @@ public interface ParentPlatformMapper { @@ -68,9 +69,12 @@ public interface ParentPlatformMapper {
68 "FROM parent_platform pp ") 69 "FROM parent_platform pp ")
69 List<ParentPlatform> getParentPlatformList(); 70 List<ParentPlatform> getParentPlatformList();
70 71
71 - @Select("SELECT * FROM parent_platform WHERE enable=#{enable}") 72 + @Select("SELECT * FROM parent_platform WHERE enable=#{enable} ")
72 List<ParentPlatform> getEnableParentPlatformList(boolean enable); 73 List<ParentPlatform> getEnableParentPlatformList(boolean enable);
73 74
  75 + @Select("SELECT * FROM parent_platform WHERE enable=1 and asMessageChannel = 1")
  76 + List<ParentPlatform> queryEnablePlatformListWithAsMessageChannel();
  77 +
74 @Select("SELECT * FROM parent_platform WHERE serverGBId=#{platformGbId}") 78 @Select("SELECT * FROM parent_platform WHERE serverGBId=#{platformGbId}")
75 ParentPlatform getParentPlatByServerGBId(String platformGbId); 79 ParentPlatform getParentPlatByServerGBId(String platformGbId);
76 80
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -177,12 +177,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -177,12 +177,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
177 @Override 177 @Override
178 public boolean startDownload(StreamInfo stream, String callId) { 178 public boolean startDownload(StreamInfo stream, String callId) {
179 boolean result; 179 boolean result;
  180 + String key=String.format("%S_%s_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,
  181 + userSetting.getServerId(), stream.getMediaServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId);
180 if (stream.getProgress() == 1) { 182 if (stream.getProgress() == 1) {
181 - result = RedisUtil.set(String.format("%S_%s_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,  
182 - userSetting.getServerId(), stream.getMediaServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream); 183 + logger.debug("添加下载缓存==已完成下载=》{}",key);
  184 + result = RedisUtil.set(key, stream);
183 }else { 185 }else {
184 - result = RedisUtil.set(String.format("%S_%s_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,  
185 - userSetting.getServerId(), stream.getMediaServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream, 60*60); 186 + logger.debug("添加下载缓存==未完成下载=》{}",key);
  187 + result = RedisUtil.set(key, stream, 60*60);
186 } 188 }
187 return result; 189 return result;
188 } 190 }
@@ -617,7 +619,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -617,7 +619,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
617 stream, 619 stream,
618 callId 620 callId
619 ); 621 );
620 - List<Object> streamInfoScan = RedisUtil.scan(key); 622 + List<Object> streamInfoScan = RedisUtil.scan2(key);
621 if (streamInfoScan.size() > 0) { 623 if (streamInfoScan.size() > 0) {
622 return (StreamInfo) RedisUtil.get((String) streamInfoScan.get(0)); 624 return (StreamInfo) RedisUtil.get((String) streamInfoScan.get(0));
623 }else { 625 }else {
@@ -855,7 +857,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -855,7 +857,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
855 857
856 @Override 858 @Override
857 public void sendAlarmMsg(AlarmChannelMessage msg) { 859 public void sendAlarmMsg(AlarmChannelMessage msg) {
858 - String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE; 860 + // 此消息用于对接第三方服务下级来的消息内容
  861 + String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM;
859 logger.info("[redis发送通知] 报警{}: {}", key, JSON.toJSON(msg)); 862 logger.info("[redis发送通知] 报警{}: {}", key, JSON.toJSON(msg));
860 RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg)); 863 RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
861 } 864 }
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
@@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.storager.dao.*; @@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.storager.dao.*;
13 import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; 13 import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo;
14 import com.genersoft.iot.vmp.utils.DateUtil; 14 import com.genersoft.iot.vmp.utils.DateUtil;
15 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; 15 import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
  16 +import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend;
16 import com.github.pagehelper.PageHelper; 17 import com.github.pagehelper.PageHelper;
17 import com.github.pagehelper.PageInfo; 18 import com.github.pagehelper.PageInfo;
18 import org.slf4j.Logger; 19 import org.slf4j.Logger;
@@ -189,7 +190,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -189,7 +190,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
189 dataSourceTransactionManager.commit(transactionStatus); //手动提交 190 dataSourceTransactionManager.commit(transactionStatus); //手动提交
190 return true; 191 return true;
191 }catch (Exception e) { 192 }catch (Exception e) {
192 - e.printStackTrace(); 193 + logger.error("未处理的异常 ", e);
193 dataSourceTransactionManager.rollback(transactionStatus); 194 dataSourceTransactionManager.rollback(transactionStatus);
194 return false; 195 return false;
195 } 196 }
@@ -305,7 +306,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -305,7 +306,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
305 } 306 }
306 return true; 307 return true;
307 }catch (Exception e) { 308 }catch (Exception e) {
308 - e.printStackTrace(); 309 + logger.error("未处理的异常 ", e);
309 dataSourceTransactionManager.rollback(transactionStatus); 310 dataSourceTransactionManager.rollback(transactionStatus);
310 return false; 311 return false;
311 } 312 }
@@ -359,8 +360,8 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -359,8 +360,8 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
359 } 360 }
360 361
361 @Override 362 @Override
362 - public List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit,List<String> channelIds) {  
363 - return deviceChannelMapper.queryChannelsByDeviceIdWithStartAndLimit(deviceId, null, query, hasSubChannel, online, start, limit,channelIds); 363 + public List<DeviceChannelExtend> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, List<String> channelIds, String query, Boolean hasSubChannel, Boolean online, int start, int limit) {
  364 + return deviceChannelMapper.queryChannelsByDeviceIdWithStartAndLimit(deviceId, channelIds, null, query, hasSubChannel, online, start, limit);
364 } 365 }
365 366
366 367
@@ -370,6 +371,11 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -370,6 +371,11 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
370 } 371 }
371 372
372 @Override 373 @Override
  374 + public List<DeviceChannelExtend> queryChannelsByDeviceId(String deviceId, List<String> channelIds, Boolean online) {
  375 + return deviceChannelMapper.queryChannelsWithDeviceInfo(deviceId, null,null, null, online,channelIds);
  376 + }
  377 +
  378 + @Override
373 public PageInfo<DeviceChannel> querySubChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online, int page, int count) { 379 public PageInfo<DeviceChannel> querySubChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online, int page, int count) {
374 PageHelper.startPage(page, count); 380 PageHelper.startPage(page, count);
375 List<DeviceChannel> all = deviceChannelMapper.queryChannels(deviceId, parentChannelId, query, hasSubChannel, online,null); 381 List<DeviceChannel> all = deviceChannelMapper.queryChannels(deviceId, parentChannelId, query, hasSubChannel, online,null);
@@ -512,6 +518,16 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -512,6 +518,16 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
512 } 518 }
513 519
514 @Override 520 @Override
  521 + public List<ParentPlatform> queryEnablePlatformListWithAsMessageChannel() {
  522 + return platformMapper.queryEnablePlatformListWithAsMessageChannel();
  523 + }
  524 +
  525 + @Override
  526 + public List<Device> queryDeviceWithAsMessageChannel() {
  527 + return deviceMapper.queryDeviceWithAsMessageChannel();
  528 + }
  529 +
  530 + @Override
515 public void outlineForAllParentPlatform() { 531 public void outlineForAllParentPlatform() {
516 platformMapper.outlineForAllParentPlatform(); 532 platformMapper.outlineForAllParentPlatform();
517 } 533 }
src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java
@@ -45,7 +45,6 @@ public class DateUtil { @@ -45,7 +45,6 @@ public class DateUtil {
45 45
46 public static String ISO8601Toyyyy_MM_dd_HH_mm_ss(String formatTime) { 46 public static String ISO8601Toyyyy_MM_dd_HH_mm_ss(String formatTime) {
47 return formatter.format(formatterCompatibleISO8601.parse(formatTime)); 47 return formatter.format(formatterCompatibleISO8601.parse(formatTime));
48 -  
49 } 48 }
50 49
51 /** 50 /**
src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java
@@ -881,7 +881,13 @@ public class RedisUtil { @@ -881,7 +881,13 @@ public class RedisUtil {
881 881
882 return new ArrayList<>(resultKeys); 882 return new ArrayList<>(resultKeys);
883 } 883 }
884 - 884 + public static List<Object> scan2(String query) {
  885 + if (redisTemplate == null) {
  886 + redisTemplate = SpringBeanFactory.getBean("redisTemplate");
  887 + }
  888 + Set<String> keys = redisTemplate.keys(query);
  889 + return new ArrayList<>(keys);
  890 + }
885 // ============================== 消息发送与订阅 ============================== 891 // ============================== 消息发送与订阅 ==============================
886 public static void convertAndSend(String channel, JSONObject msg) { 892 public static void convertAndSend(String channel, JSONObject msg) {
887 if (redisTemplate == null) { 893 if (redisTemplate == null) {
src/main/java/com/genersoft/iot/vmp/vmanager/bean/WVPResult.java
@@ -28,6 +28,10 @@ public class WVPResult&lt;T&gt; implements Cloneable{ @@ -28,6 +28,10 @@ public class WVPResult&lt;T&gt; implements Cloneable{
28 return new WVPResult<>(ErrorCode.SUCCESS.getCode(), msg, t); 28 return new WVPResult<>(ErrorCode.SUCCESS.getCode(), msg, t);
29 } 29 }
30 30
  31 + public static WVPResult success() {
  32 + return new WVPResult<>(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
  33 + }
  34 +
31 public static <T> WVPResult<T> success(T t) { 35 public static <T> WVPResult<T> success(T t) {
32 return success(t, ErrorCode.SUCCESS.getMsg()); 36 return success(t, ErrorCode.SUCCESS.getMsg());
33 } 37 }
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
@@ -30,7 +30,7 @@ import java.util.UUID; @@ -30,7 +30,7 @@ import java.util.UUID;
30 * 位置信息管理 30 * 位置信息管理
31 */ 31 */
32 @Tag(name = "位置信息管理") 32 @Tag(name = "位置信息管理")
33 -@CrossOrigin 33 +
34 @RestController 34 @RestController
35 @RequestMapping("/api/position") 35 @RequestMapping("/api/position")
36 public class MobilePositionController { 36 public class MobilePositionController {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/SseController/SseController.java
@@ -17,7 +17,7 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; @@ -17,7 +17,7 @@ import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
17 * @data: 2021-01-20 17 * @data: 2021-01-20
18 */ 18 */
19 @Tag(name = "SSE推送") 19 @Tag(name = "SSE推送")
20 -@CrossOrigin 20 +
21 @Controller 21 @Controller
22 @RequestMapping("/api") 22 @RequestMapping("/api")
23 public class SseController { 23 public class SseController {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java
@@ -6,35 +6,28 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; @@ -6,35 +6,28 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
9 -import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookListener;  
10 import com.genersoft.iot.vmp.service.IDeviceAlarmService; 9 import com.genersoft.iot.vmp.service.IDeviceAlarmService;
11 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 10 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
12 import com.genersoft.iot.vmp.utils.DateUtil; 11 import com.genersoft.iot.vmp.utils.DateUtil;
13 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 12 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
14 -import com.genersoft.iot.vmp.vmanager.bean.WVPResult;  
15 import com.github.pagehelper.PageInfo; 13 import com.github.pagehelper.PageInfo;
16 import io.swagger.v3.oas.annotations.Operation; 14 import io.swagger.v3.oas.annotations.Operation;
17 import io.swagger.v3.oas.annotations.Parameter; 15 import io.swagger.v3.oas.annotations.Parameter;
18 -import io.swagger.v3.oas.annotations.responses.ApiResponse;  
19 import io.swagger.v3.oas.annotations.tags.Tag; 16 import io.swagger.v3.oas.annotations.tags.Tag;
20 import org.slf4j.Logger; 17 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory; 18 import org.slf4j.LoggerFactory;
22 import org.springframework.beans.factory.annotation.Autowired; 19 import org.springframework.beans.factory.annotation.Autowired;
23 -import org.springframework.http.HttpStatus;  
24 -import org.springframework.http.ResponseEntity;  
25 import org.springframework.util.ObjectUtils; 20 import org.springframework.util.ObjectUtils;
26 -import org.springframework.util.StringUtils;  
27 import org.springframework.web.bind.annotation.*; 21 import org.springframework.web.bind.annotation.*;
28 22
29 import javax.sip.InvalidArgumentException; 23 import javax.sip.InvalidArgumentException;
30 import javax.sip.SipException; 24 import javax.sip.SipException;
31 import java.text.ParseException; 25 import java.text.ParseException;
32 -import java.time.LocalDateTime;  
33 import java.util.Arrays; 26 import java.util.Arrays;
34 import java.util.List; 27 import java.util.List;
35 28
36 @Tag(name = "报警信息管理") 29 @Tag(name = "报警信息管理")
37 -@CrossOrigin 30 +
38 @RestController 31 @RestController
39 @RequestMapping("/api/alarm") 32 @RequestMapping("/api/alarm")
40 public class AlarmController { 33 public class AlarmController {
@@ -78,11 +71,11 @@ public class AlarmController { @@ -78,11 +71,11 @@ public class AlarmController {
78 if (ObjectUtils.isEmpty(deviceIds)) { 71 if (ObjectUtils.isEmpty(deviceIds)) {
79 deviceIds = null; 72 deviceIds = null;
80 } 73 }
  74 +
81 if (ObjectUtils.isEmpty(time)) { 75 if (ObjectUtils.isEmpty(time)) {
82 time = null; 76 time = null;
83 - }  
84 - if (!DateUtil.verification(time, DateUtil.formatter) ){  
85 - return null; 77 + }else if (!DateUtil.verification(time, DateUtil.formatter) ){
  78 + throw new ControllerException(ErrorCode.ERROR400.getCode(), "time格式为" + DateUtil.PATTERN);
86 } 79 }
87 List<String> deviceIdList = null; 80 List<String> deviceIdList = null;
88 if (deviceIds != null) { 81 if (deviceIds != null) {
@@ -110,7 +103,7 @@ public class AlarmController { @@ -110,7 +103,7 @@ public class AlarmController {
110 deviceAlarm.setAlarmDescription("test"); 103 deviceAlarm.setAlarmDescription("test");
111 deviceAlarm.setAlarmMethod("1"); 104 deviceAlarm.setAlarmMethod("1");
112 deviceAlarm.setAlarmPriority("1"); 105 deviceAlarm.setAlarmPriority("1");
113 - deviceAlarm.setAlarmTime(DateUtil.formatterISO8601.format(LocalDateTime.now())); 106 + deviceAlarm.setAlarmTime(DateUtil.getNow());
114 deviceAlarm.setAlarmType("1"); 107 deviceAlarm.setAlarmType("1");
115 deviceAlarm.setLongitude(115.33333); 108 deviceAlarm.setLongitude(115.33333);
116 deviceAlarm.setLatitude(39.33333); 109 deviceAlarm.setLatitude(39.33333);
@@ -177,16 +170,17 @@ public class AlarmController { @@ -177,16 +170,17 @@ public class AlarmController {
177 if (ObjectUtils.isEmpty(alarmType)) { 170 if (ObjectUtils.isEmpty(alarmType)) {
178 alarmType = null; 171 alarmType = null;
179 } 172 }
  173 +
180 if (ObjectUtils.isEmpty(startTime)) { 174 if (ObjectUtils.isEmpty(startTime)) {
181 startTime = null; 175 startTime = null;
  176 + }else if (!DateUtil.verification(startTime, DateUtil.formatter) ){
  177 + throw new ControllerException(ErrorCode.ERROR400.getCode(), "startTime格式为" + DateUtil.PATTERN);
182 } 178 }
  179 +
183 if (ObjectUtils.isEmpty(endTime)) { 180 if (ObjectUtils.isEmpty(endTime)) {
184 endTime = null; 181 endTime = null;
185 - }  
186 -  
187 -  
188 - if (!DateUtil.verification(startTime, DateUtil.formatter) || !DateUtil.verification(endTime, DateUtil.formatter)){  
189 - throw new ControllerException(ErrorCode.ERROR100.getCode(), "开始时间或结束时间格式有误"); 182 + }else if (!DateUtil.verification(endTime, DateUtil.formatter) ){
  183 + throw new ControllerException(ErrorCode.ERROR400.getCode(), "endTime格式为" + DateUtil.PATTERN);
190 } 184 }
191 185
192 return deviceAlarmService.getAllAlarm(page, count, deviceId, alarmPriority, alarmMethod, 186 return deviceAlarmService.getAllAlarm(page, count, deviceId, alarmPriority, alarmMethod,
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java
@@ -14,7 +14,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; @@ -14,7 +14,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
14 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 14 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
15 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 15 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
16 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 16 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
17 -  
18 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 17 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
19 import io.swagger.v3.oas.annotations.Operation; 18 import io.swagger.v3.oas.annotations.Operation;
20 import io.swagger.v3.oas.annotations.Parameter; 19 import io.swagger.v3.oas.annotations.Parameter;
@@ -22,9 +21,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; @@ -22,9 +21,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
22 import org.slf4j.Logger; 21 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory; 22 import org.slf4j.LoggerFactory;
24 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
25 -import org.springframework.http.ResponseEntity;  
26 import org.springframework.util.ObjectUtils; 24 import org.springframework.util.ObjectUtils;
27 -import org.springframework.util.StringUtils;  
28 import org.springframework.web.bind.annotation.*; 25 import org.springframework.web.bind.annotation.*;
29 import org.springframework.web.context.request.async.DeferredResult; 26 import org.springframework.web.context.request.async.DeferredResult;
30 27
@@ -34,7 +31,6 @@ import java.text.ParseException; @@ -34,7 +31,6 @@ import java.text.ParseException;
34 import java.util.UUID; 31 import java.util.UUID;
35 32
36 @Tag(name = "国标设备配置") 33 @Tag(name = "国标设备配置")
37 -@CrossOrigin  
38 @RestController 34 @RestController
39 @RequestMapping("/api/device/config") 35 @RequestMapping("/api/device/config")
40 public class DeviceConfig { 36 public class DeviceConfig {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java
@@ -32,7 +32,7 @@ import java.text.ParseException; @@ -32,7 +32,7 @@ import java.text.ParseException;
32 import java.util.UUID; 32 import java.util.UUID;
33 33
34 @Tag(name = "国标设备控制") 34 @Tag(name = "国标设备控制")
35 -@CrossOrigin 35 +
36 @RestController 36 @RestController
37 @RequestMapping("/api/device/control") 37 @RequestMapping("/api/device/control")
38 public class DeviceControl { 38 public class DeviceControl {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
@@ -24,6 +24,7 @@ import io.swagger.v3.oas.annotations.Operation; @@ -24,6 +24,7 @@ import io.swagger.v3.oas.annotations.Operation;
24 import io.swagger.v3.oas.annotations.Parameter; 24 import io.swagger.v3.oas.annotations.Parameter;
25 import io.swagger.v3.oas.annotations.tags.Tag; 25 import io.swagger.v3.oas.annotations.tags.Tag;
26 import org.apache.commons.compress.utils.IOUtils; 26 import org.apache.commons.compress.utils.IOUtils;
  27 +import org.apache.ibatis.annotations.Options;
27 import org.slf4j.Logger; 28 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory; 29 import org.slf4j.LoggerFactory;
29 import org.springframework.beans.factory.annotation.Autowired; 30 import org.springframework.beans.factory.annotation.Autowired;
@@ -46,7 +47,7 @@ import java.util.*; @@ -46,7 +47,7 @@ import java.util.*;
46 47
47 @Tag(name = "国标设备查询", description = "国标设备查询") 48 @Tag(name = "国标设备查询", description = "国标设备查询")
48 @SuppressWarnings("rawtypes") 49 @SuppressWarnings("rawtypes")
49 -@CrossOrigin 50 +
50 @RestController 51 @RestController
51 @RequestMapping("/api/device/query") 52 @RequestMapping("/api/device/query")
52 public class DeviceQuery { 53 public class DeviceQuery {
@@ -97,8 +98,10 @@ public class DeviceQuery { @@ -97,8 +98,10 @@ public class DeviceQuery {
97 @Parameter(name = "page", description = "当前页", required = true) 98 @Parameter(name = "page", description = "当前页", required = true)
98 @Parameter(name = "count", description = "每页查询数量", required = true) 99 @Parameter(name = "count", description = "每页查询数量", required = true)
99 @GetMapping("/devices") 100 @GetMapping("/devices")
  101 + @Options()
100 public PageInfo<Device> devices(int page, int count){ 102 public PageInfo<Device> devices(int page, int count){
101 - 103 +// if (page == null) page = 0;
  104 +// if (count == null) count = 20;
102 return storager.queryVideoDeviceList(page, count,null); 105 return storager.queryVideoDeviceList(page, count,null);
103 } 106 }
104 107
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java
@@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.*; @@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.*;
17 import java.util.List; 17 import java.util.List;
18 18
19 @Tag(name = "视频流关联到级联平台") 19 @Tag(name = "视频流关联到级联平台")
20 -@CrossOrigin 20 +
21 @RestController 21 @RestController
22 @RequestMapping("/api/gbStream") 22 @RequestMapping("/api/gbStream")
23 public class GbStreamController { 23 public class GbStreamController {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java
@@ -24,7 +24,7 @@ import javax.servlet.http.HttpServletRequest; @@ -24,7 +24,7 @@ import javax.servlet.http.HttpServletRequest;
24 24
25 @Tag(name = "媒体流相关") 25 @Tag(name = "媒体流相关")
26 @Controller 26 @Controller
27 -@CrossOrigin 27 +
28 @RequestMapping(value = "/api/media") 28 @RequestMapping(value = "/api/media")
29 public class MediaController { 29 public class MediaController {
30 30
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
@@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask; @@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
7 import com.genersoft.iot.vmp.conf.UserSetting; 7 import com.genersoft.iot.vmp.conf.UserSetting;
8 import com.genersoft.iot.vmp.conf.exception.ControllerException; 8 import com.genersoft.iot.vmp.conf.exception.ControllerException;
9 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 9 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  10 +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
10 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog; 11 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
11 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; 12 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
12 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 13 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
@@ -37,7 +38,7 @@ import java.util.List; @@ -37,7 +38,7 @@ import java.util.List;
37 * 级联平台管理 38 * 级联平台管理
38 */ 39 */
39 @Tag(name = "级联平台管理") 40 @Tag(name = "级联平台管理")
40 -@CrossOrigin 41 +
41 @RestController 42 @RestController
42 @RequestMapping("/api/platform") 43 @RequestMapping("/api/platform")
43 public class PlatformController { 44 public class PlatformController {
@@ -205,58 +206,8 @@ public class PlatformController { @@ -205,58 +206,8 @@ public class PlatformController {
205 ) { 206 ) {
206 throw new ControllerException(ErrorCode.ERROR400); 207 throw new ControllerException(ErrorCode.ERROR400);
207 } 208 }
208 - parentPlatform.setCharacterSet(parentPlatform.getCharacterSet().toUpperCase());  
209 - ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId());  
210 - parentPlatform.setUpdateTime(DateUtil.getNow());  
211 - if (!parentPlatformOld.getTreeType().equals(parentPlatform.getTreeType())) {  
212 - // 目录结构发生变化,清空之前的关联关系  
213 - logger.info("保存平台{}时发现目录结构变化,清空关联关系", parentPlatform.getDeviceGBId());  
214 - storager.cleanContentForPlatform(parentPlatform.getServerGBId());  
215 -  
216 - }  
217 - boolean updateResult = storager.updateParentPlatform(parentPlatform);  
218 -  
219 - if (updateResult) {  
220 - // 保存时启用就发送注册  
221 - if (parentPlatform.isEnable()) {  
222 - if (parentPlatformOld != null && parentPlatformOld.isStatus()) {  
223 - try {  
224 - commanderForPlatform.unregister(parentPlatformOld, null, null);  
225 - } catch (InvalidArgumentException | ParseException | SipException e) {  
226 - logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());  
227 - }  
228 - try {  
229 - Thread.sleep(500);  
230 - } catch (InterruptedException e) {  
231 - logger.error("[线程休眠失败] : {}", e.getMessage());  
232 - }  
233 - // 只要保存就发送注册  
234 - try {  
235 - commanderForPlatform.register(parentPlatform, null, null);  
236 - } catch (InvalidArgumentException | ParseException | SipException e) {  
237 - logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage());  
238 - }  
239 -  
240 - } else {  
241 - // 只要保存就发送注册  
242 - try {  
243 - commanderForPlatform.register(parentPlatform, null, null);  
244 - } catch (InvalidArgumentException | ParseException | SipException e) {  
245 - logger.error("[命令发送失败] 国标级联 注册: {}", e.getMessage());  
246 - }  
247 - }  
248 - } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()) { // 关闭启用时注销  
249 - try {  
250 - commanderForPlatform.unregister(parentPlatformOld, null, null);  
251 - } catch (InvalidArgumentException | ParseException | SipException e) {  
252 - logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());  
253 - }  
254 - // 停止订阅相关的定时任务  
255 - subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());  
256 - }  
257 - } else {  
258 - throw new ControllerException(ErrorCode.ERROR100.getCode(),"写入数据库失败");  
259 - } 209 +
  210 + platformService.update(parentPlatform);
260 } 211 }
261 212
262 /** 213 /**
@@ -279,12 +230,16 @@ public class PlatformController { @@ -279,12 +230,16 @@ public class PlatformController {
279 throw new ControllerException(ErrorCode.ERROR400); 230 throw new ControllerException(ErrorCode.ERROR400);
280 } 231 }
281 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(serverGBId); 232 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(serverGBId);
  233 + ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(serverGBId);
282 if (parentPlatform == null) { 234 if (parentPlatform == null) {
283 throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台不存在"); 235 throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台不存在");
284 } 236 }
  237 + if (parentPlatformCatch == null) {
  238 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "平台不存在");
  239 + }
285 // 发送离线消息,无论是否成功都删除缓存 240 // 发送离线消息,无论是否成功都删除缓存
286 try { 241 try {
287 - commanderForPlatform.unregister(parentPlatform, (event -> { 242 + commanderForPlatform.unregister(parentPlatform, parentPlatformCatch.getSipTransactionInfo(), (event -> {
288 // 清空redis缓存 243 // 清空redis缓存
289 redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId()); 244 redisCatchStorage.delPlatformCatchInfo(parentPlatform.getServerGBId());
290 redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId()); 245 redisCatchStorage.delPlatformKeepalive(parentPlatform.getServerGBId());
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -41,7 +41,7 @@ import java.util.UUID; @@ -41,7 +41,7 @@ import java.util.UUID;
41 * @author lin 41 * @author lin
42 */ 42 */
43 @Tag(name = "国标设备点播") 43 @Tag(name = "国标设备点播")
44 -@CrossOrigin 44 +
45 @RestController 45 @RestController
46 @RequestMapping("/api/play") 46 @RequestMapping("/api/play")
47 public class PlayController { 47 public class PlayController {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
@@ -40,7 +40,7 @@ import java.util.UUID; @@ -40,7 +40,7 @@ import java.util.UUID;
40 * @author lin 40 * @author lin
41 */ 41 */
42 @Tag(name = "视频回放") 42 @Tag(name = "视频回放")
43 -@CrossOrigin 43 +
44 @RestController 44 @RestController
45 @RequestMapping("/api/playback") 45 @RequestMapping("/api/playback")
46 public class PlaybackController { 46 public class PlaybackController {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java
1 package com.genersoft.iot.vmp.vmanager.gb28181.ptz; 1 package com.genersoft.iot.vmp.vmanager.gb28181.ptz;
2 2
3 - 3 +
4 import com.genersoft.iot.vmp.conf.exception.ControllerException; 4 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  5 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  6 +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  7 +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  8 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  9 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
5 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 10 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
6 import io.swagger.v3.oas.annotations.Operation; 11 import io.swagger.v3.oas.annotations.Operation;
7 import io.swagger.v3.oas.annotations.Parameter; 12 import io.swagger.v3.oas.annotations.Parameter;
@@ -10,23 +15,16 @@ import org.slf4j.Logger; @@ -10,23 +15,16 @@ import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory; 15 import org.slf4j.LoggerFactory;
11 import org.springframework.beans.factory.annotation.Autowired; 16 import org.springframework.beans.factory.annotation.Autowired;
12 import org.springframework.util.ObjectUtils; 17 import org.springframework.util.ObjectUtils;
13 -import org.springframework.util.StringUtils;  
14 import org.springframework.web.bind.annotation.*; 18 import org.springframework.web.bind.annotation.*;
15 import org.springframework.web.context.request.async.DeferredResult; 19 import org.springframework.web.context.request.async.DeferredResult;
16 20
17 -import com.genersoft.iot.vmp.gb28181.bean.Device;  
18 -import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;  
19 -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;  
20 -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;  
21 -import com.genersoft.iot.vmp.storager.IVideoManagerStorage;  
22 -  
23 import javax.sip.InvalidArgumentException; 21 import javax.sip.InvalidArgumentException;
24 import javax.sip.SipException; 22 import javax.sip.SipException;
25 import java.text.ParseException; 23 import java.text.ParseException;
26 import java.util.UUID; 24 import java.util.UUID;
27 25
28 @Tag(name = "云台控制") 26 @Tag(name = "云台控制")
29 -@CrossOrigin 27 +
30 @RestController 28 @RestController
31 @RequestMapping("/api/ptz") 29 @RequestMapping("/api/ptz")
32 public class PtzController { 30 public class PtzController {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
@@ -3,40 +3,37 @@ package com.genersoft.iot.vmp.vmanager.gb28181.record; @@ -3,40 +3,37 @@ package com.genersoft.iot.vmp.vmanager.gb28181.record;
3 import com.genersoft.iot.vmp.common.StreamInfo; 3 import com.genersoft.iot.vmp.common.StreamInfo;
4 import com.genersoft.iot.vmp.conf.exception.ControllerException; 4 import com.genersoft.iot.vmp.conf.exception.ControllerException;
5 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; 5 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
  6 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  7 +import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
  8 +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
6 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 9 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  10 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
7 import com.genersoft.iot.vmp.service.IDeviceService; 11 import com.genersoft.iot.vmp.service.IDeviceService;
8 import com.genersoft.iot.vmp.service.IPlayService; 12 import com.genersoft.iot.vmp.service.IPlayService;
  13 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
9 import com.genersoft.iot.vmp.utils.DateUtil; 14 import com.genersoft.iot.vmp.utils.DateUtil;
10 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 15 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
11 import com.genersoft.iot.vmp.vmanager.bean.StreamContent; 16 import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
12 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 17 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
13 -  
14 import io.swagger.v3.oas.annotations.Operation; 18 import io.swagger.v3.oas.annotations.Operation;
15 import io.swagger.v3.oas.annotations.Parameter; 19 import io.swagger.v3.oas.annotations.Parameter;
16 import io.swagger.v3.oas.annotations.tags.Tag; 20 import io.swagger.v3.oas.annotations.tags.Tag;
17 import org.slf4j.Logger; 21 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory; 22 import org.slf4j.LoggerFactory;
19 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
20 -import org.springframework.web.bind.annotation.CrossOrigin;  
21 import org.springframework.web.bind.annotation.GetMapping; 24 import org.springframework.web.bind.annotation.GetMapping;
22 import org.springframework.web.bind.annotation.PathVariable; 25 import org.springframework.web.bind.annotation.PathVariable;
23 import org.springframework.web.bind.annotation.RequestMapping; 26 import org.springframework.web.bind.annotation.RequestMapping;
24 import org.springframework.web.bind.annotation.RestController; 27 import org.springframework.web.bind.annotation.RestController;
25 import org.springframework.web.context.request.async.DeferredResult; 28 import org.springframework.web.context.request.async.DeferredResult;
26 29
27 -import com.genersoft.iot.vmp.gb28181.bean.Device;  
28 -import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;  
29 -import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;  
30 -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;  
31 -import com.genersoft.iot.vmp.storager.IVideoManagerStorage;  
32 -  
33 import javax.sip.InvalidArgumentException; 30 import javax.sip.InvalidArgumentException;
34 import javax.sip.SipException; 31 import javax.sip.SipException;
35 import java.text.ParseException; 32 import java.text.ParseException;
36 import java.util.UUID; 33 import java.util.UUID;
37 34
38 @Tag(name = "国标录像") 35 @Tag(name = "国标录像")
39 -@CrossOrigin 36 +
40 @RestController 37 @RestController
41 @RequestMapping("/api/gb_record") 38 @RequestMapping("/api/gb_record")
42 public class GBRecordController { 39 public class GBRecordController {
@@ -74,10 +71,10 @@ public class GBRecordController { @@ -74,10 +71,10 @@ public class GBRecordController {
74 } 71 }
75 DeferredResult<WVPResult<RecordInfo>> result = new DeferredResult<>(); 72 DeferredResult<WVPResult<RecordInfo>> result = new DeferredResult<>();
76 if (!DateUtil.verification(startTime, DateUtil.formatter)){ 73 if (!DateUtil.verification(startTime, DateUtil.formatter)){
77 - throw new ControllerException(ErrorCode.ERROR100.getCode(), "startTime error, format is " + DateUtil.PATTERN); 74 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "startTime格式为" + DateUtil.PATTERN);
78 } 75 }
79 if (!DateUtil.verification(endTime, DateUtil.formatter)){ 76 if (!DateUtil.verification(endTime, DateUtil.formatter)){
80 - throw new ControllerException(ErrorCode.ERROR100.getCode(), "endTime error, format is " + DateUtil.PATTERN); 77 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "endTime格式为" + DateUtil.PATTERN);
81 } 78 }
82 79
83 Device device = storager.queryVideoDevice(deviceId); 80 Device device = storager.queryVideoDevice(deviceId);
src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java
@@ -6,25 +6,18 @@ import com.genersoft.iot.vmp.service.ILogService; @@ -6,25 +6,18 @@ import com.genersoft.iot.vmp.service.ILogService;
6 import com.genersoft.iot.vmp.storager.dao.dto.LogDto; 6 import com.genersoft.iot.vmp.storager.dao.dto.LogDto;
7 import com.genersoft.iot.vmp.utils.DateUtil; 7 import com.genersoft.iot.vmp.utils.DateUtil;
8 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 8 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
9 -import com.genersoft.iot.vmp.vmanager.bean.WVPResult;  
10 import com.github.pagehelper.PageInfo; 9 import com.github.pagehelper.PageInfo;
11 -  
12 import io.swagger.v3.oas.annotations.Operation; 10 import io.swagger.v3.oas.annotations.Operation;
13 import io.swagger.v3.oas.annotations.Parameter; 11 import io.swagger.v3.oas.annotations.Parameter;
14 import io.swagger.v3.oas.annotations.tags.Tag; 12 import io.swagger.v3.oas.annotations.tags.Tag;
15 import org.slf4j.Logger; 13 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory; 14 import org.slf4j.LoggerFactory;
17 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.beans.factory.annotation.Autowired;
18 -import org.springframework.http.HttpStatus;  
19 -import org.springframework.http.ResponseEntity;  
20 import org.springframework.util.ObjectUtils; 16 import org.springframework.util.ObjectUtils;
21 -import org.springframework.util.StringUtils;  
22 import org.springframework.web.bind.annotation.*; 17 import org.springframework.web.bind.annotation.*;
23 18
24 -import java.text.ParseException;  
25 -  
26 @Tag(name = "日志管理") 19 @Tag(name = "日志管理")
27 -@CrossOrigin 20 +
28 @RestController 21 @RestController
29 @RequestMapping("/api/log") 22 @RequestMapping("/api/log")
30 public class LogController { 23 public class LogController {
@@ -67,18 +60,21 @@ public class LogController { @@ -67,18 +60,21 @@ public class LogController {
67 if (ObjectUtils.isEmpty(query)) { 60 if (ObjectUtils.isEmpty(query)) {
68 query = null; 61 query = null;
69 } 62 }
  63 +
  64 + if (!userSetting.getLogInDatebase()) {
  65 + logger.warn("自动记录日志功能已关闭,查询结果可能不完整。");
  66 + }
  67 +
70 if (ObjectUtils.isEmpty(startTime)) { 68 if (ObjectUtils.isEmpty(startTime)) {
71 startTime = null; 69 startTime = null;
  70 + }else if (!DateUtil.verification(startTime, DateUtil.formatter) ){
  71 + throw new ControllerException(ErrorCode.ERROR400.getCode(), "startTime格式为" + DateUtil.PATTERN);
72 } 72 }
  73 +
73 if (ObjectUtils.isEmpty(endTime)) { 74 if (ObjectUtils.isEmpty(endTime)) {
74 endTime = null; 75 endTime = null;
75 - }  
76 - if (!userSetting.getLogInDatebase()) {  
77 - logger.warn("自动记录日志功能已关闭,查询结果可能不完整。");  
78 - }  
79 -  
80 - if (!DateUtil.verification(startTime, DateUtil.formatter) || !DateUtil.verification(endTime, DateUtil.formatter)){  
81 - throw new ControllerException(ErrorCode.ERROR400); 76 + }else if (!DateUtil.verification(endTime, DateUtil.formatter) ){
  77 + throw new ControllerException(ErrorCode.ERROR400.getCode(), "endTime格式为" + DateUtil.PATTERN);
82 } 78 }
83 79
84 return logService.getAll(page, count, query, type, startTime, endTime); 80 return logService.getAll(page, count, query, type, startTime, endTime);
src/main/java/com/genersoft/iot/vmp/vmanager/record/RecordController.java
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 //import org.springframework.web.bind.annotation.*; 14 //import org.springframework.web.bind.annotation.*;
15 // 15 //
16 //@Tag(name = "云端录像") 16 //@Tag(name = "云端录像")
17 -//@CrossOrigin 17 +//
18 //@RestController 18 //@RestController
19 //@RequestMapping("/api/record") 19 //@RequestMapping("/api/record")
20 //public class RecordController { 20 //public class RecordController {
src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
@@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.vmanager.server; @@ -2,7 +2,6 @@ package com.genersoft.iot.vmp.vmanager.server;
2 2
3 import com.alibaba.fastjson2.JSON; 3 import com.alibaba.fastjson2.JSON;
4 import com.alibaba.fastjson2.JSONObject; 4 import com.alibaba.fastjson2.JSONObject;
5 -import com.genersoft.iot.vmp.VManageBootstrap;  
6 import com.genersoft.iot.vmp.common.SystemAllInfo; 5 import com.genersoft.iot.vmp.common.SystemAllInfo;
7 import com.genersoft.iot.vmp.common.VersionPo; 6 import com.genersoft.iot.vmp.common.VersionPo;
8 import com.genersoft.iot.vmp.conf.SipConfig; 7 import com.genersoft.iot.vmp.conf.SipConfig;
@@ -15,30 +14,24 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; @@ -15,30 +14,24 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
15 import com.genersoft.iot.vmp.service.*; 14 import com.genersoft.iot.vmp.service.*;
16 import com.genersoft.iot.vmp.service.bean.MediaServerLoad; 15 import com.genersoft.iot.vmp.service.bean.MediaServerLoad;
17 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 16 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
18 -import com.genersoft.iot.vmp.utils.SpringBeanFactory;  
19 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 17 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
20 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo; 18 import com.genersoft.iot.vmp.vmanager.bean.ResourceBaceInfo;
21 import com.genersoft.iot.vmp.vmanager.bean.ResourceInfo; 19 import com.genersoft.iot.vmp.vmanager.bean.ResourceInfo;
22 import com.genersoft.iot.vmp.vmanager.bean.SystemConfigInfo; 20 import com.genersoft.iot.vmp.vmanager.bean.SystemConfigInfo;
23 -import gov.nist.javax.sip.SipStackImpl;  
24 -  
25 import io.swagger.v3.oas.annotations.Operation; 21 import io.swagger.v3.oas.annotations.Operation;
26 import io.swagger.v3.oas.annotations.Parameter; 22 import io.swagger.v3.oas.annotations.Parameter;
27 import io.swagger.v3.oas.annotations.tags.Tag; 23 import io.swagger.v3.oas.annotations.tags.Tag;
28 import org.springframework.beans.factory.annotation.Autowired; 24 import org.springframework.beans.factory.annotation.Autowired;
29 import org.springframework.beans.factory.annotation.Value; 25 import org.springframework.beans.factory.annotation.Value;
30 -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;  
31 import org.springframework.util.ObjectUtils; 26 import org.springframework.util.ObjectUtils;
32 import org.springframework.web.bind.annotation.*; 27 import org.springframework.web.bind.annotation.*;
33 28
34 -import javax.sip.ListeningPoint;  
35 -import javax.sip.ObjectInUseException;  
36 -import javax.sip.SipProvider;  
37 -import java.util.*; 29 +import java.util.ArrayList;
  30 +import java.util.List;
38 31
39 @SuppressWarnings("rawtypes") 32 @SuppressWarnings("rawtypes")
40 @Tag(name = "服务控制") 33 @Tag(name = "服务控制")
41 -@CrossOrigin 34 +
42 @RestController 35 @RestController
43 @RequestMapping("/api/server") 36 @RequestMapping("/api/server")
44 public class ServerController { 37 public class ServerController {
@@ -77,9 +70,6 @@ public class ServerController { @@ -77,9 +70,6 @@ public class ServerController {
77 70
78 71
79 @Autowired 72 @Autowired
80 - private ThreadPoolTaskExecutor taskExecutor;  
81 -  
82 - @Autowired  
83 private IRedisCatchStorage redisCatchStorage; 73 private IRedisCatchStorage redisCatchStorage;
84 74
85 75
src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java
@@ -25,7 +25,7 @@ import org.springframework.web.bind.annotation.*; @@ -25,7 +25,7 @@ import org.springframework.web.bind.annotation.*;
25 */ 25 */
26 @Tag(name = "拉流代理", description = "") 26 @Tag(name = "拉流代理", description = "")
27 @Controller 27 @Controller
28 -@CrossOrigin 28 +
29 @RequestMapping(value = "/api/proxy") 29 @RequestMapping(value = "/api/proxy")
30 public class StreamProxyController { 30 public class StreamProxyController {
31 31
src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java
@@ -41,7 +41,7 @@ import java.util.UUID; @@ -41,7 +41,7 @@ import java.util.UUID;
41 41
42 @Tag(name = "推流信息管理") 42 @Tag(name = "推流信息管理")
43 @Controller 43 @Controller
44 -@CrossOrigin 44 +
45 @RequestMapping(value = "/api/push") 45 @RequestMapping(value = "/api/push")
46 public class StreamPushController { 46 public class StreamPushController {
47 47
@@ -181,7 +181,7 @@ public class StreamPushController { @@ -181,7 +181,7 @@ public class StreamPushController {
181 String name = file.getName(); 181 String name = file.getName();
182 inputStream = file.getInputStream(); 182 inputStream = file.getInputStream();
183 } catch (IOException e) { 183 } catch (IOException e) {
184 - e.printStackTrace(); 184 + logger.error("未处理的异常 ", e);
185 } 185 }
186 try { 186 try {
187 //传入参数 187 //传入参数
src/main/java/com/genersoft/iot/vmp/vmanager/user/RoleController.java
@@ -6,20 +6,16 @@ import com.genersoft.iot.vmp.service.IRoleService; @@ -6,20 +6,16 @@ import com.genersoft.iot.vmp.service.IRoleService;
6 import com.genersoft.iot.vmp.storager.dao.dto.Role; 6 import com.genersoft.iot.vmp.storager.dao.dto.Role;
7 import com.genersoft.iot.vmp.utils.DateUtil; 7 import com.genersoft.iot.vmp.utils.DateUtil;
8 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 8 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
9 -import com.genersoft.iot.vmp.vmanager.bean.WVPResult;  
10 -  
11 import io.swagger.v3.oas.annotations.Operation; 9 import io.swagger.v3.oas.annotations.Operation;
12 import io.swagger.v3.oas.annotations.Parameter; 10 import io.swagger.v3.oas.annotations.Parameter;
13 import io.swagger.v3.oas.annotations.tags.Tag; 11 import io.swagger.v3.oas.annotations.tags.Tag;
14 import org.springframework.beans.factory.annotation.Autowired; 12 import org.springframework.beans.factory.annotation.Autowired;
15 -import org.springframework.http.HttpStatus;  
16 -import org.springframework.http.ResponseEntity;  
17 import org.springframework.web.bind.annotation.*; 13 import org.springframework.web.bind.annotation.*;
18 14
19 import java.util.List; 15 import java.util.List;
20 16
21 @Tag(name = "角色管理") 17 @Tag(name = "角色管理")
22 -@CrossOrigin 18 +
23 @RestController 19 @RestController
24 @RequestMapping("/api/role") 20 @RequestMapping("/api/role")
25 public class RoleController { 21 public class RoleController {
src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
1 package com.genersoft.iot.vmp.vmanager.user; 1 package com.genersoft.iot.vmp.vmanager.user;
2 2
3 import com.genersoft.iot.vmp.conf.exception.ControllerException; 3 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  4 +import com.genersoft.iot.vmp.conf.security.JwtUtils;
4 import com.genersoft.iot.vmp.conf.security.SecurityUtils; 5 import com.genersoft.iot.vmp.conf.security.SecurityUtils;
5 import com.genersoft.iot.vmp.conf.security.dto.LoginUser; 6 import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
6 import com.genersoft.iot.vmp.service.IRoleService; 7 import com.genersoft.iot.vmp.service.IRoleService;
@@ -21,10 +22,11 @@ import org.springframework.util.ObjectUtils; @@ -21,10 +22,11 @@ import org.springframework.util.ObjectUtils;
21 import org.springframework.web.bind.annotation.*; 22 import org.springframework.web.bind.annotation.*;
22 23
23 import javax.security.sasl.AuthenticationException; 24 import javax.security.sasl.AuthenticationException;
  25 +import javax.servlet.http.HttpServletRequest;
  26 +import javax.servlet.http.HttpServletResponse;
24 import java.util.List; 27 import java.util.List;
25 28
26 @Tag(name = "用户管理") 29 @Tag(name = "用户管理")
27 -@CrossOrigin  
28 @RestController 30 @RestController
29 @RequestMapping("/api/user") 31 @RequestMapping("/api/user")
30 public class UserController { 32 public class UserController {
@@ -40,11 +42,13 @@ public class UserController { @@ -40,11 +42,13 @@ public class UserController {
40 42
41 @GetMapping("/login") 43 @GetMapping("/login")
42 @PostMapping("/login") 44 @PostMapping("/login")
43 - @Operation(summary = "登录") 45 + @Operation(summary = "登录", description = "登录成功后返回AccessToken, 可以从返回值获取到也可以从响应头中获取到," +
  46 + "后续的请求需要添加请求头 'access-token'或者放在参数里")
  47 +
44 @Parameter(name = "username", description = "用户名", required = true) 48 @Parameter(name = "username", description = "用户名", required = true)
45 @Parameter(name = "password", description = "密码(32位md5加密)", required = true) 49 @Parameter(name = "password", description = "密码(32位md5加密)", required = true)
46 - public LoginUser login(@RequestParam String username, @RequestParam String password){  
47 - LoginUser user = null; 50 + public LoginUser login(HttpServletRequest request, HttpServletResponse response, @RequestParam String username, @RequestParam String password){
  51 + LoginUser user;
48 try { 52 try {
49 user = SecurityUtils.login(username, password, authenticationManager); 53 user = SecurityUtils.login(username, password, authenticationManager);
50 } catch (AuthenticationException e) { 54 } catch (AuthenticationException e) {
@@ -52,10 +56,15 @@ public class UserController { @@ -52,10 +56,15 @@ public class UserController {
52 } 56 }
53 if (user == null) { 57 if (user == null) {
54 throw new ControllerException(ErrorCode.ERROR100.getCode(), "用户名或密码错误"); 58 throw new ControllerException(ErrorCode.ERROR100.getCode(), "用户名或密码错误");
  59 + }else {
  60 + String jwt = JwtUtils.createToken(username, password);
  61 + response.setHeader(JwtUtils.getHeader(), jwt);
  62 + user.setAccessToken(jwt);
55 } 63 }
56 return user; 64 return user;
57 } 65 }
58 66
  67 +
59 @PostMapping("/changePassword") 68 @PostMapping("/changePassword")
60 @Operation(summary = "修改密码") 69 @Operation(summary = "修改密码")
61 @Parameter(name = "username", description = "用户名", required = true) 70 @Parameter(name = "username", description = "用户名", required = true)
@@ -74,8 +83,8 @@ public class UserController { @@ -74,8 +83,8 @@ public class UserController {
74 if (user == null) { 83 if (user == null) {
75 throw new ControllerException(ErrorCode.ERROR100); 84 throw new ControllerException(ErrorCode.ERROR100);
76 } 85 }
77 - int userId = SecurityUtils.getUserId();  
78 - boolean result = userService.changePassword(userId, DigestUtils.md5DigestAsHex(password.getBytes())); 86 + //int userId = SecurityUtils.getUserId();
  87 + boolean result = userService.changePassword(user.getId(), DigestUtils.md5DigestAsHex(password.getBytes()));
79 if (!result) { 88 if (!result) {
80 throw new ControllerException(ErrorCode.ERROR100); 89 throw new ControllerException(ErrorCode.ERROR100);
81 } 90 }
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiControlController.java
1 package com.genersoft.iot.vmp.web.gb28181; 1 package com.genersoft.iot.vmp.web.gb28181;
2 2
3 -import com.alibaba.fastjson2.JSONObject;  
4 import com.genersoft.iot.vmp.conf.exception.ControllerException; 3 import com.genersoft.iot.vmp.conf.exception.ControllerException;
5 import com.genersoft.iot.vmp.gb28181.bean.Device; 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
@@ -9,7 +8,9 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; @@ -9,7 +8,9 @@ import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
9 import org.slf4j.Logger; 8 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory; 9 import org.slf4j.LoggerFactory;
11 import org.springframework.beans.factory.annotation.Autowired; 10 import org.springframework.beans.factory.annotation.Autowired;
12 -import org.springframework.web.bind.annotation.*; 11 +import org.springframework.web.bind.annotation.RequestMapping;
  12 +import org.springframework.web.bind.annotation.RequestParam;
  13 +import org.springframework.web.bind.annotation.RestController;
13 14
14 import javax.sip.InvalidArgumentException; 15 import javax.sip.InvalidArgumentException;
15 import javax.sip.SipException; 16 import javax.sip.SipException;
@@ -18,7 +19,7 @@ import java.text.ParseException; @@ -18,7 +19,7 @@ import java.text.ParseException;
18 /** 19 /**
19 * API兼容:设备控制 20 * API兼容:设备控制
20 */ 21 */
21 -@CrossOrigin 22 +
22 @RestController 23 @RestController
23 @RequestMapping(value = "/api/v1/control") 24 @RequestMapping(value = "/api/v1/control")
24 public class ApiControlController { 25 public class ApiControlController {
@@ -102,4 +103,53 @@ public class ApiControlController { @@ -102,4 +103,53 @@ public class ApiControlController {
102 throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); 103 throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
103 } 104 }
104 } 105 }
  106 +
  107 + /**
  108 + * 设备控制 - 预置位控制
  109 + * @param serial 设备编号
  110 + * @param code 通道编号,通过 /api/v1/device/channellist 获取的 ChannelList.ID, 该参数和 channel 二选一传递即可
  111 + * @param channel 通道序号, 默认值: 1
  112 + * @param command 控制指令 允许值: set, goto, remove
  113 + * @param preset 预置位编号(1~255)
  114 + * @param name 预置位名称, command=set 时有效
  115 + * @return
  116 + */
  117 + @RequestMapping(value = "/preset")
  118 + private void list(String serial,String command,
  119 + @RequestParam(required = false)Integer channel,
  120 + @RequestParam(required = false)String code,
  121 + @RequestParam(required = false)String name,
  122 + @RequestParam(required = false)Integer preset){
  123 +
  124 + if (logger.isDebugEnabled()) {
  125 + logger.debug("模拟接口> 预置位控制 API调用,deviceId:{} ,channelId:{} ,command:{} ,name:{} ,preset:{} ",
  126 + serial, code, command, name, preset);
  127 + }
  128 +
  129 + if (channel == null) {channel = 0;}
  130 + Device device = storager.queryVideoDevice(serial);
  131 + if (device == null) {
  132 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "device[ " + serial + " ]未找到");
  133 + }
  134 + int cmdCode = 0;
  135 + switch (command){
  136 + case "set":
  137 + cmdCode = 129;
  138 + break;
  139 + case "goto":
  140 + cmdCode = 130;
  141 + break;
  142 + case "remove":
  143 + cmdCode = 131;
  144 + break;
  145 + default:
  146 + break;
  147 + }
  148 + try {
  149 + cmder.frontEndCmd(device, code, cmdCode, 0, preset, 0);
  150 + } catch (SipException | InvalidArgumentException | ParseException e) {
  151 + logger.error("[命令发送失败] 预置位控制: {}", e.getMessage());
  152 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  153 + }
  154 + }
105 } 155 }
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiController.java
@@ -6,7 +6,6 @@ import org.slf4j.Logger; @@ -6,7 +6,6 @@ import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory; 6 import org.slf4j.LoggerFactory;
7 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.beans.factory.annotation.Autowired;
8 import org.springframework.stereotype.Controller; 8 import org.springframework.stereotype.Controller;
9 -import org.springframework.web.bind.annotation.CrossOrigin;  
10 import org.springframework.web.bind.annotation.RequestMapping; 9 import org.springframework.web.bind.annotation.RequestMapping;
11 import org.springframework.web.bind.annotation.ResponseBody; 10 import org.springframework.web.bind.annotation.ResponseBody;
12 11
@@ -14,7 +13,7 @@ import org.springframework.web.bind.annotation.ResponseBody; @@ -14,7 +13,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
14 * API兼容:系统接口 13 * API兼容:系统接口
15 */ 14 */
16 @Controller 15 @Controller
17 -@CrossOrigin 16 +
18 @RequestMapping(value = "/api/v1") 17 @RequestMapping(value = "/api/v1")
19 public class ApiController { 18 public class ApiController {
20 19
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java
@@ -2,25 +2,38 @@ package com.genersoft.iot.vmp.web.gb28181; @@ -2,25 +2,38 @@ package com.genersoft.iot.vmp.web.gb28181;
2 2
3 import com.alibaba.fastjson2.JSONArray; 3 import com.alibaba.fastjson2.JSONArray;
4 import com.alibaba.fastjson2.JSONObject; 4 import com.alibaba.fastjson2.JSONObject;
  5 +import com.genersoft.iot.vmp.conf.exception.ControllerException;
5 import com.genersoft.iot.vmp.gb28181.bean.Device; 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 7 +import com.genersoft.iot.vmp.gb28181.bean.PresetQuerySipReq;
  8 +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  9 +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  10 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
7 import com.genersoft.iot.vmp.service.IDeviceService; 11 import com.genersoft.iot.vmp.service.IDeviceService;
8 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 12 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  13 +import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx;
  14 +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
  15 +import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend;
9 import com.github.pagehelper.PageInfo; 16 import com.github.pagehelper.PageInfo;
10 import org.slf4j.Logger; 17 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory; 18 import org.slf4j.LoggerFactory;
12 import org.springframework.beans.factory.annotation.Autowired; 19 import org.springframework.beans.factory.annotation.Autowired;
  20 +import org.springframework.util.ObjectUtils;
13 import org.springframework.util.StringUtils; 21 import org.springframework.util.StringUtils;
14 -import org.springframework.web.bind.annotation.*; 22 +import org.springframework.web.bind.annotation.RequestMapping;
  23 +import org.springframework.web.bind.annotation.RequestParam;
  24 +import org.springframework.web.bind.annotation.RestController;
  25 +import org.springframework.web.context.request.async.DeferredResult;
15 26
16 -import java.util.Arrays;  
17 -import java.util.List; 27 +import javax.sip.InvalidArgumentException;
  28 +import javax.sip.SipException;
  29 +import java.text.ParseException;
  30 +import java.util.*;
18 31
19 /** 32 /**
20 * API兼容:设备信息 33 * API兼容:设备信息
21 */ 34 */
22 @SuppressWarnings("unchecked") 35 @SuppressWarnings("unchecked")
23 -@CrossOrigin 36 +
24 @RestController 37 @RestController
25 @RequestMapping(value = "/api/v1/device") 38 @RequestMapping(value = "/api/v1/device")
26 public class ApiDeviceController { 39 public class ApiDeviceController {
@@ -29,17 +42,15 @@ public class ApiDeviceController { @@ -29,17 +42,15 @@ public class ApiDeviceController {
29 42
30 @Autowired 43 @Autowired
31 private IVideoManagerStorage storager; 44 private IVideoManagerStorage storager;
  45 +
  46 + @Autowired
  47 + private SIPCommander cmder;
32 @Autowired 48 @Autowired
33 private IDeviceService deviceService; 49 private IDeviceService deviceService;
34 50
35 - // @Autowired  
36 - // private SIPCommander cmder;  
37 -  
38 - // @Autowired  
39 - // private DeferredResultHolder resultHolder; 51 + @Autowired
  52 + private DeferredResultHolder resultHolder;
40 53
41 - // @Autowired  
42 - // private DeviceOffLineDetector offLineDetector;  
43 54
44 /** 55 /**
45 * 分页获取设备列表 现在直接返回,尚未实现分页 56 * 分页获取设备列表 现在直接返回,尚未实现分页
@@ -96,8 +107,8 @@ public class ApiDeviceController { @@ -96,8 +107,8 @@ public class ApiDeviceController {
96 107
97 @RequestMapping(value = "/channellist") 108 @RequestMapping(value = "/channellist")
98 public JSONObject channellist( String serial, 109 public JSONObject channellist( String serial,
99 - @RequestParam(required = false)String code,  
100 @RequestParam(required = false)String channel_type, 110 @RequestParam(required = false)String channel_type,
  111 + @RequestParam(required = false)String code ,
101 @RequestParam(required = false)String dir_serial , 112 @RequestParam(required = false)String dir_serial ,
102 @RequestParam(required = false)Integer start, 113 @RequestParam(required = false)Integer start,
103 @RequestParam(required = false)Integer limit, 114 @RequestParam(required = false)Integer limit,
@@ -109,64 +120,138 @@ public class ApiDeviceController { @@ -109,64 +120,138 @@ public class ApiDeviceController {
109 // } 120 // }
110 JSONObject result = new JSONObject(); 121 JSONObject result = new JSONObject();
111 // 查询设备是否存在 122 // 查询设备是否存在
112 - Device device = storager.queryVideoDevice(serial);  
113 - if (device == null) {  
114 - result.put("ChannelCount", 0);  
115 - result.put("ChannelList", "[]");  
116 - return result;  
117 - }  
118 - List<DeviceChannel> deviceChannels; 123 +// Device device = storager.queryVideoDevice(serial);
  124 +// if (device == null) {
  125 +// result.put("ChannelCount", 0);
  126 +// result.put("ChannelList", "[]");
  127 +// return result;
  128 +// }
  129 + List<DeviceChannelExtend> deviceChannels;
119 List<String> channelIds = null; 130 List<String> channelIds = null;
120 if (!StringUtils.isEmpty(code)) { 131 if (!StringUtils.isEmpty(code)) {
121 String[] split = code.trim().split(","); 132 String[] split = code.trim().split(",");
122 channelIds = Arrays.asList(split); 133 channelIds = Arrays.asList(split);
123 } 134 }
124 - List<DeviceChannel> allDeviceChannelList = storager.queryChannelsByDeviceId(serial,online,channelIds); 135 + List<DeviceChannelExtend> allDeviceChannelList = storager.queryChannelsByDeviceId(serial,channelIds,online);
125 if (start == null || limit ==null) { 136 if (start == null || limit ==null) {
126 deviceChannels = allDeviceChannelList; 137 deviceChannels = allDeviceChannelList;
127 result.put("ChannelCount", deviceChannels.size()); 138 result.put("ChannelCount", deviceChannels.size());
128 }else { 139 }else {
129 - deviceChannels = storager.queryChannelsByDeviceIdWithStartAndLimit(serial, null, null, online,start, limit,channelIds); 140 + deviceChannels = storager.queryChannelsByDeviceIdWithStartAndLimit(serial,channelIds, null, null, online,start, limit);
130 int total = allDeviceChannelList.size(); 141 int total = allDeviceChannelList.size();
131 result.put("ChannelCount", total); 142 result.put("ChannelCount", total);
132 } 143 }
133 144
134 JSONArray channleJSONList = new JSONArray(); 145 JSONArray channleJSONList = new JSONArray();
135 - for (DeviceChannel deviceChannel : deviceChannels) { 146 + for (DeviceChannelExtend deviceChannelExtend : deviceChannels) {
136 JSONObject deviceJOSNChannel = new JSONObject(); 147 JSONObject deviceJOSNChannel = new JSONObject();
137 - deviceJOSNChannel.put("ID", deviceChannel.getChannelId());  
138 - deviceJOSNChannel.put("DeviceID", device.getDeviceId());  
139 - deviceJOSNChannel.put("DeviceName", device.getName());  
140 - deviceJOSNChannel.put("DeviceOnline", device.getOnline() == 1);  
141 - deviceJOSNChannel.put("Channel", 0); // 自定义序号  
142 - deviceJOSNChannel.put("Name", deviceChannel.getName()); 148 + deviceJOSNChannel.put("ID", deviceChannelExtend.getChannelId());
  149 + deviceJOSNChannel.put("DeviceID", deviceChannelExtend.getDeviceId());
  150 + deviceJOSNChannel.put("DeviceName", deviceChannelExtend.getDeviceName());
  151 + deviceJOSNChannel.put("DeviceOnline", deviceChannelExtend.getDeviceOnline() == 1);
  152 + deviceJOSNChannel.put("Channel", 0); // TODO 自定义序号
  153 + deviceJOSNChannel.put("Name", deviceChannelExtend.getName());
143 deviceJOSNChannel.put("Custom", false); 154 deviceJOSNChannel.put("Custom", false);
144 deviceJOSNChannel.put("CustomName", ""); 155 deviceJOSNChannel.put("CustomName", "");
145 - deviceJOSNChannel.put("SubCount", deviceChannel.getSubCount()); // 子节点数, SubCount > 0 表示该通道为子目录 156 + deviceJOSNChannel.put("SubCount", deviceChannelExtend.getSubCount()); // TODO ? 子节点数, SubCount > 0 表示该通道为子目录
146 deviceJOSNChannel.put("SnapURL", ""); 157 deviceJOSNChannel.put("SnapURL", "");
147 - deviceJOSNChannel.put("Manufacturer ", deviceChannel.getManufacture());  
148 - deviceJOSNChannel.put("Model", deviceChannel.getModel());  
149 - deviceJOSNChannel.put("Owner", deviceChannel.getOwner());  
150 - deviceJOSNChannel.put("CivilCode", deviceChannel.getCivilCode());  
151 - deviceJOSNChannel.put("Address", deviceChannel.getAddress());  
152 - deviceJOSNChannel.put("Parental", deviceChannel.getParental()); // 当为通道设备时, 是否有通道子设备, 1-有,0-没有  
153 - deviceJOSNChannel.put("ParentID", deviceChannel.getParentId()); // 直接上级编号  
154 - deviceJOSNChannel.put("Secrecy", deviceChannel.getSecrecy()); 158 + deviceJOSNChannel.put("Manufacturer ", deviceChannelExtend.getManufacture());
  159 + deviceJOSNChannel.put("Model", deviceChannelExtend.getModel());
  160 + deviceJOSNChannel.put("Owner", deviceChannelExtend.getOwner());
  161 + deviceJOSNChannel.put("CivilCode", deviceChannelExtend.getCivilCode());
  162 + deviceJOSNChannel.put("Address", deviceChannelExtend.getAddress());
  163 + deviceJOSNChannel.put("Parental", deviceChannelExtend.getParental()); // 当为通道设备时, 是否有通道子设备, 1-有,0-没有
  164 + deviceJOSNChannel.put("ParentID", deviceChannelExtend.getParentId()); // 直接上级编号
  165 + deviceJOSNChannel.put("Secrecy", deviceChannelExtend.getSecrecy());
155 deviceJOSNChannel.put("RegisterWay", 1); // 注册方式, 缺省为1, 允许值: 1, 2, 3 166 deviceJOSNChannel.put("RegisterWay", 1); // 注册方式, 缺省为1, 允许值: 1, 2, 3
156 - // 1-IETF RFC3261,  
157 - // 2-基于口令的双向认证,  
158 - // 3-基于数字证书的双向认证  
159 - deviceJOSNChannel.put("Status", deviceChannel.getStatus() == 1 ? "ON":"OFF");  
160 - deviceJOSNChannel.put("Longitude", deviceChannel.getLongitude());  
161 - deviceJOSNChannel.put("Latitude", deviceChannel.getLatitude());  
162 - deviceJOSNChannel.put("PTZType ", deviceChannel.getPTZType()); // 云台类型, 0 - 未知, 1 - 球机, 2 - 半球,  
163 - // 3 - 固定枪机, 4 - 遥控枪机 167 + // 1-IETF RFC3261,
  168 + // 2-基于口令的双向认证,
  169 + // 3-基于数字证书的双向认证
  170 + deviceJOSNChannel.put("Status", deviceChannelExtend.getStatus() == 1 ? "ON":"OFF");
  171 + deviceJOSNChannel.put("Longitude", deviceChannelExtend.getLongitude());
  172 + deviceJOSNChannel.put("Latitude", deviceChannelExtend.getLatitude());
  173 + deviceJOSNChannel.put("PTZType ", deviceChannelExtend.getPTZType()); // 云台类型, 0 - 未知, 1 - 球机, 2 - 半球,
  174 + // 3 - 固定枪机, 4 - 遥控枪机
164 deviceJOSNChannel.put("CustomPTZType", ""); 175 deviceJOSNChannel.put("CustomPTZType", "");
165 - deviceJOSNChannel.put("StreamID", deviceChannel.getStreamId()); // StreamID 直播流ID, 有值表示正在直播 176 + deviceJOSNChannel.put("StreamID", deviceChannelExtend.getStreamId()); // StreamID 直播流ID, 有值表示正在直播
166 deviceJOSNChannel.put("NumOutputs ", -1); // 直播在线人数 177 deviceJOSNChannel.put("NumOutputs ", -1); // 直播在线人数
167 channleJSONList.add(deviceJOSNChannel); 178 channleJSONList.add(deviceJOSNChannel);
168 } 179 }
169 result.put("ChannelList", channleJSONList); 180 result.put("ChannelList", channleJSONList);
170 return result; 181 return result;
171 } 182 }
  183 +
  184 + /**
  185 + * 设备信息 - 获取下级通道预置位
  186 + * @param serial 设备编号
  187 + * @param code 通道编号,通过 /api/v1/device/channellist 获取的 ChannelList.ID, 该参数和 channel 二选一传递即可
  188 + * @param channel 通道序号, 默认值: 1
  189 + * @param fill 是否填充空置预置位,当下级返回预置位,但不够255个时,自动填充空置预置位到255个, 默认值: true, 允许值: true, false
  190 + * @param timeout 超时时间(秒) 默认值: 15
  191 + * @return
  192 + */
  193 + @RequestMapping(value = "/fetchpreset")
  194 + private DeferredResult<Object> list(String serial,
  195 + @RequestParam(required = false)Integer channel,
  196 + @RequestParam(required = false)String code,
  197 + @RequestParam(required = false)Boolean fill,
  198 + @RequestParam(required = false)Integer timeout){
  199 +
  200 + if (logger.isDebugEnabled()) {
  201 + logger.debug("<模拟接口> 获取下级通道预置位 API调用,deviceId:{} ,channel:{} ,code:{} ,fill:{} ,timeout:{} ",
  202 + serial, channel, code, fill, timeout);
  203 + }
  204 +
  205 + Device device = storager.queryVideoDevice(serial);
  206 + String uuid = UUID.randomUUID().toString();
  207 + String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (ObjectUtils.isEmpty(code) ? serial : code);
  208 + DeferredResult<Object> result = new DeferredResult<> (timeout * 1000L);
  209 + DeferredResultEx<Object> deferredResultEx = new DeferredResultEx<>(result);
  210 + result.onTimeout(()->{
  211 + logger.warn("<模拟接口> 获取设备预置位超时");
  212 + // 释放rtpserver
  213 + RequestMessage msg = new RequestMessage();
  214 + msg.setId(uuid);
  215 + msg.setKey(key);
  216 + msg.setData("wait for presetquery timeout["+timeout+"s]");
  217 + resultHolder.invokeResult(msg);
  218 + });
  219 + if (resultHolder.exist(key, null)) {
  220 + return result;
  221 + }
  222 +
  223 + deferredResultEx.setFilter(filterResult->{
  224 + List<PresetQuerySipReq> presetQuerySipReqList = (List<PresetQuerySipReq>)filterResult;
  225 + HashMap<String, Object> resultMap = new HashMap<>();
  226 + resultMap.put("DeviceID", code);
  227 + resultMap.put("Result", "OK");
  228 + resultMap.put("SumNum", presetQuerySipReqList.size());
  229 + ArrayList<Map<String, Object>> presetItemList = new ArrayList<>(presetQuerySipReqList.size());
  230 + for (PresetQuerySipReq presetQuerySipReq : presetQuerySipReqList) {
  231 + Map<String, Object> item = new HashMap<>();
  232 + item.put("PresetID", presetQuerySipReq.getPresetId());
  233 + item.put("PresetName", presetQuerySipReq.getPresetName());
  234 + item.put("PresetEnable", true);
  235 + presetItemList.add(item);
  236 + }
  237 + resultMap.put("PresetItemList",presetItemList );
  238 + return resultMap;
  239 + });
  240 +
  241 + resultHolder.put(key, uuid, deferredResultEx);
  242 +
  243 + try {
  244 + cmder.presetQuery(device, code, event -> {
  245 + RequestMessage msg = new RequestMessage();
  246 + msg.setId(uuid);
  247 + msg.setKey(key);
  248 + msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", event.statusCode, event.msg));
  249 + resultHolder.invokeResult(msg);
  250 + });
  251 + } catch (InvalidArgumentException | SipException | ParseException e) {
  252 + logger.error("[命令发送失败] 获取设备预置位: {}", e.getMessage());
  253 + throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
  254 + }
  255 + return result;
  256 + }
172 } 257 }
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java
@@ -26,7 +26,7 @@ import java.text.ParseException; @@ -26,7 +26,7 @@ import java.text.ParseException;
26 * API兼容:实时直播 26 * API兼容:实时直播
27 */ 27 */
28 @SuppressWarnings(value = {"rawtypes", "unchecked"}) 28 @SuppressWarnings(value = {"rawtypes", "unchecked"})
29 -@CrossOrigin 29 +
30 @RestController 30 @RestController
31 @RequestMapping(value = "/api/v1/stream") 31 @RequestMapping(value = "/api/v1/stream")
32 public class ApiStreamController { 32 public class ApiStreamController {
src/main/java/com/genersoft/iot/vmp/web/gb28181/AuthController.java
@@ -5,7 +5,7 @@ import com.genersoft.iot.vmp.storager.dao.dto.User; @@ -5,7 +5,7 @@ import com.genersoft.iot.vmp.storager.dao.dto.User;
5 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.web.bind.annotation.*; 6 import org.springframework.web.bind.annotation.*;
7 7
8 -@CrossOrigin 8 +
9 @RestController 9 @RestController
10 @RequestMapping(value = "/auth") 10 @RequestMapping(value = "/auth")
11 public class AuthController { 11 public class AuthController {
src/main/java/com/genersoft/iot/vmp/web/gb28181/dto/DeviceChannelExtend.java 0 → 100644
  1 +package com.genersoft.iot.vmp.web.gb28181.dto;
  2 +
  3 +public class DeviceChannelExtend {
  4 +
  5 +
  6 + /**
  7 + * 数据库自增ID
  8 + */
  9 + private int id;
  10 +
  11 + /**
  12 + * 通道id
  13 + */
  14 + private String channelId;
  15 +
  16 + /**
  17 + * 设备id
  18 + */
  19 + private String deviceId;
  20 +
  21 + /**
  22 + * 通道名
  23 + */
  24 + private String name;
  25 +
  26 + private String deviceName;
  27 +
  28 + private int deviceOnline;
  29 +
  30 + /**
  31 + * 生产厂商
  32 + */
  33 + private String manufacture;
  34 +
  35 + /**
  36 + * 型号
  37 + */
  38 + private String model;
  39 +
  40 + /**
  41 + * 设备归属
  42 + */
  43 + private String owner;
  44 +
  45 + /**
  46 + * 行政区域
  47 + */
  48 + private String civilCode;
  49 +
  50 + /**
  51 + * 警区
  52 + */
  53 + private String block;
  54 +
  55 + /**
  56 + * 安装地址
  57 + */
  58 + private String address;
  59 +
  60 + /**
  61 + * 是否有子设备 1有, 0没有
  62 + */
  63 + private int parental;
  64 +
  65 + /**
  66 + * 父级id
  67 + */
  68 + private String parentId;
  69 +
  70 + /**
  71 + * 信令安全模式 缺省为0; 0:不采用; 2: S/MIME签名方式; 3: S/ MIME加密签名同时采用方式; 4:数字摘要方式
  72 + */
  73 + private int safetyWay;
  74 +
  75 + /**
  76 + * 注册方式 缺省为1;1:符合IETFRFC3261标准的认证注册模 式; 2:基于口令的双向认证注册模式; 3:基于数字证书的双向认证注册模式
  77 + */
  78 + private int registerWay;
  79 +
  80 + /**
  81 + * 证书序列号
  82 + */
  83 + private String certNum;
  84 +
  85 + /**
  86 + * 证书有效标识 缺省为0;证书有效标识:0:无效1: 有效
  87 + */
  88 + private int certifiable;
  89 +
  90 + /**
  91 + * 证书无效原因码
  92 + */
  93 + private int errCode;
  94 +
  95 + /**
  96 + * 证书终止有效期
  97 + */
  98 + private String endTime;
  99 +
  100 + /**
  101 + * 保密属性 缺省为0; 0:不涉密, 1:涉密
  102 + */
  103 + private String secrecy;
  104 +
  105 + /**
  106 + * IP地址
  107 + */
  108 + private String ipAddress;
  109 +
  110 + /**
  111 + * 端口号
  112 + */
  113 + private int port;
  114 +
  115 + /**
  116 + * 密码
  117 + */
  118 + private String password;
  119 +
  120 + /**
  121 + * 云台类型
  122 + */
  123 + private int PTZType;
  124 +
  125 + /**
  126 + * 云台类型描述字符串
  127 + */
  128 + private String PTZTypeText;
  129 +
  130 + /**
  131 + * 创建时间
  132 + */
  133 + private String createTime;
  134 +
  135 + /**
  136 + * 更新时间
  137 + */
  138 + private String updateTime;
  139 +
  140 + /**
  141 + * 在线/离线
  142 + * 1在线,0离线
  143 + * 默认在线
  144 + * 信令:
  145 + * <Status>ON</Status>
  146 + * <Status>OFF</Status>
  147 + * 遇到过NVR下的IPC下发信令可以推流, 但是 Status 响应 OFF
  148 + */
  149 + private int status;
  150 +
  151 + /**
  152 + * 经度
  153 + */
  154 + private double longitude;
  155 +
  156 + /**
  157 + * 纬度
  158 + */
  159 + private double latitude;
  160 +
  161 + /**
  162 + * 经度 GCJ02
  163 + */
  164 + private double longitudeGcj02;
  165 +
  166 + /**
  167 + * 纬度 GCJ02
  168 + */
  169 + private double latitudeGcj02;
  170 +
  171 + /**
  172 + * 经度 WGS84
  173 + */
  174 + private double longitudeWgs84;
  175 +
  176 + /**
  177 + * 纬度 WGS84
  178 + */
  179 + private double latitudeWgs84;
  180 +
  181 + /**
  182 + * 子设备数
  183 + */
  184 + private int subCount;
  185 +
  186 + /**
  187 + * 流唯一编号,存在表示正在直播
  188 + */
  189 + private String streamId;
  190 +
  191 + /**
  192 + * 是否含有音频
  193 + */
  194 + private boolean hasAudio;
  195 +
  196 + /**
  197 + * 标记通道的类型,0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划
  198 + */
  199 + private int channelType;
  200 +
  201 + /**
  202 + * 业务分组
  203 + */
  204 + private String businessGroupId;
  205 +
  206 + /**
  207 + * GPS的更新时间
  208 + */
  209 + private String gpsTime;
  210 +
  211 + public int getId() {
  212 + return id;
  213 + }
  214 +
  215 + public void setId(int id) {
  216 + this.id = id;
  217 + }
  218 +
  219 + public String getDeviceId() {
  220 + return deviceId;
  221 + }
  222 +
  223 + public void setDeviceId(String deviceId) {
  224 + this.deviceId = deviceId;
  225 + }
  226 +
  227 + public void setPTZType(int PTZType) {
  228 + this.PTZType = PTZType;
  229 + switch (PTZType) {
  230 + case 0:
  231 + this.PTZTypeText = "未知";
  232 + break;
  233 + case 1:
  234 + this.PTZTypeText = "球机";
  235 + break;
  236 + case 2:
  237 + this.PTZTypeText = "半球";
  238 + break;
  239 + case 3:
  240 + this.PTZTypeText = "固定枪机";
  241 + break;
  242 + case 4:
  243 + this.PTZTypeText = "遥控枪机";
  244 + break;
  245 + }
  246 + }
  247 +
  248 + public String getChannelId() {
  249 + return channelId;
  250 + }
  251 +
  252 + public void setChannelId(String channelId) {
  253 + this.channelId = channelId;
  254 + }
  255 +
  256 + public String getName() {
  257 + return name;
  258 + }
  259 +
  260 + public void setName(String name) {
  261 + this.name = name;
  262 + }
  263 +
  264 + public String getManufacture() {
  265 + return manufacture;
  266 + }
  267 +
  268 + public void setManufacture(String manufacture) {
  269 + this.manufacture = manufacture;
  270 + }
  271 +
  272 + public String getModel() {
  273 + return model;
  274 + }
  275 +
  276 + public void setModel(String model) {
  277 + this.model = model;
  278 + }
  279 +
  280 + public String getOwner() {
  281 + return owner;
  282 + }
  283 +
  284 + public void setOwner(String owner) {
  285 + this.owner = owner;
  286 + }
  287 +
  288 + public String getCivilCode() {
  289 + return civilCode;
  290 + }
  291 +
  292 + public void setCivilCode(String civilCode) {
  293 + this.civilCode = civilCode;
  294 + }
  295 +
  296 + public String getBlock() {
  297 + return block;
  298 + }
  299 +
  300 + public void setBlock(String block) {
  301 + this.block = block;
  302 + }
  303 +
  304 + public String getAddress() {
  305 + return address;
  306 + }
  307 +
  308 + public void setAddress(String address) {
  309 + this.address = address;
  310 + }
  311 +
  312 + public int getParental() {
  313 + return parental;
  314 + }
  315 +
  316 + public void setParental(int parental) {
  317 + this.parental = parental;
  318 + }
  319 +
  320 + public String getParentId() {
  321 + return parentId;
  322 + }
  323 +
  324 + public void setParentId(String parentId) {
  325 + this.parentId = parentId;
  326 + }
  327 +
  328 + public int getSafetyWay() {
  329 + return safetyWay;
  330 + }
  331 +
  332 + public void setSafetyWay(int safetyWay) {
  333 + this.safetyWay = safetyWay;
  334 + }
  335 +
  336 + public int getRegisterWay() {
  337 + return registerWay;
  338 + }
  339 +
  340 + public void setRegisterWay(int registerWay) {
  341 + this.registerWay = registerWay;
  342 + }
  343 +
  344 + public String getCertNum() {
  345 + return certNum;
  346 + }
  347 +
  348 + public void setCertNum(String certNum) {
  349 + this.certNum = certNum;
  350 + }
  351 +
  352 + public int getCertifiable() {
  353 + return certifiable;
  354 + }
  355 +
  356 + public void setCertifiable(int certifiable) {
  357 + this.certifiable = certifiable;
  358 + }
  359 +
  360 + public int getErrCode() {
  361 + return errCode;
  362 + }
  363 +
  364 + public void setErrCode(int errCode) {
  365 + this.errCode = errCode;
  366 + }
  367 +
  368 + public String getEndTime() {
  369 + return endTime;
  370 + }
  371 +
  372 + public void setEndTime(String endTime) {
  373 + this.endTime = endTime;
  374 + }
  375 +
  376 + public String getSecrecy() {
  377 + return secrecy;
  378 + }
  379 +
  380 + public void setSecrecy(String secrecy) {
  381 + this.secrecy = secrecy;
  382 + }
  383 +
  384 + public String getIpAddress() {
  385 + return ipAddress;
  386 + }
  387 +
  388 + public void setIpAddress(String ipAddress) {
  389 + this.ipAddress = ipAddress;
  390 + }
  391 +
  392 + public int getPort() {
  393 + return port;
  394 + }
  395 +
  396 + public void setPort(int port) {
  397 + this.port = port;
  398 + }
  399 +
  400 + public String getPassword() {
  401 + return password;
  402 + }
  403 +
  404 + public void setPassword(String password) {
  405 + this.password = password;
  406 + }
  407 +
  408 + public int getPTZType() {
  409 + return PTZType;
  410 + }
  411 +
  412 + public String getPTZTypeText() {
  413 + return PTZTypeText;
  414 + }
  415 +
  416 + public void setPTZTypeText(String PTZTypeText) {
  417 + this.PTZTypeText = PTZTypeText;
  418 + }
  419 +
  420 + public int getStatus() {
  421 + return status;
  422 + }
  423 +
  424 + public void setStatus(int status) {
  425 + this.status = status;
  426 + }
  427 +
  428 + public double getLongitude() {
  429 + return longitude;
  430 + }
  431 +
  432 + public void setLongitude(double longitude) {
  433 + this.longitude = longitude;
  434 + }
  435 +
  436 + public double getLatitude() {
  437 + return latitude;
  438 + }
  439 +
  440 + public void setLatitude(double latitude) {
  441 + this.latitude = latitude;
  442 + }
  443 +
  444 + public double getLongitudeGcj02() {
  445 + return longitudeGcj02;
  446 + }
  447 +
  448 + public void setLongitudeGcj02(double longitudeGcj02) {
  449 + this.longitudeGcj02 = longitudeGcj02;
  450 + }
  451 +
  452 + public double getLatitudeGcj02() {
  453 + return latitudeGcj02;
  454 + }
  455 +
  456 + public void setLatitudeGcj02(double latitudeGcj02) {
  457 + this.latitudeGcj02 = latitudeGcj02;
  458 + }
  459 +
  460 + public double getLongitudeWgs84() {
  461 + return longitudeWgs84;
  462 + }
  463 +
  464 + public void setLongitudeWgs84(double longitudeWgs84) {
  465 + this.longitudeWgs84 = longitudeWgs84;
  466 + }
  467 +
  468 + public double getLatitudeWgs84() {
  469 + return latitudeWgs84;
  470 + }
  471 +
  472 + public void setLatitudeWgs84(double latitudeWgs84) {
  473 + this.latitudeWgs84 = latitudeWgs84;
  474 + }
  475 +
  476 + public int getSubCount() {
  477 + return subCount;
  478 + }
  479 +
  480 + public void setSubCount(int subCount) {
  481 + this.subCount = subCount;
  482 + }
  483 +
  484 + public boolean isHasAudio() {
  485 + return hasAudio;
  486 + }
  487 +
  488 + public void setHasAudio(boolean hasAudio) {
  489 + this.hasAudio = hasAudio;
  490 + }
  491 +
  492 + public String getStreamId() {
  493 + return streamId;
  494 + }
  495 +
  496 + public void setStreamId(String streamId) {
  497 + this.streamId = streamId;
  498 + }
  499 +
  500 + public String getCreateTime() {
  501 + return createTime;
  502 + }
  503 +
  504 + public void setCreateTime(String createTime) {
  505 + this.createTime = createTime;
  506 + }
  507 +
  508 + public String getUpdateTime() {
  509 + return updateTime;
  510 + }
  511 +
  512 + public void setUpdateTime(String updateTime) {
  513 + this.updateTime = updateTime;
  514 + }
  515 +
  516 + public int getChannelType() {
  517 + return channelType;
  518 + }
  519 +
  520 + public void setChannelType(int channelType) {
  521 + this.channelType = channelType;
  522 + }
  523 +
  524 + public String getBusinessGroupId() {
  525 + return businessGroupId;
  526 + }
  527 +
  528 + public void setBusinessGroupId(String businessGroupId) {
  529 + this.businessGroupId = businessGroupId;
  530 + }
  531 +
  532 + public String getGpsTime() {
  533 + return gpsTime;
  534 + }
  535 +
  536 + public void setGpsTime(String gpsTime) {
  537 + this.gpsTime = gpsTime;
  538 + }
  539 +
  540 + public String getDeviceName() {
  541 + return deviceName;
  542 + }
  543 +
  544 + public void setDeviceName(String deviceName) {
  545 + this.deviceName = deviceName;
  546 + }
  547 +
  548 + public int getDeviceOnline() {
  549 + return deviceOnline;
  550 + }
  551 +
  552 + public void setDeviceOnline(int deviceOnline) {
  553 + this.deviceOnline = deviceOnline;
  554 + }
  555 +}
src/main/resources/all-application.yml
@@ -30,44 +30,19 @@ spring: @@ -30,44 +30,19 @@ spring:
30 poolMaxWait: 5 30 poolMaxWait: 5
31 # [必选] jdbc数据库配置 31 # [必选] jdbc数据库配置
32 datasource: 32 datasource:
33 - type: com.alibaba.druid.pool.DruidDataSource 33 + type: com.zaxxer.hikari.HikariDataSource
34 driver-class-name: com.mysql.cj.jdbc.Driver 34 driver-class-name: com.mysql.cj.jdbc.Driver
35 url: jdbc:mysql://127.0.0.1:3306/wvp2?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true 35 url: jdbc:mysql://127.0.0.1:3306/wvp2?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true
36 username: root 36 username: root
37 password: root123 37 password: root123
38 - druid: 38 + hikari:
  39 + connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
39 initialSize: 10 # 连接池初始化连接数 40 initialSize: 10 # 连接池初始化连接数
40 - maxActive: 200 # 连接池最大连接数  
41 - minIdle: 5 # 连接池最小空闲连接数  
42 - maxWait: 60000 # 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。  
43 - keepAlive: true # 连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。  
44 - validationQuery: select 1 # 检测连接是否有效sql,要求是查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。  
45 - testWhileIdle: true # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。  
46 - testOnBorrow: false # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。  
47 - testOnReturn: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。  
48 - poolPreparedStatements: false # 是否開啟PSCache,並且指定每個連線上PSCache的大小  
49 - timeBetweenEvictionRunsMillis: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒  
50 - minEvictableIdleTimeMillis: 300000 # 配置一個連線在池中最小生存的時間,單位是毫秒  
51 - filters: stat,slf4j # 配置监控统计拦截的filters,监控统计用的filter:sta, 日志用的filter:log4j  
52 - useGlobalDataSourceStat: true # 合并多个DruidDataSource的监控数据  
53 - # 通过connectProperties属性来打开mergeSql功能;慢SQL记录  
54 - connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=1000  
55 - #stat-view-servlet.url-pattern: /admin/druid/* 41 + maximum-pool-size: 200 # 连接池最大连接数
  42 + minimum-idle: 5 # 连接池最小空闲连接数
  43 + idle-timeout: 300000 # 允许连接在连接池中空闲的最长时间(以毫秒为单位)
  44 + max-lifetime: 1200000 # 是池中连接关闭后的最长生命周期(以毫秒为单位)
56 45
57 -# druid管理监控页面的一些配置  
58 -rj-druid-manage:  
59 - allow: # 访问druid监控页面的IP白名单  
60 - deny: 192.168.1.100 # 访问druid监控页面IP黑名单  
61 - loginUsername: rjAdmin # 访问druid监控页面账号  
62 - loginPassword: rj@2022 # 访问druid监控页面密码  
63 -  
64 -#mybatis:  
65 -# configuration:  
66 -# # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用  
67 -# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  
68 -# # 返回类型为Map,显示null对应的字段  
69 -# call-setters-on-nulls: true  
70 -## [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口  
71 46
72 # [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 47 # [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
73 server: 48 server:
@@ -90,10 +65,10 @@ server: @@ -90,10 +65,10 @@ server:
90 65
91 # 作为28181服务器的配置 66 # 作为28181服务器的配置
92 sip: 67 sip:
93 - # [必须修改] 本机的IP, 必须是网卡上的IP,用于sip下协议栈监听ip,如果监听所有设置为0.0.0.0  
94 - monitor-ip: 0.0.0.0  
95 # [必须修改] 本机的IP 68 # [必须修改] 本机的IP
96 ip: 192.168.0.100 69 ip: 192.168.0.100
  70 + # [可选] 没有任何业务需求,仅仅是在前端展示的时候用
  71 + show-ip: 192.168.0.100
97 # [可选] 28181服务监听的端口 72 # [可选] 28181服务监听的端口
98 port: 5060 73 port: 5060
99 # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) 74 # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
@@ -203,6 +178,14 @@ user-settings: @@ -203,6 +178,14 @@ user-settings:
203 sip-log: true 178 sip-log: true
204 # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流 179 # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
205 push-stream-after-ack: false 180 push-stream-after-ack: false
  181 + # 消息通道功能-缺少国标ID是否给所有上级发送消息
  182 + send-to-platforms-when-id-lost: true
  183 + # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
  184 + refuse-channel-status-channel-form-notify: false
  185 + # 跨域配置,配置你访问前端页面的地址即可, 可以配置多个
  186 + allowed-origins:
  187 + - http://localhost:8008
  188 + - http://192.168.1.3:8008
206 189
207 # 关闭在线文档(生产环境建议关闭) 190 # 关闭在线文档(生产环境建议关闭)
208 springdoc: 191 springdoc:
web_src/build/utils.js
@@ -47,8 +47,7 @@ exports.cssLoaders = function (options) { @@ -47,8 +47,7 @@ exports.cssLoaders = function (options) {
47 if (options.extract) { 47 if (options.extract) {
48 return ExtractTextPlugin.extract({ 48 return ExtractTextPlugin.extract({
49 use: loaders, 49 use: loaders,
50 - fallback: 'vue-style-loader',  
51 - publicPath: '../../' 50 + fallback: 'vue-style-loader'
52 }) 51 })
53 } else { 52 } else {
54 return ['vue-style-loader'].concat(loaders) 53 return ['vue-style-loader'].concat(loaders)
web_src/config/index.js
@@ -8,8 +8,8 @@ module.exports = { @@ -8,8 +8,8 @@ module.exports = {
8 dev: { 8 dev: {
9 9
10 // Paths 10 // Paths
11 - assetsSubDirectory: './static',  
12 - assetsPublicPath: './', 11 + assetsSubDirectory: 'static',
  12 + assetsPublicPath: '/',
13 proxyTable: { 13 proxyTable: {
14 '/debug': { 14 '/debug': {
15 target: 'https://default.wvp-pro.cn:18082', 15 target: 'https://default.wvp-pro.cn:18082',
@@ -61,7 +61,7 @@ module.exports = { @@ -61,7 +61,7 @@ module.exports = {
61 // Paths 61 // Paths
62 assetsRoot: path.resolve(__dirname, '../../src/main/resources/static/'), 62 assetsRoot: path.resolve(__dirname, '../../src/main/resources/static/'),
63 assetsSubDirectory: './static', 63 assetsSubDirectory: './static',
64 - assetsPublicPath: './', 64 + assetsPublicPath: '/',
65 65
66 /** 66 /**
67 * Source Maps 67 * Source Maps
web_src/index.html
@@ -13,7 +13,8 @@ @@ -13,7 +13,8 @@
13 <script type="text/javascript" src="./static/js/EasyWasmPlayer.js"></script> 13 <script type="text/javascript" src="./static/js/EasyWasmPlayer.js"></script>
14 <script type="text/javascript" src="./static/js/liveplayer-lib.min.js"></script> 14 <script type="text/javascript" src="./static/js/liveplayer-lib.min.js"></script>
15 <script type="text/javascript" src="./static/js/ZLMRTCClient.js"></script> 15 <script type="text/javascript" src="./static/js/ZLMRTCClient.js"></script>
16 - <script type="text/javascript" src="./static/js/mapConfig.js"></script> 16 + <script type="text/javascript" src="./static/js/config.js"></script>
17 <div id="app"></div> 17 <div id="app"></div>
  18 +
18 </body> 19 </body>
19 </html> 20 </html>
web_src/package-lock.json
@@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
23 "vue-clipboard2": "^0.3.1", 23 "vue-clipboard2": "^0.3.1",
24 "vue-clipboards": "^1.3.0", 24 "vue-clipboards": "^1.3.0",
25 "vue-contextmenujs": "^1.3.13", 25 "vue-contextmenujs": "^1.3.13",
26 - "vue-cookies": "^1.7.4", 26 + "vue-cookies": "^1.8.3",
27 "vue-giant-tree": "^0.1.5", 27 "vue-giant-tree": "^0.1.5",
28 "vue-router": "^3.1.6", 28 "vue-router": "^3.1.6",
29 "vue-ztree-2.0": "^1.0.4" 29 "vue-ztree-2.0": "^1.0.4"
@@ -13135,9 +13135,9 @@ @@ -13135,9 +13135,9 @@
13135 "integrity": "sha1-O9rgI8e9QgleeNpCWAACUNUKuO8=" 13135 "integrity": "sha1-O9rgI8e9QgleeNpCWAACUNUKuO8="
13136 }, 13136 },
13137 "node_modules/vue-cookies": { 13137 "node_modules/vue-cookies": {
13138 - "version": "1.7.4",  
13139 - "resolved": "https://registry.npm.taobao.org/vue-cookies/download/vue-cookies-1.7.4.tgz?cache=0&sync_timestamp=1598941352058&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-cookies%2Fdownload%2Fvue-cookies-1.7.4.tgz",  
13140 - "integrity": "sha1-0kHQoEMdoHlYN2UdELTXPnyNPo0=" 13138 + "version": "1.8.3",
  13139 + "resolved": "https://registry.npmmirror.com/vue-cookies/-/vue-cookies-1.8.3.tgz",
  13140 + "integrity": "sha512-VBRsyRMVdahBgFfh389TMHPmDdr4URDJNMk4FKSCfuNITs7+jitBDhwyL4RJd3WUsfOYNNjPAkfbehyH9AFuoA=="
13141 }, 13141 },
13142 "node_modules/vue-giant-tree": { 13142 "node_modules/vue-giant-tree": {
13143 "version": "0.1.5", 13143 "version": "0.1.5",
@@ -25489,9 +25489,9 @@ @@ -25489,9 +25489,9 @@
25489 "integrity": "sha1-O9rgI8e9QgleeNpCWAACUNUKuO8=" 25489 "integrity": "sha1-O9rgI8e9QgleeNpCWAACUNUKuO8="
25490 }, 25490 },
25491 "vue-cookies": { 25491 "vue-cookies": {
25492 - "version": "1.7.4",  
25493 - "resolved": "https://registry.npm.taobao.org/vue-cookies/download/vue-cookies-1.7.4.tgz?cache=0&sync_timestamp=1598941352058&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-cookies%2Fdownload%2Fvue-cookies-1.7.4.tgz",  
25494 - "integrity": "sha1-0kHQoEMdoHlYN2UdELTXPnyNPo0=" 25492 + "version": "1.8.3",
  25493 + "resolved": "https://registry.npmmirror.com/vue-cookies/-/vue-cookies-1.8.3.tgz",
  25494 + "integrity": "sha512-VBRsyRMVdahBgFfh389TMHPmDdr4URDJNMk4FKSCfuNITs7+jitBDhwyL4RJd3WUsfOYNNjPAkfbehyH9AFuoA=="
25495 }, 25495 },
25496 "vue-giant-tree": { 25496 "vue-giant-tree": {
25497 "version": "0.1.5", 25497 "version": "0.1.5",
web_src/package.json
@@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
25 "vue-clipboard2": "^0.3.1", 25 "vue-clipboard2": "^0.3.1",
26 "vue-clipboards": "^1.3.0", 26 "vue-clipboards": "^1.3.0",
27 "vue-contextmenujs": "^1.3.13", 27 "vue-contextmenujs": "^1.3.13",
28 - "vue-cookies": "^1.7.4", 28 + "vue-cookies": "^1.8.3",
29 "vue-giant-tree": "^0.1.5", 29 "vue-giant-tree": "^0.1.5",
30 "vue-router": "^3.1.6", 30 "vue-router": "^3.1.6",
31 "vue-ztree-2.0": "^1.0.4" 31 "vue-ztree-2.0": "^1.0.4"
web_src/src/App.vue
@@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
5 </template> 5 </template>
6 6
7 <script> 7 <script>
  8 +import userService from './components/service/UserService'
8 export default { 9 export default {
9 name: 'app', 10 name: 'app',
10 data(){ 11 data(){
@@ -19,7 +20,7 @@ export default { @@ -19,7 +20,7 @@ export default {
19 } 20 }
20 }, 21 },
21 created() { 22 created() {
22 - if(!this.$cookies.get("session")){ 23 + if (userService.getToken() == null){
23 //如果没有登录状态则跳转到登录页 24 //如果没有登录状态则跳转到登录页
24 this.$router.push('/login'); 25 this.$router.push('/login');
25 } 26 }
@@ -33,28 +34,14 @@ export default { @@ -33,28 +34,14 @@ export default {
33 // this.getUserInfo(); 34 // this.getUserInfo();
34 }, 35 },
35 methods: { 36 methods: {
36 - //请求用户的一些信息  
37 - getUserInfo(){  
38 - var userinfo = this.$cookies.get("session");  
39 - },  
40 checkLogin(){ 37 checkLogin(){
41 //检查是否存在session 38 //检查是否存在session
42 - //cookie操作方法在源码里有或者参考网上的即可  
43 - if(!this.$cookies.get("session")){ 39 + if (userService.getToken() == null){
44 //如果没有登录状态则跳转到登录页 40 //如果没有登录状态则跳转到登录页
45 - this.$router.push('/login'); 41 + // this.$router.push('/login');
46 } 42 }
  43 +
47 }, 44 },
48 - getCookie: function (cname) {  
49 - var name = cname + "=";  
50 - var ca = document.cookie.split(';');  
51 - for (var i = 0; i < ca.length; i++) {  
52 - var c = ca[i];  
53 - while (c.charAt(0) == ' ') c = c.substring(1);  
54 - if (c.indexOf(name) != -1) return c.substring(name.length, c.length);  
55 - }  
56 - return "";  
57 - }  
58 }, 45 },
59 components: {} 46 components: {}
60 }; 47 };
web_src/src/components/CloudRecord.vue
@@ -133,7 +133,7 @@ @@ -133,7 +133,7 @@
133 let that = this; 133 let that = this;
134 this.$axios({ 134 this.$axios({
135 method: 'get', 135 method: 'get',
136 - url:`./record_proxy/${that.mediaServerId}/api/record/list`, 136 + url:`/record_proxy/${that.mediaServerId}/api/record/list`,
137 params: { 137 params: {
138 page: that.currentPage, 138 page: that.currentPage,
139 count: that.count 139 count: that.count
@@ -185,7 +185,7 @@ @@ -185,7 +185,7 @@
185 let that = this; 185 let that = this;
186 this.$axios({ 186 this.$axios({
187 method: 'delete', 187 method: 'delete',
188 - url:`./record_proxy/api/record/delete`, 188 + url:`/record_proxy/api/record/delete`,
189 params: { 189 params: {
190 page: that.currentPage, 190 page: that.currentPage,
191 count: that.count 191 count: that.count
web_src/src/components/CloudRecordDetail.vue
@@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
18 <i class="el-icon-video-camera" ></i> 18 <i class="el-icon-video-camera" ></i>
19 {{ item.substring(0,17)}} 19 {{ item.substring(0,17)}}
20 </el-tag> 20 </el-tag>
21 - <a class="el-icon-download" style="color: #409EFF;font-weight: 600;margin-left: 10px;" :href="`${basePath}/download.html?url=record/${recordFile.app}/${recordFile.stream}/${chooseDate}/${item}`" target="_blank" /> 21 + <a class="el-icon-download" style="color: #409EFF;font-weight: 600;margin-left: 10px;" :href="`${getFileBasePath()}/download.html?url=download/${recordFile.app}/${recordFile.stream}/${chooseDate}/${item}`" target="_blank" />
22 </li> 22 </li>
23 </ul> 23 </ul>
24 </div> 24 </div>
@@ -76,7 +76,7 @@ @@ -76,7 +76,7 @@
76 <li class="task-list-item" v-for="(item, index) in taskListEnded" :key="index"> 76 <li class="task-list-item" v-for="(item, index) in taskListEnded" :key="index">
77 <div class="task-list-item-box" style="height: 2rem;line-height: 2rem;"> 77 <div class="task-list-item-box" style="height: 2rem;line-height: 2rem;">
78 <span>{{ item.startTime.substr(10) }}-{{item.endTime.substr(10)}}</span> 78 <span>{{ item.startTime.substr(10) }}-{{item.endTime.substr(10)}}</span>
79 - <a class="el-icon-download download-btn" :href="mediaServerPath + '/download.html?url=../' + item.recordFile" target="_blank"> 79 + <a class="el-icon-download download-btn" :href="getFileBasePath() + '/download.html?url=download/' + item.recordFile" target="_blank">
80 </a> 80 </a>
81 </div> 81 </div>
82 </li> 82 </li>
@@ -107,15 +107,15 @@ @@ -107,15 +107,15 @@
107 import uiHeader from '../layout/UiHeader.vue' 107 import uiHeader from '../layout/UiHeader.vue'
108 import player from './dialog/easyPlayer.vue' 108 import player from './dialog/easyPlayer.vue'
109 import moment from 'moment' 109 import moment from 'moment'
  110 + import axios from "axios";
110 export default { 111 export default {
111 name: 'app', 112 name: 'app',
112 components: { 113 components: {
113 uiHeader, player 114 uiHeader, player
114 }, 115 },
115 - props: ['recordFile', 'mediaServerId', 'dateFiles', 'mediaServerPath'], 116 + props: ['recordFile', 'mediaServerId', 'dateFiles'],
116 data() { 117 data() {
117 return { 118 return {
118 - basePath: `${this.mediaServerPath}`,  
119 dateFilesObj: [], 119 dateFilesObj: [],
120 detailFiles: [], 120 detailFiles: [],
121 chooseDate: null, 121 chooseDate: null,
@@ -220,14 +220,18 @@ @@ -220,14 +220,18 @@
220 } 220 }
221 this.queryRecordDetails(()=>{ 221 this.queryRecordDetails(()=>{
222 if (this.detailFiles.length > 0){ 222 if (this.detailFiles.length > 0){
  223 + console.log(this.detailFiles)
223 let timeForFile = this.getTimeForFile(this.detailFiles[0]); 224 let timeForFile = this.getTimeForFile(this.detailFiles[0]);
224 let lastTimeForFile = this.getTimeForFile(this.detailFiles[this.detailFiles.length - 1]); 225 let lastTimeForFile = this.getTimeForFile(this.detailFiles[this.detailFiles.length - 1]);
225 let timeNum = timeForFile[0].getTime() - new Date(this.chooseDate + " " + this.timeFormat).getTime() 226 let timeNum = timeForFile[0].getTime() - new Date(this.chooseDate + " " + this.timeFormat).getTime()
  227 + console.log(timeNum)
226 let lastTimeNum = lastTimeForFile[1].getTime() - new Date(this.chooseDate + " " + this.timeFormat).getTime() 228 let lastTimeNum = lastTimeForFile[1].getTime() - new Date(this.chooseDate + " " + this.timeFormat).getTime()
227 229
228 this.playTime = parseInt(timeNum/1000) 230 this.playTime = parseInt(timeNum/1000)
229 this.sliderMIn = parseInt(timeNum/1000 - timeNum/1000%(60*60)) 231 this.sliderMIn = parseInt(timeNum/1000 - timeNum/1000%(60*60))
  232 + console.log(this.sliderMIn )
230 this.sliderMax = parseInt(lastTimeNum/1000 - lastTimeNum/1000%(60*60)) + 60*60 233 this.sliderMax = parseInt(lastTimeNum/1000 - lastTimeNum/1000%(60*60)) + 60*60
  234 + console.log(this.sliderMax )
231 } 235 }
232 }); 236 });
233 }, 237 },
@@ -241,7 +245,7 @@ @@ -241,7 +245,7 @@
241 let that = this; 245 let that = this;
242 that.$axios({ 246 that.$axios({
243 method: 'get', 247 method: 'get',
244 - url:`./record_proxy/${that.mediaServerId}/api/record/file/list`, 248 + url:`/record_proxy/${that.mediaServerId}/api/record/file/list`,
245 params: { 249 params: {
246 app: that.recordFile.app, 250 app: that.recordFile.app,
247 stream: that.recordFile.stream, 251 stream: that.recordFile.stream,
@@ -267,13 +271,23 @@ @@ -267,13 +271,23 @@
267 if (file == null) { 271 if (file == null) {
268 this.videoUrl = ""; 272 this.videoUrl = "";
269 }else { 273 }else {
270 - // TODO 控制列表滚动条  
271 - this.videoUrl = `${this.basePath}/record/${this.recordFile.app}/${this.recordFile.stream}/${this.chooseDate}/${this.choosedFile}` 274 + this.videoUrl = `${this.getFileBasePath()}/download/${this.recordFile.app}/${this.recordFile.stream}/${this.chooseDate}/${this.choosedFile}`
  275 +
272 console.log(this.videoUrl) 276 console.log(this.videoUrl)
273 } 277 }
274 278
275 }, 279 },
276 280
  281 + getFileBasePath(){
  282 + let basePath = ""
  283 + if (axios.defaults.baseURL.startsWith("http")) {
  284 + basePath = `${axios.defaults.baseURL}/record_proxy/${this.mediaServerId}`
  285 + }else {
  286 + basePath = `${window.location.origin}${axios.defaults.baseURL}/record_proxy/${this.mediaServerId}`
  287 + }
  288 + return basePath;
  289 + },
  290 +
277 getDataWidth(item){ 291 getDataWidth(item){
278 let timeForFile = this.getTimeForFile(item); 292 let timeForFile = this.getTimeForFile(item);
279 let result = (timeForFile[2])/((this.sliderMax - this.sliderMIn)*1000) 293 let result = (timeForFile[2])/((this.sliderMax - this.sliderMIn)*1000)
@@ -301,11 +315,12 @@ @@ -301,11 +315,12 @@
301 } 315 }
302 }, 316 },
303 getTimeForFile(file){ 317 getTimeForFile(file){
  318 + console.log(file)
304 let timeStr = file.substring(0,17); 319 let timeStr = file.substring(0,17);
305 if(timeStr.indexOf("~") > 0){ 320 if(timeStr.indexOf("~") > 0){
306 timeStr = timeStr.replaceAll("-",":") 321 timeStr = timeStr.replaceAll("-",":")
307 } 322 }
308 - let timeArr = timeStr.split("~"); 323 + let timeArr = timeStr.split("-");
309 let starTime = new Date(this.chooseDate + " " + timeArr[0]); 324 let starTime = new Date(this.chooseDate + " " + timeArr[0]);
310 let endTime = new Date(this.chooseDate + " " + timeArr[1]); 325 let endTime = new Date(this.chooseDate + " " + timeArr[1]);
311 if(this.checkIsOver24h(starTime,endTime)){ 326 if(this.checkIsOver24h(starTime,endTime)){
@@ -340,7 +355,7 @@ @@ -340,7 +355,7 @@
340 let that = this; 355 let that = this;
341 this.$axios({ 356 this.$axios({
342 method: 'delete', 357 method: 'delete',
343 - url:`./record_proxy/${that.mediaServerId}/api/record/delete`, 358 + url:`/record_proxy/${that.mediaServerId}/api/record/delete`,
344 params: { 359 params: {
345 page: that.currentPage, 360 page: that.currentPage,
346 count: that.count 361 count: that.count
@@ -359,7 +374,7 @@ @@ -359,7 +374,7 @@
359 that.dateFilesObj = {}; 374 that.dateFilesObj = {};
360 this.$axios({ 375 this.$axios({
361 method: 'get', 376 method: 'get',
362 - url:`./record_proxy/${that.mediaServerId}/api/record/date/list`, 377 + url:`/record_proxy/${that.mediaServerId}/api/record/date/list`,
363 params: { 378 params: {
364 app: that.recordFile.app, 379 app: that.recordFile.app,
365 stream: that.recordFile.stream 380 stream: that.recordFile.stream
@@ -408,7 +423,7 @@ @@ -408,7 +423,7 @@
408 let that = this; 423 let that = this;
409 this.$axios({ 424 this.$axios({
410 method: 'get', 425 method: 'get',
411 - url:`./record_proxy/${that.mediaServerId}/api/record/file/download/task/add`, 426 + url:`/record_proxy/${that.mediaServerId}/api/record/file/download/task/add`,
412 params: { 427 params: {
413 app: that.recordFile.app, 428 app: that.recordFile.app,
414 stream: that.recordFile.stream, 429 stream: that.recordFile.stream,
@@ -433,7 +448,7 @@ @@ -433,7 +448,7 @@
433 let that = this; 448 let that = this;
434 this.$axios({ 449 this.$axios({
435 method: 'get', 450 method: 'get',
436 - url:`./record_proxy/${that.mediaServerId}/api/record/file/download/task/list`, 451 + url:`/record_proxy/${that.mediaServerId}/api/record/file/download/task/list`,
437 params: { 452 params: {
438 isEnd: isEnd, 453 isEnd: isEnd,
439 } 454 }
web_src/src/components/DeviceList.vue
@@ -152,7 +152,7 @@ export default { @@ -152,7 +152,7 @@ export default {
152 this.getDeviceListLoading = true; 152 this.getDeviceListLoading = true;
153 this.$axios({ 153 this.$axios({
154 method: 'get', 154 method: 'get',
155 - url: `./api/device/query/devices`, 155 + url: `/api/device/query/devices`,
156 params: { 156 params: {
157 page: this.currentPage, 157 page: this.currentPage,
158 count: this.count 158 count: this.count
@@ -182,7 +182,7 @@ export default { @@ -182,7 +182,7 @@ export default {
182 }).then(() => { 182 }).then(() => {
183 this.$axios({ 183 this.$axios({
184 method: 'delete', 184 method: 'delete',
185 - url: `./api/device/query/devices/${row.deviceId}/delete` 185 + url: `/api/device/query/devices/${row.deviceId}/delete`
186 }).then((res) => { 186 }).then((res) => {
187 this.getDeviceList(); 187 this.getDeviceList();
188 }).catch((error) => { 188 }).catch((error) => {
@@ -208,7 +208,7 @@ export default { @@ -208,7 +208,7 @@ export default {
208 let that = this; 208 let that = this;
209 this.$axios({ 209 this.$axios({
210 method: 'get', 210 method: 'get',
211 - url: './api/device/query/devices/' + itemData.deviceId + '/sync' 211 + url: '/api/device/query/devices/' + itemData.deviceId + '/sync'
212 }).then((res) => { 212 }).then((res) => {
213 console.log("刷新设备结果:" + JSON.stringify(res)); 213 console.log("刷新设备结果:" + JSON.stringify(res));
214 if (res.data.code !== 0) { 214 if (res.data.code !== 0) {
@@ -242,7 +242,7 @@ export default { @@ -242,7 +242,7 @@ export default {
242 await this.$axios({ 242 await this.$axios({
243 method: 'get', 243 method: 'get',
244 async: false, 244 async: false,
245 - url: `./api/device/query/${deviceId}/sync_status/`, 245 + url: `/api/device/query/${deviceId}/sync_status/`,
246 }).then((res) => { 246 }).then((res) => {
247 if (res.data.code == 0) { 247 if (res.data.code == 0) {
248 if (res.data.data.errorMsg !== null) { 248 if (res.data.data.errorMsg !== null) {
@@ -261,7 +261,7 @@ export default { @@ -261,7 +261,7 @@ export default {
261 let that = this; 261 let that = this;
262 this.$axios({ 262 this.$axios({
263 method: 'post', 263 method: 'post',
264 - url: './api/device/query/transport/' + row.deviceId + '/' + row.streamMode 264 + url: '/api/device/query/transport/' + row.deviceId + '/' + row.streamMode
265 }).then(function (res) { 265 }).then(function (res) {
266 266
267 }).catch(function (e) { 267 }).catch(function (e) {
web_src/src/components/GBRecordDetail.vue
@@ -197,7 +197,7 @@ @@ -197,7 +197,7 @@
197 this.detailFiles = []; 197 this.detailFiles = [];
198 this.$axios({ 198 this.$axios({
199 method: 'get', 199 method: 'get',
200 - url: './api/gb_record/query/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.startTime + '&endTime=' + this.endTime 200 + url: '/api/gb_record/query/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.startTime + '&endTime=' + this.endTime
201 }).then((res)=>{ 201 }).then((res)=>{
202 this.recordsLoading = false; 202 this.recordsLoading = false;
203 if(res.data.code === 0) { 203 if(res.data.code === 0) {
@@ -249,7 +249,7 @@ @@ -249,7 +249,7 @@
249 } else { 249 } else {
250 this.$axios({ 250 this.$axios({
251 method: 'get', 251 method: 'get',
252 - url: './api/playback/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.startTime + '&endTime=' + 252 + url: '/api/playback/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.startTime + '&endTime=' +
253 this.endTime 253 this.endTime
254 }).then((res)=> { 254 }).then((res)=> {
255 if (res.data.code === 0) { 255 if (res.data.code === 0) {
@@ -273,7 +273,7 @@ @@ -273,7 +273,7 @@
273 console.log('前端控制:播放'); 273 console.log('前端控制:播放');
274 this.$axios({ 274 this.$axios({
275 method: 'get', 275 method: 'get',
276 - url: './api/playback/resume/' + this.streamId 276 + url: '/api/playback/resume/' + this.streamId
277 }).then((res)=> { 277 }).then((res)=> {
278 this.$refs["recordVideoPlayer"].play(this.videoUrl) 278 this.$refs["recordVideoPlayer"].play(this.videoUrl)
279 }); 279 });
@@ -282,14 +282,14 @@ @@ -282,14 +282,14 @@
282 console.log('前端控制:暂停'); 282 console.log('前端控制:暂停');
283 this.$axios({ 283 this.$axios({
284 method: 'get', 284 method: 'get',
285 - url: './api/playback/pause/' + this.streamId 285 + url: '/api/playback/pause/' + this.streamId
286 }).then(function (res) {}); 286 }).then(function (res) {});
287 }, 287 },
288 gbScale(command){ 288 gbScale(command){
289 console.log('前端控制:倍速 ' + command); 289 console.log('前端控制:倍速 ' + command);
290 this.$axios({ 290 this.$axios({
291 method: 'get', 291 method: 'get',
292 - url: `./api/playback/speed/${this.streamId }/${command}` 292 + url: `/api/playback/speed/${this.streamId }/${command}`
293 }).then(function (res) {}); 293 }).then(function (res) {});
294 }, 294 },
295 downloadRecord: function (row) { 295 downloadRecord: function (row) {
@@ -311,7 +311,7 @@ @@ -311,7 +311,7 @@
311 }else { 311 }else {
312 this.$axios({ 312 this.$axios({
313 method: 'get', 313 method: 'get',
314 - url: './api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' + 314 + url: '/api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
315 row.endTime + '&downloadSpeed=4' 315 row.endTime + '&downloadSpeed=4'
316 }).then( (res)=> { 316 }).then( (res)=> {
317 if (res.data.code === 0) { 317 if (res.data.code === 0) {
@@ -332,7 +332,7 @@ @@ -332,7 +332,7 @@
332 this.videoUrl = ''; 332 this.videoUrl = '';
333 this.$axios({ 333 this.$axios({
334 method: 'get', 334 method: 'get',
335 - url: './api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId 335 + url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId
336 }).then((res)=> { 336 }).then((res)=> {
337 if (callback) callback(res) 337 if (callback) callback(res)
338 }); 338 });
@@ -342,7 +342,7 @@ @@ -342,7 +342,7 @@
342 this.videoUrl = ''; 342 this.videoUrl = '';
343 this.$axios({ 343 this.$axios({
344 method: 'get', 344 method: 'get',
345 - url: './api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId 345 + url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId
346 }).then(function (res) { 346 }).then(function (res) {
347 if (callback) callback() 347 if (callback) callback()
348 }); 348 });
web_src/src/components/Login.vue
@@ -35,6 +35,7 @@ @@ -35,6 +35,7 @@
35 35
36 <script> 36 <script>
37 import crypto from 'crypto' 37 import crypto from 'crypto'
  38 +import userService from "./service/UserService";
38 export default { 39 export default {
39 name: 'Login', 40 name: 'Login',
40 data(){ 41 data(){
@@ -81,13 +82,14 @@ export default { @@ -81,13 +82,14 @@ export default {
81 82
82 this.$axios({ 83 this.$axios({
83 method: 'get', 84 method: 'get',
84 - url:"./api/user/login", 85 + url:"/api/user/login",
85 params: loginParam 86 params: loginParam
86 }).then(function (res) { 87 }).then(function (res) {
87 window.clearTimeout(timeoutTask) 88 window.clearTimeout(timeoutTask)
88 - console.log(JSON.stringify(res)); 89 + console.log(res);
  90 + console.log("登录成功");
89 if (res.data.code === 0 ) { 91 if (res.data.code === 0 ) {
90 - that.$cookies.set("session", {"username": that.username,"roleId":res.data.data.role.id}) ; 92 + userService.setUser(res.data.data)
91 //登录成功后 93 //登录成功后
92 that.cancelEnterkeyDefaultAction(); 94 that.cancelEnterkeyDefaultAction();
93 that.$router.push('/'); 95 that.$router.push('/');
@@ -106,14 +108,6 @@ export default { @@ -106,14 +108,6 @@ export default {
106 that.isLoging = false; 108 that.isLoging = false;
107 }); 109 });
108 }, 110 },
109 - setCookie: function (cname, cvalue, exdays) {  
110 - var d = new Date();  
111 - d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));  
112 - var expires = "expires=" + d.toUTCString();  
113 - console.info(cname + "=" + cvalue + "; " + expires);  
114 - document.cookie = cname + "=" + cvalue + "; " + expires;  
115 - console.info(document.cookie);  
116 - },  
117 cancelEnterkeyDefaultAction: function() { 111 cancelEnterkeyDefaultAction: function() {
118 document.onkeydown = function(e) { 112 document.onkeydown = function(e) {
119 var key = window.event.keyCode; 113 var key = window.event.keyCode;
web_src/src/components/ParentPlatformList.vue
@@ -128,7 +128,7 @@ export default { @@ -128,7 +128,7 @@ export default {
128 var that = this; 128 var that = this;
129 that.$axios({ 129 that.$axios({
130 method: 'delete', 130 method: 'delete',
131 - url:`./api/platform/delete/${platform.serverGBId}` 131 + url:`/api/platform/delete/${platform.serverGBId}`
132 }).then(function (res) { 132 }).then(function (res) {
133 if (res.data.code === 0) { 133 if (res.data.code === 0) {
134 that.$message({ 134 that.$message({
@@ -162,7 +162,7 @@ export default { @@ -162,7 +162,7 @@ export default {
162 162
163 this.$axios({ 163 this.$axios({
164 method: 'get', 164 method: 'get',
165 - url:`./api/platform/query/${that.count}/${that.currentPage}` 165 + url:`/api/platform/query/${that.count}/${that.currentPage}`
166 }).then(function (res) { 166 }).then(function (res) {
167 if (res.data.code === 0) { 167 if (res.data.code === 0) {
168 that.total = res.data.data.total; 168 that.total = res.data.data.total;
web_src/src/components/PushVideoList.vue
@@ -171,7 +171,7 @@ export default { @@ -171,7 +171,7 @@ export default {
171 this.getDeviceListLoading = true; 171 this.getDeviceListLoading = true;
172 this.$axios({ 172 this.$axios({
173 method: 'get', 173 method: 'get',
174 - url: `./api/push/list`, 174 + url: `/api/push/list`,
175 params: { 175 params: {
176 page: that.currentPage, 176 page: that.currentPage,
177 count: that.count, 177 count: that.count,
@@ -197,7 +197,7 @@ export default { @@ -197,7 +197,7 @@ export default {
197 this.getListLoading = true; 197 this.getListLoading = true;
198 this.$axios({ 198 this.$axios({
199 method: 'get', 199 method: 'get',
200 - url: './api/push/getPlayUrl', 200 + url: '/api/push/getPlayUrl',
201 params: { 201 params: {
202 app: row.app, 202 app: row.app,
203 stream: row.stream, 203 stream: row.stream,
@@ -223,7 +223,7 @@ export default { @@ -223,7 +223,7 @@ export default {
223 let that = this; 223 let that = this;
224 that.$axios({ 224 that.$axios({
225 method: "post", 225 method: "post",
226 - url: "./api/push/stop", 226 + url: "/api/push/stop",
227 params: { 227 params: {
228 app: row.app, 228 app: row.app,
229 streamId: row.stream 229 streamId: row.stream
@@ -247,7 +247,7 @@ export default { @@ -247,7 +247,7 @@ export default {
247 let that = this; 247 let that = this;
248 that.$axios({ 248 that.$axios({
249 method: "delete", 249 method: "delete",
250 - url: "./api/push/remove_form_gb", 250 + url: "/api/push/remove_form_gb",
251 data: row 251 data: row
252 }).then((res) => { 252 }).then((res) => {
253 if (res.data.code === 0) { 253 if (res.data.code === 0) {
@@ -274,7 +274,7 @@ export default { @@ -274,7 +274,7 @@ export default {
274 let that = this; 274 let that = this;
275 that.$axios({ 275 that.$axios({
276 method: "delete", 276 method: "delete",
277 - url: "./api/push/batchStop", 277 + url: "/api/push/batchStop",
278 data: { 278 data: {
279 gbStreams: this.multipleSelection 279 gbStreams: this.multipleSelection
280 } 280 }
web_src/src/components/StreamProxyList.vue
@@ -167,7 +167,7 @@ @@ -167,7 +167,7 @@
167 let that = this; 167 let that = this;
168 this.$axios({ 168 this.$axios({
169 method: 'get', 169 method: 'get',
170 - url:`./api/proxy/list`, 170 + url:`/api/proxy/list`,
171 params: { 171 params: {
172 page: that.currentPage, 172 page: that.currentPage,
173 count: that.count 173 count: that.count
@@ -190,7 +190,7 @@ @@ -190,7 +190,7 @@
190 addOnvif: function(){ 190 addOnvif: function(){
191 this.$axios({ 191 this.$axios({
192 method: 'get', 192 method: 'get',
193 - url:`./api/onvif/search?timeout=3000`, 193 + url:`/api/onvif/search?timeout=3000`,
194 }).then((res) =>{ 194 }).then((res) =>{
195 if (res.data.code === 0 ){ 195 if (res.data.code === 0 ){
196 if (res.data.data.length > 0) { 196 if (res.data.data.length > 0) {
@@ -218,7 +218,7 @@ @@ -218,7 +218,7 @@
218 let that = this; 218 let that = this;
219 this.$axios({ 219 this.$axios({
220 method: 'get', 220 method: 'get',
221 - url:`./api/push/getPlayUrl`, 221 + url:`/api/push/getPlayUrl`,
222 params: { 222 params: {
223 app: row.app, 223 app: row.app,
224 stream: row.stream, 224 stream: row.stream,
@@ -247,7 +247,7 @@ @@ -247,7 +247,7 @@
247 let that = this; 247 let that = this;
248 that.$axios({ 248 that.$axios({
249 method:"delete", 249 method:"delete",
250 - url:"./api/proxy/del", 250 + url:"/api/proxy/del",
251 params:{ 251 params:{
252 app: row.app, 252 app: row.app,
253 stream: row.stream 253 stream: row.stream
@@ -263,7 +263,7 @@ @@ -263,7 +263,7 @@
263 this.$set(row, 'startBtnLoading', true) 263 this.$set(row, 'startBtnLoading', true)
264 this.$axios({ 264 this.$axios({
265 method: 'get', 265 method: 'get',
266 - url:`./api/proxy/start`, 266 + url:`/api/proxy/start`,
267 params: { 267 params: {
268 app: row.app, 268 app: row.app,
269 stream: row.stream 269 stream: row.stream
@@ -295,7 +295,7 @@ @@ -295,7 +295,7 @@
295 let that = this; 295 let that = this;
296 this.$axios({ 296 this.$axios({
297 method: 'get', 297 method: 'get',
298 - url:`./api/proxy/stop`, 298 + url:`/api/proxy/stop`,
299 params: { 299 params: {
300 app: row.app, 300 app: row.app,
301 stream: row.stream 301 stream: row.stream
web_src/src/components/UserManager.vue
@@ -99,7 +99,7 @@ export default { @@ -99,7 +99,7 @@ export default {
99 this.getUserListLoading = true; 99 this.getUserListLoading = true;
100 this.$axios({ 100 this.$axios({
101 method: 'get', 101 method: 'get',
102 - url: `./api/user/users`, 102 + url: `/api/user/users`,
103 params: { 103 params: {
104 page: that.currentPage, 104 page: that.currentPage,
105 count: that.count 105 count: that.count
@@ -141,7 +141,7 @@ export default { @@ -141,7 +141,7 @@ export default {
141 }).then(() => { 141 }).then(() => {
142 this.$axios({ 142 this.$axios({
143 method: 'delete', 143 method: 'delete',
144 - url: `./api/user/delete?id=${row.id}` 144 + url: `/api/user/delete?id=${row.id}`
145 }).then((res) => { 145 }).then((res) => {
146 this.getUserList(); 146 this.getUserList();
147 }).catch((error) => { 147 }).catch((error) => {
web_src/src/components/channelList.vue
@@ -69,7 +69,7 @@ @@ -69,7 +69,7 @@
69 <span v-if="scope.row.longitude*scope.row.latitude === 0">无</span> 69 <span v-if="scope.row.longitude*scope.row.latitude === 0">无</span>
70 </template> 70 </template>
71 </el-table-column> 71 </el-table-column>
72 - <el-table-column prop="ptztypeText" label="云台类型" min-width="120"/> 72 + <el-table-column prop="PTZTypeText" label="云台类型" min-width="120"/>
73 <el-table-column label="开启音频" min-width="120"> 73 <el-table-column label="开启音频" min-width="120">
74 <template slot-scope="scope"> 74 <template slot-scope="scope">
75 <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF"> 75 <el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
@@ -206,7 +206,7 @@ export default { @@ -206,7 +206,7 @@ export default {
206 if (typeof (this.$route.params.deviceId) == "undefined") return; 206 if (typeof (this.$route.params.deviceId) == "undefined") return;
207 this.$axios({ 207 this.$axios({
208 method: 'get', 208 method: 'get',
209 - url: `./api/device/query/devices/${this.$route.params.deviceId}/channels`, 209 + url: `/api/device/query/devices/${this.$route.params.deviceId}/channels`,
210 params: { 210 params: {
211 page: that.currentPage, 211 page: that.currentPage,
212 count: that.count, 212 count: that.count,
@@ -238,7 +238,7 @@ export default { @@ -238,7 +238,7 @@ export default {
238 let that = this; 238 let that = this;
239 this.$axios({ 239 this.$axios({
240 method: 'get', 240 method: 'get',
241 - url: './api/play/start/' + deviceId + '/' + channelId 241 + url: '/api/play/start/' + deviceId + '/' + channelId
242 }).then(function (res) { 242 }).then(function (res) {
243 console.log(res) 243 console.log(res)
244 that.isLoging = false; 244 that.isLoging = false;
@@ -278,7 +278,7 @@ export default { @@ -278,7 +278,7 @@ export default {
278 var that = this; 278 var that = this;
279 this.$axios({ 279 this.$axios({
280 method: 'get', 280 method: 'get',
281 - url: './api/play/stop/' + this.deviceId + "/" + itemData.channelId 281 + url: '/api/play/stop/' + this.deviceId + "/" + itemData.channelId
282 }).then(function (res) { 282 }).then(function (res) {
283 that.initData(); 283 that.initData();
284 }).catch(function (error) { 284 }).catch(function (error) {
@@ -334,7 +334,7 @@ export default { @@ -334,7 +334,7 @@ export default {
334 if (!this.showTree) { 334 if (!this.showTree) {
335 this.$axios({ 335 this.$axios({
336 method: 'get', 336 method: 'get',
337 - url: `./api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`, 337 + url: `/api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`,
338 params: { 338 params: {
339 page: this.currentPage, 339 page: this.currentPage,
340 count: this.count, 340 count: this.count,
@@ -358,7 +358,7 @@ export default { @@ -358,7 +358,7 @@ export default {
358 }else { 358 }else {
359 this.$axios({ 359 this.$axios({
360 method: 'get', 360 method: 'get',
361 - url: `./api/device/query/tree/channel/${this.deviceId}`, 361 + url: `/api/device/query/tree/channel/${this.deviceId}`,
362 params: { 362 params: {
363 parentId: this.parentChannelId, 363 parentId: this.parentChannelId,
364 page: this.currentPage, 364 page: this.currentPage,
@@ -387,7 +387,7 @@ export default { @@ -387,7 +387,7 @@ export default {
387 updateChannel: function (row) { 387 updateChannel: function (row) {
388 this.$axios({ 388 this.$axios({
389 method: 'post', 389 method: 'post',
390 - url: `./api/device/query/channel/update/${this.deviceId}`, 390 + url: `/api/device/query/channel/update/${this.deviceId}`,
391 params: row 391 params: row
392 }).then(function (res) { 392 }).then(function (res) {
393 console.log(JSON.stringify(res)); 393 console.log(JSON.stringify(res));
web_src/src/components/common/jessibuca.vue
1 <template> 1 <template>
2 - <div ref="container" @dblclick="fullscreenSwich" style="width:100%;height:100%;background-color: #000000;margin:0 auto;"> 2 + <div ref="container" @dblclick="fullscreenSwich"
  3 + style="width:100%;height:100%;background-color: #000000;margin:0 auto;">
3 <div class="buttons-box" id="buttonsBox"> 4 <div class="buttons-box" id="buttonsBox">
4 <div class="buttons-box-left"> 5 <div class="buttons-box-left">
5 <i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick"></i> 6 <i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick"></i>
@@ -12,7 +13,7 @@ @@ -12,7 +13,7 @@
12 <span class="jessibuca-btn">{{ kBps }} kb/s</span> 13 <span class="jessibuca-btn">{{ kBps }} kb/s</span>
13 <!-- <i class="iconfont icon-file-record1 jessibuca-btn"></i>--> 14 <!-- <i class="iconfont icon-file-record1 jessibuca-btn"></i>-->
14 <!-- <i class="iconfont icon-xiangqing2 jessibuca-btn" ></i>--> 15 <!-- <i class="iconfont icon-xiangqing2 jessibuca-btn" ></i>-->
15 - <i class="iconfont icon-camera1196054easyiconnet jessibuca-btn" @click="jessibuca.screenshot('截图','png',0.5)" 16 + <i class="iconfont icon-camera1196054easyiconnet jessibuca-btn" @click="screenshot"
16 style="font-size: 1rem !important"></i> 17 style="font-size: 1rem !important"></i>
17 <i class="iconfont icon-shuaxin11 jessibuca-btn" @click="playBtnClick"></i> 18 <i class="iconfont icon-shuaxin11 jessibuca-btn" @click="playBtnClick"></i>
18 <i v-if="!fullscreen" class="iconfont icon-weibiaoti10 jessibuca-btn" @click="fullscreenSwich"></i> 19 <i v-if="!fullscreen" class="iconfont icon-weibiaoti10 jessibuca-btn" @click="fullscreenSwich"></i>
@@ -92,29 +93,49 @@ export default { @@ -92,29 +93,49 @@ export default {
92 jessibucaPlayer[this._uid] = new window.Jessibuca(Object.assign( 93 jessibucaPlayer[this._uid] = new window.Jessibuca(Object.assign(
93 { 94 {
94 container: this.$refs.container, 95 container: this.$refs.container,
95 - videoBuffer: 0.2, // 最大缓冲时长,单位秒  
96 - isResize: true, 96 + autoWasm: true,
  97 + background: "",
  98 + controlAutoHide: false,
  99 + debug: false,
97 decoder: "static/js/jessibuca/decoder.js", 100 decoder: "static/js/jessibuca/decoder.js",
98 - useMSE: false,  
99 - showBandwidth: false,  
100 - isFlv: true,  
101 - // text: "WVP-PRO",  
102 - // background: "static/images/zlm-logo.png",  
103 - loadingText: "加载中", 101 + forceNoOffscreen: true,
104 hasAudio: typeof (this.hasAudio) == "undefined" ? true : this.hasAudio, 102 hasAudio: typeof (this.hasAudio) == "undefined" ? true : this.hasAudio,
105 - debug: false,  
106 - supportDblclickFullscreen: false, // 是否支持屏幕的双击事件,触发全屏,取消全屏事件。 103 + hasVideo: true,
  104 + heartTimeout: 5,
  105 + heartTimeoutReplay: true,
  106 + heartTimeoutReplayTimes: 3,
  107 + hiddenAutoPause: false,
  108 + hotKey: false,
  109 + isFlv: false,
  110 + isFullResize: false,
  111 + isNotMute: this.isNotMute,
  112 + isResize: false,
  113 + keepScreenOn: false,
  114 + loadingText: "请稍等, 视频加载中......",
  115 + loadingTimeout: 10,
  116 + loadingTimeoutReplay: true,
  117 + loadingTimeoutReplayTimes: 3,
  118 + openWebglAlignment: false,
107 operateBtns: { 119 operateBtns: {
108 fullscreen: false, 120 fullscreen: false,
109 screenshot: false, 121 screenshot: false,
110 play: false, 122 play: false,
111 audio: false, 123 audio: false,
112 - recorder: false, 124 + record: false
113 }, 125 },
114 - record: "record",  
115 - vod: this.vod,  
116 - forceNoOffscreen: this.forceNoOffscreen,  
117 - isNotMute: this.isNotMute, 126 + recordType: "webm",
  127 + rotate: 0,
  128 + showBandwidth: false,
  129 + supportDblclickFullscreen: false,
  130 + timeout: 10,
  131 + useMSE: location.hostname !== "localhost" && location.protocol !== "https:",
  132 + useOffscreen: false,
  133 + useWCS: location.hostname === "localhost" || location.protocol === "https",
  134 + useWebFullScreen: false,
  135 + videoBuffer: 0,
  136 + wasmDecodeAudioSyncVideo: true,
  137 + wasmDecodeErrorReplay: true,
  138 + wcsUseVideoRender: true
118 }, 139 },
119 options 140 options
120 )); 141 ));
@@ -146,13 +167,7 @@ export default { @@ -146,13 +167,7 @@ export default {
146 _this.isNotMute = !msg; 167 _this.isNotMute = !msg;
147 }); 168 });
148 jessibuca.on("audioInfo", function (msg) { 169 jessibuca.on("audioInfo", function (msg) {
149 - // console.log("audioInfo", msg);  
150 - });  
151 -  
152 - jessibuca.on("videoInfo", function (msg) {  
153 - // this.videoInfo = msg;  
154 - console.log("videoInfo", msg);  
155 - 170 + console.log("audioInfo", msg);
156 }); 171 });
157 172
158 jessibuca.on("bps", function (bps) { 173 jessibuca.on("bps", function (bps) {
@@ -243,6 +258,11 @@ export default { @@ -243,6 +258,11 @@ export default {
243 this.err = ""; 258 this.err = "";
244 this.performance = ""; 259 this.performance = "";
245 }, 260 },
  261 + screenshot: function () {
  262 + if (jessibucaPlayer[this._uid]) {
  263 + jessibucaPlayer[this._uid].screenshot();
  264 + }
  265 + },
246 mute: function () { 266 mute: function () {
247 if (jessibucaPlayer[this._uid]) { 267 if (jessibucaPlayer[this._uid]) {
248 jessibucaPlayer[this._uid].mute(); 268 jessibucaPlayer[this._uid].mute();
web_src/src/components/console.vue
@@ -114,7 +114,7 @@ export default { @@ -114,7 +114,7 @@ export default {
114 getSystemInfo: function (){ 114 getSystemInfo: function (){
115 this.$axios({ 115 this.$axios({
116 method: 'get', 116 method: 'get',
117 - url: `./api/server/system/info`, 117 + url: `/api/server/system/info`,
118 }).then( (res)=> { 118 }).then( (res)=> {
119 if (res.data.code === 0) { 119 if (res.data.code === 0) {
120 this.$refs.consoleCPU.setData(res.data.data.cpu) 120 this.$refs.consoleCPU.setData(res.data.data.cpu)
@@ -128,7 +128,7 @@ export default { @@ -128,7 +128,7 @@ export default {
128 getLoad: function (){ 128 getLoad: function (){
129 this.$axios({ 129 this.$axios({
130 method: 'get', 130 method: 'get',
131 - url: `./api/server/media_server/load`, 131 + url: `/api/server/media_server/load`,
132 }).then( (res)=> { 132 }).then( (res)=> {
133 if (res.data.code === 0) { 133 if (res.data.code === 0) {
134 this.$refs.consoleNodeLoad.setData(res.data.data) 134 this.$refs.consoleNodeLoad.setData(res.data.data)
@@ -139,7 +139,7 @@ export default { @@ -139,7 +139,7 @@ export default {
139 getResourceInfo: function (){ 139 getResourceInfo: function (){
140 this.$axios({ 140 this.$axios({
141 method: 'get', 141 method: 'get',
142 - url: `./api/server/resource/info`, 142 + url: `/api/server/resource/info`,
143 }).then( (res)=> { 143 }).then( (res)=> {
144 if (res.data.code === 0) { 144 if (res.data.code === 0) {
145 this.$refs.consoleResource.setData(res.data.data) 145 this.$refs.consoleResource.setData(res.data.data)
@@ -151,7 +151,7 @@ export default { @@ -151,7 +151,7 @@ export default {
151 151
152 this.$axios({ 152 this.$axios({
153 method: 'get', 153 method: 'get',
154 - url: `./api/server/system/configInfo`, 154 + url: `/api/server/system/configInfo`,
155 }).then( (res)=> { 155 }).then( (res)=> {
156 console.log(res) 156 console.log(res)
157 if (res.data.code === 0) { 157 if (res.data.code === 0) {
web_src/src/components/dialog/MediaServerEdit.vue
@@ -78,7 +78,7 @@ @@ -78,7 +78,7 @@
78 <el-switch v-model="mediaServerForm.autoConfig" :disabled="mediaServerForm.defaultServer"></el-switch> 78 <el-switch v-model="mediaServerForm.autoConfig" :disabled="mediaServerForm.defaultServer"></el-switch>
79 </el-form-item> 79 </el-form-item>
80 <el-form-item label="收流端口模式" > 80 <el-form-item label="收流端口模式" >
81 - <el-switch active-text="多端口" inactive-text="单端口" v-model="mediaServerForm.rtpEnable" :disabled="mediaServerForm.defaultServer"></el-switch> 81 + <el-switch active-text="多端口" inactive-text="单端口" @change="portRangeChange" v-model="mediaServerForm.rtpEnable" :disabled="mediaServerForm.defaultServer"></el-switch>
82 </el-form-item> 82 </el-form-item>
83 83
84 <el-form-item v-if="!mediaServerForm.rtpEnable" label="收流端口" prop="rtpProxyPort"> 84 <el-form-item v-if="!mediaServerForm.rtpEnable" label="收流端口" prop="rtpProxyPort">
@@ -335,7 +335,7 @@ export default { @@ -335,7 +335,7 @@ export default {
335 var that = this; 335 var that = this;
336 await that.$axios({ 336 await that.$axios({
337 method: 'get', 337 method: 'get',
338 - url:`./api/platform/exit/${deviceGbId}` 338 + url:`/api/platform/exit/${deviceGbId}`
339 }).then(function (res) { 339 }).then(function (res) {
340 result = res.data; 340 result = res.data;
341 }).catch(function (error) { 341 }).catch(function (error) {
@@ -349,8 +349,10 @@ export default { @@ -349,8 +349,10 @@ export default {
349 } 349 }
350 }, 350 },
351 portRangeChange: function() { 351 portRangeChange: function() {
352 - this.mediaServerForm.rtpPortRange = this.rtpPortRange1 + "," + this.rtpPortRange2  
353 - console.log(this.mediaServerForm.rtpPortRange) 352 + if (this.mediaServerForm.rtpEnable) {
  353 + this.mediaServerForm.rtpPortRange = this.rtpPortRange1 + "," + this.rtpPortRange2
  354 + console.log(this.mediaServerForm.rtpPortRange)
  355 + }
354 } 356 }
355 }, 357 },
356 }; 358 };
web_src/src/components/dialog/StreamProxyEdit.vue
@@ -195,7 +195,7 @@ export default { @@ -195,7 +195,7 @@ export default {
195 let that = this; 195 let that = this;
196 this.$axios({ 196 this.$axios({
197 method: 'get', 197 method: 'get',
198 - url:`./api/platform/query/10000/1` 198 + url:`/api/platform/query/10000/1`
199 }).then(function (res) { 199 }).then(function (res) {
200 that.platformList = res.data.data.list; 200 that.platformList = res.data.data.list;
201 }).catch(function (error) { 201 }).catch(function (error) {
@@ -212,7 +212,7 @@ export default { @@ -212,7 +212,7 @@ export default {
212 if (that.proxyParam.mediaServerId !== "auto"){ 212 if (that.proxyParam.mediaServerId !== "auto"){
213 that.$axios({ 213 that.$axios({
214 method: 'get', 214 method: 'get',
215 - url:`./api/proxy/ffmpeg_cmd/list`, 215 + url:`/api/proxy/ffmpeg_cmd/list`,
216 params: { 216 params: {
217 mediaServerId: that.proxyParam.mediaServerId 217 mediaServerId: that.proxyParam.mediaServerId
218 } 218 }
@@ -230,7 +230,7 @@ export default { @@ -230,7 +230,7 @@ export default {
230 this.noneReaderHandler(); 230 this.noneReaderHandler();
231 this.$axios({ 231 this.$axios({
232 method: 'post', 232 method: 'post',
233 - url:`./api/proxy/save`, 233 + url:`/api/proxy/save`,
234 data: this.proxyParam 234 data: this.proxyParam
235 }).then((res)=> { 235 }).then((res)=> {
236 this.dialogLoading = false; 236 this.dialogLoading = false;
@@ -261,7 +261,7 @@ export default { @@ -261,7 +261,7 @@ export default {
261 var that = this; 261 var that = this;
262 await that.$axios({ 262 await that.$axios({
263 method: 'get', 263 method: 'get',
264 - url:`./api/platform/exit/${deviceGbId}` 264 + url:`/api/platform/exit/${deviceGbId}`
265 }).then(function (res) { 265 }).then(function (res) {
266 result = res.data; 266 result = res.data;
267 }).catch(function (error) { 267 }).catch(function (error) {
web_src/src/components/dialog/SyncChannelProgress.vue
@@ -55,7 +55,7 @@ export default { @@ -55,7 +55,7 @@ export default {
55 getProgress(){ 55 getProgress(){
56 this.$axios({ 56 this.$axios({
57 method: 'get', 57 method: 'get',
58 - url:`./api/device/query/${this.deviceId}/sync_status/`, 58 + url:`/api/device/query/${this.deviceId}/sync_status/`,
59 }).then((res) => { 59 }).then((res) => {
60 if (res.data.code === 0) { 60 if (res.data.code === 0) {
61 if (!this.syncFlag) { 61 if (!this.syncFlag) {
web_src/src/components/dialog/addUser.vue
@@ -100,7 +100,7 @@ export default { @@ -100,7 +100,7 @@ export default {
100 onSubmit: function () { 100 onSubmit: function () {
101 this.$axios({ 101 this.$axios({
102 method: 'post', 102 method: 'post',
103 - url: "./api/user/add", 103 + url: "/api/user/add",
104 params: { 104 params: {
105 username: this.username, 105 username: this.username,
106 password: this.password, 106 password: this.password,
@@ -139,7 +139,7 @@ export default { @@ -139,7 +139,7 @@ export default {
139 139
140 this.$axios({ 140 this.$axios({
141 method: 'get', 141 method: 'get',
142 - url: "./api/role/all" 142 + url: "/api/role/all"
143 }).then((res) => { 143 }).then((res) => {
144 this.loading = true; 144 this.loading = true;
145 if (res.data.code === 0) { 145 if (res.data.code === 0) {
web_src/src/components/dialog/catalogEdit.vue
@@ -116,7 +116,7 @@ export default { @@ -116,7 +116,7 @@ export default {
116 console.log(this.form); 116 console.log(this.form);
117 this.$axios({ 117 this.$axios({
118 method:"post", 118 method:"post",
119 - url:`./api/platform/catalog/${!this.isEdit? "add":"edit"}`, 119 + url:`/api/platform/catalog/${!this.isEdit? "add":"edit"}`,
120 data: this.form 120 data: this.form
121 }).then((res)=> { 121 }).then((res)=> {
122 if (res.data.code === 0) { 122 if (res.data.code === 0) {
web_src/src/components/dialog/changePassword.vue
@@ -35,6 +35,7 @@ @@ -35,6 +35,7 @@
35 35
36 <script> 36 <script>
37 import crypto from 'crypto' 37 import crypto from 'crypto'
  38 +import userService from "../service/UserService";
38 export default { 39 export default {
39 name: "changePassword", 40 name: "changePassword",
40 props: {}, 41 props: {},
@@ -90,7 +91,7 @@ export default { @@ -90,7 +91,7 @@ export default {
90 onSubmit: function () { 91 onSubmit: function () {
91 this.$axios({ 92 this.$axios({
92 method: 'post', 93 method: 'post',
93 - url:"./api/user/changePassword", 94 + url:"/api/user/changePassword",
94 params: { 95 params: {
95 oldPassword: crypto.createHash('md5').update(this.oldPassword, "utf8").digest('hex'), 96 oldPassword: crypto.createHash('md5').update(this.oldPassword, "utf8").digest('hex'),
96 password: this.newPassword 97 password: this.newPassword
@@ -105,7 +106,7 @@ export default { @@ -105,7 +106,7 @@ export default {
105 this.showDialog = false; 106 this.showDialog = false;
106 setTimeout(()=>{ 107 setTimeout(()=>{
107 // 删除cookie,回到登录页面 108 // 删除cookie,回到登录页面
108 - this.$cookies.remove("session"); 109 + userService.clearUserInfo();
109 this.$router.push('/login'); 110 this.$router.push('/login');
110 this.sseSource.close(); 111 this.sseSource.close();
111 },800) 112 },800)
web_src/src/components/dialog/changePasswordForAdmin.vue
@@ -85,7 +85,7 @@ export default { @@ -85,7 +85,7 @@ export default {
85 onSubmit: function () { 85 onSubmit: function () {
86 this.$axios({ 86 this.$axios({
87 method: 'post', 87 method: 'post',
88 - url:"./api/user/changePasswordForAdmin", 88 + url:"/api/user/changePasswordForAdmin",
89 params: { 89 params: {
90 password: this.newPassword, 90 password: this.newPassword,
91 userId: this.form.id, 91 userId: this.form.id,
web_src/src/components/dialog/changePushKey.vue
@@ -65,7 +65,7 @@ export default { @@ -65,7 +65,7 @@ export default {
65 onSubmit: function () { 65 onSubmit: function () {
66 this.$axios({ 66 this.$axios({
67 method: 'post', 67 method: 'post',
68 - url:"./api/user/changePushKey", 68 + url:"/api/user/changePushKey",
69 params: { 69 params: {
70 pushKey: this.newPushKey, 70 pushKey: this.newPushKey,
71 userId: this.form.id, 71 userId: this.form.id,
web_src/src/components/dialog/channelMapInfobox.vue
@@ -44,7 +44,7 @@ export default { @@ -44,7 +44,7 @@ export default {
44 let that = this; 44 let that = this;
45 this.$axios({ 45 this.$axios({
46 method: 'get', 46 method: 'get',
47 - url: './api/play/start/' + deviceId + '/' + channelId 47 + url: '/api/play/start/' + deviceId + '/' + channelId
48 }).then(function (res) { 48 }).then(function (res) {
49 that.isLoging = false; 49 that.isLoging = false;
50 if (res.data.code === 0) { 50 if (res.data.code === 0) {
web_src/src/components/dialog/chooseChannel.vue
1 <template> 1 <template>
2 -<div id="chooseChannel" v-loading="isLoging"> 2 +<div id="chooseChannel" >
3 3
4 - <el-dialog title="选择通道" v-if="showDialog" top="2rem" width="90%" :close-on-click-modal="false" :visible.sync="showDialog" :destroy-on-close="true" @close="close()"> 4 + <el-dialog title="选择通道" v-loading="loading" v-if="showDialog" top="2rem" width="90%" :close-on-click-modal="false" :visible.sync="showDialog" :destroy-on-close="true" @close="close()">
5 <el-row> 5 <el-row>
6 <el-col :span="10"> 6 <el-col :span="10">
7 <el-tabs v-model="catalogTabActiveName" > 7 <el-tabs v-model="catalogTabActiveName" >
@@ -56,7 +56,7 @@ export default { @@ -56,7 +56,7 @@ export default {
56 }, 56 },
57 data() { 57 data() {
58 return { 58 return {
59 - isLoging: false, 59 + loading: false,
60 tabActiveName: "gbChannel", 60 tabActiveName: "gbChannel",
61 catalogTabActiveName: "catalog", 61 catalogTabActiveName: "catalog",
62 platformId: "", 62 platformId: "",
@@ -94,18 +94,17 @@ export default { @@ -94,18 +94,17 @@ export default {
94 94
95 }, 95 },
96 save: function() { 96 save: function() {
97 - var that = this;  
98 97
99 this.$axios({ 98 this.$axios({
100 method:"post", 99 method:"post",
101 - url:"./api/platform/update_channel_for_gb", 100 + url:"/api/platform/update_channel_for_gb",
102 data:{ 101 data:{
103 - platformId: that.platformId,  
104 - channelReduces: that.chooseData 102 + platformId: this.platformId,
  103 + channelReduces: this.chooseData
105 } 104 }
106 }).then((res)=>{ 105 }).then((res)=>{
107 if (res.data.code === 0) { 106 if (res.data.code === 0) {
108 - that.$message({ 107 + this.$message({
109 showClose: true, 108 showClose: true,
110 message: '保存成功,', 109 message: '保存成功,',
111 type: 'success' 110 type: 'success'
@@ -114,6 +113,7 @@ export default { @@ -114,6 +113,7 @@ export default {
114 }).catch(function (error) { 113 }).catch(function (error) {
115 console.log(error); 114 console.log(error);
116 }); 115 });
  116 +
117 }, 117 },
118 catalogIdChange: function (id, name) { 118 catalogIdChange: function (id, name) {
119 this.catalogId = id; 119 this.catalogId = id;
web_src/src/components/dialog/chooseChannelForCatalog.vue
@@ -82,7 +82,7 @@ export default { @@ -82,7 +82,7 @@ export default {
82 let that = this; 82 let that = this;
83 this.$axios({ 83 this.$axios({
84 method:"get", 84 method:"get",
85 - url:`./api/platform/catalog`, 85 + url:`/api/platform/catalog`,
86 params: { 86 params: {
87 platformId: that.platformId, 87 platformId: that.platformId,
88 parentId: parentId 88 parentId: parentId
@@ -134,7 +134,7 @@ export default { @@ -134,7 +134,7 @@ export default {
134 removeCatalog: function (id, node){ 134 removeCatalog: function (id, node){
135 this.$axios({ 135 this.$axios({
136 method:"delete", 136 method:"delete",
137 - url:`./api/platform/catalog/del`, 137 + url:`/api/platform/catalog/del`,
138 params: { 138 params: {
139 id: id, 139 id: id,
140 platformId: this.platformId, 140 platformId: this.platformId,
@@ -156,7 +156,7 @@ export default { @@ -156,7 +156,7 @@ export default {
156 setDefaultCatalog: function (id){ 156 setDefaultCatalog: function (id){
157 this.$axios({ 157 this.$axios({
158 method:"post", 158 method:"post",
159 - url:`./api/platform/catalog/default/update`, 159 + url:`/api/platform/catalog/default/update`,
160 params: { 160 params: {
161 platformId: this.platformId, 161 platformId: this.platformId,
162 catalogId: id, 162 catalogId: id,
@@ -201,7 +201,7 @@ export default { @@ -201,7 +201,7 @@ export default {
201 onClick: () => { 201 onClick: () => {
202 this.$axios({ 202 this.$axios({
203 method:"delete", 203 method:"delete",
204 - url:"./api/platform/catalog/relation/del", 204 + url:"/api/platform/catalog/relation/del",
205 data: data 205 data: data
206 }).then((res)=>{ 206 }).then((res)=>{
207 console.log("移除成功") 207 console.log("移除成功")
web_src/src/components/dialog/chooseChannelForGb.vue
1 <template> 1 <template>
2 -<div id="chooseChannelForGb" > 2 +<div id="chooseChannelForGb" v-loading="loading">
3 <div style="font-size: 17px; color: #606060; white-space: nowrap; line-height: 30px; font-family: monospace;"> 3 <div style="font-size: 17px; color: #606060; white-space: nowrap; line-height: 30px; font-family: monospace;">
4 <span v-if="catalogId == null">{{catalogName}}的国标通道</span> 4 <span v-if="catalogId == null">{{catalogName}}的国标通道</span>
5 <span v-if="catalogId != null">{{catalogName}}({{catalogId}})的国标通道</span> 5 <span v-if="catalogId != null">{{catalogName}}({{catalogId}})的国标通道</span>
@@ -79,6 +79,7 @@ export default { @@ -79,6 +79,7 @@ export default {
79 }, 79 },
80 data() { 80 data() {
81 return { 81 return {
  82 + loading: false,
82 gbChannels: [], 83 gbChannels: [],
83 gbChoosechannel:{}, 84 gbChoosechannel:{},
84 searchSrt: "", 85 searchSrt: "",
@@ -118,10 +119,12 @@ export default { @@ -118,10 +119,12 @@ export default {
118 }, 119 },
119 add: function (row) { 120 add: function (row) {
120 let all = typeof(row) === "undefined" 121 let all = typeof(row) === "undefined"
  122 +
121 this.getCatalogFromUser((catalogId)=> { 123 this.getCatalogFromUser((catalogId)=> {
  124 + let task = null;
122 this.$axios({ 125 this.$axios({
123 method:"post", 126 method:"post",
124 - url:"./api/platform/update_channel_for_gb", 127 + url:"/api/platform/update_channel_for_gb",
125 data:{ 128 data:{
126 platformId: this.platformId, 129 platformId: this.platformId,
127 all: all, 130 all: all,
@@ -130,12 +133,20 @@ export default { @@ -130,12 +133,20 @@ export default {
130 } 133 }
131 }).then((res)=>{ 134 }).then((res)=>{
132 console.log("保存成功") 135 console.log("保存成功")
  136 + window.clearTimeout(task);
  137 + this.loading = false;
133 this.getChannelList(); 138 this.getChannelList();
134 - }).catch(function (error) { 139 + }).catch((error)=> {
  140 + window.clearTimeout(task);
  141 + this.loading = false;
135 console.log(error); 142 console.log(error);
136 }); 143 });
  144 + task= setTimeout(()=>{
  145 + this.loading = true;
  146 + }, 200)
137 }) 147 })
138 148
  149 +
139 }, 150 },
140 remove: function (row) { 151 remove: function (row) {
141 let all = typeof(row) === "undefined" 152 let all = typeof(row) === "undefined"
@@ -149,7 +160,7 @@ export default { @@ -149,7 +160,7 @@ export default {
149 160
150 this.$axios({ 161 this.$axios({
151 method:"delete", 162 method:"delete",
152 - url:"./api/platform/del_channel_for_gb", 163 + url:"/api/platform/del_channel_for_gb",
153 data:{ 164 data:{
154 platformId: this.platformId, 165 platformId: this.platformId,
155 all: all, 166 all: all,
@@ -248,7 +259,7 @@ export default { @@ -248,7 +259,7 @@ export default {
248 259
249 this.$axios({ 260 this.$axios({
250 method:"get", 261 method:"get",
251 - url:`./api/platform/channel_list`, 262 + url:`/api/platform/channel_list`,
252 params: { 263 params: {
253 page: that.currentPage, 264 page: that.currentPage,
254 count: that.count, 265 count: that.count,
@@ -290,7 +301,7 @@ export default { @@ -290,7 +301,7 @@ export default {
290 }).then(() => { 301 }).then(() => {
291 this.$axios({ 302 this.$axios({
292 method:"delete", 303 method:"delete",
293 - url:"./api/platform/del_channel_for_gb", 304 + url:"/api/platform/del_channel_for_gb",
294 data:{ 305 data:{
295 platformId: this.platformId, 306 platformId: this.platformId,
296 channelReduces: this.multipleSelection 307 channelReduces: this.multipleSelection
@@ -310,7 +321,7 @@ export default { @@ -310,7 +321,7 @@ export default {
310 321
311 this.$axios({ 322 this.$axios({
312 method: "post", 323 method: "post",
313 - url: "./api/platform/update_channel_for_gb", 324 + url: "/api/platform/update_channel_for_gb",
314 data: { 325 data: {
315 platformId: this.platformId, 326 platformId: this.platformId,
316 channelReduces: this.multipleSelection, 327 channelReduces: this.multipleSelection,
web_src/src/components/dialog/chooseChannelForStream.vue
1 <template> 1 <template>
2 -<div id="chooseChannelFoStream" > 2 +<div id="chooseChannelFoStream" v-loading="loading">
3 <div style="font-size: 17px; color: #606060; white-space: nowrap; line-height: 30px; font-family: monospace;"> 3 <div style="font-size: 17px; color: #606060; white-space: nowrap; line-height: 30px; font-family: monospace;">
4 <span v-if="catalogId == null">{{catalogName}}的直播通道</span> 4 <span v-if="catalogId == null">{{catalogName}}的直播通道</span>
5 <span v-if="catalogId != null">{{catalogName}}({{catalogId}})的直播通道</span> 5 <span v-if="catalogId != null">{{catalogName}}({{catalogId}})的直播通道</span>
@@ -85,6 +85,7 @@ export default { @@ -85,6 +85,7 @@ export default {
85 }, 85 },
86 data() { 86 data() {
87 return { 87 return {
  88 + loading: false,
88 gbStreams: [], 89 gbStreams: [],
89 gbChoosechannel:{}, 90 gbChoosechannel:{},
90 channelType: "", 91 channelType: "",
@@ -132,9 +133,10 @@ export default { @@ -132,9 +133,10 @@ export default {
132 add: function (row, scope) { 133 add: function (row, scope) {
133 let all = typeof(row) === "undefined" 134 let all = typeof(row) === "undefined"
134 this.getCatalogFromUser((catalogId)=>{ 135 this.getCatalogFromUser((catalogId)=>{
  136 + let task = null;
135 this.$axios({ 137 this.$axios({
136 method:"post", 138 method:"post",
137 - url:"./api/gbStream/add", 139 + url:"/api/gbStream/add",
138 data:{ 140 data:{
139 platformId: this.platformId, 141 platformId: this.platformId,
140 catalogId: catalogId, 142 catalogId: catalogId,
@@ -143,11 +145,18 @@ export default { @@ -143,11 +145,18 @@ export default {
143 } 145 }
144 }).then((res)=>{ 146 }).then((res)=>{
145 console.log("保存成功") 147 console.log("保存成功")
  148 + window.clearTimeout(task);
  149 + this.loading = false;
146 // this.gbStreams.splice(scope.$index,1) 150 // this.gbStreams.splice(scope.$index,1)
147 this.getChannelList(); 151 this.getChannelList();
148 }).catch(function (error) { 152 }).catch(function (error) {
  153 + window.clearTimeout(task);
  154 + this.loading = false;
149 console.log(error); 155 console.log(error);
150 }); 156 });
  157 + task= setTimeout(()=>{
  158 + this.loading = true;
  159 + }, 200)
151 }) 160 })
152 161
153 162
@@ -163,7 +172,7 @@ export default { @@ -163,7 +172,7 @@ export default {
163 172
164 this.$axios({ 173 this.$axios({
165 method:"delete", 174 method:"delete",
166 - url:"./api/gbStream/del", 175 + url:"/api/gbStream/del",
167 data:{ 176 data:{
168 platformId: this.platformId, 177 platformId: this.platformId,
169 all: all, 178 all: all,
@@ -186,7 +195,7 @@ export default { @@ -186,7 +195,7 @@ export default {
186 195
187 this.$axios({ 196 this.$axios({
188 method: 'get', 197 method: 'get',
189 - url:`./api/gbStream/list`, 198 + url:`/api/gbStream/list`,
190 params: { 199 params: {
191 page: that.currentPage, 200 page: that.currentPage,
192 count: that.count, 201 count: that.count,
@@ -222,7 +231,7 @@ export default { @@ -222,7 +231,7 @@ export default {
222 }).then(() => { 231 }).then(() => {
223 this.$axios({ 232 this.$axios({
224 method:"delete", 233 method:"delete",
225 - url:"./api/gbStream/del", 234 + url:"/api/gbStream/del",
226 data:{ 235 data:{
227 platformId: this.platformId, 236 platformId: this.platformId,
228 gbStreams: this.multipleSelection, 237 gbStreams: this.multipleSelection,
@@ -242,7 +251,7 @@ export default { @@ -242,7 +251,7 @@ export default {
242 this.getCatalogFromUser((catalogId)=>{ 251 this.getCatalogFromUser((catalogId)=>{
243 this.$axios({ 252 this.$axios({
244 method:"post", 253 method:"post",
245 - url:"./api/gbStream/add", 254 + url:"/api/gbStream/add",
246 data:{ 255 data:{
247 platformId: this.platformId, 256 platformId: this.platformId,
248 catalogId: catalogId, 257 catalogId: catalogId,
web_src/src/components/dialog/configInfo.vue
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 <el-descriptions title="国标服务信息" v-if="configInfoData.sip" :span="2"> 13 <el-descriptions title="国标服务信息" v-if="configInfoData.sip" :span="2">
14 <el-descriptions-item label="编号" >{{configInfoData.sip.id}}</el-descriptions-item> 14 <el-descriptions-item label="编号" >{{configInfoData.sip.id}}</el-descriptions-item>
15 <el-descriptions-item label="域">{{configInfoData.sip.domain}}</el-descriptions-item> 15 <el-descriptions-item label="域">{{configInfoData.sip.domain}}</el-descriptions-item>
16 - <el-descriptions-item label="IP">{{configInfoData.sip.ip}}</el-descriptions-item> 16 + <el-descriptions-item label="IP">{{configInfoData.sip.showIp}}</el-descriptions-item>
17 <el-descriptions-item label="端口">{{configInfoData.sip.port}}</el-descriptions-item> 17 <el-descriptions-item label="端口">{{configInfoData.sip.port}}</el-descriptions-item>
18 <el-descriptions-item label="密码"> 18 <el-descriptions-item label="密码">
19 <el-tag size="small">{{configInfoData.sip.password}}</el-tag> 19 <el-tag size="small">{{configInfoData.sip.password}}</el-tag>
web_src/src/components/dialog/deviceEdit.vue
@@ -69,6 +69,7 @@ @@ -69,6 +69,7 @@
69 </el-form-item> 69 </el-form-item>
70 <el-form-item label="其他选项"> 70 <el-form-item label="其他选项">
71 <el-checkbox label="SSRC校验" v-model="form.ssrcCheck" style="float: left"></el-checkbox> 71 <el-checkbox label="SSRC校验" v-model="form.ssrcCheck" style="float: left"></el-checkbox>
  72 + <el-checkbox label="作为消息通道" v-model="form.asMessageChannel" style="float: left"></el-checkbox>
72 </el-form-item> 73 </el-form-item>
73 <el-form-item> 74 <el-form-item>
74 <div style="float: right;"> 75 <div style="float: right;">
@@ -134,7 +135,7 @@ export default { @@ -134,7 +135,7 @@ export default {
134 this.form.mobilePositionSubmissionInterval = this.form.mobilePositionSubmissionInterval||0 135 this.form.mobilePositionSubmissionInterval = this.form.mobilePositionSubmissionInterval||0
135 this.$axios({ 136 this.$axios({
136 method: 'post', 137 method: 'post',
137 - url:`./api/device/query/device/${this.isEdit?'update':'add'}/`, 138 + url:`/api/device/query/device/${this.isEdit?'update':'add'}/`,
138 params: this.form 139 params: this.form
139 }).then((res) => { 140 }).then((res) => {
140 console.log(res.data) 141 console.log(res.data)
web_src/src/components/dialog/getCatalog.vue
@@ -89,7 +89,7 @@ export default { @@ -89,7 +89,7 @@ export default {
89 let that = this; 89 let that = this;
90 this.$axios({ 90 this.$axios({
91 method:"get", 91 method:"get",
92 - url:`./api/platform/catalog`, 92 + url:`/api/platform/catalog`,
93 params: { 93 params: {
94 platformId: that.platformId, 94 platformId: that.platformId,
95 parentId: parentId 95 parentId: parentId
@@ -111,7 +111,7 @@ export default { @@ -111,7 +111,7 @@ export default {
111 if (node.level === 0) { 111 if (node.level === 0) {
112 this.$axios({ 112 this.$axios({
113 method:"get", 113 method:"get",
114 - url:`./api/platform/info/` + this.platformId, 114 + url:`/api/platform/info/` + this.platformId,
115 }) 115 })
116 .then((res)=> { 116 .then((res)=> {
117 if (res.data.code === 0) { 117 if (res.data.code === 0) {
web_src/src/components/dialog/importChannel.vue
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 drag 16 drag
17 :action="uploadUrl" 17 :action="uploadUrl"
18 name="file" 18 name="file"
  19 + :headers="headers"
19 :on-success="successHook" 20 :on-success="successHook"
20 :on-error="errorHook" 21 :on-error="errorHook"
21 > 22 >
@@ -33,6 +34,8 @@ @@ -33,6 +34,8 @@
33 34
34 import ShowErrorData from './importChannelShowErrorData.vue' 35 import ShowErrorData from './importChannelShowErrorData.vue'
35 36
  37 +import userService from "../service/UserService";
  38 +
36 export default { 39 export default {
37 name: "importChannel", 40 name: "importChannel",
38 components: { 41 components: {
@@ -47,7 +50,10 @@ export default { @@ -47,7 +50,10 @@ export default {
47 isEdit: false, 50 isEdit: false,
48 errorStreams: [], 51 errorStreams: [],
49 errorGBIds: [], 52 errorGBIds: [],
50 - uploadUrl: process.env.NODE_ENV === 'development'?`debug/api/push/upload`:`api/push/upload`, 53 + headers: {
  54 + "access-token": userService.getToken()
  55 + },
  56 + uploadUrl: process.env.NODE_ENV === 'development'? `http://127.0.0.1:8080/debug/api/push/upload`: (window.baseUrl ? window.baseUrl : "") + `/api/push/upload`,
51 }; 57 };
52 }, 58 },
53 methods: { 59 methods: {
@@ -60,7 +66,7 @@ export default { @@ -60,7 +66,7 @@ export default {
60 console.log(this.form); 66 console.log(this.form);
61 this.$axios({ 67 this.$axios({
62 method:"post", 68 method:"post",
63 - url:`./api/platform/catalog/${!this.isEdit? "add":"edit"}`, 69 + url:`/api/platform/catalog/${!this.isEdit? "add":"edit"}`,
64 data: this.form 70 data: this.form
65 }) 71 })
66 .then((res)=> { 72 .then((res)=> {
web_src/src/components/dialog/onvifEdit.vue
@@ -81,7 +81,7 @@ export default { @@ -81,7 +81,7 @@ export default {
81 console.log(this.form); 81 console.log(this.form);
82 this.$axios({ 82 this.$axios({
83 method: 'get', 83 method: 'get',
84 - url:`./api/onvif/rtsp`, 84 + url:`/api/onvif/rtsp`,
85 params: { 85 params: {
86 hostname: this.form.hostName, 86 hostname: this.form.hostName,
87 timeout: 3000, 87 timeout: 3000,
web_src/src/components/dialog/platformEdit.vue
@@ -96,9 +96,10 @@ @@ -96,9 +96,10 @@
96 </el-form-item> 96 </el-form-item>
97 <el-form-item label="其他选项"> 97 <el-form-item label="其他选项">
98 <el-checkbox label="启用" v-model="platform.enable" @change="checkExpires"></el-checkbox> 98 <el-checkbox label="启用" v-model="platform.enable" @change="checkExpires"></el-checkbox>
99 - <el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox> 99 +<!-- <el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox>-->
100 <el-checkbox label="拉起离线推流" v-model="platform.startOfflinePush"></el-checkbox> 100 <el-checkbox label="拉起离线推流" v-model="platform.startOfflinePush"></el-checkbox>
101 <el-checkbox label="RTCP保活" v-model="platform.rtcp" @change="rtcpCheckBoxChange"></el-checkbox> 101 <el-checkbox label="RTCP保活" v-model="platform.rtcp" @change="rtcpCheckBoxChange"></el-checkbox>
  102 + <el-checkbox label="作为消息通道" v-model="platform.asMessageChannel" ></el-checkbox>
102 </el-form-item> 103 </el-form-item>
103 <el-form-item> 104 <el-form-item>
104 <el-button type="primary" @click="onSubmit">{{ 105 <el-button type="primary" @click="onSubmit">{{
@@ -138,13 +139,14 @@ export default { @@ -138,13 +139,14 @@ export default {
138 showDialog: false, 139 showDialog: false,
139 isLoging: false, 140 isLoging: false,
140 onSubmit_text: "立即创建", 141 onSubmit_text: "立即创建",
141 - saveUrl: "./api/platform/save", 142 + saveUrl: "/api/platform/save",
142 143
143 platform: { 144 platform: {
144 id: null, 145 id: null,
145 enable: true, 146 enable: true,
146 ptz: true, 147 ptz: true,
147 rtcp: false, 148 rtcp: false,
  149 + asMessageChannel: false,
148 name: null, 150 name: null,
149 serverGBId: null, 151 serverGBId: null,
150 serverGBDomain: null, 152 serverGBDomain: null,
@@ -155,7 +157,7 @@ export default { @@ -155,7 +157,7 @@ export default {
155 devicePort: null, 157 devicePort: null,
156 username: null, 158 username: null,
157 password: null, 159 password: null,
158 - expires: 300, 160 + expires: 3600,
159 keepTimeout: 60, 161 keepTimeout: 60,
160 transport: "UDP", 162 transport: "UDP",
161 characterSet: "GB2312", 163 characterSet: "GB2312",
@@ -192,7 +194,7 @@ export default { @@ -192,7 +194,7 @@ export default {
192 this.saveUrl = "/api/platform/add"; 194 this.saveUrl = "/api/platform/add";
193 this.$axios({ 195 this.$axios({
194 method: 'get', 196 method: 'get',
195 - url:`./api/platform/server_config` 197 + url:`/api/platform/server_config`
196 }).then(function (res) { 198 }).then(function (res) {
197 console.log(res); 199 console.log(res);
198 if (res.data.code === 0) { 200 if (res.data.code === 0) {
@@ -213,6 +215,7 @@ export default { @@ -213,6 +215,7 @@ export default {
213 this.platform.enable = platform.enable; 215 this.platform.enable = platform.enable;
214 this.platform.ptz = platform.ptz; 216 this.platform.ptz = platform.ptz;
215 this.platform.rtcp = platform.rtcp; 217 this.platform.rtcp = platform.rtcp;
  218 + this.platform.asMessageChannel = platform.asMessageChannel;
216 this.platform.name = platform.name; 219 this.platform.name = platform.name;
217 this.platform.serverGBId = platform.serverGBId; 220 this.platform.serverGBId = platform.serverGBId;
218 this.platform.serverGBDomain = platform.serverGBDomain; 221 this.platform.serverGBDomain = platform.serverGBDomain;
@@ -290,6 +293,7 @@ export default { @@ -290,6 +293,7 @@ export default {
290 enable: true, 293 enable: true,
291 ptz: true, 294 ptz: true,
292 rtcp: false, 295 rtcp: false,
  296 + asMessageChannel: false,
293 name: null, 297 name: null,
294 serverGBId: null, 298 serverGBId: null,
295 administrativeDivision: null, 299 administrativeDivision: null,
@@ -301,7 +305,7 @@ export default { @@ -301,7 +305,7 @@ export default {
301 devicePort: null, 305 devicePort: null,
302 username: null, 306 username: null,
303 password: null, 307 password: null,
304 - expires: 300, 308 + expires: 3600,
305 keepTimeout: 60, 309 keepTimeout: 60,
306 transport: "UDP", 310 transport: "UDP",
307 characterSet: "GB2312", 311 characterSet: "GB2312",
@@ -315,7 +319,7 @@ export default { @@ -315,7 +319,7 @@ export default {
315 var that = this; 319 var that = this;
316 await that.$axios({ 320 await that.$axios({
317 method: 'get', 321 method: 'get',
318 - url:`./api/platform/exit/${deviceGbId}`}) 322 + url:`/api/platform/exit/${deviceGbId}`})
319 .then(function (res) { 323 .then(function (res) {
320 if (res.data.code === 0) { 324 if (res.data.code === 0) {
321 result = res.data.data; 325 result = res.data.data;
@@ -327,8 +331,8 @@ export default { @@ -327,8 +331,8 @@ export default {
327 return result; 331 return result;
328 }, 332 },
329 checkExpires: function() { 333 checkExpires: function() {
330 - if (this.platform.enable && this.platform.expires == "0") {  
331 - this.platform.expires = "300"; 334 + if (this.platform.enable && this.platform.expires === "0") {
  335 + this.platform.expires = "3600";
332 } 336 }
333 }, 337 },
334 rtcpCheckBoxChange: function (result){ 338 rtcpCheckBoxChange: function (result){
web_src/src/components/dialog/pushStreamEdit.vue
@@ -109,7 +109,7 @@ export default { @@ -109,7 +109,7 @@ export default {
109 if (this.edit) { 109 if (this.edit) {
110 this.$axios({ 110 this.$axios({
111 method:"post", 111 method:"post",
112 - url:`./api/push/save_to_gb`, 112 + url:`/api/push/save_to_gb`,
113 data: this.proxyParam 113 data: this.proxyParam
114 }).then( (res) => { 114 }).then( (res) => {
115 if (res.data.code === 0) { 115 if (res.data.code === 0) {
@@ -129,7 +129,7 @@ export default { @@ -129,7 +129,7 @@ export default {
129 }else { 129 }else {
130 this.$axios({ 130 this.$axios({
131 method:"post", 131 method:"post",
132 - url:`./api/push/add`, 132 + url:`/api/push/add`,
133 data: this.proxyParam 133 data: this.proxyParam
134 }).then( (res) => { 134 }).then( (res) => {
135 if (res.data.code === 0) { 135 if (res.data.code === 0) {
@@ -159,7 +159,7 @@ export default { @@ -159,7 +159,7 @@ export default {
159 var that = this; 159 var that = this;
160 await that.$axios({ 160 await that.$axios({
161 method:"get", 161 method:"get",
162 - url:`./api/platform/exit/${deviceGbId}` 162 + url:`/api/platform/exit/${deviceGbId}`
163 }).then(function (res) { 163 }).then(function (res) {
164 result = res.data; 164 result = res.data;
165 }).catch(function (error) { 165 }).catch(function (error) {
web_src/src/components/dialog/queryTrace.vue
@@ -72,7 +72,7 @@ export default { @@ -72,7 +72,7 @@ export default {
72 onSubmit: function () { 72 onSubmit: function () {
73 console.log("onSubmit"); 73 console.log("onSubmit");
74 this.isLoging = true; 74 this.isLoging = true;
75 - let url = `./api/position/history/${this.channel.deviceId}?start=${this.searchFrom}&end=${this.searchTo}`; 75 + let url = `/api/position/history/${this.channel.deviceId}?start=${this.searchFrom}&end=${this.searchTo}`;
76 if (this.channel.channelId) { 76 if (this.channel.channelId) {
77 url+="&channelId=${this.channel.channelId}" 77 url+="&channelId=${this.channel.channelId}"
78 } 78 }
web_src/src/components/dialog/recordDownload.vue
@@ -71,7 +71,7 @@ export default { @@ -71,7 +71,7 @@ export default {
71 getProgress: function (callback){ 71 getProgress: function (callback){
72 this.$axios({ 72 this.$axios({
73 method: 'get', 73 method: 'get',
74 - url: `./api/gb_record/download/progress/${this.deviceId}/${this.channelId}/${this.stream}` 74 + url: `/api/gb_record/download/progress/${this.deviceId}/${this.channelId}/${this.stream}`
75 }).then((res)=> { 75 }).then((res)=> {
76 console.log(res) 76 console.log(res)
77 if (res.data.code === 0) { 77 if (res.data.code === 0) {
@@ -124,7 +124,7 @@ export default { @@ -124,7 +124,7 @@ export default {
124 stopDownloadRecord: function (callback) { 124 stopDownloadRecord: function (callback) {
125 this.$axios({ 125 this.$axios({
126 method: 'get', 126 method: 'get',
127 - url: './api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.stream 127 + url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.stream
128 }).then((res)=> { 128 }).then((res)=> {
129 if (callback) callback(res) 129 if (callback) callback(res)
130 }); 130 });
@@ -132,7 +132,7 @@ export default { @@ -132,7 +132,7 @@ export default {
132 getFileDownload: function (){ 132 getFileDownload: function (){
133 this.$axios({ 133 this.$axios({
134 method: 'get', 134 method: 'get',
135 - url:`./record_proxy/${this.mediaServerId}/api/record/file/download/task/add`, 135 + url:`/record_proxy/${this.mediaServerId}/api/record/file/download/task/add`,
136 params: { 136 params: {
137 app: this.app, 137 app: this.app,
138 stream: this.stream, 138 stream: this.stream,
@@ -164,7 +164,7 @@ export default { @@ -164,7 +164,7 @@ export default {
164 getProgressForFile: function (callback){ 164 getProgressForFile: function (callback){
165 this.$axios({ 165 this.$axios({
166 method: 'get', 166 method: 'get',
167 - url:`./record_proxy/${this.mediaServerId}/api/record/file/download/task/list`, 167 + url:`/record_proxy/${this.mediaServerId}/api/record/file/download/task/list`,
168 params: { 168 params: {
169 app: this.app, 169 app: this.app,
170 stream: this.stream, 170 stream: this.stream,
web_src/src/components/live.vue
@@ -135,7 +135,7 @@ export default { @@ -135,7 +135,7 @@ export default {
135 this.loading = true 135 this.loading = true
136 this.$axios({ 136 this.$axios({
137 method: 'get', 137 method: 'get',
138 - url: './api/play/start/' + deviceId + '/' + channelId 138 + url: '/api/play/start/' + deviceId + '/' + channelId
139 }).then(function (res) { 139 }).then(function (res) {
140 if (res.data.code === 0 && res.data.data) { 140 if (res.data.code === 0 && res.data.data) {
141 let videoUrl; 141 let videoUrl;
web_src/src/components/map.vue
@@ -298,7 +298,7 @@ export default { @@ -298,7 +298,7 @@ export default {
298 let that = this; 298 let that = this;
299 this.$axios({ 299 this.$axios({
300 method: 'get', 300 method: 'get',
301 - url: './api/play/start/' + deviceId + '/' + channelId 301 + url: '/api/play/start/' + deviceId + '/' + channelId
302 }).then(function (res) { 302 }).then(function (res) {
303 that.isLoging = false; 303 that.isLoging = false;
304 if (res.data.code === 0) { 304 if (res.data.code === 0) {
web_src/src/components/service/DeviceService.js
@@ -9,7 +9,7 @@ class DeviceService{ @@ -9,7 +9,7 @@ class DeviceService{
9 getDeviceList(currentPage, count, callback, errorCallback){ 9 getDeviceList(currentPage, count, callback, errorCallback){
10 this.$axios({ 10 this.$axios({
11 method: 'get', 11 method: 'get',
12 - url:`./api/device/query/devices`, 12 + url:`/api/device/query/devices`,
13 params: { 13 params: {
14 page: currentPage, 14 page: currentPage,
15 count: count 15 count: count
@@ -25,7 +25,7 @@ class DeviceService{ @@ -25,7 +25,7 @@ class DeviceService{
25 getDevice(deviceId, callback, errorCallback){ 25 getDevice(deviceId, callback, errorCallback){
26 this.$axios({ 26 this.$axios({
27 method: 'get', 27 method: 'get',
28 - url:`./api/device/query/devices/${deviceId}`, 28 + url:`/api/device/query/devices/${deviceId}`,
29 }).then((res) => { 29 }).then((res) => {
30 if (typeof (callback) == "function") callback(res.data) 30 if (typeof (callback) == "function") callback(res.data)
31 }).catch((error) => { 31 }).catch((error) => {
@@ -82,7 +82,7 @@ class DeviceService{ @@ -82,7 +82,7 @@ class DeviceService{
82 getChanel(isCatalog, catalogUnderDevice, deviceId, currentPage, count, callback, errorCallback) { 82 getChanel(isCatalog, catalogUnderDevice, deviceId, currentPage, count, callback, errorCallback) {
83 this.$axios({ 83 this.$axios({
84 method: 'get', 84 method: 'get',
85 - url: `./api/device/query/devices/${deviceId}/channels`, 85 + url: `/api/device/query/devices/${deviceId}/channels`,
86 params:{ 86 params:{
87 page: currentPage, 87 page: currentPage,
88 count: count, 88 count: count,
@@ -121,7 +121,7 @@ class DeviceService{ @@ -121,7 +121,7 @@ class DeviceService{
121 getSubChannel(isCatalog, deviceId, channelId, currentPage, count, callback, errorCallback) { 121 getSubChannel(isCatalog, deviceId, channelId, currentPage, count, callback, errorCallback) {
122 this.$axios({ 122 this.$axios({
123 method: 'get', 123 method: 'get',
124 - url: `./api/device/query/sub_channels/${deviceId}/${channelId}/channels`, 124 + url: `/api/device/query/sub_channels/${deviceId}/${channelId}/channels`,
125 params:{ 125 params:{
126 page: currentPage, 126 page: currentPage,
127 count: count, 127 count: count,
@@ -161,7 +161,7 @@ class DeviceService{ @@ -161,7 +161,7 @@ class DeviceService{
161 } 161 }
162 this.$axios({ 162 this.$axios({
163 method: 'get', 163 method: 'get',
164 - url: `./api/device/query/tree/${deviceId}`, 164 + url: `/api/device/query/tree/${deviceId}`,
165 params:{ 165 params:{
166 page: currentPage, 166 page: currentPage,
167 count: count, 167 count: count,
web_src/src/components/service/MediaServer.js
@@ -9,7 +9,7 @@ class MediaServer{ @@ -9,7 +9,7 @@ class MediaServer{
9 getOnlineMediaServerList(callback){ 9 getOnlineMediaServerList(callback){
10 this.$axios({ 10 this.$axios({
11 method: 'get', 11 method: 'get',
12 - url:`./api/server/media_server/online/list`, 12 + url:`/api/server/media_server/online/list`,
13 }).then((res) => { 13 }).then((res) => {
14 if (typeof (callback) == "function") callback(res.data) 14 if (typeof (callback) == "function") callback(res.data)
15 }).catch((error) => { 15 }).catch((error) => {
@@ -19,7 +19,7 @@ class MediaServer{ @@ -19,7 +19,7 @@ class MediaServer{
19 getMediaServerList(callback){ 19 getMediaServerList(callback){
20 this.$axios({ 20 this.$axios({
21 method: 'get', 21 method: 'get',
22 - url:`./api/server/media_server/list`, 22 + url:`/api/server/media_server/list`,
23 }).then(function (res) { 23 }).then(function (res) {
24 if (typeof (callback) == "function") callback(res.data) 24 if (typeof (callback) == "function") callback(res.data)
25 }).catch(function (error) { 25 }).catch(function (error) {
@@ -30,7 +30,7 @@ class MediaServer{ @@ -30,7 +30,7 @@ class MediaServer{
30 getMediaServer(id, callback){ 30 getMediaServer(id, callback){
31 this.$axios({ 31 this.$axios({
32 method: 'get', 32 method: 'get',
33 - url:`./api/server/media_server/one/` + id, 33 + url:`/api/server/media_server/one/` + id,
34 }).then(function (res) { 34 }).then(function (res) {
35 if (typeof (callback) == "function") callback(res.data) 35 if (typeof (callback) == "function") callback(res.data)
36 }).catch(function (error) { 36 }).catch(function (error) {
@@ -41,7 +41,7 @@ class MediaServer{ @@ -41,7 +41,7 @@ class MediaServer{
41 checkServer(param, callback){ 41 checkServer(param, callback){
42 this.$axios({ 42 this.$axios({
43 method: 'get', 43 method: 'get',
44 - url:`./api/server/media_server/check`, 44 + url:`/api/server/media_server/check`,
45 params: { 45 params: {
46 ip: param.ip, 46 ip: param.ip,
47 port: param.httpPort, 47 port: param.httpPort,
@@ -57,7 +57,7 @@ class MediaServer{ @@ -57,7 +57,7 @@ class MediaServer{
57 checkRecordServer(param, callback){ 57 checkRecordServer(param, callback){
58 this.$axios({ 58 this.$axios({
59 method: 'get', 59 method: 'get',
60 - url:`./api/server/media_server/record/check`, 60 + url:`/api/server/media_server/record/check`,
61 params: { 61 params: {
62 ip: param.ip, 62 ip: param.ip,
63 port: param.recordAssistPort 63 port: param.recordAssistPort
@@ -72,7 +72,7 @@ class MediaServer{ @@ -72,7 +72,7 @@ class MediaServer{
72 addServer(param, callback){ 72 addServer(param, callback){
73 this.$axios({ 73 this.$axios({
74 method: 'post', 74 method: 'post',
75 - url:`./api/server/media_server/save`, 75 + url:`/api/server/media_server/save`,
76 data: param 76 data: param
77 }).then(function (res) { 77 }).then(function (res) {
78 if (typeof (callback) == "function") callback(res.data) 78 if (typeof (callback) == "function") callback(res.data)
@@ -84,7 +84,7 @@ class MediaServer{ @@ -84,7 +84,7 @@ class MediaServer{
84 delete(id, callback) { 84 delete(id, callback) {
85 this.$axios({ 85 this.$axios({
86 method: 'delete', 86 method: 'delete',
87 - url:`./api/server/media_server/delete`, 87 + url:`/api/server/media_server/delete`,
88 params: { 88 params: {
89 id: id 89 id: id
90 } 90 }
web_src/src/components/service/UserService.js 0 → 100644
  1 +
  2 +export default {
  3 +
  4 + /**
  5 + * 存储用户信息
  6 + * @param username
  7 + * @param token
  8 + */
  9 + setUser(user){
  10 + localStorage.setItem("wvp-user", JSON.stringify(user));
  11 + },
  12 +
  13 + /**
  14 + * 获取用户
  15 + */
  16 + getUser(){
  17 + return JSON.parse(localStorage.getItem("wvp-user"));
  18 + },
  19 +
  20 +
  21 + /**
  22 + * 获取登录token
  23 + */
  24 + getToken(){
  25 + return localStorage.getItem("wvp-token");
  26 + },
  27 +
  28 + /**
  29 + * 清理用户信息
  30 + */
  31 + clearUserInfo(){
  32 + localStorage.removeItem("wvp-user");
  33 + localStorage.removeItem("wvp-token");
  34 + },
  35 + /**
  36 + * 更新token
  37 + * @param header
  38 + */
  39 + setToken(token) {
  40 + localStorage.setItem("wvp-token", token);
  41 + }
  42 +}
web_src/src/layout/UiHeader.vue
@@ -23,9 +23,9 @@ @@ -23,9 +23,9 @@
23 <!-- </el-submenu>--> 23 <!-- </el-submenu>-->
24 <!-- <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>--> 24 <!-- <el-menu-item style="float: right;" @click="loginout">退出</el-menu-item>-->
25 <el-submenu index="" style="float: right;"> 25 <el-submenu index="" style="float: right;">
26 - <template slot="title">欢迎,{{ this.$cookies.get("session").username }}</template> 26 + <template slot="title">欢迎,{{ username }}</template>
27 <el-menu-item @click="openDoc">在线文档</el-menu-item> 27 <el-menu-item @click="openDoc">在线文档</el-menu-item>
28 - <el-menu-item > 28 + <el-menu-item>
29 <el-switch v-model="alarmNotify" inactive-text="报警信息推送" @change="alarmNotifyChannge"></el-switch> 29 <el-switch v-model="alarmNotify" inactive-text="报警信息推送" @change="alarmNotifyChannge"></el-switch>
30 </el-menu-item> 30 </el-menu-item>
31 <el-menu-item @click="changePassword">修改密码</el-menu-item> 31 <el-menu-item @click="changePassword">修改密码</el-menu-item>
@@ -39,6 +39,7 @@ @@ -39,6 +39,7 @@
39 <script> 39 <script>
40 40
41 import changePasswordDialog from '../components/dialog/changePassword.vue' 41 import changePasswordDialog from '../components/dialog/changePassword.vue'
  42 +import userService from '../components/service/UserService'
42 43
43 export default { 44 export default {
44 name: "UiHeader", 45 name: "UiHeader",
@@ -47,14 +48,17 @@ export default { @@ -47,14 +48,17 @@ export default {
47 return { 48 return {
48 alarmNotify: false, 49 alarmNotify: false,
49 sseSource: null, 50 sseSource: null,
  51 + username: userService.getUser().username,
50 activeIndex: this.$route.path, 52 activeIndex: this.$route.path,
51 - editUser: this.$cookies.get("session").roleId==1 53 + editUser: userService.getUser() ? userService.getUser().role.id === 1 : false
52 }; 54 };
53 }, 55 },
54 created() { 56 created() {
55 - console.log(this.$cookies.get("session")) 57 + console.log(4444)
  58 + console.log(JSON.stringify(userService.getUser()))
56 if (this.$route.path.startsWith("/channelList")) { 59 if (this.$route.path.startsWith("/channelList")) {
57 this.activeIndex = "/deviceList" 60 this.activeIndex = "/deviceList"
  61 +
58 } 62 }
59 }, 63 },
60 mounted() { 64 mounted() {
@@ -69,10 +73,13 @@ export default { @@ -69,10 +73,13 @@ export default {
69 method: 'get', 73 method: 'get',
70 url: "/api/user/logout" 74 url: "/api/user/logout"
71 }).then((res) => { 75 }).then((res) => {
72 - // 删除cookie,回到登录页面  
73 - this.$cookies.remove("session"); 76 + // 删除用户信息,回到登录页面
  77 + userService.clearUserInfo()
74 this.$router.push('/login'); 78 this.$router.push('/login');
75 - this.sseSource.close(); 79 + if (this.sseSource != null) {
  80 + this.sseSource.close();
  81 + }
  82 +
76 }).catch((error) => { 83 }).catch((error) => {
77 console.error("登出失败") 84 console.error("登出失败")
78 console.error(error) 85 console.error(error)
@@ -151,16 +158,19 @@ export default { @@ -151,16 +158,19 @@ export default {
151 </script> 158 </script>
152 <style> 159 <style>
153 #UiHeader .el-switch__label { 160 #UiHeader .el-switch__label {
154 - color: white ; 161 + color: white;
155 } 162 }
  163 +
156 .el-menu--popup .el-menu-item .el-switch .el-switch__label { 164 .el-menu--popup .el-menu-item .el-switch .el-switch__label {
157 color: white !important; 165 color: white !important;
158 } 166 }
159 -#UiHeader .el-switch__label.is-active{ 167 +
  168 +#UiHeader .el-switch__label.is-active {
160 color: #409EFF; 169 color: #409EFF;
161 } 170 }
  171 +
162 #UiHeader .el-menu-item.is-active { 172 #UiHeader .el-menu-item.is-active {
163 - color: #fff!important;  
164 - background-color: #1890ff!important; 173 + color: #fff !important;
  174 + background-color: #1890ff !important;
165 } 175 }
166 </style> 176 </style>
web_src/src/main.js
1 import Vue from 'vue'; 1 import Vue from 'vue';
2 import App from './App.vue'; 2 import App from './App.vue';
  3 +
3 Vue.config.productionTip = false; 4 Vue.config.productionTip = false;
4 import ElementUI from 'element-ui'; 5 import ElementUI from 'element-ui';
5 import 'element-ui/lib/theme-chalk/index.css'; 6 import 'element-ui/lib/theme-chalk/index.css';
@@ -10,15 +11,16 @@ import echarts from &#39;echarts&#39;; @@ -10,15 +11,16 @@ import echarts from &#39;echarts&#39;;
10 import VCharts from 'v-charts'; 11 import VCharts from 'v-charts';
11 12
12 import VueClipboard from 'vue-clipboard2'; 13 import VueClipboard from 'vue-clipboard2';
13 -import { Notification } from 'element-ui'; 14 +import {Notification} from 'element-ui';
14 import Fingerprint2 from 'fingerprintjs2'; 15 import Fingerprint2 from 'fingerprintjs2';
15 import VueClipboards from 'vue-clipboards'; 16 import VueClipboards from 'vue-clipboards';
16 import Contextmenu from "vue-contextmenujs" 17 import Contextmenu from "vue-contextmenujs"
  18 +import userService from "./components/service/UserService"
17 19
18 20
19 // 生成唯一ID 21 // 生成唯一ID
20 -Fingerprint2.get(function(components) {  
21 - const values = components.map(function(component,index) { 22 +Fingerprint2.get(function (components) {
  23 + const values = components.map(function (component, index) {
22 if (index === 0) { //把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样 24 if (index === 0) { //把微信浏览器里UA的wifi或4G等网络替换成空,不然切换网络会ID不一样
23 return component.value.replace(/\bNetType\/\w+\b/, ''); 25 return component.value.replace(/\bNetType\/\w+\b/, '');
24 } 26 }
@@ -37,18 +39,22 @@ Vue.use(VueClipboard); @@ -37,18 +39,22 @@ Vue.use(VueClipboard);
37 Vue.use(ElementUI); 39 Vue.use(ElementUI);
38 Vue.use(VueCookies); 40 Vue.use(VueCookies);
39 Vue.use(VueClipboards); 41 Vue.use(VueClipboards);
40 -Vue.prototype.$axios = axios; 42 +
41 Vue.prototype.$notify = Notification; 43 Vue.prototype.$notify = Notification;
42 Vue.use(Contextmenu); 44 Vue.use(Contextmenu);
43 Vue.use(VCharts); 45 Vue.use(VCharts);
44 46
45 -axios.defaults.baseURL = (process.env.NODE_ENV === 'development') ? process.env.BASE_API : "";  
46 - 47 +axios.defaults.baseURL = (process.env.NODE_ENV === 'development') ? process.env.BASE_API : (window.baseUrl ? window.baseUrl : "");
  48 +axios.defaults.withCredentials = true;
47 // api 返回401自动回登陆页面 49 // api 返回401自动回登陆页面
48 -axios.interceptors.response.use(function (response) { 50 +axios.interceptors.response.use((response) => {
49 // 对响应数据做点什么 51 // 对响应数据做点什么
  52 + let token = response.headers["access-token"];
  53 + if (token) {
  54 + userService.setToken(token)
  55 + }
50 return response; 56 return response;
51 -}, function (error) { 57 +}, (error) => {
52 // 对响应错误做点什么 58 // 对响应错误做点什么
53 if (error.response.status === 401) { 59 if (error.response.status === 401) {
54 console.log("Received 401 Response") 60 console.log("Received 401 Response")
@@ -56,10 +62,22 @@ axios.interceptors.response.use(function (response) { @@ -56,10 +62,22 @@ axios.interceptors.response.use(function (response) {
56 } 62 }
57 return Promise.reject(error); 63 return Promise.reject(error);
58 }); 64 });
  65 +axios.interceptors.request.use(
  66 + config => {
  67 + if (userService.getToken() != null && config.url !== "/api/user/login") {
  68 + config.headers['access-token'] = `${userService.getToken()}`;
  69 + }
  70 + return config;
  71 + },
  72 + error => {
  73 + return Promise.reject(error);
  74 + }
  75 +);
59 76
  77 +Vue.prototype.$axios = axios;
60 Vue.prototype.$cookies.config(60*30); 78 Vue.prototype.$cookies.config(60*30);
61 79
62 new Vue({ 80 new Vue({
63 - router: router,  
64 - render: h => h(App), 81 + router: router,
  82 + render: h => h(App),
65 }).$mount('#app') 83 }).$mount('#app')
web_src/static/js/mapConfig.js renamed to web_src/static/js/config.js
  1 +
  2 +window.baseUrl = ""
  3 +
1 // map组件全局参数, 注释此内容可以关闭地图功能 4 // map组件全局参数, 注释此内容可以关闭地图功能
2 window.mapParam = { 5 window.mapParam = {
3 // 开启/关闭地图功能 6 // 开启/关闭地图功能
web_src/static/js/jessibuca/decoder.js
1 -!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(require("path"),require("fs"),require("crypto")):"function"==typeof define&&define.amd?define(["path","fs","crypto"],r):r((e="undefined"!=typeof globalThis?globalThis:e||self).path,e.fs,e.crypto$1)}(this,(function(e,r,t){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var o=n(e),a=n(r),i=n(t);var s=function(e,r){return e(r={exports:{}},r.exports),r.exports}((function(e){var r,t=void 0!==t?t:{},n=(t={print:function(e){console.log("Jessibuca: [worker]:",e)},printErr:function(e){console.warn("Jessibuca: [worker]:",e),postMessage({cmd:"wasmError",message:e})}},{});for(r in t)t.hasOwnProperty(r)&&(n[r]=t[r]);var s,u,c,f,l="./this.program";s="object"==typeof window,u="function"==typeof importScripts,c="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node,f=!s&&!c&&!u;var d,p,h,m,v,g="";c?(g=u?o.default.dirname(g)+"/":__dirname+"/",d=function(e,r){return m||(m=a.default),v||(v=o.default),e=v.normalize(e),m.readFileSync(e,r?null:"utf8")},h=function(e){var r=d(e,!0);return r.buffer||(r=new Uint8Array(r)),T(r.buffer),r},process.argv.length>1&&(l=process.argv[1].replace(/\\/g,"/")),process.argv.slice(2),e.exports=t,process.on("uncaughtException",(function(e){if(!(e instanceof et))throw e})),process.on("unhandledRejection",te),t.inspect=function(){return"[Emscripten Module object]"}):f?("undefined"!=typeof read&&(d=function(e){return read(e)}),h=function(e){var r;return"function"==typeof readbuffer?new Uint8Array(readbuffer(e)):(T("object"==typeof(r=read(e,"binary"))),r)},"undefined"!=typeof scriptArgs&&scriptArgs,"undefined"!=typeof print&&("undefined"==typeof console&&(console={}),console.log=print,console.warn=console.error="undefined"!=typeof printErr?printErr:print)):(s||u)&&(u?g=self.location.href:"undefined"!=typeof document&&document.currentScript&&(g=document.currentScript.src),g=0!==g.indexOf("blob:")?g.substr(0,g.lastIndexOf("/")+1):"",d=function(e){var r=new XMLHttpRequest;return r.open("GET",e,!1),r.send(null),r.responseText},u&&(h=function(e){var r=new XMLHttpRequest;return r.open("GET",e,!1),r.responseType="arraybuffer",r.send(null),new Uint8Array(r.response)}),p=function(e,r,t){var n=new XMLHttpRequest;n.open("GET",e,!0),n.responseType="arraybuffer",n.onload=function(){200==n.status||0==n.status&&n.response?r(n.response):t()},n.onerror=t,n.send(null)});var y=t.print||console.log.bind(console),w=t.printErr||console.warn.bind(console);for(r in n)n.hasOwnProperty(r)&&(t[r]=n[r]);n=null,t.arguments,t.thisProgram&&(l=t.thisProgram),t.quit;var E,b;function _(e){_.shown||(_.shown={}),_.shown[e]||(_.shown[e]=1,w(e))}t.wasmBinary&&(E=t.wasmBinary),t.noExitRuntime,"object"!=typeof WebAssembly&&te("no native wasm support detected");var k=!1;function T(e,r){e||te("Assertion failed: "+r)}var P="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0;function C(e,r,t){for(var n=r+t,o=r;e[o]&&!(o>=n);)++o;if(o-r>16&&e.subarray&&P)return P.decode(e.subarray(r,o));for(var a="";r<o;){var i=e[r++];if(128&i){var s=63&e[r++];if(192!=(224&i)){var u=63&e[r++];if((i=224==(240&i)?(15&i)<<12|s<<6|u:(7&i)<<18|s<<12|u<<6|63&e[r++])<65536)a+=String.fromCharCode(i);else{var c=i-65536;a+=String.fromCharCode(55296|c>>10,56320|1023&c)}}else a+=String.fromCharCode((31&i)<<6|s)}else a+=String.fromCharCode(i)}return a}function A(e,r){return e?C(R,e,r):""}function D(e,r,t,n){if(!(n>0))return 0;for(var o=t,a=t+n-1,i=0;i<e.length;++i){var s=e.charCodeAt(i);if(s>=55296&&s<=57343)s=65536+((1023&s)<<10)|1023&e.charCodeAt(++i);if(s<=127){if(t>=a)break;r[t++]=s}else if(s<=2047){if(t+1>=a)break;r[t++]=192|s>>6,r[t++]=128|63&s}else if(s<=65535){if(t+2>=a)break;r[t++]=224|s>>12,r[t++]=128|s>>6&63,r[t++]=128|63&s}else{if(t+3>=a)break;r[t++]=240|s>>18,r[t++]=128|s>>12&63,r[t++]=128|s>>6&63,r[t++]=128|63&s}}return r[t]=0,t-o}function S(e,r,t){return D(e,R,r,t)}function F(e){for(var r=0,t=0;t<e.length;++t){var n=e.charCodeAt(t);n>=55296&&n<=57343&&(n=65536+((1023&n)<<10)|1023&e.charCodeAt(++t)),n<=127?++r:r+=n<=2047?2:n<=65535?3:4}return r}var x,$,R,M,O,I,j,U,N,B,W="undefined"!=typeof TextDecoder?new TextDecoder("utf-16le"):void 0;function L(e,r){for(var t=e,n=t>>1,o=n+r/2;!(n>=o)&&O[n];)++n;if((t=n<<1)-e>32&&W)return W.decode(R.subarray(e,t));for(var a="",i=0;!(i>=r/2);++i){var s=M[e+2*i>>1];if(0==s)break;a+=String.fromCharCode(s)}return a}function z(e,r,t){if(void 0===t&&(t=2147483647),t<2)return 0;for(var n=r,o=(t-=2)<2*e.length?t/2:e.length,a=0;a<o;++a){var i=e.charCodeAt(a);M[r>>1]=i,r+=2}return M[r>>1]=0,r-n}function H(e){return 2*e.length}function V(e,r){for(var t=0,n="";!(t>=r/4);){var o=I[e+4*t>>2];if(0==o)break;if(++t,o>=65536){var a=o-65536;n+=String.fromCharCode(55296|a>>10,56320|1023&a)}else n+=String.fromCharCode(o)}return n}function X(e,r,t){if(void 0===t&&(t=2147483647),t<4)return 0;for(var n=r,o=n+t-4,a=0;a<e.length;++a){var i=e.charCodeAt(a);if(i>=55296&&i<=57343)i=65536+((1023&i)<<10)|1023&e.charCodeAt(++a);if(I[r>>2]=i,(r+=4)+4>o)break}return I[r>>2]=0,r-n}function G(e){for(var r=0,t=0;t<e.length;++t){var n=e.charCodeAt(t);n>=55296&&n<=57343&&++t,r+=4}return r}t.INITIAL_MEMORY;var q=[],J=[],Y=[],K=[];var Q=0,Z=null;function ee(e){Q++,t.monitorRunDependencies&&t.monitorRunDependencies(Q)}function re(e){if(Q--,t.monitorRunDependencies&&t.monitorRunDependencies(Q),0==Q&&Z){var r=Z;Z=null,r()}}function te(e){throw t.onAbort&&t.onAbort(e),w(e+=""),k=!0,e="abort("+e+"). Build with -s ASSERTIONS=1 for more info.",new WebAssembly.RuntimeError(e)}function ne(e,r){return String.prototype.startsWith?e.startsWith(r):0===e.indexOf(r)}t.preloadedImages={},t.preloadedAudios={};function oe(e){return ne(e,"data:application/octet-stream;base64,")}function ae(e){return ne(e,"file://")}var ie,se,ue="decoder.wasm";function ce(e){try{if(e==ue&&E)return new Uint8Array(E);if(h)return h(e);throw"both async and sync fetching of the wasm failed"}catch(e){te(e)}}function fe(e){for(;e.length>0;){var r=e.shift();if("function"!=typeof r){var n=r.func;"number"==typeof n?void 0===r.arg?B.get(n)():B.get(n)(r.arg):n(void 0===r.arg?null:r.arg)}else r(t)}}function le(){var e=new Error;if(!e.stack){try{throw new Error}catch(r){e=r}if(!e.stack)return"(no stack trace available)"}return e.stack.toString()}oe(ue)||(ue=function(e){return t.locateFile?t.locateFile(e,g):g+e}(ue));var de={splitPath:function(e){return/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(e).slice(1)},normalizeArray:function(e,r){for(var t=0,n=e.length-1;n>=0;n--){var o=e[n];"."===o?e.splice(n,1):".."===o?(e.splice(n,1),t++):t&&(e.splice(n,1),t--)}if(r)for(;t;t--)e.unshift("..");return e},normalize:function(e){var r="/"===e.charAt(0),t="/"===e.substr(-1);return(e=de.normalizeArray(e.split("/").filter((function(e){return!!e})),!r).join("/"))||r||(e="."),e&&t&&(e+="/"),(r?"/":"")+e},dirname:function(e){var r=de.splitPath(e),t=r[0],n=r[1];return t||n?(n&&(n=n.substr(0,n.length-1)),t+n):"."},basename:function(e){if("/"===e)return"/";var r=(e=(e=de.normalize(e)).replace(/\/$/,"")).lastIndexOf("/");return-1===r?e:e.substr(r+1)},extname:function(e){return de.splitPath(e)[3]},join:function(){var e=Array.prototype.slice.call(arguments,0);return de.normalize(e.join("/"))},join2:function(e,r){return de.normalize(e+"/"+r)}};var pe={resolve:function(){for(var e="",r=!1,t=arguments.length-1;t>=-1&&!r;t--){var n=t>=0?arguments[t]:ge.cwd();if("string"!=typeof n)throw new TypeError("Arguments to path.resolve must be strings");if(!n)return"";e=n+"/"+e,r="/"===n.charAt(0)}return(r?"/":"")+(e=de.normalizeArray(e.split("/").filter((function(e){return!!e})),!r).join("/"))||"."},relative:function(e,r){function t(e){for(var r=0;r<e.length&&""===e[r];r++);for(var t=e.length-1;t>=0&&""===e[t];t--);return r>t?[]:e.slice(r,t-r+1)}e=pe.resolve(e).substr(1),r=pe.resolve(r).substr(1);for(var n=t(e.split("/")),o=t(r.split("/")),a=Math.min(n.length,o.length),i=a,s=0;s<a;s++)if(n[s]!==o[s]){i=s;break}var u=[];for(s=i;s<n.length;s++)u.push("..");return(u=u.concat(o.slice(i))).join("/")}},he={ttys:[],init:function(){},shutdown:function(){},register:function(e,r){he.ttys[e]={input:[],output:[],ops:r},ge.registerDevice(e,he.stream_ops)},stream_ops:{open:function(e){var r=he.ttys[e.node.rdev];if(!r)throw new ge.ErrnoError(43);e.tty=r,e.seekable=!1},close:function(e){e.tty.ops.flush(e.tty)},flush:function(e){e.tty.ops.flush(e.tty)},read:function(e,r,t,n,o){if(!e.tty||!e.tty.ops.get_char)throw new ge.ErrnoError(60);for(var a=0,i=0;i<n;i++){var s;try{s=e.tty.ops.get_char(e.tty)}catch(e){throw new ge.ErrnoError(29)}if(void 0===s&&0===a)throw new ge.ErrnoError(6);if(null==s)break;a++,r[t+i]=s}return a&&(e.node.timestamp=Date.now()),a},write:function(e,r,t,n,o){if(!e.tty||!e.tty.ops.put_char)throw new ge.ErrnoError(60);try{for(var a=0;a<n;a++)e.tty.ops.put_char(e.tty,r[t+a])}catch(e){throw new ge.ErrnoError(29)}return n&&(e.node.timestamp=Date.now()),a}},default_tty_ops:{get_char:function(e){if(!e.input.length){var r=null;if(c){var t=Buffer.alloc?Buffer.alloc(256):new Buffer(256),n=0;try{n=m.readSync(process.stdin.fd,t,0,256,null)}catch(e){if(-1==e.toString().indexOf("EOF"))throw e;n=0}r=n>0?t.slice(0,n).toString("utf-8"):null}else"undefined"!=typeof window&&"function"==typeof window.prompt?null!==(r=window.prompt("Input: "))&&(r+="\n"):"function"==typeof readline&&null!==(r=readline())&&(r+="\n");if(!r)return null;e.input=Xr(r,!0)}return e.input.shift()},put_char:function(e,r){null===r||10===r?(y(C(e.output,0)),e.output=[]):0!=r&&e.output.push(r)},flush:function(e){e.output&&e.output.length>0&&(y(C(e.output,0)),e.output=[])}},default_tty1_ops:{put_char:function(e,r){null===r||10===r?(w(C(e.output,0)),e.output=[]):0!=r&&e.output.push(r)},flush:function(e){e.output&&e.output.length>0&&(w(C(e.output,0)),e.output=[])}}};function me(e){for(var r=function(e,r){return r||(r=16),Math.ceil(e/r)*r}(e,16384),t=Yr(r);e<r;)$[t+e++]=0;return t}var ve={ops_table:null,mount:function(e){return ve.createNode(null,"/",16895,0)},createNode:function(e,r,t,n){if(ge.isBlkdev(t)||ge.isFIFO(t))throw new ge.ErrnoError(63);ve.ops_table||(ve.ops_table={dir:{node:{getattr:ve.node_ops.getattr,setattr:ve.node_ops.setattr,lookup:ve.node_ops.lookup,mknod:ve.node_ops.mknod,rename:ve.node_ops.rename,unlink:ve.node_ops.unlink,rmdir:ve.node_ops.rmdir,readdir:ve.node_ops.readdir,symlink:ve.node_ops.symlink},stream:{llseek:ve.stream_ops.llseek}},file:{node:{getattr:ve.node_ops.getattr,setattr:ve.node_ops.setattr},stream:{llseek:ve.stream_ops.llseek,read:ve.stream_ops.read,write:ve.stream_ops.write,allocate:ve.stream_ops.allocate,mmap:ve.stream_ops.mmap,msync:ve.stream_ops.msync}},link:{node:{getattr:ve.node_ops.getattr,setattr:ve.node_ops.setattr,readlink:ve.node_ops.readlink},stream:{}},chrdev:{node:{getattr:ve.node_ops.getattr,setattr:ve.node_ops.setattr},stream:ge.chrdev_stream_ops}});var o=ge.createNode(e,r,t,n);return ge.isDir(o.mode)?(o.node_ops=ve.ops_table.dir.node,o.stream_ops=ve.ops_table.dir.stream,o.contents={}):ge.isFile(o.mode)?(o.node_ops=ve.ops_table.file.node,o.stream_ops=ve.ops_table.file.stream,o.usedBytes=0,o.contents=null):ge.isLink(o.mode)?(o.node_ops=ve.ops_table.link.node,o.stream_ops=ve.ops_table.link.stream):ge.isChrdev(o.mode)&&(o.node_ops=ve.ops_table.chrdev.node,o.stream_ops=ve.ops_table.chrdev.stream),o.timestamp=Date.now(),e&&(e.contents[r]=o,e.timestamp=o.timestamp),o},getFileDataAsTypedArray:function(e){return e.contents?e.contents.subarray?e.contents.subarray(0,e.usedBytes):new Uint8Array(e.contents):new Uint8Array(0)},expandFileStorage:function(e,r){var t=e.contents?e.contents.length:0;if(!(t>=r)){r=Math.max(r,t*(t<1048576?2:1.125)>>>0),0!=t&&(r=Math.max(r,256));var n=e.contents;e.contents=new Uint8Array(r),e.usedBytes>0&&e.contents.set(n.subarray(0,e.usedBytes),0)}},resizeFileStorage:function(e,r){if(e.usedBytes!=r)if(0==r)e.contents=null,e.usedBytes=0;else{var t=e.contents;e.contents=new Uint8Array(r),t&&e.contents.set(t.subarray(0,Math.min(r,e.usedBytes))),e.usedBytes=r}},node_ops:{getattr:function(e){var r={};return r.dev=ge.isChrdev(e.mode)?e.id:1,r.ino=e.id,r.mode=e.mode,r.nlink=1,r.uid=0,r.gid=0,r.rdev=e.rdev,ge.isDir(e.mode)?r.size=4096:ge.isFile(e.mode)?r.size=e.usedBytes:ge.isLink(e.mode)?r.size=e.link.length:r.size=0,r.atime=new Date(e.timestamp),r.mtime=new Date(e.timestamp),r.ctime=new Date(e.timestamp),r.blksize=4096,r.blocks=Math.ceil(r.size/r.blksize),r},setattr:function(e,r){void 0!==r.mode&&(e.mode=r.mode),void 0!==r.timestamp&&(e.timestamp=r.timestamp),void 0!==r.size&&ve.resizeFileStorage(e,r.size)},lookup:function(e,r){throw ge.genericErrors[44]},mknod:function(e,r,t,n){return ve.createNode(e,r,t,n)},rename:function(e,r,t){if(ge.isDir(e.mode)){var n;try{n=ge.lookupNode(r,t)}catch(e){}if(n)for(var o in n.contents)throw new ge.ErrnoError(55)}delete e.parent.contents[e.name],e.parent.timestamp=Date.now(),e.name=t,r.contents[t]=e,r.timestamp=e.parent.timestamp,e.parent=r},unlink:function(e,r){delete e.contents[r],e.timestamp=Date.now()},rmdir:function(e,r){var t=ge.lookupNode(e,r);for(var n in t.contents)throw new ge.ErrnoError(55);delete e.contents[r],e.timestamp=Date.now()},readdir:function(e){var r=[".",".."];for(var t in e.contents)e.contents.hasOwnProperty(t)&&r.push(t);return r},symlink:function(e,r,t){var n=ve.createNode(e,r,41471,0);return n.link=t,n},readlink:function(e){if(!ge.isLink(e.mode))throw new ge.ErrnoError(28);return e.link}},stream_ops:{read:function(e,r,t,n,o){var a=e.node.contents;if(o>=e.node.usedBytes)return 0;var i=Math.min(e.node.usedBytes-o,n);if(i>8&&a.subarray)r.set(a.subarray(o,o+i),t);else for(var s=0;s<i;s++)r[t+s]=a[o+s];return i},write:function(e,r,t,n,o,a){if(!n)return 0;var i=e.node;if(i.timestamp=Date.now(),r.subarray&&(!i.contents||i.contents.subarray)){if(a)return i.contents=r.subarray(t,t+n),i.usedBytes=n,n;if(0===i.usedBytes&&0===o)return i.contents=r.slice(t,t+n),i.usedBytes=n,n;if(o+n<=i.usedBytes)return i.contents.set(r.subarray(t,t+n),o),n}if(ve.expandFileStorage(i,o+n),i.contents.subarray&&r.subarray)i.contents.set(r.subarray(t,t+n),o);else for(var s=0;s<n;s++)i.contents[o+s]=r[t+s];return i.usedBytes=Math.max(i.usedBytes,o+n),n},llseek:function(e,r,t){var n=r;if(1===t?n+=e.position:2===t&&ge.isFile(e.node.mode)&&(n+=e.node.usedBytes),n<0)throw new ge.ErrnoError(28);return n},allocate:function(e,r,t){ve.expandFileStorage(e.node,r+t),e.node.usedBytes=Math.max(e.node.usedBytes,r+t)},mmap:function(e,r,t,n,o,a){if(0!==r)throw new ge.ErrnoError(28);if(!ge.isFile(e.node.mode))throw new ge.ErrnoError(43);var i,s,u=e.node.contents;if(2&a||u.buffer!==x){if((n>0||n+t<u.length)&&(u=u.subarray?u.subarray(n,n+t):Array.prototype.slice.call(u,n,n+t)),s=!0,!(i=me(t)))throw new ge.ErrnoError(48);$.set(u,i)}else s=!1,i=u.byteOffset;return{ptr:i,allocated:s}},msync:function(e,r,t,n,o){if(!ge.isFile(e.node.mode))throw new ge.ErrnoError(43);return 2&o||ve.stream_ops.write(e,r,0,n,t,!1),0}}},ge={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:!1,ignorePermissions:!0,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath:function(e,r){if(r=r||{},!(e=pe.resolve(ge.cwd(),e)))return{path:"",node:null};var t={follow_mount:!0,recurse_count:0};for(var n in t)void 0===r[n]&&(r[n]=t[n]);if(r.recurse_count>8)throw new ge.ErrnoError(32);for(var o=de.normalizeArray(e.split("/").filter((function(e){return!!e})),!1),a=ge.root,i="/",s=0;s<o.length;s++){var u=s===o.length-1;if(u&&r.parent)break;if(a=ge.lookupNode(a,o[s]),i=de.join2(i,o[s]),ge.isMountpoint(a)&&(!u||u&&r.follow_mount)&&(a=a.mounted.root),!u||r.follow)for(var c=0;ge.isLink(a.mode);){var f=ge.readlink(i);if(i=pe.resolve(de.dirname(i),f),a=ge.lookupPath(i,{recurse_count:r.recurse_count}).node,c++>40)throw new ge.ErrnoError(32)}}return{path:i,node:a}},getPath:function(e){for(var r;;){if(ge.isRoot(e)){var t=e.mount.mountpoint;return r?"/"!==t[t.length-1]?t+"/"+r:t+r:t}r=r?e.name+"/"+r:e.name,e=e.parent}},hashName:function(e,r){for(var t=0,n=0;n<r.length;n++)t=(t<<5)-t+r.charCodeAt(n)|0;return(e+t>>>0)%ge.nameTable.length},hashAddNode:function(e){var r=ge.hashName(e.parent.id,e.name);e.name_next=ge.nameTable[r],ge.nameTable[r]=e},hashRemoveNode:function(e){var r=ge.hashName(e.parent.id,e.name);if(ge.nameTable[r]===e)ge.nameTable[r]=e.name_next;else for(var t=ge.nameTable[r];t;){if(t.name_next===e){t.name_next=e.name_next;break}t=t.name_next}},lookupNode:function(e,r){var t=ge.mayLookup(e);if(t)throw new ge.ErrnoError(t,e);for(var n=ge.hashName(e.id,r),o=ge.nameTable[n];o;o=o.name_next){var a=o.name;if(o.parent.id===e.id&&a===r)return o}return ge.lookup(e,r)},createNode:function(e,r,t,n){var o=new ge.FSNode(e,r,t,n);return ge.hashAddNode(o),o},destroyNode:function(e){ge.hashRemoveNode(e)},isRoot:function(e){return e===e.parent},isMountpoint:function(e){return!!e.mounted},isFile:function(e){return 32768==(61440&e)},isDir:function(e){return 16384==(61440&e)},isLink:function(e){return 40960==(61440&e)},isChrdev:function(e){return 8192==(61440&e)},isBlkdev:function(e){return 24576==(61440&e)},isFIFO:function(e){return 4096==(61440&e)},isSocket:function(e){return 49152==(49152&e)},flagModes:{r:0,"r+":2,w:577,"w+":578,a:1089,"a+":1090},modeStringToFlags:function(e){var r=ge.flagModes[e];if(void 0===r)throw new Error("Unknown file open mode: "+e);return r},flagsToPermissionString:function(e){var r=["r","w","rw"][3&e];return 512&e&&(r+="w"),r},nodePermissions:function(e,r){return ge.ignorePermissions||(-1===r.indexOf("r")||292&e.mode)&&(-1===r.indexOf("w")||146&e.mode)&&(-1===r.indexOf("x")||73&e.mode)?0:2},mayLookup:function(e){var r=ge.nodePermissions(e,"x");return r||(e.node_ops.lookup?0:2)},mayCreate:function(e,r){try{ge.lookupNode(e,r);return 20}catch(e){}return ge.nodePermissions(e,"wx")},mayDelete:function(e,r,t){var n;try{n=ge.lookupNode(e,r)}catch(e){return e.errno}var o=ge.nodePermissions(e,"wx");if(o)return o;if(t){if(!ge.isDir(n.mode))return 54;if(ge.isRoot(n)||ge.getPath(n)===ge.cwd())return 10}else if(ge.isDir(n.mode))return 31;return 0},mayOpen:function(e,r){return e?ge.isLink(e.mode)?32:ge.isDir(e.mode)&&("r"!==ge.flagsToPermissionString(r)||512&r)?31:ge.nodePermissions(e,ge.flagsToPermissionString(r)):44},MAX_OPEN_FDS:4096,nextfd:function(e,r){e=e||0,r=r||ge.MAX_OPEN_FDS;for(var t=e;t<=r;t++)if(!ge.streams[t])return t;throw new ge.ErrnoError(33)},getStream:function(e){return ge.streams[e]},createStream:function(e,r,t){ge.FSStream||(ge.FSStream=function(){},ge.FSStream.prototype={object:{get:function(){return this.node},set:function(e){this.node=e}},isRead:{get:function(){return 1!=(2097155&this.flags)}},isWrite:{get:function(){return 0!=(2097155&this.flags)}},isAppend:{get:function(){return 1024&this.flags}}});var n=new ge.FSStream;for(var o in e)n[o]=e[o];e=n;var a=ge.nextfd(r,t);return e.fd=a,ge.streams[a]=e,e},closeStream:function(e){ge.streams[e]=null},chrdev_stream_ops:{open:function(e){var r=ge.getDevice(e.node.rdev);e.stream_ops=r.stream_ops,e.stream_ops.open&&e.stream_ops.open(e)},llseek:function(){throw new ge.ErrnoError(70)}},major:function(e){return e>>8},minor:function(e){return 255&e},makedev:function(e,r){return e<<8|r},registerDevice:function(e,r){ge.devices[e]={stream_ops:r}},getDevice:function(e){return ge.devices[e]},getMounts:function(e){for(var r=[],t=[e];t.length;){var n=t.pop();r.push(n),t.push.apply(t,n.mounts)}return r},syncfs:function(e,r){"function"==typeof e&&(r=e,e=!1),ge.syncFSRequests++,ge.syncFSRequests>1&&w("warning: "+ge.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work");var t=ge.getMounts(ge.root.mount),n=0;function o(e){return ge.syncFSRequests--,r(e)}function a(e){if(e)return a.errored?void 0:(a.errored=!0,o(e));++n>=t.length&&o(null)}t.forEach((function(r){if(!r.type.syncfs)return a(null);r.type.syncfs(r,e,a)}))},mount:function(e,r,t){var n,o="/"===t,a=!t;if(o&&ge.root)throw new ge.ErrnoError(10);if(!o&&!a){var i=ge.lookupPath(t,{follow_mount:!1});if(t=i.path,n=i.node,ge.isMountpoint(n))throw new ge.ErrnoError(10);if(!ge.isDir(n.mode))throw new ge.ErrnoError(54)}var s={type:e,opts:r,mountpoint:t,mounts:[]},u=e.mount(s);return u.mount=s,s.root=u,o?ge.root=u:n&&(n.mounted=s,n.mount&&n.mount.mounts.push(s)),u},unmount:function(e){var r=ge.lookupPath(e,{follow_mount:!1});if(!ge.isMountpoint(r.node))throw new ge.ErrnoError(28);var t=r.node,n=t.mounted,o=ge.getMounts(n);Object.keys(ge.nameTable).forEach((function(e){for(var r=ge.nameTable[e];r;){var t=r.name_next;-1!==o.indexOf(r.mount)&&ge.destroyNode(r),r=t}})),t.mounted=null;var a=t.mount.mounts.indexOf(n);t.mount.mounts.splice(a,1)},lookup:function(e,r){return e.node_ops.lookup(e,r)},mknod:function(e,r,t){var n=ge.lookupPath(e,{parent:!0}).node,o=de.basename(e);if(!o||"."===o||".."===o)throw new ge.ErrnoError(28);var a=ge.mayCreate(n,o);if(a)throw new ge.ErrnoError(a);if(!n.node_ops.mknod)throw new ge.ErrnoError(63);return n.node_ops.mknod(n,o,r,t)},create:function(e,r){return r=void 0!==r?r:438,r&=4095,r|=32768,ge.mknod(e,r,0)},mkdir:function(e,r){return r=void 0!==r?r:511,r&=1023,r|=16384,ge.mknod(e,r,0)},mkdirTree:function(e,r){for(var t=e.split("/"),n="",o=0;o<t.length;++o)if(t[o]){n+="/"+t[o];try{ge.mkdir(n,r)}catch(e){if(20!=e.errno)throw e}}},mkdev:function(e,r,t){return void 0===t&&(t=r,r=438),r|=8192,ge.mknod(e,r,t)},symlink:function(e,r){if(!pe.resolve(e))throw new ge.ErrnoError(44);var t=ge.lookupPath(r,{parent:!0}).node;if(!t)throw new ge.ErrnoError(44);var n=de.basename(r),o=ge.mayCreate(t,n);if(o)throw new ge.ErrnoError(o);if(!t.node_ops.symlink)throw new ge.ErrnoError(63);return t.node_ops.symlink(t,n,e)},rename:function(e,r){var t,n,o=de.dirname(e),a=de.dirname(r),i=de.basename(e),s=de.basename(r);if(t=ge.lookupPath(e,{parent:!0}).node,n=ge.lookupPath(r,{parent:!0}).node,!t||!n)throw new ge.ErrnoError(44);if(t.mount!==n.mount)throw new ge.ErrnoError(75);var u,c=ge.lookupNode(t,i),f=pe.relative(e,a);if("."!==f.charAt(0))throw new ge.ErrnoError(28);if("."!==(f=pe.relative(r,o)).charAt(0))throw new ge.ErrnoError(55);try{u=ge.lookupNode(n,s)}catch(e){}if(c!==u){var l=ge.isDir(c.mode),d=ge.mayDelete(t,i,l);if(d)throw new ge.ErrnoError(d);if(d=u?ge.mayDelete(n,s,l):ge.mayCreate(n,s))throw new ge.ErrnoError(d);if(!t.node_ops.rename)throw new ge.ErrnoError(63);if(ge.isMountpoint(c)||u&&ge.isMountpoint(u))throw new ge.ErrnoError(10);if(n!==t&&(d=ge.nodePermissions(t,"w")))throw new ge.ErrnoError(d);try{ge.trackingDelegate.willMovePath}catch(t){w("FS.trackingDelegate['willMovePath']('"+e+"', '"+r+"') threw an exception: "+t.message)}ge.hashRemoveNode(c);try{t.node_ops.rename(c,n,s)}catch(e){throw e}finally{ge.hashAddNode(c)}try{ge.trackingDelegate.onMovePath}catch(t){w("FS.trackingDelegate['onMovePath']('"+e+"', '"+r+"') threw an exception: "+t.message)}}},rmdir:function(e){var r=ge.lookupPath(e,{parent:!0}).node,t=de.basename(e),n=ge.lookupNode(r,t),o=ge.mayDelete(r,t,!0);if(o)throw new ge.ErrnoError(o);if(!r.node_ops.rmdir)throw new ge.ErrnoError(63);if(ge.isMountpoint(n))throw new ge.ErrnoError(10);try{ge.trackingDelegate.willDeletePath}catch(r){w("FS.trackingDelegate['willDeletePath']('"+e+"') threw an exception: "+r.message)}r.node_ops.rmdir(r,t),ge.destroyNode(n);try{ge.trackingDelegate.onDeletePath}catch(r){w("FS.trackingDelegate['onDeletePath']('"+e+"') threw an exception: "+r.message)}},readdir:function(e){var r=ge.lookupPath(e,{follow:!0}).node;if(!r.node_ops.readdir)throw new ge.ErrnoError(54);return r.node_ops.readdir(r)},unlink:function(e){var r=ge.lookupPath(e,{parent:!0}).node,t=de.basename(e),n=ge.lookupNode(r,t),o=ge.mayDelete(r,t,!1);if(o)throw new ge.ErrnoError(o);if(!r.node_ops.unlink)throw new ge.ErrnoError(63);if(ge.isMountpoint(n))throw new ge.ErrnoError(10);try{ge.trackingDelegate.willDeletePath}catch(r){w("FS.trackingDelegate['willDeletePath']('"+e+"') threw an exception: "+r.message)}r.node_ops.unlink(r,t),ge.destroyNode(n);try{ge.trackingDelegate.onDeletePath}catch(r){w("FS.trackingDelegate['onDeletePath']('"+e+"') threw an exception: "+r.message)}},readlink:function(e){var r=ge.lookupPath(e).node;if(!r)throw new ge.ErrnoError(44);if(!r.node_ops.readlink)throw new ge.ErrnoError(28);return pe.resolve(ge.getPath(r.parent),r.node_ops.readlink(r))},stat:function(e,r){var t=ge.lookupPath(e,{follow:!r}).node;if(!t)throw new ge.ErrnoError(44);if(!t.node_ops.getattr)throw new ge.ErrnoError(63);return t.node_ops.getattr(t)},lstat:function(e){return ge.stat(e,!0)},chmod:function(e,r,t){var n;"string"==typeof e?n=ge.lookupPath(e,{follow:!t}).node:n=e;if(!n.node_ops.setattr)throw new ge.ErrnoError(63);n.node_ops.setattr(n,{mode:4095&r|-4096&n.mode,timestamp:Date.now()})},lchmod:function(e,r){ge.chmod(e,r,!0)},fchmod:function(e,r){var t=ge.getStream(e);if(!t)throw new ge.ErrnoError(8);ge.chmod(t.node,r)},chown:function(e,r,t,n){var o;"string"==typeof e?o=ge.lookupPath(e,{follow:!n}).node:o=e;if(!o.node_ops.setattr)throw new ge.ErrnoError(63);o.node_ops.setattr(o,{timestamp:Date.now()})},lchown:function(e,r,t){ge.chown(e,r,t,!0)},fchown:function(e,r,t){var n=ge.getStream(e);if(!n)throw new ge.ErrnoError(8);ge.chown(n.node,r,t)},truncate:function(e,r){if(r<0)throw new ge.ErrnoError(28);var t;"string"==typeof e?t=ge.lookupPath(e,{follow:!0}).node:t=e;if(!t.node_ops.setattr)throw new ge.ErrnoError(63);if(ge.isDir(t.mode))throw new ge.ErrnoError(31);if(!ge.isFile(t.mode))throw new ge.ErrnoError(28);var n=ge.nodePermissions(t,"w");if(n)throw new ge.ErrnoError(n);t.node_ops.setattr(t,{size:r,timestamp:Date.now()})},ftruncate:function(e,r){var t=ge.getStream(e);if(!t)throw new ge.ErrnoError(8);if(0==(2097155&t.flags))throw new ge.ErrnoError(28);ge.truncate(t.node,r)},utime:function(e,r,t){var n=ge.lookupPath(e,{follow:!0}).node;n.node_ops.setattr(n,{timestamp:Math.max(r,t)})},open:function(e,r,n,o,a){if(""===e)throw new ge.ErrnoError(44);var i;if(n=void 0===n?438:n,n=64&(r="string"==typeof r?ge.modeStringToFlags(r):r)?4095&n|32768:0,"object"==typeof e)i=e;else{e=de.normalize(e);try{i=ge.lookupPath(e,{follow:!(131072&r)}).node}catch(e){}}var s=!1;if(64&r)if(i){if(128&r)throw new ge.ErrnoError(20)}else i=ge.mknod(e,n,0),s=!0;if(!i)throw new ge.ErrnoError(44);if(ge.isChrdev(i.mode)&&(r&=-513),65536&r&&!ge.isDir(i.mode))throw new ge.ErrnoError(54);if(!s){var u=ge.mayOpen(i,r);if(u)throw new ge.ErrnoError(u)}512&r&&ge.truncate(i,0),r&=-131713;var c=ge.createStream({node:i,path:ge.getPath(i),flags:r,seekable:!0,position:0,stream_ops:i.stream_ops,ungotten:[],error:!1},o,a);c.stream_ops.open&&c.stream_ops.open(c),!t.logReadFiles||1&r||(ge.readFiles||(ge.readFiles={}),e in ge.readFiles||(ge.readFiles[e]=1,w("FS.trackingDelegate error on read file: "+e)));try{ge.trackingDelegate.onOpenFile}catch(r){w("FS.trackingDelegate['onOpenFile']('"+e+"', flags) threw an exception: "+r.message)}return c},close:function(e){if(ge.isClosed(e))throw new ge.ErrnoError(8);e.getdents&&(e.getdents=null);try{e.stream_ops.close&&e.stream_ops.close(e)}catch(e){throw e}finally{ge.closeStream(e.fd)}e.fd=null},isClosed:function(e){return null===e.fd},llseek:function(e,r,t){if(ge.isClosed(e))throw new ge.ErrnoError(8);if(!e.seekable||!e.stream_ops.llseek)throw new ge.ErrnoError(70);if(0!=t&&1!=t&&2!=t)throw new ge.ErrnoError(28);return e.position=e.stream_ops.llseek(e,r,t),e.ungotten=[],e.position},read:function(e,r,t,n,o){if(n<0||o<0)throw new ge.ErrnoError(28);if(ge.isClosed(e))throw new ge.ErrnoError(8);if(1==(2097155&e.flags))throw new ge.ErrnoError(8);if(ge.isDir(e.node.mode))throw new ge.ErrnoError(31);if(!e.stream_ops.read)throw new ge.ErrnoError(28);var a=void 0!==o;if(a){if(!e.seekable)throw new ge.ErrnoError(70)}else o=e.position;var i=e.stream_ops.read(e,r,t,n,o);return a||(e.position+=i),i},write:function(e,r,t,n,o,a){if(n<0||o<0)throw new ge.ErrnoError(28);if(ge.isClosed(e))throw new ge.ErrnoError(8);if(0==(2097155&e.flags))throw new ge.ErrnoError(8);if(ge.isDir(e.node.mode))throw new ge.ErrnoError(31);if(!e.stream_ops.write)throw new ge.ErrnoError(28);e.seekable&&1024&e.flags&&ge.llseek(e,0,2);var i=void 0!==o;if(i){if(!e.seekable)throw new ge.ErrnoError(70)}else o=e.position;var s=e.stream_ops.write(e,r,t,n,o,a);i||(e.position+=s);try{e.path&&ge.trackingDelegate.onWriteToFile&&ge.trackingDelegate.onWriteToFile(e.path)}catch(r){w("FS.trackingDelegate['onWriteToFile']('"+e.path+"') threw an exception: "+r.message)}return s},allocate:function(e,r,t){if(ge.isClosed(e))throw new ge.ErrnoError(8);if(r<0||t<=0)throw new ge.ErrnoError(28);if(0==(2097155&e.flags))throw new ge.ErrnoError(8);if(!ge.isFile(e.node.mode)&&!ge.isDir(e.node.mode))throw new ge.ErrnoError(43);if(!e.stream_ops.allocate)throw new ge.ErrnoError(138);e.stream_ops.allocate(e,r,t)},mmap:function(e,r,t,n,o,a){if(0!=(2&o)&&0==(2&a)&&2!=(2097155&e.flags))throw new ge.ErrnoError(2);if(1==(2097155&e.flags))throw new ge.ErrnoError(2);if(!e.stream_ops.mmap)throw new ge.ErrnoError(43);return e.stream_ops.mmap(e,r,t,n,o,a)},msync:function(e,r,t,n,o){return e&&e.stream_ops.msync?e.stream_ops.msync(e,r,t,n,o):0},munmap:function(e){return 0},ioctl:function(e,r,t){if(!e.stream_ops.ioctl)throw new ge.ErrnoError(59);return e.stream_ops.ioctl(e,r,t)},readFile:function(e,r){if((r=r||{}).flags=r.flags||0,r.encoding=r.encoding||"binary","utf8"!==r.encoding&&"binary"!==r.encoding)throw new Error('Invalid encoding type "'+r.encoding+'"');var t,n=ge.open(e,r.flags),o=ge.stat(e).size,a=new Uint8Array(o);return ge.read(n,a,0,o,0),"utf8"===r.encoding?t=C(a,0):"binary"===r.encoding&&(t=a),ge.close(n),t},writeFile:function(e,r,t){(t=t||{}).flags=t.flags||577;var n=ge.open(e,t.flags,t.mode);if("string"==typeof r){var o=new Uint8Array(F(r)+1),a=D(r,o,0,o.length);ge.write(n,o,0,a,void 0,t.canOwn)}else{if(!ArrayBuffer.isView(r))throw new Error("Unsupported data type");ge.write(n,r,0,r.byteLength,void 0,t.canOwn)}ge.close(n)},cwd:function(){return ge.currentPath},chdir:function(e){var r=ge.lookupPath(e,{follow:!0});if(null===r.node)throw new ge.ErrnoError(44);if(!ge.isDir(r.node.mode))throw new ge.ErrnoError(54);var t=ge.nodePermissions(r.node,"x");if(t)throw new ge.ErrnoError(t);ge.currentPath=r.path},createDefaultDirectories:function(){ge.mkdir("/tmp"),ge.mkdir("/home"),ge.mkdir("/home/web_user")},createDefaultDevices:function(){ge.mkdir("/dev"),ge.registerDevice(ge.makedev(1,3),{read:function(){return 0},write:function(e,r,t,n,o){return n}}),ge.mkdev("/dev/null",ge.makedev(1,3)),he.register(ge.makedev(5,0),he.default_tty_ops),he.register(ge.makedev(6,0),he.default_tty1_ops),ge.mkdev("/dev/tty",ge.makedev(5,0)),ge.mkdev("/dev/tty1",ge.makedev(6,0));var e=function(){if("object"==typeof crypto&&"function"==typeof crypto.getRandomValues){var e=new Uint8Array(1);return function(){return crypto.getRandomValues(e),e[0]}}if(c)try{var r=i.default;return function(){return r.randomBytes(1)[0]}}catch(e){}return function(){te("randomDevice")}}();ge.createDevice("/dev","random",e),ge.createDevice("/dev","urandom",e),ge.mkdir("/dev/shm"),ge.mkdir("/dev/shm/tmp")},createSpecialDirectories:function(){ge.mkdir("/proc");var e=ge.mkdir("/proc/self");ge.mkdir("/proc/self/fd"),ge.mount({mount:function(){var r=ge.createNode(e,"fd",16895,73);return r.node_ops={lookup:function(e,r){var t=+r,n=ge.getStream(t);if(!n)throw new ge.ErrnoError(8);var o={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:function(){return n.path}}};return o.parent=o,o}},r}},{},"/proc/self/fd")},createStandardStreams:function(){t.stdin?ge.createDevice("/dev","stdin",t.stdin):ge.symlink("/dev/tty","/dev/stdin"),t.stdout?ge.createDevice("/dev","stdout",null,t.stdout):ge.symlink("/dev/tty","/dev/stdout"),t.stderr?ge.createDevice("/dev","stderr",null,t.stderr):ge.symlink("/dev/tty1","/dev/stderr"),ge.open("/dev/stdin",0),ge.open("/dev/stdout",1),ge.open("/dev/stderr",1)},ensureErrnoError:function(){ge.ErrnoError||(ge.ErrnoError=function(e,r){this.node=r,this.setErrno=function(e){this.errno=e},this.setErrno(e),this.message="FS error"},ge.ErrnoError.prototype=new Error,ge.ErrnoError.prototype.constructor=ge.ErrnoError,[44].forEach((function(e){ge.genericErrors[e]=new ge.ErrnoError(e),ge.genericErrors[e].stack="<generic error, no stack>"})))},staticInit:function(){ge.ensureErrnoError(),ge.nameTable=new Array(4096),ge.mount(ve,{},"/"),ge.createDefaultDirectories(),ge.createDefaultDevices(),ge.createSpecialDirectories(),ge.filesystems={MEMFS:ve}},init:function(e,r,n){ge.init.initialized=!0,ge.ensureErrnoError(),t.stdin=e||t.stdin,t.stdout=r||t.stdout,t.stderr=n||t.stderr,ge.createStandardStreams()},quit:function(){ge.init.initialized=!1;var e=t._fflush;e&&e(0);for(var r=0;r<ge.streams.length;r++){var n=ge.streams[r];n&&ge.close(n)}},getMode:function(e,r){var t=0;return e&&(t|=365),r&&(t|=146),t},findObject:function(e,r){var t=ge.analyzePath(e,r);return t.exists?t.object:null},analyzePath:function(e,r){try{e=(n=ge.lookupPath(e,{follow:!r})).path}catch(e){}var t={isRoot:!1,exists:!1,error:0,name:null,path:null,object:null,parentExists:!1,parentPath:null,parentObject:null};try{var n=ge.lookupPath(e,{parent:!0});t.parentExists=!0,t.parentPath=n.path,t.parentObject=n.node,t.name=de.basename(e),n=ge.lookupPath(e,{follow:!r}),t.exists=!0,t.path=n.path,t.object=n.node,t.name=n.node.name,t.isRoot="/"===n.path}catch(e){t.error=e.errno}return t},createPath:function(e,r,t,n){e="string"==typeof e?e:ge.getPath(e);for(var o=r.split("/").reverse();o.length;){var a=o.pop();if(a){var i=de.join2(e,a);try{ge.mkdir(i)}catch(e){}e=i}}return i},createFile:function(e,r,t,n,o){var a=de.join2("string"==typeof e?e:ge.getPath(e),r),i=ge.getMode(n,o);return ge.create(a,i)},createDataFile:function(e,r,t,n,o,a){var i=r?de.join2("string"==typeof e?e:ge.getPath(e),r):e,s=ge.getMode(n,o),u=ge.create(i,s);if(t){if("string"==typeof t){for(var c=new Array(t.length),f=0,l=t.length;f<l;++f)c[f]=t.charCodeAt(f);t=c}ge.chmod(u,146|s);var d=ge.open(u,577);ge.write(d,t,0,t.length,0,a),ge.close(d),ge.chmod(u,s)}return u},createDevice:function(e,r,t,n){var o=de.join2("string"==typeof e?e:ge.getPath(e),r),a=ge.getMode(!!t,!!n);ge.createDevice.major||(ge.createDevice.major=64);var i=ge.makedev(ge.createDevice.major++,0);return ge.registerDevice(i,{open:function(e){e.seekable=!1},close:function(e){n&&n.buffer&&n.buffer.length&&n(10)},read:function(e,r,n,o,a){for(var i=0,s=0;s<o;s++){var u;try{u=t()}catch(e){throw new ge.ErrnoError(29)}if(void 0===u&&0===i)throw new ge.ErrnoError(6);if(null==u)break;i++,r[n+s]=u}return i&&(e.node.timestamp=Date.now()),i},write:function(e,r,t,o,a){for(var i=0;i<o;i++)try{n(r[t+i])}catch(e){throw new ge.ErrnoError(29)}return o&&(e.node.timestamp=Date.now()),i}}),ge.mkdev(o,a,i)},forceLoadFile:function(e){if(e.isDevice||e.isFolder||e.link||e.contents)return!0;if("undefined"!=typeof XMLHttpRequest)throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");if(!d)throw new Error("Cannot load without read() or XMLHttpRequest.");try{e.contents=Xr(d(e.url),!0),e.usedBytes=e.contents.length}catch(e){throw new ge.ErrnoError(29)}},createLazyFile:function(e,r,t,n,o){function a(){this.lengthKnown=!1,this.chunks=[]}if(a.prototype.get=function(e){if(!(e>this.length-1||e<0)){var r=e%this.chunkSize,t=e/this.chunkSize|0;return this.getter(t)[r]}},a.prototype.setDataGetter=function(e){this.getter=e},a.prototype.cacheLength=function(){var e=new XMLHttpRequest;if(e.open("HEAD",t,!1),e.send(null),!(e.status>=200&&e.status<300||304===e.status))throw new Error("Couldn't load "+t+". Status: "+e.status);var r,n=Number(e.getResponseHeader("Content-length")),o=(r=e.getResponseHeader("Accept-Ranges"))&&"bytes"===r,a=(r=e.getResponseHeader("Content-Encoding"))&&"gzip"===r,i=1048576;o||(i=n);var s=this;s.setDataGetter((function(e){var r=e*i,o=(e+1)*i-1;if(o=Math.min(o,n-1),void 0===s.chunks[e]&&(s.chunks[e]=function(e,r){if(e>r)throw new Error("invalid range ("+e+", "+r+") or no bytes requested!");if(r>n-1)throw new Error("only "+n+" bytes available! programmer error!");var o=new XMLHttpRequest;if(o.open("GET",t,!1),n!==i&&o.setRequestHeader("Range","bytes="+e+"-"+r),"undefined"!=typeof Uint8Array&&(o.responseType="arraybuffer"),o.overrideMimeType&&o.overrideMimeType("text/plain; charset=x-user-defined"),o.send(null),!(o.status>=200&&o.status<300||304===o.status))throw new Error("Couldn't load "+t+". Status: "+o.status);return void 0!==o.response?new Uint8Array(o.response||[]):Xr(o.responseText||"",!0)}(r,o)),void 0===s.chunks[e])throw new Error("doXHR failed!");return s.chunks[e]})),!a&&n||(i=n=1,n=this.getter(0).length,i=n,y("LazyFiles on gzip forces download of the whole file when length is accessed")),this._length=n,this._chunkSize=i,this.lengthKnown=!0},"undefined"!=typeof XMLHttpRequest){if(!u)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var i=new a;Object.defineProperties(i,{length:{get:function(){return this.lengthKnown||this.cacheLength(),this._length}},chunkSize:{get:function(){return this.lengthKnown||this.cacheLength(),this._chunkSize}}});var s={isDevice:!1,contents:i}}else s={isDevice:!1,url:t};var c=ge.createFile(e,r,s,n,o);s.contents?c.contents=s.contents:s.url&&(c.contents=null,c.url=s.url),Object.defineProperties(c,{usedBytes:{get:function(){return this.contents.length}}});var f={};return Object.keys(c.stream_ops).forEach((function(e){var r=c.stream_ops[e];f[e]=function(){return ge.forceLoadFile(c),r.apply(null,arguments)}})),f.read=function(e,r,t,n,o){ge.forceLoadFile(c);var a=e.node.contents;if(o>=a.length)return 0;var i=Math.min(a.length-o,n);if(a.slice)for(var s=0;s<i;s++)r[t+s]=a[o+s];else for(s=0;s<i;s++)r[t+s]=a.get(o+s);return i},c.stream_ops=f,c},createPreloadedFile:function(e,r,n,o,a,i,s,u,c,f){Browser.init();var l=r?pe.resolve(de.join2(e,r)):e;function d(n){function d(t){f&&f(),u||ge.createDataFile(e,r,t,o,a,c),i&&i(),re()}var p=!1;t.preloadPlugins.forEach((function(e){p||e.canHandle(l)&&(e.handle(n,l,d,(function(){s&&s(),re()})),p=!0)})),p||d(n)}ee(),"string"==typeof n?Browser.asyncLoad(n,(function(e){d(e)}),s):d(n)},indexedDB:function(){return window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB},DB_NAME:function(){return"EM_FS_"+window.location.pathname},DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function(e,r,t){r=r||function(){},t=t||function(){};var n=ge.indexedDB();try{var o=n.open(ge.DB_NAME(),ge.DB_VERSION)}catch(e){return t(e)}o.onupgradeneeded=function(){y("creating db"),o.result.createObjectStore(ge.DB_STORE_NAME)},o.onsuccess=function(){var n=o.result.transaction([ge.DB_STORE_NAME],"readwrite"),a=n.objectStore(ge.DB_STORE_NAME),i=0,s=0,u=e.length;function c(){0==s?r():t()}e.forEach((function(e){var r=a.put(ge.analyzePath(e).object.contents,e);r.onsuccess=function(){++i+s==u&&c()},r.onerror=function(){s++,i+s==u&&c()}})),n.onerror=t},o.onerror=t},loadFilesFromDB:function(e,r,t){r=r||function(){},t=t||function(){};var n=ge.indexedDB();try{var o=n.open(ge.DB_NAME(),ge.DB_VERSION)}catch(e){return t(e)}o.onupgradeneeded=t,o.onsuccess=function(){var n=o.result;try{var a=n.transaction([ge.DB_STORE_NAME],"readonly")}catch(e){return void t(e)}var i=a.objectStore(ge.DB_STORE_NAME),s=0,u=0,c=e.length;function f(){0==u?r():t()}e.forEach((function(e){var r=i.get(e);r.onsuccess=function(){ge.analyzePath(e).exists&&ge.unlink(e),ge.createDataFile(de.dirname(e),de.basename(e),r.result,!0,!0,!0),++s+u==c&&f()},r.onerror=function(){u++,s+u==c&&f()}})),a.onerror=t},o.onerror=t}},ye={mappings:{},DEFAULT_POLLMASK:5,umask:511,calculateAt:function(e,r,t){if("/"===r[0])return r;var n;if(-100===e)n=ge.cwd();else{var o=ge.getStream(e);if(!o)throw new ge.ErrnoError(8);n=o.path}if(0==r.length){if(!t)throw new ge.ErrnoError(44);return n}return de.join2(n,r)},doStat:function(e,r,t){try{var n=e(r)}catch(e){if(e&&e.node&&de.normalize(r)!==de.normalize(ge.getPath(e.node)))return-54;throw e}return I[t>>2]=n.dev,I[t+4>>2]=0,I[t+8>>2]=n.ino,I[t+12>>2]=n.mode,I[t+16>>2]=n.nlink,I[t+20>>2]=n.uid,I[t+24>>2]=n.gid,I[t+28>>2]=n.rdev,I[t+32>>2]=0,se=[n.size>>>0,(ie=n.size,+Math.abs(ie)>=1?ie>0?(0|Math.min(+Math.floor(ie/4294967296),4294967295))>>>0:~~+Math.ceil((ie-+(~~ie>>>0))/4294967296)>>>0:0)],I[t+40>>2]=se[0],I[t+44>>2]=se[1],I[t+48>>2]=4096,I[t+52>>2]=n.blocks,I[t+56>>2]=n.atime.getTime()/1e3|0,I[t+60>>2]=0,I[t+64>>2]=n.mtime.getTime()/1e3|0,I[t+68>>2]=0,I[t+72>>2]=n.ctime.getTime()/1e3|0,I[t+76>>2]=0,se=[n.ino>>>0,(ie=n.ino,+Math.abs(ie)>=1?ie>0?(0|Math.min(+Math.floor(ie/4294967296),4294967295))>>>0:~~+Math.ceil((ie-+(~~ie>>>0))/4294967296)>>>0:0)],I[t+80>>2]=se[0],I[t+84>>2]=se[1],0},doMsync:function(e,r,t,n,o){var a=R.slice(e,e+t);ge.msync(r,a,o,t,n)},doMkdir:function(e,r){return"/"===(e=de.normalize(e))[e.length-1]&&(e=e.substr(0,e.length-1)),ge.mkdir(e,r,0),0},doMknod:function(e,r,t){switch(61440&r){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-28}return ge.mknod(e,r,t),0},doReadlink:function(e,r,t){if(t<=0)return-28;var n=ge.readlink(e),o=Math.min(t,F(n)),a=$[r+o];return S(n,r,t+1),$[r+o]=a,o},doAccess:function(e,r){if(-8&r)return-28;var t;if(!(t=ge.lookupPath(e,{follow:!0}).node))return-44;var n="";return 4&r&&(n+="r"),2&r&&(n+="w"),1&r&&(n+="x"),n&&ge.nodePermissions(t,n)?-2:0},doDup:function(e,r,t){var n=ge.getStream(t);return n&&ge.close(n),ge.open(e,r,0,t,t).fd},doReadv:function(e,r,t,n){for(var o=0,a=0;a<t;a++){var i=I[r+8*a>>2],s=I[r+(8*a+4)>>2],u=ge.read(e,$,i,s,n);if(u<0)return-1;if(o+=u,u<s)break}return o},doWritev:function(e,r,t,n){for(var o=0,a=0;a<t;a++){var i=I[r+8*a>>2],s=I[r+(8*a+4)>>2],u=ge.write(e,$,i,s,n);if(u<0)return-1;o+=u}return o},varargs:void 0,get:function(){return ye.varargs+=4,I[ye.varargs-4>>2]},getStr:function(e){return A(e)},getStreamFromFD:function(e){var r=ge.getStream(e);if(!r)throw new ge.ErrnoError(8);return r},get64:function(e,r){return e}};function we(e){switch(e){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+e)}}var Ee=void 0;function be(e){for(var r="",t=e;R[t];)r+=Ee[R[t++]];return r}var _e={},ke={},Te={};function Pe(e){if(void 0===e)return"_unknown";var r=(e=e.replace(/[^a-zA-Z0-9_]/g,"$")).charCodeAt(0);return r>=48&&r<=57?"_"+e:e}function Ce(e,r){return e=Pe(e),new Function("body","return function "+e+'() {\n "use strict"; return body.apply(this, arguments);\n};\n')(r)}function Ae(e,r){var t=Ce(r,(function(e){this.name=r,this.message=e;var t=new Error(e).stack;void 0!==t&&(this.stack=this.toString()+"\n"+t.replace(/^Error(:[^\n]*)?\n/,""))}));return t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.prototype.toString=function(){return void 0===this.message?this.name:this.name+": "+this.message},t}var De=void 0;function Se(e){throw new De(e)}var Fe=void 0;function xe(e){throw new Fe(e)}function $e(e,r,t){function n(r){var n=t(r);n.length!==e.length&&xe("Mismatched type converter count");for(var o=0;o<e.length;++o)Re(e[o],n[o])}e.forEach((function(e){Te[e]=r}));var o=new Array(r.length),a=[],i=0;r.forEach((function(e,r){ke.hasOwnProperty(e)?o[r]=ke[e]:(a.push(e),_e.hasOwnProperty(e)||(_e[e]=[]),_e[e].push((function(){o[r]=ke[e],++i===a.length&&n(o)})))})),0===a.length&&n(o)}function Re(e,r,t){if(t=t||{},!("argPackAdvance"in r))throw new TypeError("registerType registeredInstance requires argPackAdvance");var n=r.name;if(e||Se('type "'+n+'" must have a positive integer typeid pointer'),ke.hasOwnProperty(e)){if(t.ignoreDuplicateRegistrations)return;Se("Cannot register type '"+n+"' twice")}if(ke[e]=r,delete Te[e],_e.hasOwnProperty(e)){var o=_e[e];delete _e[e],o.forEach((function(e){e()}))}}function Me(e){if(!(this instanceof Ge))return!1;if(!(e instanceof Ge))return!1;for(var r=this.$$.ptrType.registeredClass,t=this.$$.ptr,n=e.$$.ptrType.registeredClass,o=e.$$.ptr;r.baseClass;)t=r.upcast(t),r=r.baseClass;for(;n.baseClass;)o=n.upcast(o),n=n.baseClass;return r===n&&t===o}function Oe(e){Se(e.$$.ptrType.registeredClass.name+" instance already deleted")}var Ie=!1;function je(e){}function Ue(e){e.count.value-=1,0===e.count.value&&function(e){e.smartPtr?e.smartPtrType.rawDestructor(e.smartPtr):e.ptrType.registeredClass.rawDestructor(e.ptr)}(e)}function Ne(e){return"undefined"==typeof FinalizationGroup?(Ne=function(e){return e},e):(Ie=new FinalizationGroup((function(e){for(var r=e.next();!r.done;r=e.next()){var t=r.value;t.ptr?Ue(t):console.warn("object already deleted: "+t.ptr)}})),Ne=function(e){return Ie.register(e,e.$$,e.$$),e},je=function(e){Ie.unregister(e.$$)},Ne(e))}function Be(){if(this.$$.ptr||Oe(this),this.$$.preservePointerOnDelete)return this.$$.count.value+=1,this;var e,r=Ne(Object.create(Object.getPrototypeOf(this),{$$:{value:(e=this.$$,{count:e.count,deleteScheduled:e.deleteScheduled,preservePointerOnDelete:e.preservePointerOnDelete,ptr:e.ptr,ptrType:e.ptrType,smartPtr:e.smartPtr,smartPtrType:e.smartPtrType})}}));return r.$$.count.value+=1,r.$$.deleteScheduled=!1,r}function We(){this.$$.ptr||Oe(this),this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete&&Se("Object already scheduled for deletion"),je(this),Ue(this.$$),this.$$.preservePointerOnDelete||(this.$$.smartPtr=void 0,this.$$.ptr=void 0)}function Le(){return!this.$$.ptr}var ze=void 0,He=[];function Ve(){for(;He.length;){var e=He.pop();e.$$.deleteScheduled=!1,e.delete()}}function Xe(){return this.$$.ptr||Oe(this),this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete&&Se("Object already scheduled for deletion"),He.push(this),1===He.length&&ze&&ze(Ve),this.$$.deleteScheduled=!0,this}function Ge(){}var qe={};function Je(e,r,t){if(void 0===e[r].overloadTable){var n=e[r];e[r]=function(){return e[r].overloadTable.hasOwnProperty(arguments.length)||Se("Function '"+t+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+e[r].overloadTable+")!"),e[r].overloadTable[arguments.length].apply(this,arguments)},e[r].overloadTable=[],e[r].overloadTable[n.argCount]=n}}function Ye(e,r,t,n,o,a,i,s){this.name=e,this.constructor=r,this.instancePrototype=t,this.rawDestructor=n,this.baseClass=o,this.getActualType=a,this.upcast=i,this.downcast=s,this.pureVirtualFunctions=[]}function Ke(e,r,t){for(;r!==t;)r.upcast||Se("Expected null or instance of "+t.name+", got an instance of "+r.name),e=r.upcast(e),r=r.baseClass;return e}function Qe(e,r){if(null===r)return this.isReference&&Se("null is not a valid "+this.name),0;r.$$||Se('Cannot pass "'+Sr(r)+'" as a '+this.name),r.$$.ptr||Se("Cannot pass deleted object as a pointer of type "+this.name);var t=r.$$.ptrType.registeredClass;return Ke(r.$$.ptr,t,this.registeredClass)}function Ze(e,r){var t;if(null===r)return this.isReference&&Se("null is not a valid "+this.name),this.isSmartPointer?(t=this.rawConstructor(),null!==e&&e.push(this.rawDestructor,t),t):0;r.$$||Se('Cannot pass "'+Sr(r)+'" as a '+this.name),r.$$.ptr||Se("Cannot pass deleted object as a pointer of type "+this.name),!this.isConst&&r.$$.ptrType.isConst&&Se("Cannot convert argument of type "+(r.$$.smartPtrType?r.$$.smartPtrType.name:r.$$.ptrType.name)+" to parameter type "+this.name);var n=r.$$.ptrType.registeredClass;if(t=Ke(r.$$.ptr,n,this.registeredClass),this.isSmartPointer)switch(void 0===r.$$.smartPtr&&Se("Passing raw pointer to smart pointer is illegal"),this.sharingPolicy){case 0:r.$$.smartPtrType===this?t=r.$$.smartPtr:Se("Cannot convert argument of type "+(r.$$.smartPtrType?r.$$.smartPtrType.name:r.$$.ptrType.name)+" to parameter type "+this.name);break;case 1:t=r.$$.smartPtr;break;case 2:if(r.$$.smartPtrType===this)t=r.$$.smartPtr;else{var o=r.clone();t=this.rawShare(t,Dr((function(){o.delete()}))),null!==e&&e.push(this.rawDestructor,t)}break;default:Se("Unsupporting sharing policy")}return t}function er(e,r){if(null===r)return this.isReference&&Se("null is not a valid "+this.name),0;r.$$||Se('Cannot pass "'+Sr(r)+'" as a '+this.name),r.$$.ptr||Se("Cannot pass deleted object as a pointer of type "+this.name),r.$$.ptrType.isConst&&Se("Cannot convert argument of type "+r.$$.ptrType.name+" to parameter type "+this.name);var t=r.$$.ptrType.registeredClass;return Ke(r.$$.ptr,t,this.registeredClass)}function rr(e){return this.fromWireType(j[e>>2])}function tr(e){return this.rawGetPointee&&(e=this.rawGetPointee(e)),e}function nr(e){this.rawDestructor&&this.rawDestructor(e)}function or(e){null!==e&&e.delete()}function ar(e,r,t){if(r===t)return e;if(void 0===t.baseClass)return null;var n=ar(e,r,t.baseClass);return null===n?null:t.downcast(n)}function ir(){return Object.keys(cr).length}function sr(){var e=[];for(var r in cr)cr.hasOwnProperty(r)&&e.push(cr[r]);return e}function ur(e){ze=e,He.length&&ze&&ze(Ve)}var cr={};function fr(e,r){return r=function(e,r){for(void 0===r&&Se("ptr should not be undefined");e.baseClass;)r=e.upcast(r),e=e.baseClass;return r}(e,r),cr[r]}function lr(e,r){return r.ptrType&&r.ptr||xe("makeClassHandle requires ptr and ptrType"),!!r.smartPtrType!==!!r.smartPtr&&xe("Both smartPtrType and smartPtr must be specified"),r.count={value:1},Ne(Object.create(e,{$$:{value:r}}))}function dr(e){var r=this.getPointee(e);if(!r)return this.destructor(e),null;var t=fr(this.registeredClass,r);if(void 0!==t){if(0===t.$$.count.value)return t.$$.ptr=r,t.$$.smartPtr=e,t.clone();var n=t.clone();return this.destructor(e),n}function o(){return this.isSmartPointer?lr(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:r,smartPtrType:this,smartPtr:e}):lr(this.registeredClass.instancePrototype,{ptrType:this,ptr:e})}var a,i=this.registeredClass.getActualType(r),s=qe[i];if(!s)return o.call(this);a=this.isConst?s.constPointerType:s.pointerType;var u=ar(r,this.registeredClass,a.registeredClass);return null===u?o.call(this):this.isSmartPointer?lr(a.registeredClass.instancePrototype,{ptrType:a,ptr:u,smartPtrType:this,smartPtr:e}):lr(a.registeredClass.instancePrototype,{ptrType:a,ptr:u})}function pr(e,r,t,n,o,a,i,s,u,c,f){this.name=e,this.registeredClass=r,this.isReference=t,this.isConst=n,this.isSmartPointer=o,this.pointeeType=a,this.sharingPolicy=i,this.rawGetPointee=s,this.rawConstructor=u,this.rawShare=c,this.rawDestructor=f,o||void 0!==r.baseClass?this.toWireType=Ze:n?(this.toWireType=Qe,this.destructorFunction=null):(this.toWireType=er,this.destructorFunction=null)}function hr(e,r,n){return-1!=e.indexOf("j")?function(e,r,n){var o=t["dynCall_"+e];return n&&n.length?o.apply(null,[r].concat(n)):o.call(null,r)}(e,r,n):B.get(r).apply(null,n)}function mr(e,r){var t,n,o,a=-1!=(e=be(e)).indexOf("j")?(t=e,n=r,o=[],function(){o.length=arguments.length;for(var e=0;e<arguments.length;e++)o[e]=arguments[e];return hr(t,n,o)}):B.get(r);return"function"!=typeof a&&Se("unknown function pointer with signature "+e+": "+r),a}var vr=void 0;function gr(e){var r=Zr(e),t=be(r);return Jr(r),t}function yr(e,r){var t=[],n={};throw r.forEach((function e(r){n[r]||ke[r]||(Te[r]?Te[r].forEach(e):(t.push(r),n[r]=!0))})),new vr(e+": "+t.map(gr).join([", "]))}function wr(e,r){for(var t=[],n=0;n<e;n++)t.push(I[(r>>2)+n]);return t}function Er(e){for(;e.length;){var r=e.pop();e.pop()(r)}}function br(e,r){if(!(e instanceof Function))throw new TypeError("new_ called with constructor type "+typeof e+" which is not a function");var t=Ce(e.name||"unknownFunctionName",(function(){}));t.prototype=e.prototype;var n=new t,o=e.apply(n,r);return o instanceof Object?o:n}function _r(e,r,t){return e instanceof Object||Se(t+' with invalid "this": '+e),e instanceof r.registeredClass.constructor||Se(t+' incompatible with "this" of type '+e.constructor.name),e.$$.ptr||Se("cannot call emscripten binding method "+t+" on deleted object"),Ke(e.$$.ptr,e.$$.ptrType.registeredClass,r.registeredClass)}var kr=[],Tr=[{},{value:void 0},{value:null},{value:!0},{value:!1}];function Pr(e){e>4&&0==--Tr[e].refcount&&(Tr[e]=void 0,kr.push(e))}function Cr(){for(var e=0,r=5;r<Tr.length;++r)void 0!==Tr[r]&&++e;return e}function Ar(){for(var e=5;e<Tr.length;++e)if(void 0!==Tr[e])return Tr[e];return null}function Dr(e){switch(e){case void 0:return 1;case null:return 2;case!0:return 3;case!1:return 4;default:var r=kr.length?kr.pop():Tr.length;return Tr[r]={refcount:1,value:e},r}}function Sr(e){if(null===e)return"null";var r=typeof e;return"object"===r||"array"===r||"function"===r?e.toString():""+e}function Fr(e,r){switch(r){case 2:return function(e){return this.fromWireType(U[e>>2])};case 3:return function(e){return this.fromWireType(N[e>>3])};default:throw new TypeError("Unknown float type: "+e)}}function xr(e,r,t){switch(r){case 0:return t?function(e){return $[e]}:function(e){return R[e]};case 1:return t?function(e){return M[e>>1]}:function(e){return O[e>>1]};case 2:return t?function(e){return I[e>>2]}:function(e){return j[e>>2]};default:throw new TypeError("Unknown integer type: "+e)}}function $r(e){return e||Se("Cannot use deleted val. handle = "+e),Tr[e].value}function Rr(e,r){var t=ke[e];return void 0===t&&Se(r+" has unknown type "+gr(e)),t}var Mr={};var Or=[];function Ir(e,r){return(e>>>0)+4294967296*r}function jr(e,r){if(e<=0)return e;var t=r<=32?Math.abs(1<<r-1):Math.pow(2,r-1);return e>=t&&(r<=32||e>t)&&(e=-2*t+e),e}function Ur(e,r){return e>=0?e:r<=32?2*Math.abs(1<<r-1)+e:Math.pow(2,r)+e}function Nr(e){if(!e||!e.callee||!e.callee.name)return[null,"",""];e.callee.toString();var r=e.callee.name,t="(",n=!0;for(var o in e){var a=e[o];n||(t+=", "),n=!1,t+="number"==typeof a||"string"==typeof a?a:"("+typeof a+")"}t+=")";var i=e.callee.caller;return n&&(t=""),[e=i?i.arguments:[],r,t]}function Br(e,r){24&e&&(r=r.replace(/\s+$/,""),r+=(r.length>0?"\n":"")+function(e){var r=le(),t=r.lastIndexOf("_emscripten_log"),n=r.lastIndexOf("_emscripten_get_callstack"),o=r.indexOf("\n",Math.max(t,n))+1;r=r.slice(o),32&e&&_("EM_LOG_DEMANGLE is deprecated; ignoring"),8&e&&"undefined"==typeof emscripten_source_map&&(_('Source map information is not available, emscripten_log with EM_LOG_C_STACK will be ignored. Build with "--pre-js $EMSCRIPTEN/src/emscripten-source-map.min.js" linker flag to add source map loading to code.'),e^=8,e|=16);var a=null;if(128&e)for(a=Nr(arguments);a[1].indexOf("_emscripten_")>=0;)a=Nr(a[0]);var i=r.split("\n");r="";var s=new RegExp("\\s*(.*?)@(.*?):([0-9]+):([0-9]+)"),u=new RegExp("\\s*(.*?)@(.*):(.*)(:(.*))?"),c=new RegExp("\\s*at (.*?) \\((.*):(.*):(.*)\\)");for(var f in i){var l=i[f],d="",p="",h=0,m=0,v=c.exec(l);if(v&&5==v.length)d=v[1],p=v[2],h=v[3],m=v[4];else{if((v=s.exec(l))||(v=u.exec(l)),!(v&&v.length>=4)){r+=l+"\n";continue}d=v[1],p=v[2],h=v[3],m=0|v[4]}var g=!1;if(8&e){var y=emscripten_source_map.originalPositionFor({line:h,column:m});(g=y&&y.source)&&(64&e&&(y.source=y.source.substring(y.source.replace(/\\/g,"/").lastIndexOf("/")+1)),r+=" at "+d+" ("+y.source+":"+y.line+":"+y.column+")\n")}(16&e||!g)&&(64&e&&(p=p.substring(p.replace(/\\/g,"/").lastIndexOf("/")+1)),r+=(g?" = "+d:" at "+d)+" ("+p+":"+h+":"+m+")\n"),128&e&&a[0]&&(a[1]==d&&a[2].length>0&&(r=r.replace(/\s+$/,""),r+=" with values: "+a[1]+a[2]+"\n"),a=Nr(a[0]))}return r.replace(/\s+$/,"")}(e)),1&e?4&e?console.error(r):2&e?console.warn(r):512&e?console.info(r):256&e?console.debug(r):console.log(r):6&e?w(r):y(r)}var Wr={};function Lr(){if(!Lr.strings){var e={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"==typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:l||"./this.program"};for(var r in Wr)e[r]=Wr[r];var t=[];for(var r in e)t.push(r+"="+e[r]);Lr.strings=t}return Lr.strings}var zr=function(e,r,t,n){e||(e=this),this.parent=e,this.mount=e.mount,this.mounted=null,this.id=ge.nextInode++,this.name=r,this.mode=t,this.node_ops={},this.stream_ops={},this.rdev=n},Hr=365,Vr=146;function Xr(e,r,t){var n=t>0?t:F(e)+1,o=new Array(n),a=D(e,o,0,o.length);return r&&(o.length=a),o}Object.defineProperties(zr.prototype,{read:{get:function(){return(this.mode&Hr)===Hr},set:function(e){e?this.mode|=Hr:this.mode&=-366}},write:{get:function(){return(this.mode&Vr)===Vr},set:function(e){e?this.mode|=Vr:this.mode&=-147}},isFolder:{get:function(){return ge.isDir(this.mode)}},isDevice:{get:function(){return ge.isChrdev(this.mode)}}}),ge.FSNode=zr,ge.staticInit(),function(){for(var e=new Array(256),r=0;r<256;++r)e[r]=String.fromCharCode(r);Ee=e}(),De=t.BindingError=Ae(Error,"BindingError"),Fe=t.InternalError=Ae(Error,"InternalError"),Ge.prototype.isAliasOf=Me,Ge.prototype.clone=Be,Ge.prototype.delete=We,Ge.prototype.isDeleted=Le,Ge.prototype.deleteLater=Xe,pr.prototype.getPointee=tr,pr.prototype.destructor=nr,pr.prototype.argPackAdvance=8,pr.prototype.readValueFromPointer=rr,pr.prototype.deleteObject=or,pr.prototype.fromWireType=dr,t.getInheritedInstanceCount=ir,t.getLiveInheritedInstances=sr,t.flushPendingDeletes=Ve,t.setDelayFunction=ur,vr=t.UnboundTypeError=Ae(Error,"UnboundTypeError"),t.count_emval_handles=Cr,t.get_first_emval=Ar;var Gr={x:function(e,r,t){ye.varargs=t;try{var n=ye.getStreamFromFD(e);switch(r){case 0:return(o=ye.get())<0?-28:ge.open(n.path,n.flags,0,o).fd;case 1:case 2:case 13:case 14:return 0;case 3:return n.flags;case 4:var o=ye.get();return n.flags|=o,0;case 12:o=ye.get();return M[o+0>>1]=2,0;case 16:case 8:default:return-28;case 9:return a=28,I[Kr()>>2]=a,-1}}catch(e){return void 0!==ge&&e instanceof ge.ErrnoError||te(e),-e.errno}var a},w:function(e,r,t){ye.varargs=t;try{var n=ye.getStr(e),o=t?ye.get():0;return ge.open(n,r,o).fd}catch(e){return void 0!==ge&&e instanceof ge.ErrnoError||te(e),-e.errno}},C:function(e,r,t,n,o){var a=we(t);Re(e,{name:r=be(r),fromWireType:function(e){return!!e},toWireType:function(e,r){return r?n:o},argPackAdvance:8,readValueFromPointer:function(e){var n;if(1===t)n=$;else if(2===t)n=M;else{if(4!==t)throw new TypeError("Unknown boolean type size: "+r);n=I}return this.fromWireType(n[e>>a])},destructorFunction:null})},n:function(e,r,n,o,a,i,s,u,c,f,l,d,p){l=be(l),i=mr(a,i),u&&(u=mr(s,u)),f&&(f=mr(c,f)),p=mr(d,p);var h=Pe(l);!function(e,r,n){t.hasOwnProperty(e)?((void 0===n||void 0!==t[e].overloadTable&&void 0!==t[e].overloadTable[n])&&Se("Cannot register public name '"+e+"' twice"),Je(t,e,e),t.hasOwnProperty(n)&&Se("Cannot register multiple overloads of a function with the same number of arguments ("+n+")!"),t[e].overloadTable[n]=r):(t[e]=r,void 0!==n&&(t[e].numArguments=n))}(h,(function(){yr("Cannot construct "+l+" due to unbound types",[o])})),$e([e,r,n],o?[o]:[],(function(r){var n,a;r=r[0],a=o?(n=r.registeredClass).instancePrototype:Ge.prototype;var s=Ce(h,(function(){if(Object.getPrototypeOf(this)!==c)throw new De("Use 'new' to construct "+l);if(void 0===d.constructor_body)throw new De(l+" has no accessible constructor");var e=d.constructor_body[arguments.length];if(void 0===e)throw new De("Tried to invoke ctor of "+l+" with invalid number of parameters ("+arguments.length+") - expected ("+Object.keys(d.constructor_body).toString()+") parameters instead!");return e.apply(this,arguments)})),c=Object.create(a,{constructor:{value:s}});s.prototype=c;var d=new Ye(l,s,c,p,n,i,u,f),m=new pr(l,d,!0,!1,!1),v=new pr(l+"*",d,!1,!1,!1),g=new pr(l+" const*",d,!1,!0,!1);return qe[e]={pointerType:v,constPointerType:g},function(e,r,n){t.hasOwnProperty(e)||xe("Replacing nonexistant public symbol"),void 0!==t[e].overloadTable&&void 0!==n?t[e].overloadTable[n]=r:(t[e]=r,t[e].argCount=n)}(h,s),[m,v,g]}))},i:function(e,r,t,n,o,a){T(r>0);var i=wr(r,t);o=mr(n,o);var s=[a],u=[];$e([],[e],(function(e){var t="constructor "+(e=e[0]).name;if(void 0===e.registeredClass.constructor_body&&(e.registeredClass.constructor_body=[]),void 0!==e.registeredClass.constructor_body[r-1])throw new De("Cannot register multiple constructors with identical number of parameters ("+(r-1)+") for class '"+e.name+"'! Overload resolution is currently only performed using the parameter count, not actual type info!");return e.registeredClass.constructor_body[r-1]=function(){yr("Cannot construct "+e.name+" due to unbound types",i)},$e([],i,(function(n){return e.registeredClass.constructor_body[r-1]=function(){arguments.length!==r-1&&Se(t+" called with "+arguments.length+" arguments, expected "+(r-1)),u.length=0,s.length=r;for(var e=1;e<r;++e)s[e]=n[e].toWireType(u,arguments[e-1]);var a=o.apply(null,s);return Er(u),n[0].fromWireType(a)},[]})),[]}))},f:function(e,r,t,n,o,a,i,s){var u=wr(t,n);r=be(r),a=mr(o,a),$e([],[e],(function(e){var n=(e=e[0]).name+"."+r;function o(){yr("Cannot call "+n+" due to unbound types",u)}s&&e.registeredClass.pureVirtualFunctions.push(r);var c=e.registeredClass.instancePrototype,f=c[r];return void 0===f||void 0===f.overloadTable&&f.className!==e.name&&f.argCount===t-2?(o.argCount=t-2,o.className=e.name,c[r]=o):(Je(c,r,n),c[r].overloadTable[t-2]=o),$e([],u,(function(o){var s=function(e,r,t,n,o){var a=r.length;a<2&&Se("argTypes array size mismatch! Must at least get return value and 'this' types!");for(var i=null!==r[1]&&null!==t,s=!1,u=1;u<r.length;++u)if(null!==r[u]&&void 0===r[u].destructorFunction){s=!0;break}var c="void"!==r[0].name,f="",l="";for(u=0;u<a-2;++u)f+=(0!==u?", ":"")+"arg"+u,l+=(0!==u?", ":"")+"arg"+u+"Wired";var d="return function "+Pe(e)+"("+f+") {\nif (arguments.length !== "+(a-2)+") {\nthrowBindingError('function "+e+" called with ' + arguments.length + ' arguments, expected "+(a-2)+" args!');\n}\n";s&&(d+="var destructors = [];\n");var p=s?"destructors":"null",h=["throwBindingError","invoker","fn","runDestructors","retType","classParam"],m=[Se,n,o,Er,r[0],r[1]];for(i&&(d+="var thisWired = classParam.toWireType("+p+", this);\n"),u=0;u<a-2;++u)d+="var arg"+u+"Wired = argType"+u+".toWireType("+p+", arg"+u+"); // "+r[u+2].name+"\n",h.push("argType"+u),m.push(r[u+2]);if(i&&(l="thisWired"+(l.length>0?", ":"")+l),d+=(c?"var rv = ":"")+"invoker(fn"+(l.length>0?", ":"")+l+");\n",s)d+="runDestructors(destructors);\n";else for(u=i?1:2;u<r.length;++u){var v=1===u?"thisWired":"arg"+(u-2)+"Wired";null!==r[u].destructorFunction&&(d+=v+"_dtor("+v+"); // "+r[u].name+"\n",h.push(v+"_dtor"),m.push(r[u].destructorFunction))}return c&&(d+="var ret = retType.fromWireType(rv);\nreturn ret;\n"),d+="}\n",h.push(d),br(Function,h).apply(null,m)}(n,o,e,a,i);return void 0===c[r].overloadTable?(s.argCount=t-2,c[r]=s):c[r].overloadTable[t-2]=s,[]})),[]}))},H:function(e,r,t,n,o,a,i,s,u,c){r=be(r),o=mr(n,o),$e([],[e],(function(e){var n=(e=e[0]).name+"."+r,f={get:function(){yr("Cannot access "+n+" due to unbound types",[t,i])},enumerable:!0,configurable:!0};return f.set=u?function(){yr("Cannot access "+n+" due to unbound types",[t,i])}:function(e){Se(n+" is a read-only property")},Object.defineProperty(e.registeredClass.instancePrototype,r,f),$e([],u?[t,i]:[t],(function(t){var i=t[0],f={get:function(){var r=_r(this,e,n+" getter");return i.fromWireType(o(a,r))},enumerable:!0};if(u){u=mr(s,u);var l=t[1];f.set=function(r){var t=_r(this,e,n+" setter"),o=[];u(c,t,l.toWireType(o,r)),Er(o)}}return Object.defineProperty(e.registeredClass.instancePrototype,r,f),[]})),[]}))},B:function(e,r){Re(e,{name:r=be(r),fromWireType:function(e){var r=Tr[e].value;return Pr(e),r},toWireType:function(e,r){return Dr(r)},argPackAdvance:8,readValueFromPointer:rr,destructorFunction:null})},l:function(e,r,t){var n=we(t);Re(e,{name:r=be(r),fromWireType:function(e){return e},toWireType:function(e,r){if("number"!=typeof r&&"boolean"!=typeof r)throw new TypeError('Cannot convert "'+Sr(r)+'" to '+this.name);return r},argPackAdvance:8,readValueFromPointer:Fr(r,n),destructorFunction:null})},c:function(e,r,t,n,o){r=be(r),-1===o&&(o=4294967295);var a=we(t),i=function(e){return e};if(0===n){var s=32-8*t;i=function(e){return e<<s>>>s}}var u=-1!=r.indexOf("unsigned");Re(e,{name:r,fromWireType:i,toWireType:function(e,t){if("number"!=typeof t&&"boolean"!=typeof t)throw new TypeError('Cannot convert "'+Sr(t)+'" to '+this.name);if(t<n||t>o)throw new TypeError('Passing a number "'+Sr(t)+'" from JS side to C/C++ side to an argument of type "'+r+'", which is outside the valid range ['+n+", "+o+"]!");return u?t>>>0:0|t},argPackAdvance:8,readValueFromPointer:xr(r,a,0!==n),destructorFunction:null})},b:function(e,r,t){var n=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][r];function o(e){var r=j,t=r[e>>=2],o=r[e+1];return new n(x,o,t)}Re(e,{name:t=be(t),fromWireType:o,argPackAdvance:8,readValueFromPointer:o},{ignoreDuplicateRegistrations:!0})},m:function(e,r){var t="std::string"===(r=be(r));Re(e,{name:r,fromWireType:function(e){var r,n=j[e>>2];if(t)for(var o=e+4,a=0;a<=n;++a){var i=e+4+a;if(a==n||0==R[i]){var s=A(o,i-o);void 0===r?r=s:(r+=String.fromCharCode(0),r+=s),o=i+1}}else{var u=new Array(n);for(a=0;a<n;++a)u[a]=String.fromCharCode(R[e+4+a]);r=u.join("")}return Jr(e),r},toWireType:function(e,r){r instanceof ArrayBuffer&&(r=new Uint8Array(r));var n="string"==typeof r;n||r instanceof Uint8Array||r instanceof Uint8ClampedArray||r instanceof Int8Array||Se("Cannot pass non-string to std::string");var o=(t&&n?function(){return F(r)}:function(){return r.length})(),a=Yr(4+o+1);if(j[a>>2]=o,t&&n)S(r,a+4,o+1);else if(n)for(var i=0;i<o;++i){var s=r.charCodeAt(i);s>255&&(Jr(a),Se("String has UTF-16 code units that do not fit in 8 bits")),R[a+4+i]=s}else for(i=0;i<o;++i)R[a+4+i]=r[i];return null!==e&&e.push(Jr,a),a},argPackAdvance:8,readValueFromPointer:rr,destructorFunction:function(e){Jr(e)}})},h:function(e,r,t){var n,o,a,i,s;t=be(t),2===r?(n=L,o=z,i=H,a=function(){return O},s=1):4===r&&(n=V,o=X,i=G,a=function(){return j},s=2),Re(e,{name:t,fromWireType:function(e){for(var t,o=j[e>>2],i=a(),u=e+4,c=0;c<=o;++c){var f=e+4+c*r;if(c==o||0==i[f>>s]){var l=n(u,f-u);void 0===t?t=l:(t+=String.fromCharCode(0),t+=l),u=f+r}}return Jr(e),t},toWireType:function(e,n){"string"!=typeof n&&Se("Cannot pass non-string to C++ string type "+t);var a=i(n),u=Yr(4+a+r);return j[u>>2]=a>>s,o(n,u+4,a+r),null!==e&&e.push(Jr,u),u},argPackAdvance:8,readValueFromPointer:rr,destructorFunction:function(e){Jr(e)}})},D:function(e,r){Re(e,{isVoid:!0,name:r=be(r),argPackAdvance:0,fromWireType:function(){},toWireType:function(e,r){}})},u:function(e,r,t){e=$r(e),r=Rr(r,"emval::as");var n=[],o=Dr(n);return I[t>>2]=o,r.toWireType(n,e)},e:function(e,r,t,n){var o,a;(e=Or[e])(r=$r(r),t=void 0===(a=Mr[o=t])?be(o):a,null,n)},p:Pr,d:function(e,r){for(var t=function(e,r){for(var t=new Array(e),n=0;n<e;++n)t[n]=Rr(I[(r>>2)+n],"parameter "+n);return t}(e,r),n=t[0],o=n.name+"_$"+t.slice(1).map((function(e){return e.name})).join("_")+"$",a=["retType"],i=[n],s="",u=0;u<e-1;++u)s+=(0!==u?", ":"")+"arg"+u,a.push("argType"+u),i.push(t[1+u]);var c="return function "+Pe("methodCaller_"+o)+"(handle, name, destructors, args) {\n",f=0;for(u=0;u<e-1;++u)c+=" var arg"+u+" = argType"+u+".readValueFromPointer(args"+(f?"+"+f:"")+");\n",f+=t[u+1].argPackAdvance;for(c+=" var rv = handle[name]("+s+");\n",u=0;u<e-1;++u)t[u+1].deleteObject&&(c+=" argType"+u+".deleteObject(arg"+u+");\n");n.isVoid||(c+=" return retType.toWireType(destructors, rv);\n"),c+="};\n",a.push(c);var l,d,p=br(Function,a).apply(null,i);return l=p,d=Or.length,Or.push(l),d},o:function(e){e>4&&(Tr[e].refcount+=1)},q:function(e){Er(Tr[e].value),Pr(e)},A:function(e,r){return Dr((e=Rr(e,"_emval_take_value")).readValueFromPointer(r))},a:function(){te()},F:function e(){return void 0===e.start&&(e.start=Date.now()),1e3*(Date.now()-e.start)|0},G:function(e,r,t){var n=function(e,r){var t=e,n=r;function o(e){var r;return n=function(e,r){return"double"!==r&&"i64"!==r||7&e&&(e+=4),e}(n,e),"double"===e?(r=N[n>>3],n+=8):"i64"==e?(r=[I[n>>2],I[n+4>>2]],n+=8):(e="i32",r=I[n>>2],n+=4),r}for(var a,i,s,u,c=[];;){var f=t;if(0===(a=$[t>>0]))break;if(i=$[t+1>>0],37==a){var l=!1,d=!1,p=!1,h=!1,m=!1;e:for(;;){switch(i){case 43:l=!0;break;case 45:d=!0;break;case 35:p=!0;break;case 48:if(h)break e;h=!0;break;case 32:m=!0;break;default:break e}t++,i=$[t+1>>0]}var v=0;if(42==i)v=o("i32"),t++,i=$[t+1>>0];else for(;i>=48&&i<=57;)v=10*v+(i-48),t++,i=$[t+1>>0];var g,y=!1,w=-1;if(46==i){if(w=0,y=!0,t++,42==(i=$[t+1>>0]))w=o("i32"),t++;else for(;;){var E=$[t+1>>0];if(E<48||E>57)break;w=10*w+(E-48),t++}i=$[t+1>>0]}switch(w<0&&(w=6,y=!1),String.fromCharCode(i)){case"h":104==$[t+2>>0]?(t++,g=1):g=2;break;case"l":108==$[t+2>>0]?(t++,g=8):g=4;break;case"L":case"q":case"j":g=8;break;case"z":case"t":case"I":g=4;break;default:g=null}switch(g&&t++,i=$[t+1>>0],String.fromCharCode(i)){case"d":case"i":case"u":case"o":case"x":case"X":case"p":var b=100==i||105==i;s=o("i"+8*(g=g||4)),8==g&&(s=117==i?(s[0]>>>0)+4294967296*(s[1]>>>0):Ir(s[0],s[1])),g<=4&&(s=(b?jr:Ur)(s&Math.pow(256,g)-1,8*g));var _=Math.abs(s),k="";if(100==i||105==i)C=jr(s,8*g).toString(10);else if(117==i)C=Ur(s,8*g).toString(10),s=Math.abs(s);else if(111==i)C=(p?"0":"")+_.toString(8);else if(120==i||88==i){if(k=p&&0!=s?"0x":"",s<0){s=-s,C=(_-1).toString(16);for(var T=[],P=0;P<C.length;P++)T.push((15-parseInt(C[P],16)).toString(16));for(C=T.join("");C.length<2*g;)C="f"+C}else C=_.toString(16);88==i&&(k=k.toUpperCase(),C=C.toUpperCase())}else 112==i&&(0===_?C="(nil)":(k="0x",C=_.toString(16)));if(y)for(;C.length<w;)C="0"+C;for(s>=0&&(l?k="+"+k:m&&(k=" "+k)),"-"==C.charAt(0)&&(k="-"+k,C=C.substr(1));k.length+C.length<v;)d?C+=" ":h?C="0"+C:k=" "+k;(C=k+C).split("").forEach((function(e){c.push(e.charCodeAt(0))}));break;case"f":case"F":case"e":case"E":case"g":case"G":var C;if(s=o("double"),isNaN(s))C="nan",h=!1;else if(isFinite(s)){var A=!1,D=Math.min(w,20);if(103==i||71==i){A=!0,w=w||1;var S=parseInt(s.toExponential(D).split("e")[1],10);w>S&&S>=-4?(i=(103==i?"f":"F").charCodeAt(0),w-=S+1):(i=(103==i?"e":"E").charCodeAt(0),w--),D=Math.min(w,20)}101==i||69==i?(C=s.toExponential(D),/[eE][-+]\d$/.test(C)&&(C=C.slice(0,-1)+"0"+C.slice(-1))):102!=i&&70!=i||(C=s.toFixed(D),0===s&&((u=s)<0||0===u&&1/u==-1/0)&&(C="-"+C));var F=C.split("e");if(A&&!p)for(;F[0].length>1&&-1!=F[0].indexOf(".")&&("0"==F[0].slice(-1)||"."==F[0].slice(-1));)F[0]=F[0].slice(0,-1);else for(p&&-1==C.indexOf(".")&&(F[0]+=".");w>D++;)F[0]+="0";C=F[0]+(F.length>1?"e"+F[1]:""),69==i&&(C=C.toUpperCase()),s>=0&&(l?C="+"+C:m&&(C=" "+C))}else C=(s<0?"-":"")+"inf",h=!1;for(;C.length<v;)d?C+=" ":C=!h||"-"!=C[0]&&"+"!=C[0]?(h?"0":" ")+C:C[0]+"0"+C.slice(1);i<97&&(C=C.toUpperCase()),C.split("").forEach((function(e){c.push(e.charCodeAt(0))}));break;case"s":var x=o("i8*"),M=x?Qr(x):"(null)".length;if(y&&(M=Math.min(M,w)),!d)for(;M<v--;)c.push(32);if(x)for(P=0;P<M;P++)c.push(R[x++>>0]);else c=c.concat(Xr("(null)".substr(0,M),!0));if(d)for(;M<v--;)c.push(32);break;case"c":for(d&&c.push(o("i8"));--v>0;)c.push(32);d||c.push(o("i8"));break;case"n":var O=o("i32*");I[O>>2]=c.length;break;case"%":c.push(a);break;default:for(P=f;P<t+2;P++)c.push($[P>>0])}t+=2}else c.push(a),t+=1}return c}(r,t);Br(e,C(n,0))},s:function(e){R.length,te("OOM")},t:function(e,r){try{var t=0;return Lr().forEach((function(n,o){var a=r+t;I[e+4*o>>2]=a,function(e,r,t){for(var n=0;n<e.length;++n)$[r++>>0]=e.charCodeAt(n);t||($[r>>0]=0)}(n,a),t+=n.length+1})),0}catch(e){return void 0!==ge&&e instanceof ge.ErrnoError||te(e),e.errno}},v:function(e,r){try{var t=Lr();I[e>>2]=t.length;var n=0;return t.forEach((function(e){n+=e.length+1})),I[r>>2]=n,0}catch(e){return void 0!==ge&&e instanceof ge.ErrnoError||te(e),e.errno}},k:function(e){try{var r=ye.getStreamFromFD(e);return ge.close(r),0}catch(e){return void 0!==ge&&e instanceof ge.ErrnoError||te(e),e.errno}},y:function(e,r){try{var t=ye.getStreamFromFD(e),n=t.tty?2:ge.isDir(t.mode)?3:ge.isLink(t.mode)?7:4;return $[r>>0]=n,0}catch(e){return void 0!==ge&&e instanceof ge.ErrnoError||te(e),e.errno}},z:function(e,r,t,n){try{var o=ye.getStreamFromFD(e),a=ye.doReadv(o,r,t);return I[n>>2]=a,0}catch(e){return void 0!==ge&&e instanceof ge.ErrnoError||te(e),e.errno}},r:function(e,r,t,n,o){try{var a=ye.getStreamFromFD(e),i=4294967296*t+(r>>>0),s=9007199254740992;return i<=-s||i>=s?-61:(ge.llseek(a,i,n),se=[a.position>>>0,(ie=a.position,+Math.abs(ie)>=1?ie>0?(0|Math.min(+Math.floor(ie/4294967296),4294967295))>>>0:~~+Math.ceil((ie-+(~~ie>>>0))/4294967296)>>>0:0)],I[o>>2]=se[0],I[o+4>>2]=se[1],a.getdents&&0===i&&0===n&&(a.getdents=null),0)}catch(e){return void 0!==ge&&e instanceof ge.ErrnoError||te(e),e.errno}},j:function(e,r,t,n){try{var o=ye.getStreamFromFD(e),a=ye.doWritev(o,r,t);return I[n>>2]=a,0}catch(e){return void 0!==ge&&e instanceof ge.ErrnoError||te(e),e.errno}},E:function(e){var r=Date.now();return I[e>>2]=r/1e3|0,I[e+4>>2]=r%1e3*1e3|0,0},g:function(e){}};!function(){var e={a:Gr};function r(e,r){var n,o,a=e.exports;t.asm=a,b=t.asm.I,n=b.buffer,x=n,t.HEAP8=$=new Int8Array(n),t.HEAP16=M=new Int16Array(n),t.HEAP32=I=new Int32Array(n),t.HEAPU8=R=new Uint8Array(n),t.HEAPU16=O=new Uint16Array(n),t.HEAPU32=j=new Uint32Array(n),t.HEAPF32=U=new Float32Array(n),t.HEAPF64=N=new Float64Array(n),B=t.asm.M,o=t.asm.J,J.unshift(o),re()}function n(e){r(e.instance)}function o(r){return function(){if(!E&&(s||u)){if("function"==typeof fetch&&!ae(ue))return fetch(ue,{credentials:"same-origin"}).then((function(e){if(!e.ok)throw"failed to load wasm binary file at '"+ue+"'";return e.arrayBuffer()})).catch((function(){return ce(ue)}));if(p)return new Promise((function(e,r){p(ue,(function(r){e(new Uint8Array(r))}),r)}))}return Promise.resolve().then((function(){return ce(ue)}))}().then((function(r){return WebAssembly.instantiate(r,e)})).then(r,(function(e){w("failed to asynchronously prepare wasm: "+e),te(e)}))}if(ee(),t.instantiateWasm)try{return t.instantiateWasm(e,r)}catch(e){return w("Module.instantiateWasm callback failed with error: "+e),!1}E||"function"!=typeof WebAssembly.instantiateStreaming||oe(ue)||ae(ue)||"function"!=typeof fetch?o(n):fetch(ue,{credentials:"same-origin"}).then((function(r){return WebAssembly.instantiateStreaming(r,e).then(n,(function(e){return w("wasm streaming compile failed: "+e),w("falling back to ArrayBuffer instantiation"),o(n)}))}))}(),t.___wasm_call_ctors=function(){return(t.___wasm_call_ctors=t.asm.J).apply(null,arguments)};var qr,Jr=t._free=function(){return(Jr=t._free=t.asm.K).apply(null,arguments)},Yr=t._malloc=function(){return(Yr=t._malloc=t.asm.L).apply(null,arguments)},Kr=t.___errno_location=function(){return(Kr=t.___errno_location=t.asm.N).apply(null,arguments)},Qr=t._strlen=function(){return(Qr=t._strlen=t.asm.O).apply(null,arguments)},Zr=t.___getTypeName=function(){return(Zr=t.___getTypeName=t.asm.P).apply(null,arguments)};function et(e){this.name="ExitStatus",this.message="Program terminated with exit("+e+")",this.status=e}function rt(e){function r(){qr||(qr=!0,t.calledRun=!0,k||(t.noFSInit||ge.init.initialized||ge.init(),fe(J),ge.ignorePermissions=!1,fe(Y),t.onRuntimeInitialized&&t.onRuntimeInitialized(),function(){if(t.postRun)for("function"==typeof t.postRun&&(t.postRun=[t.postRun]);t.postRun.length;)e=t.postRun.shift(),K.unshift(e);var e;fe(K)}()))}Q>0||(!function(){if(t.preRun)for("function"==typeof t.preRun&&(t.preRun=[t.preRun]);t.preRun.length;)e=t.preRun.shift(),q.unshift(e);var e;fe(q)}(),Q>0||(t.setStatus?(t.setStatus("Running..."),setTimeout((function(){setTimeout((function(){t.setStatus("")}),1),r()}),1)):r()))}if(t.___embind_register_native_and_builtin_types=function(){return(t.___embind_register_native_and_builtin_types=t.asm.Q).apply(null,arguments)},t.dynCall_ijiii=function(){return(t.dynCall_ijiii=t.asm.R).apply(null,arguments)},t.dynCall_viiijj=function(){return(t.dynCall_viiijj=t.asm.S).apply(null,arguments)},t.dynCall_jij=function(){return(t.dynCall_jij=t.asm.T).apply(null,arguments)},t.dynCall_jii=function(){return(t.dynCall_jii=t.asm.U).apply(null,arguments)},t.dynCall_jiji=function(){return(t.dynCall_jiji=t.asm.V).apply(null,arguments)},t._ff_h264_cabac_tables=82789,Z=function e(){qr||rt(),qr||(Z=e)},t.run=rt,t.preInit)for("function"==typeof t.preInit&&(t.preInit=[t.preInit]);t.preInit.length>0;)t.preInit.pop()();rt(),e.exports=t}));const u=1e3,c=!1,f=!0,l=!1,d=!1,p="initVideo",h="render",m="playAudio",v="initAudio",g="audioCode",y="videoCode",w=1,E=2,b="init",_="decode",k="audioDecode",T="videoDecode",P="close",C="updateConfig",A="key",D="delta";(()=>{try{if("object"==typeof WebAssembly&&"function"==typeof WebAssembly.instantiate){const e=new WebAssembly.Module(Uint8Array.of(0,97,115,109,1,0,0,0));if(e instanceof WebAssembly.Module)return new WebAssembly.Instance(e)instanceof WebAssembly.Instance}}catch(e){}})(),Date.now||(Date.now=function(){return(new Date).getTime()}),s.postRun=function(){var e=[],r=[],t={};"VideoEncoder"in self&&(t={hasInit:!1,isEmitInfo:!1,offscreenCanvas:null,offscreenCanvasCtx:null,decoder:new VideoDecoder({output:function(e){t.isEmitInfo||(n.opt.debug&&console.log("Jessibuca: [worker] Webcodecs Video Decoder initSize"),postMessage({cmd:p,w:e.codedWidth,h:e.codedHeight}),t.isEmitInfo=!0,t.offscreenCanvas=new OffscreenCanvas(e.codedWidth,e.codedHeight),t.offscreenCanvasCtx=t.offscreenCanvas.getContext("2d")),t.offscreenCanvasCtx.drawImage(e,0,0,e.codedWidth,e.codedHeight);let r=t.offscreenCanvas.transferToImageBitmap();postMessage({cmd:h,buffer:r,delay:n.delay,ts:0},[r]),setTimeout((function(){e.close?e.close():e.destroy()}),100)},error:function(e){console.error(e)}}),decode:function(e,r){const o=e[0]>>4==1;if(t.hasInit){const n=new EncodedVideoChunk({data:e.slice(5),timestamp:r,type:o?A:D});t.decoder.decode(n)}else if(o&&0===e[1]){const r=15&e[0];n.setVideoCodec(r);const o=function(e){let r=e.subarray(1,4),t="avc1.";for(let e=0;e<3;e++){let n=r[e].toString(16);n.length<2&&(n="0"+n),t+=n}return{codec:t,description:e}}(e.slice(5));t.decoder.configure(o),t.hasInit=!0}},reset(){t.hasInit=!1,t.isEmitInfo=!1,t.offscreenCanvas=null,t.offscreenCanvasCtx=null}});var n={opt:{debug:c,forceNoOffscreen:f,useWCS:l,videoBuffer:u,openWebglAlignment:d},useOffscreen:function(){return!n.opt.forceNoOffscreen&&"undefined"!=typeof OffscreenCanvas},initAudioPlanar:function(e,t){postMessage({cmd:v,sampleRate:t,channels:e});var n=[],o=0;this.playAudioPlanar=function(t,a,i){for(var u=a,c=[],f=0,l=0;l<2;l++){var d=s.HEAPU32[(t>>2)+l]>>2;c[l]=s.HEAPF32.subarray(d,d+u)}if(o){if(!(u>=(a=1024-o)))return o+=u,r[0]=Float32Array.of(...r[0],...c[0]),void(2==e&&(r[1]=Float32Array.of(...r[1],...c[1])));n[0]=Float32Array.of(...r[0],...c[0].subarray(0,a)),2==e&&(n[1]=Float32Array.of(...r[1],...c[1].subarray(0,a))),postMessage({cmd:m,buffer:n,ts:i},n.map((e=>e.buffer))),f=a,u-=a}for(o=u;o>=1024;o-=1024)n[0]=c[0].slice(f,f+=1024),2==e&&(n[1]=c[1].slice(f-1024,f)),postMessage({cmd:m,buffer:n,ts:i},n.map((e=>e.buffer)));o&&(r[0]=c[0].slice(f),2==e&&(r[1]=c[1].slice(f)))}},setVideoCodec:function(e){postMessage({cmd:y,code:e})},setAudioCodec:function(e){postMessage({cmd:g,code:e})},setVideoSize:function(e,r){postMessage({cmd:p,w:e,h:r});var t=e*r,o=t>>2;n.useOffscreen()?(this.offscreenCanvas=new OffscreenCanvas(e,r),this.offscreenCanvasGL=this.offscreenCanvas.getContext("webgl"),this.webglObj=((e,r)=>{var t=["attribute vec4 vertexPos;","attribute vec4 texturePos;","varying vec2 textureCoord;","void main()","{","gl_Position = vertexPos;","textureCoord = texturePos.xy;","}"].join("\n"),n=["precision highp float;","varying highp vec2 textureCoord;","uniform sampler2D ySampler;","uniform sampler2D uSampler;","uniform sampler2D vSampler;","const mat4 YUV2RGB = mat4","(","1.1643828125, 0, 1.59602734375, -.87078515625,","1.1643828125, -.39176171875, -.81296875, .52959375,","1.1643828125, 2.017234375, 0, -1.081390625,","0, 0, 0, 1",");","void main(void) {","highp float y = texture2D(ySampler, textureCoord).r;","highp float u = texture2D(uSampler, textureCoord).r;","highp float v = texture2D(vSampler, textureCoord).r;","gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;","}"].join("\n");r&&e.pixelStorei(e.UNPACK_ALIGNMENT,1);var o=e.createShader(e.VERTEX_SHADER);e.shaderSource(o,t),e.compileShader(o),e.getShaderParameter(o,e.COMPILE_STATUS)||console.log("Vertex shader failed to compile: "+e.getShaderInfoLog(o));var a=e.createShader(e.FRAGMENT_SHADER);e.shaderSource(a,n),e.compileShader(a),e.getShaderParameter(a,e.COMPILE_STATUS)||console.log("Fragment shader failed to compile: "+e.getShaderInfoLog(a));var i=e.createProgram();e.attachShader(i,o),e.attachShader(i,a),e.linkProgram(i),e.getProgramParameter(i,e.LINK_STATUS)||console.log("Program failed to compile: "+e.getProgramInfoLog(i)),e.useProgram(i);var s=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,s),e.bufferData(e.ARRAY_BUFFER,new Float32Array([1,1,-1,1,1,-1,-1,-1]),e.STATIC_DRAW);var u=e.getAttribLocation(i,"vertexPos");e.enableVertexAttribArray(u),e.vertexAttribPointer(u,2,e.FLOAT,!1,0,0);var c=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,c),e.bufferData(e.ARRAY_BUFFER,new Float32Array([1,0,0,0,1,1,0,1]),e.STATIC_DRAW);var f=e.getAttribLocation(i,"texturePos");function l(r,t){var n=e.createTexture();return e.bindTexture(e.TEXTURE_2D,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.bindTexture(e.TEXTURE_2D,null),e.uniform1i(e.getUniformLocation(i,r),t),n}e.enableVertexAttribArray(f),e.vertexAttribPointer(f,2,e.FLOAT,!1,0,0);var d=l("ySampler",0),p=l("uSampler",1),h=l("vSampler",2);return{render:function(r,t,n,o,a){e.viewport(0,0,r,t),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,d),e.texImage2D(e.TEXTURE_2D,0,e.LUMINANCE,r,t,0,e.LUMINANCE,e.UNSIGNED_BYTE,n),e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,p),e.texImage2D(e.TEXTURE_2D,0,e.LUMINANCE,r/2,t/2,0,e.LUMINANCE,e.UNSIGNED_BYTE,o),e.activeTexture(e.TEXTURE2),e.bindTexture(e.TEXTURE_2D,h),e.texImage2D(e.TEXTURE_2D,0,e.LUMINANCE,r/2,t/2,0,e.LUMINANCE,e.UNSIGNED_BYTE,a),e.drawArrays(e.TRIANGLE_STRIP,0,4)},destroy:function(){try{e.deleteProgram(i),e.deleteBuffer(s),e.deleteBuffer(c),e.deleteTexture(d),e.deleteTexture(p),e.deleteBuffer(h)}catch(e){}}}})(this.offscreenCanvasGL,n.opt.openWebglAlignment),this.draw=function(n,a,i,u){this.webglObj.render(e,r,s.HEAPU8.subarray(a,a+t),s.HEAPU8.subarray(i,i+o),s.HEAPU8.subarray(u,u+o));let c=this.offscreenCanvas.transferToImageBitmap();postMessage({cmd:h,buffer:c,delay:this.delay,ts:n},[c])}):this.draw=function(e,r,n,a){var i=[s.HEAPU8.subarray(r,r+t),s.HEAPU8.subarray(n,n+o),s.HEAPU8.subarray(a,a+o)].map((e=>Uint8Array.from(e)));postMessage({cmd:h,output:i,delay:this.delay,ts:e},i.map((e=>e.buffer)))}},getDelay:function(e){return e?(this.firstTimestamp?e&&(this.delay=Date.now()-this.startTimestamp-(e-this.firstTimestamp)):(this.firstTimestamp=e,this.startTimestamp=Date.now(),this.delay=-1),this.delay):-1},resetDelay:function(){this.firstTimestamp=null,this.startTimestamp=null,this.delay=-1},init:function(){n.opt.debug&&console.log("Jessibuca: [worker] init");const r=e=>{n.opt.useWCS&&n.useOffscreen()&&e.type===E&&t.decode?t.decode(e.payload,e.ts):e.decoder.decode(e.payload,e.ts)};this.stopId=setInterval((()=>{if(e.length)if(this.dropping){for((t=e.shift()).type===w&&0===t.payload[1]&&r(t);!t.isIFrame&&e.length;)(t=e.shift()).type===w&&0===t.payload[1]&&r(t);t.isIFrame&&(this.dropping=!1,r(t))}else{var t=e[0];if(-1===this.getDelay(t.ts))n.opt.debug&&console.log("Jessibuca: [worker]: common dumex delay is -1"),e.shift(),r(t);else if(this.delay>n.opt.videoBuffer+1e3)n.opt.debug&&console.log("Jessibuca: [worker]:",`delay is ${this.delay}, set dropping is true`),this.resetDelay(),this.dropping=!0;else for(;e.length&&(t=e[0],this.getDelay(t.ts)>n.opt.videoBuffer);)e.shift(),r(t)}}),10)},close:function(){n.opt.debug&&console.log("Jessibuca: [worker]: close"),clearInterval(this.stopId),this.stopId=null,o.clear(),a.clear(),t.reset&&t.reset(),this.firstTimestamp=null,this.startTimestamp=null,this.delay=-1,this.dropping=!1,this.webglObj&&(this.webglObj.destroy(),this.offscreenCanvas=null,this.offscreenCanvasGL=null,this.offscreenCanvasCtx=null),e=[],r=[],delete this.playAudioPlanar,delete this.draw},pushBuffer:function(r,t){t.type===w?e.push({ts:t.ts,payload:r,decoder:o,type:w}):t.type===E&&e.push({ts:t.ts,payload:r,decoder:a,type:E,isIFrame:t.isIFrame})}},o=new s.AudioDecoder(n),a=new s.VideoDecoder(n);postMessage({cmd:b}),self.onmessage=function(e){var r=e.data;switch(r.cmd){case b:try{n.opt=Object.assign(n.opt,JSON.parse(r.opt))}catch(e){}o.sample_rate=r.sampleRate,n.init();break;case _:n.pushBuffer(r.buffer,r.options);break;case k:o.decode(r.buffer,r.ts);break;case T:a.decode(r.buffer,r.ts);break;case P:n.close();break;case C:n.opt[r.key]=r.value}}}})); 1 +!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(require("path"),require("fs"),require("crypto")):"function"==typeof define&&define.amd?define(["path","fs","crypto"],r):r((e="undefined"!=typeof globalThis?globalThis:e||self).path,e.fs,e.crypto$1)}(this,(function(e,r,t){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var o=n(e),i=n(r),a=n(t);function s(e,r){return e(r={exports:{}},r.exports),r.exports}var l=s((function(e){var r=void 0!==r?r:{},t=(r={print:function(e){console.log("Jessibuca: [worker]:",e)},printErr:function(e){console.warn("Jessibuca: [worker]:",e),postMessage({cmd:"wasmError",message:e})}},Object.assign({},r)),n="./this.program",s="object"==typeof window,l="function"==typeof importScripts,u="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node,c=!s&&!u&&!l;if(r.ENVIRONMENT)throw new Error("Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node)");var d,f,p,m,h,g,v="";if(u){if("object"!=typeof process)throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");v=l?o.default.dirname(v)+"/":__dirname+"/",g=()=>{h||(m=i.default,h=o.default)},d=function(e,r){return g(),e=h.normalize(e),m.readFileSync(e,r?void 0:"utf8")},p=e=>{var r=d(e,!0);return r.buffer||(r=new Uint8Array(r)),F(r.buffer),r},f=(e,r,t)=>{g(),e=h.normalize(e),m.readFile(e,(function(e,n){e?t(e):r(n.buffer)}))},process.argv.length>1&&(n=process.argv[1].replace(/\\/g,"/")),process.argv.slice(2),e.exports=r,process.on("uncaughtException",(function(e){if(!(e instanceof St))throw e})),process.on("unhandledRejection",(function(e){throw e})),r.inspect=function(){return"[Emscripten Module object]"}}else if(c){if("object"==typeof process||"object"==typeof window||"function"==typeof importScripts)throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");"undefined"!=typeof read&&(d=function(e){return read(e)}),p=function(e){let r;return"function"==typeof readbuffer?new Uint8Array(readbuffer(e)):(r=read(e,"binary"),F("object"==typeof r),r)},f=function(e,r,t){setTimeout((()=>r(p(e))),0)},"undefined"!=typeof scriptArgs&&scriptArgs,"undefined"!=typeof print&&("undefined"==typeof console&&(console={}),console.log=print,console.warn=console.error="undefined"!=typeof printErr?printErr:print)}else{if(!s&&!l)throw new Error("environment detection error");if(l?v=self.location.href:"undefined"!=typeof document&&document.currentScript&&(v=document.currentScript.src),v=0!==v.indexOf("blob:")?v.substr(0,v.replace(/[?#].*/,"").lastIndexOf("/")+1):"","object"!=typeof window&&"function"!=typeof importScripts)throw new Error("not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)");d=e=>{var r=new XMLHttpRequest;return r.open("GET",e,!1),r.send(null),r.responseText},l&&(p=e=>{var r=new XMLHttpRequest;return r.open("GET",e,!1),r.responseType="arraybuffer",r.send(null),new Uint8Array(r.response)}),f=(e,r,t)=>{var n=new XMLHttpRequest;n.open("GET",e,!0),n.responseType="arraybuffer",n.onload=()=>{200==n.status||0==n.status&&n.response?r(n.response):t()},n.onerror=t,n.send(null)}}var y,E,w,b=r.print||console.log.bind(console),_=r.printErr||console.warn.bind(console);function T(e){T.shown||(T.shown={}),T.shown[e]||(T.shown[e]=1,_(e))}function k(e,t){Object.getOwnPropertyDescriptor(r,e)||Object.defineProperty(r,e,{configurable:!0,get:function(){ge("Module."+e+" has been replaced with plain "+t+" (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)")}})}function S(e,r){var t="'"+e+"' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)";return r&&(t+=". Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you"),t}function C(e,t){Object.getOwnPropertyDescriptor(r,e)||Object.defineProperty(r,e,{configurable:!0,get:function(){ge(S(e,t))}})}function P(e,t){Object.getOwnPropertyDescriptor(r,e)||(r[e]=()=>ge(S(e,t)))}Object.assign(r,t),t=null,y="fetchSettings",Object.getOwnPropertyDescriptor(r,y)&&ge("`Module."+y+"` was supplied but `"+y+"` not included in INCOMING_MODULE_JS_API"),r.arguments,k("arguments","arguments_"),r.thisProgram&&(n=r.thisProgram),k("thisProgram","thisProgram"),r.quit,k("quit","quit_"),F(void 0===r.memoryInitializerPrefixURL,"Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead"),F(void 0===r.pthreadMainPrefixURL,"Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead"),F(void 0===r.cdInitializerPrefixURL,"Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead"),F(void 0===r.filePackagePrefixURL,"Module.filePackagePrefixURL option was removed, use Module.locateFile instead"),F(void 0===r.read,"Module.read option was removed (modify read_ in JS)"),F(void 0===r.readAsync,"Module.readAsync option was removed (modify readAsync in JS)"),F(void 0===r.readBinary,"Module.readBinary option was removed (modify readBinary in JS)"),F(void 0===r.setWindowTitle,"Module.setWindowTitle option was removed (modify setWindowTitle in JS)"),F(void 0===r.TOTAL_MEMORY,"Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY"),k("read","read_"),k("readAsync","readAsync"),k("readBinary","readBinary"),k("setWindowTitle","setWindowTitle"),F(!c,"shell environment detected but not enabled at build time. Add 'shell' to `-sENVIRONMENT` to enable."),r.wasmBinary&&(E=r.wasmBinary),k("wasmBinary","wasmBinary"),r.noExitRuntime,k("noExitRuntime","noExitRuntime"),"object"!=typeof WebAssembly&&ge("no native wasm support detected");var A=!1;function F(e,r){e||ge("Assertion failed"+(r?": "+r:""))}var D="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0;function O(e,r,t){for(var n=r+t,o=r;e[o]&&!(o>=n);)++o;if(o-r>16&&e.buffer&&D)return D.decode(e.subarray(r,o));for(var i="";r<o;){var a=e[r++];if(128&a){var s=63&e[r++];if(192!=(224&a)){var l=63&e[r++];if(224==(240&a)?a=(15&a)<<12|s<<6|l:(240!=(248&a)&&T("Invalid UTF-8 leading byte 0x"+a.toString(16)+" encountered when deserializing a UTF-8 string in wasm memory to a JS string!"),a=(7&a)<<18|s<<12|l<<6|63&e[r++]),a<65536)i+=String.fromCharCode(a);else{var u=a-65536;i+=String.fromCharCode(55296|u>>10,56320|1023&u)}}else i+=String.fromCharCode((31&a)<<6|s)}else i+=String.fromCharCode(a)}return i}function R(e,r){return e?O(U,e,r):""}function M(e,r,t,n){if(!(n>0))return 0;for(var o=t,i=t+n-1,a=0;a<e.length;++a){var s=e.charCodeAt(a);if(s>=55296&&s<=57343)s=65536+((1023&s)<<10)|1023&e.charCodeAt(++a);if(s<=127){if(t>=i)break;r[t++]=s}else if(s<=2047){if(t+1>=i)break;r[t++]=192|s>>6,r[t++]=128|63&s}else if(s<=65535){if(t+2>=i)break;r[t++]=224|s>>12,r[t++]=128|s>>6&63,r[t++]=128|63&s}else{if(t+3>=i)break;s>1114111&&T("Invalid Unicode code point 0x"+s.toString(16)+" encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF)."),r[t++]=240|s>>18,r[t++]=128|s>>12&63,r[t++]=128|s>>6&63,r[t++]=128|63&s}}return r[t]=0,t-o}function N(e,r,t){return F("number"==typeof t,"stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!"),M(e,U,r,t)}function I(e){for(var r=0,t=0;t<e.length;++t){var n=e.charCodeAt(t);n>=55296&&n<=57343&&(n=65536+((1023&n)<<10)|1023&e.charCodeAt(++t)),n<=127?++r:r+=n<=2047?2:n<=65535?3:4}return r}var L,x,U,B,j,$,W,z,H,G="undefined"!=typeof TextDecoder?new TextDecoder("utf-16le"):void 0;function V(e,r){F(e%2==0,"Pointer passed to UTF16ToString must be aligned to two bytes!");for(var t=e,n=t>>1,o=n+r/2;!(n>=o)&&j[n];)++n;if((t=n<<1)-e>32&&G)return G.decode(U.subarray(e,t));for(var i="",a=0;!(a>=r/2);++a){var s=B[e+2*a>>1];if(0==s)break;i+=String.fromCharCode(s)}return i}function Y(e,r,t){if(F(r%2==0,"Pointer passed to stringToUTF16 must be aligned to two bytes!"),F("number"==typeof t,"stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!"),void 0===t&&(t=2147483647),t<2)return 0;for(var n=r,o=(t-=2)<2*e.length?t/2:e.length,i=0;i<o;++i){var a=e.charCodeAt(i);B[r>>1]=a,r+=2}return B[r>>1]=0,r-n}function q(e){return 2*e.length}function X(e,r){F(e%4==0,"Pointer passed to UTF32ToString must be aligned to four bytes!");for(var t=0,n="";!(t>=r/4);){var o=$[e+4*t>>2];if(0==o)break;if(++t,o>=65536){var i=o-65536;n+=String.fromCharCode(55296|i>>10,56320|1023&i)}else n+=String.fromCharCode(o)}return n}function K(e,r,t){if(F(r%4==0,"Pointer passed to stringToUTF32 must be aligned to four bytes!"),F("number"==typeof t,"stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!"),void 0===t&&(t=2147483647),t<4)return 0;for(var n=r,o=n+t-4,i=0;i<e.length;++i){var a=e.charCodeAt(i);if(a>=55296&&a<=57343)a=65536+((1023&a)<<10)|1023&e.charCodeAt(++i);if($[r>>2]=a,(r+=4)+4>o)break}return $[r>>2]=0,r-n}function J(e){for(var r=0,t=0;t<e.length;++t){var n=e.charCodeAt(t);n>=55296&&n<=57343&&++t,r+=4}return r}function Q(e){var r=I(e)+1,t=gt(r);return t&&M(e,x,t,r),t}function Z(e){L=e,r.HEAP8=x=new Int8Array(e),r.HEAP16=B=new Int16Array(e),r.HEAP32=$=new Int32Array(e),r.HEAPU8=U=new Uint8Array(e),r.HEAPU16=j=new Uint16Array(e),r.HEAPU32=W=new Uint32Array(e),r.HEAPF32=z=new Float32Array(e),r.HEAPF64=H=new Float64Array(e)}var ee=5242880;r.TOTAL_STACK&&F(ee===r.TOTAL_STACK,"the stack size can no longer be determined at runtime");var re,te=r.INITIAL_MEMORY||67108864;function ne(){var e=kt();F(0==(3&e)),$[e>>2]=34821223,$[e+4>>2]=2310721022,$[0]=1668509029}function oe(){if(!A){var e=kt(),r=W[e>>2],t=W[e+4>>2];34821223==r&&2310721022==t||ge("Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x"+t.toString(16)+" 0x"+r.toString(16)),1668509029!==$[0]&&ge("Runtime error: The application has corrupted its heap memory area (address zero)!")}}k("INITIAL_MEMORY","INITIAL_MEMORY"),F(te>=ee,"INITIAL_MEMORY should be larger than TOTAL_STACK, was "+te+"! (TOTAL_STACK="+"5242880)"),F("undefined"!=typeof Int32Array&&"undefined"!=typeof Float64Array&&null!=Int32Array.prototype.subarray&&null!=Int32Array.prototype.set,"JS engine does not provide full typed array support"),F(!r.wasmMemory,"Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally"),F(67108864==te,"Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically"),function(){var e=new Int16Array(1),r=new Int8Array(e.buffer);if(e[0]=25459,115!==r[0]||99!==r[1])throw"Runtime error: expected the system to be little-endian! (Run with -sSUPPORT_BIG_ENDIAN to bypass)"}();var ie=[],ae=[],se=[],le=!1;F(Math.imul,"This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"),F(Math.fround,"This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"),F(Math.clz32,"This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill"),F(Math.trunc,"This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill");var ue=0,ce=null,de=null,fe={};function pe(e){for(var r=e;;){if(!fe[e])return e;e=r+Math.random()}}function me(e){ue++,r.monitorRunDependencies&&r.monitorRunDependencies(ue),e?(F(!fe[e]),fe[e]=1,null===ce&&"undefined"!=typeof setInterval&&(ce=setInterval((function(){if(A)return clearInterval(ce),void(ce=null);var e=!1;for(var r in fe)e||(e=!0,_("still waiting on run dependencies:")),_("dependency: "+r);e&&_("(end of list)")}),1e4))):_("warning: run dependency added without ID")}function he(e){if(ue--,r.monitorRunDependencies&&r.monitorRunDependencies(ue),e?(F(fe[e]),delete fe[e]):_("warning: run dependency removed without ID"),0==ue&&(null!==ce&&(clearInterval(ce),ce=null),de)){var t=de;de=null,t()}}function ge(e){throw r.onAbort&&r.onAbort(e),_(e="Aborted("+e+")"),A=!0,new WebAssembly.RuntimeError(e)}var ve,ye,Ee;function we(e){return e.startsWith("data:application/octet-stream;base64,")}function be(e){return e.startsWith("file://")}function _e(e,t){return function(){var n=e,o=t;return t||(o=r.asm),F(le,"native function `"+n+"` called before runtime initialization"),o[e]||F(o[e],"exported native function `"+n+"` not found"),o[e].apply(null,arguments)}}function Te(e){try{if(e==ve&&E)return new Uint8Array(E);if(p)return p(e);throw"both async and sync fetching of the wasm failed"}catch(e){ge(e)}}function ke(e){for(;e.length>0;){var t=e.shift();if("function"!=typeof t){var n=t.func;"number"==typeof n?void 0===t.arg?Ce(n)():Ce(n)(t.arg):n(void 0===t.arg?null:t.arg)}else t(r)}}function Se(e){return e.replace(/\b_Z[\w\d_]+/g,(function(e){var r,t=(r=e,T("warning: build with -sDEMANGLE_SUPPORT to link in libcxxabi demangling"),r);return e===t?e:t+" ["+e+"]"}))}function Ce(e){return re.get(e)}function Pe(){var e=new Error;if(!e.stack){try{throw new Error}catch(r){e=r}if(!e.stack)return"(no stack trace available)"}return e.stack.toString()}we(ve="decoder.wasm")||(ve=function(e){return r.locateFile?r.locateFile(e,v):v+e}(ve));var Ae={isAbs:e=>"/"===e.charAt(0),splitPath:e=>/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(e).slice(1),normalizeArray:(e,r)=>{for(var t=0,n=e.length-1;n>=0;n--){var o=e[n];"."===o?e.splice(n,1):".."===o?(e.splice(n,1),t++):t&&(e.splice(n,1),t--)}if(r)for(;t;t--)e.unshift("..");return e},normalize:e=>{var r=Ae.isAbs(e),t="/"===e.substr(-1);return(e=Ae.normalizeArray(e.split("/").filter((e=>!!e)),!r).join("/"))||r||(e="."),e&&t&&(e+="/"),(r?"/":"")+e},dirname:e=>{var r=Ae.splitPath(e),t=r[0],n=r[1];return t||n?(n&&(n=n.substr(0,n.length-1)),t+n):"."},basename:e=>{if("/"===e)return"/";var r=(e=(e=Ae.normalize(e)).replace(/\/$/,"")).lastIndexOf("/");return-1===r?e:e.substr(r+1)},join:function(){var e=Array.prototype.slice.call(arguments,0);return Ae.normalize(e.join("/"))},join2:(e,r)=>Ae.normalize(e+"/"+r)};var Fe={resolve:function(){for(var e="",r=!1,t=arguments.length-1;t>=-1&&!r;t--){var n=t>=0?arguments[t]:Ie.cwd();if("string"!=typeof n)throw new TypeError("Arguments to path.resolve must be strings");if(!n)return"";e=n+"/"+e,r=Ae.isAbs(n)}return(r?"/":"")+(e=Ae.normalizeArray(e.split("/").filter((e=>!!e)),!r).join("/"))||"."},relative:(e,r)=>{function t(e){for(var r=0;r<e.length&&""===e[r];r++);for(var t=e.length-1;t>=0&&""===e[t];t--);return r>t?[]:e.slice(r,t-r+1)}e=Fe.resolve(e).substr(1),r=Fe.resolve(r).substr(1);for(var n=t(e.split("/")),o=t(r.split("/")),i=Math.min(n.length,o.length),a=i,s=0;s<i;s++)if(n[s]!==o[s]){a=s;break}var l=[];for(s=a;s<n.length;s++)l.push("..");return(l=l.concat(o.slice(a))).join("/")}},De={ttys:[],init:function(){},shutdown:function(){},register:function(e,r){De.ttys[e]={input:[],output:[],ops:r},Ie.registerDevice(e,De.stream_ops)},stream_ops:{open:function(e){var r=De.ttys[e.node.rdev];if(!r)throw new Ie.ErrnoError(43);e.tty=r,e.seekable=!1},close:function(e){e.tty.ops.flush(e.tty)},flush:function(e){e.tty.ops.flush(e.tty)},read:function(e,r,t,n,o){if(!e.tty||!e.tty.ops.get_char)throw new Ie.ErrnoError(60);for(var i=0,a=0;a<n;a++){var s;try{s=e.tty.ops.get_char(e.tty)}catch(e){throw new Ie.ErrnoError(29)}if(void 0===s&&0===i)throw new Ie.ErrnoError(6);if(null==s)break;i++,r[t+a]=s}return i&&(e.node.timestamp=Date.now()),i},write:function(e,r,t,n,o){if(!e.tty||!e.tty.ops.put_char)throw new Ie.ErrnoError(60);try{for(var i=0;i<n;i++)e.tty.ops.put_char(e.tty,r[t+i])}catch(e){throw new Ie.ErrnoError(29)}return n&&(e.node.timestamp=Date.now()),i}},default_tty_ops:{get_char:function(e){if(!e.input.length){var r=null;if(u){var t=Buffer.alloc(256),n=0;try{n=m.readSync(process.stdin.fd,t,0,256,-1)}catch(e){if(!e.toString().includes("EOF"))throw e;n=0}r=n>0?t.slice(0,n).toString("utf-8"):null}else"undefined"!=typeof window&&"function"==typeof window.prompt?null!==(r=window.prompt("Input: "))&&(r+="\n"):"function"==typeof readline&&null!==(r=readline())&&(r+="\n");if(!r)return null;e.input=pt(r,!0)}return e.input.shift()},put_char:function(e,r){null===r||10===r?(b(O(e.output,0)),e.output=[]):0!=r&&e.output.push(r)},flush:function(e){e.output&&e.output.length>0&&(b(O(e.output,0)),e.output=[])}},default_tty1_ops:{put_char:function(e,r){null===r||10===r?(_(O(e.output,0)),e.output=[]):0!=r&&e.output.push(r)},flush:function(e){e.output&&e.output.length>0&&(_(O(e.output,0)),e.output=[])}}};function Oe(e){e=function(e,r){return F(r,"alignment argument is required"),Math.ceil(e/r)*r}(e,65536);var r=bt(65536,e);return r?(function(e,r){U.fill(0,e,e+r)}(r,e),r):0}var Re={ops_table:null,mount:function(e){return Re.createNode(null,"/",16895,0)},createNode:function(e,r,t,n){if(Ie.isBlkdev(t)||Ie.isFIFO(t))throw new Ie.ErrnoError(63);Re.ops_table||(Re.ops_table={dir:{node:{getattr:Re.node_ops.getattr,setattr:Re.node_ops.setattr,lookup:Re.node_ops.lookup,mknod:Re.node_ops.mknod,rename:Re.node_ops.rename,unlink:Re.node_ops.unlink,rmdir:Re.node_ops.rmdir,readdir:Re.node_ops.readdir,symlink:Re.node_ops.symlink},stream:{llseek:Re.stream_ops.llseek}},file:{node:{getattr:Re.node_ops.getattr,setattr:Re.node_ops.setattr},stream:{llseek:Re.stream_ops.llseek,read:Re.stream_ops.read,write:Re.stream_ops.write,allocate:Re.stream_ops.allocate,mmap:Re.stream_ops.mmap,msync:Re.stream_ops.msync}},link:{node:{getattr:Re.node_ops.getattr,setattr:Re.node_ops.setattr,readlink:Re.node_ops.readlink},stream:{}},chrdev:{node:{getattr:Re.node_ops.getattr,setattr:Re.node_ops.setattr},stream:Ie.chrdev_stream_ops}});var o=Ie.createNode(e,r,t,n);return Ie.isDir(o.mode)?(o.node_ops=Re.ops_table.dir.node,o.stream_ops=Re.ops_table.dir.stream,o.contents={}):Ie.isFile(o.mode)?(o.node_ops=Re.ops_table.file.node,o.stream_ops=Re.ops_table.file.stream,o.usedBytes=0,o.contents=null):Ie.isLink(o.mode)?(o.node_ops=Re.ops_table.link.node,o.stream_ops=Re.ops_table.link.stream):Ie.isChrdev(o.mode)&&(o.node_ops=Re.ops_table.chrdev.node,o.stream_ops=Re.ops_table.chrdev.stream),o.timestamp=Date.now(),e&&(e.contents[r]=o,e.timestamp=o.timestamp),o},getFileDataAsTypedArray:function(e){return e.contents?e.contents.subarray?e.contents.subarray(0,e.usedBytes):new Uint8Array(e.contents):new Uint8Array(0)},expandFileStorage:function(e,r){var t=e.contents?e.contents.length:0;if(!(t>=r)){r=Math.max(r,t*(t<1048576?2:1.125)>>>0),0!=t&&(r=Math.max(r,256));var n=e.contents;e.contents=new Uint8Array(r),e.usedBytes>0&&e.contents.set(n.subarray(0,e.usedBytes),0)}},resizeFileStorage:function(e,r){if(e.usedBytes!=r)if(0==r)e.contents=null,e.usedBytes=0;else{var t=e.contents;e.contents=new Uint8Array(r),t&&e.contents.set(t.subarray(0,Math.min(r,e.usedBytes))),e.usedBytes=r}},node_ops:{getattr:function(e){var r={};return r.dev=Ie.isChrdev(e.mode)?e.id:1,r.ino=e.id,r.mode=e.mode,r.nlink=1,r.uid=0,r.gid=0,r.rdev=e.rdev,Ie.isDir(e.mode)?r.size=4096:Ie.isFile(e.mode)?r.size=e.usedBytes:Ie.isLink(e.mode)?r.size=e.link.length:r.size=0,r.atime=new Date(e.timestamp),r.mtime=new Date(e.timestamp),r.ctime=new Date(e.timestamp),r.blksize=4096,r.blocks=Math.ceil(r.size/r.blksize),r},setattr:function(e,r){void 0!==r.mode&&(e.mode=r.mode),void 0!==r.timestamp&&(e.timestamp=r.timestamp),void 0!==r.size&&Re.resizeFileStorage(e,r.size)},lookup:function(e,r){throw Ie.genericErrors[44]},mknod:function(e,r,t,n){return Re.createNode(e,r,t,n)},rename:function(e,r,t){if(Ie.isDir(e.mode)){var n;try{n=Ie.lookupNode(r,t)}catch(e){}if(n)for(var o in n.contents)throw new Ie.ErrnoError(55)}delete e.parent.contents[e.name],e.parent.timestamp=Date.now(),e.name=t,r.contents[t]=e,r.timestamp=e.parent.timestamp,e.parent=r},unlink:function(e,r){delete e.contents[r],e.timestamp=Date.now()},rmdir:function(e,r){var t=Ie.lookupNode(e,r);for(var n in t.contents)throw new Ie.ErrnoError(55);delete e.contents[r],e.timestamp=Date.now()},readdir:function(e){var r=[".",".."];for(var t in e.contents)e.contents.hasOwnProperty(t)&&r.push(t);return r},symlink:function(e,r,t){var n=Re.createNode(e,r,41471,0);return n.link=t,n},readlink:function(e){if(!Ie.isLink(e.mode))throw new Ie.ErrnoError(28);return e.link}},stream_ops:{read:function(e,r,t,n,o){var i=e.node.contents;if(o>=e.node.usedBytes)return 0;var a=Math.min(e.node.usedBytes-o,n);if(F(a>=0),a>8&&i.subarray)r.set(i.subarray(o,o+a),t);else for(var s=0;s<a;s++)r[t+s]=i[o+s];return a},write:function(e,r,t,n,o,i){if(F(!(r instanceof ArrayBuffer)),r.buffer===x.buffer&&(i=!1),!n)return 0;var a=e.node;if(a.timestamp=Date.now(),r.subarray&&(!a.contents||a.contents.subarray)){if(i)return F(0===o,"canOwn must imply no weird position inside the file"),a.contents=r.subarray(t,t+n),a.usedBytes=n,n;if(0===a.usedBytes&&0===o)return a.contents=r.slice(t,t+n),a.usedBytes=n,n;if(o+n<=a.usedBytes)return a.contents.set(r.subarray(t,t+n),o),n}if(Re.expandFileStorage(a,o+n),a.contents.subarray&&r.subarray)a.contents.set(r.subarray(t,t+n),o);else for(var s=0;s<n;s++)a.contents[o+s]=r[t+s];return a.usedBytes=Math.max(a.usedBytes,o+n),n},llseek:function(e,r,t){var n=r;if(1===t?n+=e.position:2===t&&Ie.isFile(e.node.mode)&&(n+=e.node.usedBytes),n<0)throw new Ie.ErrnoError(28);return n},allocate:function(e,r,t){Re.expandFileStorage(e.node,r+t),e.node.usedBytes=Math.max(e.node.usedBytes,r+t)},mmap:function(e,r,t,n,o,i){if(0!==r)throw new Ie.ErrnoError(28);if(!Ie.isFile(e.node.mode))throw new Ie.ErrnoError(43);var a,s,l=e.node.contents;if(2&i||l.buffer!==L){if((n>0||n+t<l.length)&&(l=l.subarray?l.subarray(n,n+t):Array.prototype.slice.call(l,n,n+t)),s=!0,!(a=Oe(t)))throw new Ie.ErrnoError(48);x.set(l,a)}else s=!1,a=l.byteOffset;return{ptr:a,allocated:s}},msync:function(e,r,t,n,o){if(!Ie.isFile(e.node.mode))throw new Ie.ErrnoError(43);return 2&o||Re.stream_ops.write(e,r,0,n,t,!1),0}}};var Me={0:"Success",1:"Arg list too long",2:"Permission denied",3:"Address already in use",4:"Address not available",5:"Address family not supported by protocol family",6:"No more processes",7:"Socket already connected",8:"Bad file number",9:"Trying to read unreadable message",10:"Mount device busy",11:"Operation canceled",12:"No children",13:"Connection aborted",14:"Connection refused",15:"Connection reset by peer",16:"File locking deadlock error",17:"Destination address required",18:"Math arg out of domain of func",19:"Quota exceeded",20:"File exists",21:"Bad address",22:"File too large",23:"Host is unreachable",24:"Identifier removed",25:"Illegal byte sequence",26:"Connection already in progress",27:"Interrupted system call",28:"Invalid argument",29:"I/O error",30:"Socket is already connected",31:"Is a directory",32:"Too many symbolic links",33:"Too many open files",34:"Too many links",35:"Message too long",36:"Multihop attempted",37:"File or path name too long",38:"Network interface is not configured",39:"Connection reset by network",40:"Network is unreachable",41:"Too many open files in system",42:"No buffer space available",43:"No such device",44:"No such file or directory",45:"Exec format error",46:"No record locks available",47:"The link has been severed",48:"Not enough core",49:"No message of desired type",50:"Protocol not available",51:"No space left on device",52:"Function not implemented",53:"Socket is not connected",54:"Not a directory",55:"Directory not empty",56:"State not recoverable",57:"Socket operation on non-socket",59:"Not a typewriter",60:"No such device or address",61:"Value too large for defined data type",62:"Previous owner died",63:"Not super-user",64:"Broken pipe",65:"Protocol error",66:"Unknown protocol",67:"Protocol wrong type for socket",68:"Math result not representable",69:"Read only file system",70:"Illegal seek",71:"No such process",72:"Stale file handle",73:"Connection timed out",74:"Text file busy",75:"Cross-device link",100:"Device not a stream",101:"Bad font file fmt",102:"Invalid slot",103:"Invalid request code",104:"No anode",105:"Block device required",106:"Channel number out of range",107:"Level 3 halted",108:"Level 3 reset",109:"Link number out of range",110:"Protocol driver not attached",111:"No CSI structure available",112:"Level 2 halted",113:"Invalid exchange",114:"Invalid request descriptor",115:"Exchange full",116:"No data (for no delay io)",117:"Timer expired",118:"Out of streams resources",119:"Machine is not on the network",120:"Package not installed",121:"The object is remote",122:"Advertise error",123:"Srmount error",124:"Communication error on send",125:"Cross mount point (not really error)",126:"Given log. name not unique",127:"f.d. invalid for this operation",128:"Remote address changed",129:"Can access a needed shared lib",130:"Accessing a corrupted shared lib",131:".lib section in a.out corrupted",132:"Attempting to link in too many libs",133:"Attempting to exec a shared library",135:"Streams pipe error",136:"Too many users",137:"Socket type not supported",138:"Not supported",139:"Protocol family not supported",140:"Can't send after socket shutdown",141:"Too many references",142:"Host is down",148:"No medium (in tape drive)",156:"Level 2 not synchronized"},Ne={},Ie={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:!1,ignorePermissions:!0,ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!(e=Fe.resolve(Ie.cwd(),e)))return{path:"",node:null};var t={follow_mount:!0,recurse_count:0};if(r=Object.assign(t,r),r.recurse_count>8)throw new Ie.ErrnoError(32);for(var n=Ae.normalizeArray(e.split("/").filter((e=>!!e)),!1),o=Ie.root,i="/",a=0;a<n.length;a++){var s=a===n.length-1;if(s&&r.parent)break;if(o=Ie.lookupNode(o,n[a]),i=Ae.join2(i,n[a]),Ie.isMountpoint(o)&&(!s||s&&r.follow_mount)&&(o=o.mounted.root),!s||r.follow)for(var l=0;Ie.isLink(o.mode);){var u=Ie.readlink(i);i=Fe.resolve(Ae.dirname(i),u);var c=Ie.lookupPath(i,{recurse_count:r.recurse_count+1});if(o=c.node,l++>40)throw new Ie.ErrnoError(32)}}return{path:i,node:o}},getPath:e=>{for(var r;;){if(Ie.isRoot(e)){var t=e.mount.mountpoint;return r?"/"!==t[t.length-1]?t+"/"+r:t+r:t}r=r?e.name+"/"+r:e.name,e=e.parent}},hashName:(e,r)=>{for(var t=0,n=0;n<r.length;n++)t=(t<<5)-t+r.charCodeAt(n)|0;return(e+t>>>0)%Ie.nameTable.length},hashAddNode:e=>{var r=Ie.hashName(e.parent.id,e.name);e.name_next=Ie.nameTable[r],Ie.nameTable[r]=e},hashRemoveNode:e=>{var r=Ie.hashName(e.parent.id,e.name);if(Ie.nameTable[r]===e)Ie.nameTable[r]=e.name_next;else for(var t=Ie.nameTable[r];t;){if(t.name_next===e){t.name_next=e.name_next;break}t=t.name_next}},lookupNode:(e,r)=>{var t=Ie.mayLookup(e);if(t)throw new Ie.ErrnoError(t,e);for(var n=Ie.hashName(e.id,r),o=Ie.nameTable[n];o;o=o.name_next){var i=o.name;if(o.parent.id===e.id&&i===r)return o}return Ie.lookup(e,r)},createNode:(e,r,t,n)=>{F("object"==typeof e);var o=new Ie.FSNode(e,r,t,n);return Ie.hashAddNode(o),o},destroyNode:e=>{Ie.hashRemoveNode(e)},isRoot:e=>e===e.parent,isMountpoint:e=>!!e.mounted,isFile:e=>32768==(61440&e),isDir:e=>16384==(61440&e),isLink:e=>40960==(61440&e),isChrdev:e=>8192==(61440&e),isBlkdev:e=>24576==(61440&e),isFIFO:e=>4096==(61440&e),isSocket:e=>49152==(49152&e),flagModes:{r:0,"r+":2,w:577,"w+":578,a:1089,"a+":1090},modeStringToFlags:e=>{var r=Ie.flagModes[e];if(void 0===r)throw new Error("Unknown file open mode: "+e);return r},flagsToPermissionString:e=>{var r=["r","w","rw"][3&e];return 512&e&&(r+="w"),r},nodePermissions:(e,r)=>Ie.ignorePermissions||(!r.includes("r")||292&e.mode)&&(!r.includes("w")||146&e.mode)&&(!r.includes("x")||73&e.mode)?0:2,mayLookup:e=>{var r=Ie.nodePermissions(e,"x");return r||(e.node_ops.lookup?0:2)},mayCreate:(e,r)=>{try{Ie.lookupNode(e,r);return 20}catch(e){}return Ie.nodePermissions(e,"wx")},mayDelete:(e,r,t)=>{var n;try{n=Ie.lookupNode(e,r)}catch(e){return e.errno}var o=Ie.nodePermissions(e,"wx");if(o)return o;if(t){if(!Ie.isDir(n.mode))return 54;if(Ie.isRoot(n)||Ie.getPath(n)===Ie.cwd())return 10}else if(Ie.isDir(n.mode))return 31;return 0},mayOpen:(e,r)=>e?Ie.isLink(e.mode)?32:Ie.isDir(e.mode)&&("r"!==Ie.flagsToPermissionString(r)||512&r)?31:Ie.nodePermissions(e,Ie.flagsToPermissionString(r)):44,MAX_OPEN_FDS:4096,nextfd:function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Ie.MAX_OPEN_FDS;for(var t=e;t<=r;t++)if(!Ie.streams[t])return t;throw new Ie.ErrnoError(33)},getStream:e=>Ie.streams[e],createStream:(e,r,t)=>{Ie.FSStream||(Ie.FSStream=function(){this.shared={}},Ie.FSStream.prototype={object:{get:function(){return this.node},set:function(e){this.node=e}},isRead:{get:function(){return 1!=(2097155&this.flags)}},isWrite:{get:function(){return 0!=(2097155&this.flags)}},isAppend:{get:function(){return 1024&this.flags}},flags:{get:function(){return this.shared.flags},set:function(e){this.shared.flags=e}},position:{get function(){return this.shared.position},set:function(e){this.shared.position=e}}}),e=Object.assign(new Ie.FSStream,e);var n=Ie.nextfd(r,t);return e.fd=n,Ie.streams[n]=e,e},closeStream:e=>{Ie.streams[e]=null},chrdev_stream_ops:{open:e=>{var r=Ie.getDevice(e.node.rdev);e.stream_ops=r.stream_ops,e.stream_ops.open&&e.stream_ops.open(e)},llseek:()=>{throw new Ie.ErrnoError(70)}},major:e=>e>>8,minor:e=>255&e,makedev:(e,r)=>e<<8|r,registerDevice:(e,r)=>{Ie.devices[e]={stream_ops:r}},getDevice:e=>Ie.devices[e],getMounts:e=>{for(var r=[],t=[e];t.length;){var n=t.pop();r.push(n),t.push.apply(t,n.mounts)}return r},syncfs:(e,r)=>{"function"==typeof e&&(r=e,e=!1),Ie.syncFSRequests++,Ie.syncFSRequests>1&&_("warning: "+Ie.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work");var t=Ie.getMounts(Ie.root.mount),n=0;function o(e){return F(Ie.syncFSRequests>0),Ie.syncFSRequests--,r(e)}function i(e){if(e)return i.errored?void 0:(i.errored=!0,o(e));++n>=t.length&&o(null)}t.forEach((r=>{if(!r.type.syncfs)return i(null);r.type.syncfs(r,e,i)}))},mount:(e,r,t)=>{if("string"==typeof e)throw e;var n,o="/"===t,i=!t;if(o&&Ie.root)throw new Ie.ErrnoError(10);if(!o&&!i){var a=Ie.lookupPath(t,{follow_mount:!1});if(t=a.path,n=a.node,Ie.isMountpoint(n))throw new Ie.ErrnoError(10);if(!Ie.isDir(n.mode))throw new Ie.ErrnoError(54)}var s={type:e,opts:r,mountpoint:t,mounts:[]},l=e.mount(s);return l.mount=s,s.root=l,o?Ie.root=l:n&&(n.mounted=s,n.mount&&n.mount.mounts.push(s)),l},unmount:e=>{var r=Ie.lookupPath(e,{follow_mount:!1});if(!Ie.isMountpoint(r.node))throw new Ie.ErrnoError(28);var t=r.node,n=t.mounted,o=Ie.getMounts(n);Object.keys(Ie.nameTable).forEach((e=>{for(var r=Ie.nameTable[e];r;){var t=r.name_next;o.includes(r.mount)&&Ie.destroyNode(r),r=t}})),t.mounted=null;var i=t.mount.mounts.indexOf(n);F(-1!==i),t.mount.mounts.splice(i,1)},lookup:(e,r)=>e.node_ops.lookup(e,r),mknod:(e,r,t)=>{var n=Ie.lookupPath(e,{parent:!0}).node,o=Ae.basename(e);if(!o||"."===o||".."===o)throw new Ie.ErrnoError(28);var i=Ie.mayCreate(n,o);if(i)throw new Ie.ErrnoError(i);if(!n.node_ops.mknod)throw new Ie.ErrnoError(63);return n.node_ops.mknod(n,o,r,t)},create:(e,r)=>(r=void 0!==r?r:438,r&=4095,r|=32768,Ie.mknod(e,r,0)),mkdir:(e,r)=>(r=void 0!==r?r:511,r&=1023,r|=16384,Ie.mknod(e,r,0)),mkdirTree:(e,r)=>{for(var t=e.split("/"),n="",o=0;o<t.length;++o)if(t[o]){n+="/"+t[o];try{Ie.mkdir(n,r)}catch(e){if(20!=e.errno)throw e}}},mkdev:(e,r,t)=>(void 0===t&&(t=r,r=438),r|=8192,Ie.mknod(e,r,t)),symlink:(e,r)=>{if(!Fe.resolve(e))throw new Ie.ErrnoError(44);var t=Ie.lookupPath(r,{parent:!0}).node;if(!t)throw new Ie.ErrnoError(44);var n=Ae.basename(r),o=Ie.mayCreate(t,n);if(o)throw new Ie.ErrnoError(o);if(!t.node_ops.symlink)throw new Ie.ErrnoError(63);return t.node_ops.symlink(t,n,e)},rename:(e,r)=>{var t,n,o=Ae.dirname(e),i=Ae.dirname(r),a=Ae.basename(e),s=Ae.basename(r);if(t=Ie.lookupPath(e,{parent:!0}).node,n=Ie.lookupPath(r,{parent:!0}).node,!t||!n)throw new Ie.ErrnoError(44);if(t.mount!==n.mount)throw new Ie.ErrnoError(75);var l,u=Ie.lookupNode(t,a),c=Fe.relative(e,i);if("."!==c.charAt(0))throw new Ie.ErrnoError(28);if("."!==(c=Fe.relative(r,o)).charAt(0))throw new Ie.ErrnoError(55);try{l=Ie.lookupNode(n,s)}catch(e){}if(u!==l){var d=Ie.isDir(u.mode),f=Ie.mayDelete(t,a,d);if(f)throw new Ie.ErrnoError(f);if(f=l?Ie.mayDelete(n,s,d):Ie.mayCreate(n,s))throw new Ie.ErrnoError(f);if(!t.node_ops.rename)throw new Ie.ErrnoError(63);if(Ie.isMountpoint(u)||l&&Ie.isMountpoint(l))throw new Ie.ErrnoError(10);if(n!==t&&(f=Ie.nodePermissions(t,"w")))throw new Ie.ErrnoError(f);Ie.hashRemoveNode(u);try{t.node_ops.rename(u,n,s)}catch(e){throw e}finally{Ie.hashAddNode(u)}}},rmdir:e=>{var r=Ie.lookupPath(e,{parent:!0}).node,t=Ae.basename(e),n=Ie.lookupNode(r,t),o=Ie.mayDelete(r,t,!0);if(o)throw new Ie.ErrnoError(o);if(!r.node_ops.rmdir)throw new Ie.ErrnoError(63);if(Ie.isMountpoint(n))throw new Ie.ErrnoError(10);r.node_ops.rmdir(r,t),Ie.destroyNode(n)},readdir:e=>{var r=Ie.lookupPath(e,{follow:!0}).node;if(!r.node_ops.readdir)throw new Ie.ErrnoError(54);return r.node_ops.readdir(r)},unlink:e=>{var r=Ie.lookupPath(e,{parent:!0}).node;if(!r)throw new Ie.ErrnoError(44);var t=Ae.basename(e),n=Ie.lookupNode(r,t),o=Ie.mayDelete(r,t,!1);if(o)throw new Ie.ErrnoError(o);if(!r.node_ops.unlink)throw new Ie.ErrnoError(63);if(Ie.isMountpoint(n))throw new Ie.ErrnoError(10);r.node_ops.unlink(r,t),Ie.destroyNode(n)},readlink:e=>{var r=Ie.lookupPath(e).node;if(!r)throw new Ie.ErrnoError(44);if(!r.node_ops.readlink)throw new Ie.ErrnoError(28);return Fe.resolve(Ie.getPath(r.parent),r.node_ops.readlink(r))},stat:(e,r)=>{var t=Ie.lookupPath(e,{follow:!r}).node;if(!t)throw new Ie.ErrnoError(44);if(!t.node_ops.getattr)throw new Ie.ErrnoError(63);return t.node_ops.getattr(t)},lstat:e=>Ie.stat(e,!0),chmod:(e,r,t)=>{var n;"string"==typeof e?n=Ie.lookupPath(e,{follow:!t}).node:n=e;if(!n.node_ops.setattr)throw new Ie.ErrnoError(63);n.node_ops.setattr(n,{mode:4095&r|-4096&n.mode,timestamp:Date.now()})},lchmod:(e,r)=>{Ie.chmod(e,r,!0)},fchmod:(e,r)=>{var t=Ie.getStream(e);if(!t)throw new Ie.ErrnoError(8);Ie.chmod(t.node,r)},chown:(e,r,t,n)=>{var o;"string"==typeof e?o=Ie.lookupPath(e,{follow:!n}).node:o=e;if(!o.node_ops.setattr)throw new Ie.ErrnoError(63);o.node_ops.setattr(o,{timestamp:Date.now()})},lchown:(e,r,t)=>{Ie.chown(e,r,t,!0)},fchown:(e,r,t)=>{var n=Ie.getStream(e);if(!n)throw new Ie.ErrnoError(8);Ie.chown(n.node,r,t)},truncate:(e,r)=>{if(r<0)throw new Ie.ErrnoError(28);var t;"string"==typeof e?t=Ie.lookupPath(e,{follow:!0}).node:t=e;if(!t.node_ops.setattr)throw new Ie.ErrnoError(63);if(Ie.isDir(t.mode))throw new Ie.ErrnoError(31);if(!Ie.isFile(t.mode))throw new Ie.ErrnoError(28);var n=Ie.nodePermissions(t,"w");if(n)throw new Ie.ErrnoError(n);t.node_ops.setattr(t,{size:r,timestamp:Date.now()})},ftruncate:(e,r)=>{var t=Ie.getStream(e);if(!t)throw new Ie.ErrnoError(8);if(0==(2097155&t.flags))throw new Ie.ErrnoError(28);Ie.truncate(t.node,r)},utime:(e,r,t)=>{var n=Ie.lookupPath(e,{follow:!0}).node;n.node_ops.setattr(n,{timestamp:Math.max(r,t)})},open:(e,t,n,o,i)=>{if(""===e)throw new Ie.ErrnoError(44);var a;if(n=void 0===n?438:n,n=64&(t="string"==typeof t?Ie.modeStringToFlags(t):t)?4095&n|32768:0,"object"==typeof e)a=e;else{e=Ae.normalize(e);try{a=Ie.lookupPath(e,{follow:!(131072&t)}).node}catch(e){}}var s=!1;if(64&t)if(a){if(128&t)throw new Ie.ErrnoError(20)}else a=Ie.mknod(e,n,0),s=!0;if(!a)throw new Ie.ErrnoError(44);if(Ie.isChrdev(a.mode)&&(t&=-513),65536&t&&!Ie.isDir(a.mode))throw new Ie.ErrnoError(54);if(!s){var l=Ie.mayOpen(a,t);if(l)throw new Ie.ErrnoError(l)}512&t&&Ie.truncate(a,0),t&=-131713;var u=Ie.createStream({node:a,path:Ie.getPath(a),flags:t,seekable:!0,position:0,stream_ops:a.stream_ops,ungotten:[],error:!1},o,i);return u.stream_ops.open&&u.stream_ops.open(u),!r.logReadFiles||1&t||(Ie.readFiles||(Ie.readFiles={}),e in Ie.readFiles||(Ie.readFiles[e]=1)),u},close:e=>{if(Ie.isClosed(e))throw new Ie.ErrnoError(8);e.getdents&&(e.getdents=null);try{e.stream_ops.close&&e.stream_ops.close(e)}catch(e){throw e}finally{Ie.closeStream(e.fd)}e.fd=null},isClosed:e=>null===e.fd,llseek:(e,r,t)=>{if(Ie.isClosed(e))throw new Ie.ErrnoError(8);if(!e.seekable||!e.stream_ops.llseek)throw new Ie.ErrnoError(70);if(0!=t&&1!=t&&2!=t)throw new Ie.ErrnoError(28);return e.position=e.stream_ops.llseek(e,r,t),e.ungotten=[],e.position},read:(e,r,t,n,o)=>{if(n<0||o<0)throw new Ie.ErrnoError(28);if(Ie.isClosed(e))throw new Ie.ErrnoError(8);if(1==(2097155&e.flags))throw new Ie.ErrnoError(8);if(Ie.isDir(e.node.mode))throw new Ie.ErrnoError(31);if(!e.stream_ops.read)throw new Ie.ErrnoError(28);var i=void 0!==o;if(i){if(!e.seekable)throw new Ie.ErrnoError(70)}else o=e.position;var a=e.stream_ops.read(e,r,t,n,o);return i||(e.position+=a),a},write:(e,r,t,n,o,i)=>{if(n<0||o<0)throw new Ie.ErrnoError(28);if(Ie.isClosed(e))throw new Ie.ErrnoError(8);if(0==(2097155&e.flags))throw new Ie.ErrnoError(8);if(Ie.isDir(e.node.mode))throw new Ie.ErrnoError(31);if(!e.stream_ops.write)throw new Ie.ErrnoError(28);e.seekable&&1024&e.flags&&Ie.llseek(e,0,2);var a=void 0!==o;if(a){if(!e.seekable)throw new Ie.ErrnoError(70)}else o=e.position;var s=e.stream_ops.write(e,r,t,n,o,i);return a||(e.position+=s),s},allocate:(e,r,t)=>{if(Ie.isClosed(e))throw new Ie.ErrnoError(8);if(r<0||t<=0)throw new Ie.ErrnoError(28);if(0==(2097155&e.flags))throw new Ie.ErrnoError(8);if(!Ie.isFile(e.node.mode)&&!Ie.isDir(e.node.mode))throw new Ie.ErrnoError(43);if(!e.stream_ops.allocate)throw new Ie.ErrnoError(138);e.stream_ops.allocate(e,r,t)},mmap:(e,r,t,n,o,i)=>{if(0!=(2&o)&&0==(2&i)&&2!=(2097155&e.flags))throw new Ie.ErrnoError(2);if(1==(2097155&e.flags))throw new Ie.ErrnoError(2);if(!e.stream_ops.mmap)throw new Ie.ErrnoError(43);return e.stream_ops.mmap(e,r,t,n,o,i)},msync:(e,r,t,n,o)=>e&&e.stream_ops.msync?e.stream_ops.msync(e,r,t,n,o):0,munmap:e=>0,ioctl:(e,r,t)=>{if(!e.stream_ops.ioctl)throw new Ie.ErrnoError(59);return e.stream_ops.ioctl(e,r,t)},readFile:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(r.flags=r.flags||0,r.encoding=r.encoding||"binary","utf8"!==r.encoding&&"binary"!==r.encoding)throw new Error('Invalid encoding type "'+r.encoding+'"');var t,n=Ie.open(e,r.flags),o=Ie.stat(e),i=o.size,a=new Uint8Array(i);return Ie.read(n,a,0,i,0),"utf8"===r.encoding?t=O(a,0):"binary"===r.encoding&&(t=a),Ie.close(n),t},writeFile:function(e,r){let t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};t.flags=t.flags||577;var n=Ie.open(e,t.flags,t.mode);if("string"==typeof r){var o=new Uint8Array(I(r)+1),i=M(r,o,0,o.length);Ie.write(n,o,0,i,void 0,t.canOwn)}else{if(!ArrayBuffer.isView(r))throw new Error("Unsupported data type");Ie.write(n,r,0,r.byteLength,void 0,t.canOwn)}Ie.close(n)},cwd:()=>Ie.currentPath,chdir:e=>{var r=Ie.lookupPath(e,{follow:!0});if(null===r.node)throw new Ie.ErrnoError(44);if(!Ie.isDir(r.node.mode))throw new Ie.ErrnoError(54);var t=Ie.nodePermissions(r.node,"x");if(t)throw new Ie.ErrnoError(t);Ie.currentPath=r.path},createDefaultDirectories:()=>{Ie.mkdir("/tmp"),Ie.mkdir("/home"),Ie.mkdir("/home/web_user")},createDefaultDevices:()=>{Ie.mkdir("/dev"),Ie.registerDevice(Ie.makedev(1,3),{read:()=>0,write:(e,r,t,n,o)=>n}),Ie.mkdev("/dev/null",Ie.makedev(1,3)),De.register(Ie.makedev(5,0),De.default_tty_ops),De.register(Ie.makedev(6,0),De.default_tty1_ops),Ie.mkdev("/dev/tty",Ie.makedev(5,0)),Ie.mkdev("/dev/tty1",Ie.makedev(6,0));var e=function(){if("object"==typeof crypto&&"function"==typeof crypto.getRandomValues){var e=new Uint8Array(1);return function(){return crypto.getRandomValues(e),e[0]}}if(u)try{var r=a.default;return function(){return r.randomBytes(1)[0]}}catch(e){}return function(){ge("no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: function(array) { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };")}}();Ie.createDevice("/dev","random",e),Ie.createDevice("/dev","urandom",e),Ie.mkdir("/dev/shm"),Ie.mkdir("/dev/shm/tmp")},createSpecialDirectories:()=>{Ie.mkdir("/proc");var e=Ie.mkdir("/proc/self");Ie.mkdir("/proc/self/fd"),Ie.mount({mount:()=>{var r=Ie.createNode(e,"fd",16895,73);return r.node_ops={lookup:(e,r)=>{var t=+r,n=Ie.getStream(t);if(!n)throw new Ie.ErrnoError(8);var o={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>n.path}};return o.parent=o,o}},r}},{},"/proc/self/fd")},createStandardStreams:()=>{r.stdin?Ie.createDevice("/dev","stdin",r.stdin):Ie.symlink("/dev/tty","/dev/stdin"),r.stdout?Ie.createDevice("/dev","stdout",null,r.stdout):Ie.symlink("/dev/tty","/dev/stdout"),r.stderr?Ie.createDevice("/dev","stderr",null,r.stderr):Ie.symlink("/dev/tty1","/dev/stderr");var e=Ie.open("/dev/stdin",0),t=Ie.open("/dev/stdout",1),n=Ie.open("/dev/stderr",1);F(0===e.fd,"invalid handle for stdin ("+e.fd+")"),F(1===t.fd,"invalid handle for stdout ("+t.fd+")"),F(2===n.fd,"invalid handle for stderr ("+n.fd+")")},ensureErrnoError:()=>{Ie.ErrnoError||(Ie.ErrnoError=function(e,r){this.node=r,this.setErrno=function(e){for(var r in this.errno=e,Ne)if(Ne[r]===e){this.code=r;break}},this.setErrno(e),this.message=Me[e],this.stack&&(Object.defineProperty(this,"stack",{value:(new Error).stack,writable:!0}),this.stack=Se(this.stack))},Ie.ErrnoError.prototype=new Error,Ie.ErrnoError.prototype.constructor=Ie.ErrnoError,[44].forEach((e=>{Ie.genericErrors[e]=new Ie.ErrnoError(e),Ie.genericErrors[e].stack="<generic error, no stack>"})))},staticInit:()=>{Ie.ensureErrnoError(),Ie.nameTable=new Array(4096),Ie.mount(Re,{},"/"),Ie.createDefaultDirectories(),Ie.createDefaultDevices(),Ie.createSpecialDirectories(),Ie.filesystems={MEMFS:Re}},init:(e,t,n)=>{F(!Ie.init.initialized,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)"),Ie.init.initialized=!0,Ie.ensureErrnoError(),r.stdin=e||r.stdin,r.stdout=t||r.stdout,r.stderr=n||r.stderr,Ie.createStandardStreams()},quit:()=>{Ie.init.initialized=!1,wt();for(var e=0;e<Ie.streams.length;e++){var r=Ie.streams[e];r&&Ie.close(r)}},getMode:(e,r)=>{var t=0;return e&&(t|=365),r&&(t|=146),t},findObject:(e,r)=>{var t=Ie.analyzePath(e,r);return t.exists?t.object:null},analyzePath:(e,r)=>{try{e=(n=Ie.lookupPath(e,{follow:!r})).path}catch(e){}var t={isRoot:!1,exists:!1,error:0,name:null,path:null,object:null,parentExists:!1,parentPath:null,parentObject:null};try{var n=Ie.lookupPath(e,{parent:!0});t.parentExists=!0,t.parentPath=n.path,t.parentObject=n.node,t.name=Ae.basename(e),n=Ie.lookupPath(e,{follow:!r}),t.exists=!0,t.path=n.path,t.object=n.node,t.name=n.node.name,t.isRoot="/"===n.path}catch(e){t.error=e.errno}return t},createPath:(e,r,t,n)=>{e="string"==typeof e?e:Ie.getPath(e);for(var o=r.split("/").reverse();o.length;){var i=o.pop();if(i){var a=Ae.join2(e,i);try{Ie.mkdir(a)}catch(e){}e=a}}return a},createFile:(e,r,t,n,o)=>{var i=Ae.join2("string"==typeof e?e:Ie.getPath(e),r),a=Ie.getMode(n,o);return Ie.create(i,a)},createDataFile:(e,r,t,n,o,i)=>{var a=r;e&&(e="string"==typeof e?e:Ie.getPath(e),a=r?Ae.join2(e,r):e);var s=Ie.getMode(n,o),l=Ie.create(a,s);if(t){if("string"==typeof t){for(var u=new Array(t.length),c=0,d=t.length;c<d;++c)u[c]=t.charCodeAt(c);t=u}Ie.chmod(l,146|s);var f=Ie.open(l,577);Ie.write(f,t,0,t.length,0,i),Ie.close(f),Ie.chmod(l,s)}return l},createDevice:(e,r,t,n)=>{var o=Ae.join2("string"==typeof e?e:Ie.getPath(e),r),i=Ie.getMode(!!t,!!n);Ie.createDevice.major||(Ie.createDevice.major=64);var a=Ie.makedev(Ie.createDevice.major++,0);return Ie.registerDevice(a,{open:e=>{e.seekable=!1},close:e=>{n&&n.buffer&&n.buffer.length&&n(10)},read:(e,r,n,o,i)=>{for(var a=0,s=0;s<o;s++){var l;try{l=t()}catch(e){throw new Ie.ErrnoError(29)}if(void 0===l&&0===a)throw new Ie.ErrnoError(6);if(null==l)break;a++,r[n+s]=l}return a&&(e.node.timestamp=Date.now()),a},write:(e,r,t,o,i)=>{for(var a=0;a<o;a++)try{n(r[t+a])}catch(e){throw new Ie.ErrnoError(29)}return o&&(e.node.timestamp=Date.now()),a}}),Ie.mkdev(o,i,a)},forceLoadFile:e=>{if(e.isDevice||e.isFolder||e.link||e.contents)return!0;if("undefined"!=typeof XMLHttpRequest)throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");if(!d)throw new Error("Cannot load without read() or XMLHttpRequest.");try{e.contents=pt(d(e.url),!0),e.usedBytes=e.contents.length}catch(e){throw new Ie.ErrnoError(29)}},createLazyFile:(e,r,t,n,o)=>{function i(){this.lengthKnown=!1,this.chunks=[]}if(i.prototype.get=function(e){if(!(e>this.length-1||e<0)){var r=e%this.chunkSize,t=e/this.chunkSize|0;return this.getter(t)[r]}},i.prototype.setDataGetter=function(e){this.getter=e},i.prototype.cacheLength=function(){var e=new XMLHttpRequest;if(e.open("HEAD",t,!1),e.send(null),!(e.status>=200&&e.status<300||304===e.status))throw new Error("Couldn't load "+t+". Status: "+e.status);var r,n=Number(e.getResponseHeader("Content-length")),o=(r=e.getResponseHeader("Accept-Ranges"))&&"bytes"===r,i=(r=e.getResponseHeader("Content-Encoding"))&&"gzip"===r,a=1048576;o||(a=n);var s=this;s.setDataGetter((e=>{var r=e*a,o=(e+1)*a-1;if(o=Math.min(o,n-1),void 0===s.chunks[e]&&(s.chunks[e]=((e,r)=>{if(e>r)throw new Error("invalid range ("+e+", "+r+") or no bytes requested!");if(r>n-1)throw new Error("only "+n+" bytes available! programmer error!");var o=new XMLHttpRequest;if(o.open("GET",t,!1),n!==a&&o.setRequestHeader("Range","bytes="+e+"-"+r),o.responseType="arraybuffer",o.overrideMimeType&&o.overrideMimeType("text/plain; charset=x-user-defined"),o.send(null),!(o.status>=200&&o.status<300||304===o.status))throw new Error("Couldn't load "+t+". Status: "+o.status);return void 0!==o.response?new Uint8Array(o.response||[]):pt(o.responseText||"",!0)})(r,o)),void 0===s.chunks[e])throw new Error("doXHR failed!");return s.chunks[e]})),!i&&n||(a=n=1,n=this.getter(0).length,a=n,b("LazyFiles on gzip forces download of the whole file when length is accessed")),this._length=n,this._chunkSize=a,this.lengthKnown=!0},"undefined"!=typeof XMLHttpRequest){if(!l)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var a=new i;Object.defineProperties(a,{length:{get:function(){return this.lengthKnown||this.cacheLength(),this._length}},chunkSize:{get:function(){return this.lengthKnown||this.cacheLength(),this._chunkSize}}});var s={isDevice:!1,contents:a}}else s={isDevice:!1,url:t};var u=Ie.createFile(e,r,s,n,o);s.contents?u.contents=s.contents:s.url&&(u.contents=null,u.url=s.url),Object.defineProperties(u,{usedBytes:{get:function(){return this.contents.length}}});var c={};return Object.keys(u.stream_ops).forEach((e=>{var r=u.stream_ops[e];c[e]=function(){return Ie.forceLoadFile(u),r.apply(null,arguments)}})),c.read=(e,r,t,n,o)=>{Ie.forceLoadFile(u);var i=e.node.contents;if(o>=i.length)return 0;var a=Math.min(i.length-o,n);if(F(a>=0),i.slice)for(var s=0;s<a;s++)r[t+s]=i[o+s];else for(s=0;s<a;s++)r[t+s]=i.get(o+s);return a},u.stream_ops=c,u},createPreloadedFile:(e,r,t,n,o,i,a,s,l,u)=>{var c=r?Fe.resolve(Ae.join2(e,r)):e,d=pe("cp "+c);function p(t){function f(t){u&&u(),s||Ie.createDataFile(e,r,t,n,o,l),i&&i(),he(d)}Browser.handledByPreloadPlugin(t,c,f,(()=>{a&&a(),he(d)}))||f(t)}me(d),"string"==typeof t?function(e,r,t,n){var o=n?"":pe("al "+e);f(e,(function(t){F(t,'Loading data file "'+e+'" failed (no arrayBuffer).'),r(new Uint8Array(t)),o&&he(o)}),(function(r){if(!t)throw'Loading data file "'+e+'" failed.';t()})),o&&me(o)}(t,(e=>p(e)),a):p(t)},indexedDB:()=>window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB,DB_NAME:()=>"EM_FS_"+window.location.pathname,DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:(e,r,t)=>{r=r||(()=>{}),t=t||(()=>{});var n=Ie.indexedDB();try{var o=n.open(Ie.DB_NAME(),Ie.DB_VERSION)}catch(e){return t(e)}o.onupgradeneeded=()=>{b("creating db"),o.result.createObjectStore(Ie.DB_STORE_NAME)},o.onsuccess=()=>{var n=o.result.transaction([Ie.DB_STORE_NAME],"readwrite"),i=n.objectStore(Ie.DB_STORE_NAME),a=0,s=0,l=e.length;function u(){0==s?r():t()}e.forEach((e=>{var r=i.put(Ie.analyzePath(e).object.contents,e);r.onsuccess=()=>{++a+s==l&&u()},r.onerror=()=>{s++,a+s==l&&u()}})),n.onerror=t},o.onerror=t},loadFilesFromDB:(e,r,t)=>{r=r||(()=>{}),t=t||(()=>{});var n=Ie.indexedDB();try{var o=n.open(Ie.DB_NAME(),Ie.DB_VERSION)}catch(e){return t(e)}o.onupgradeneeded=t,o.onsuccess=()=>{var n=o.result;try{var i=n.transaction([Ie.DB_STORE_NAME],"readonly")}catch(e){return void t(e)}var a=i.objectStore(Ie.DB_STORE_NAME),s=0,l=0,u=e.length;function c(){0==l?r():t()}e.forEach((e=>{var r=a.get(e);r.onsuccess=()=>{Ie.analyzePath(e).exists&&Ie.unlink(e),Ie.createDataFile(Ae.dirname(e),Ae.basename(e),r.result,!0,!0,!0),++s+l==u&&c()},r.onerror=()=>{l++,s+l==u&&c()}})),i.onerror=t},o.onerror=t},absolutePath:()=>{ge("FS.absolutePath has been removed; use PATH_FS.resolve instead")},createFolder:()=>{ge("FS.createFolder has been removed; use FS.mkdir instead")},createLink:()=>{ge("FS.createLink has been removed; use FS.symlink instead")},joinPath:()=>{ge("FS.joinPath has been removed; use PATH.join instead")},mmapAlloc:()=>{ge("FS.mmapAlloc has been replaced by the top level function mmapAlloc")},standardizePath:()=>{ge("FS.standardizePath has been removed; use PATH.normalize instead")}},Le={DEFAULT_POLLMASK:5,calculateAt:function(e,r,t){if(Ae.isAbs(r))return r;var n;if(-100===e)n=Ie.cwd();else{var o=Ie.getStream(e);if(!o)throw new Ie.ErrnoError(8);n=o.path}if(0==r.length){if(!t)throw new Ie.ErrnoError(44);return n}return Ae.join2(n,r)},doStat:function(e,r,t){try{var n=e(r)}catch(e){if(e&&e.node&&Ae.normalize(r)!==Ae.normalize(Ie.getPath(e.node)))return-54;throw e}return $[t>>2]=n.dev,$[t+4>>2]=0,$[t+8>>2]=n.ino,$[t+12>>2]=n.mode,$[t+16>>2]=n.nlink,$[t+20>>2]=n.uid,$[t+24>>2]=n.gid,$[t+28>>2]=n.rdev,$[t+32>>2]=0,Ee=[n.size>>>0,(ye=n.size,+Math.abs(ye)>=1?ye>0?(0|Math.min(+Math.floor(ye/4294967296),4294967295))>>>0:~~+Math.ceil((ye-+(~~ye>>>0))/4294967296)>>>0:0)],$[t+40>>2]=Ee[0],$[t+44>>2]=Ee[1],$[t+48>>2]=4096,$[t+52>>2]=n.blocks,$[t+56>>2]=n.atime.getTime()/1e3|0,$[t+60>>2]=0,$[t+64>>2]=n.mtime.getTime()/1e3|0,$[t+68>>2]=0,$[t+72>>2]=n.ctime.getTime()/1e3|0,$[t+76>>2]=0,Ee=[n.ino>>>0,(ye=n.ino,+Math.abs(ye)>=1?ye>0?(0|Math.min(+Math.floor(ye/4294967296),4294967295))>>>0:~~+Math.ceil((ye-+(~~ye>>>0))/4294967296)>>>0:0)],$[t+80>>2]=Ee[0],$[t+84>>2]=Ee[1],0},doMsync:function(e,r,t,n,o){var i=U.slice(e,e+t);Ie.msync(r,i,o,t,n)},doMknod:function(e,r,t){switch(61440&r){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-28}return Ie.mknod(e,r,t),0},doReadlink:function(e,r,t){if(t<=0)return-28;var n=Ie.readlink(e),o=Math.min(t,I(n)),i=x[r+o];return N(n,r,t+1),x[r+o]=i,o},doAccess:function(e,r){if(-8&r)return-28;var t=Ie.lookupPath(e,{follow:!0}).node;if(!t)return-44;var n="";return 4&r&&(n+="r"),2&r&&(n+="w"),1&r&&(n+="x"),n&&Ie.nodePermissions(t,n)?-2:0},doReadv:function(e,r,t,n){for(var o=0,i=0;i<t;i++){var a=$[r>>2],s=$[r+4>>2];r+=8;var l=Ie.read(e,x,a,s,n);if(l<0)return-1;if(o+=l,l<s)break}return o},doWritev:function(e,r,t,n){for(var o=0,i=0;i<t;i++){var a=$[r>>2],s=$[r+4>>2];r+=8;var l=Ie.write(e,x,a,s,n);if(l<0)return-1;o+=l}return o},varargs:void 0,get:function(){return F(null!=Le.varargs),Le.varargs+=4,$[Le.varargs-4>>2]},getStr:function(e){return R(e)},getStreamFromFD:function(e){var r=Ie.getStream(e);if(!r)throw new Ie.ErrnoError(8);return r}};function xe(e){switch(e){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+e)}}var Ue=void 0;function Be(e){for(var r="",t=e;U[t];)r+=Ue[U[t++]];return r}var je={},$e={},We={};function ze(e){if(void 0===e)return"_unknown";var r=(e=e.replace(/[^a-zA-Z0-9_]/g,"$")).charCodeAt(0);return r>=48&&r<=57?"_"+e:e}function He(e,r){return e=ze(e),new Function("body","return function "+e+'() {\n "use strict"; return body.apply(this, arguments);\n};\n')(r)}function Ge(e,r){var t=He(r,(function(e){this.name=r,this.message=e;var t=new Error(e).stack;void 0!==t&&(this.stack=this.toString()+"\n"+t.replace(/^Error(:[^\n]*)?\n/,""))}));return t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.prototype.toString=function(){return void 0===this.message?this.name:this.name+": "+this.message},t}var Ve=void 0;function Ye(e){throw new Ve(e)}var qe=void 0;function Xe(e){throw new qe(e)}function Ke(e,r,t){function n(r){var n=t(r);n.length!==e.length&&Xe("Mismatched type converter count");for(var o=0;o<e.length;++o)Je(e[o],n[o])}e.forEach((function(e){We[e]=r}));var o=new Array(r.length),i=[],a=0;r.forEach(((e,r)=>{$e.hasOwnProperty(e)?o[r]=$e[e]:(i.push(e),je.hasOwnProperty(e)||(je[e]=[]),je[e].push((()=>{o[r]=$e[e],++a===i.length&&n(o)})))})),0===i.length&&n(o)}function Je(e,r){let t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(!("argPackAdvance"in r))throw new TypeError("registerType registeredInstance requires argPackAdvance");var n=r.name;if(e||Ye('type "'+n+'" must have a positive integer typeid pointer'),$e.hasOwnProperty(e)){if(t.ignoreDuplicateRegistrations)return;Ye("Cannot register type '"+n+"' twice")}if($e[e]=r,delete We[e],je.hasOwnProperty(e)){var o=je[e];delete je[e],o.forEach((e=>e()))}}function Qe(e){if(!(this instanceof wr))return!1;if(!(e instanceof wr))return!1;for(var r=this.$$.ptrType.registeredClass,t=this.$$.ptr,n=e.$$.ptrType.registeredClass,o=e.$$.ptr;r.baseClass;)t=r.upcast(t),r=r.baseClass;for(;n.baseClass;)o=n.upcast(o),n=n.baseClass;return r===n&&t===o}function Ze(e){Ye(e.$$.ptrType.registeredClass.name+" instance already deleted")}var er=!1;function rr(e){}function tr(e){e.count.value-=1,0===e.count.value&&function(e){e.smartPtr?e.smartPtrType.rawDestructor(e.smartPtr):e.ptrType.registeredClass.rawDestructor(e.ptr)}(e)}function nr(e,r,t){if(r===t)return e;if(void 0===t.baseClass)return null;var n=nr(e,r,t.baseClass);return null===n?null:t.downcast(n)}var or={};function ir(){return Object.keys(dr).length}function ar(){var e=[];for(var r in dr)dr.hasOwnProperty(r)&&e.push(dr[r]);return e}var sr=[];function lr(){for(;sr.length;){var e=sr.pop();e.$$.deleteScheduled=!1,e.delete()}}var ur=void 0;function cr(e){ur=e,sr.length&&ur&&ur(lr)}var dr={};function fr(e,r){return r=function(e,r){for(void 0===r&&Ye("ptr should not be undefined");e.baseClass;)r=e.upcast(r),e=e.baseClass;return r}(e,r),dr[r]}function pr(e,r){return r.ptrType&&r.ptr||Xe("makeClassHandle requires ptr and ptrType"),!!r.smartPtrType!==!!r.smartPtr&&Xe("Both smartPtrType and smartPtr must be specified"),r.count={value:1},hr(Object.create(e,{$$:{value:r}}))}function mr(e){var r=this.getPointee(e);if(!r)return this.destructor(e),null;var t=fr(this.registeredClass,r);if(void 0!==t){if(0===t.$$.count.value)return t.$$.ptr=r,t.$$.smartPtr=e,t.clone();var n=t.clone();return this.destructor(e),n}function o(){return this.isSmartPointer?pr(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:r,smartPtrType:this,smartPtr:e}):pr(this.registeredClass.instancePrototype,{ptrType:this,ptr:e})}var i,a=this.registeredClass.getActualType(r),s=or[a];if(!s)return o.call(this);i=this.isConst?s.constPointerType:s.pointerType;var l=nr(r,this.registeredClass,i.registeredClass);return null===l?o.call(this):this.isSmartPointer?pr(i.registeredClass.instancePrototype,{ptrType:i,ptr:l,smartPtrType:this,smartPtr:e}):pr(i.registeredClass.instancePrototype,{ptrType:i,ptr:l})}function hr(e){return"undefined"==typeof FinalizationRegistry?(hr=e=>e,e):(er=new FinalizationRegistry((e=>{console.warn(e.leakWarning.stack.replace(/^Error: /,"")),tr(e.$$)})),hr=e=>{var r=e.$$;if(!!r.smartPtr){var t={$$:r},n=r.ptrType.registeredClass;t.leakWarning=new Error("Embind found a leaked C++ instance "+n.name+" <0x"+r.ptr.toString(16)+">.\nWe'll free it automatically in this case, but this functionality is not reliable across various environments.\nMake sure to invoke .delete() manually once you're done with the instance instead.\nOriginally allocated"),"captureStackTrace"in Error&&Error.captureStackTrace(t.leakWarning,mr),er.register(e,t,e)}return e},rr=e=>er.unregister(e),hr(e))}function gr(){if(this.$$.ptr||Ze(this),this.$$.preservePointerOnDelete)return this.$$.count.value+=1,this;var e,r=hr(Object.create(Object.getPrototypeOf(this),{$$:{value:(e=this.$$,{count:e.count,deleteScheduled:e.deleteScheduled,preservePointerOnDelete:e.preservePointerOnDelete,ptr:e.ptr,ptrType:e.ptrType,smartPtr:e.smartPtr,smartPtrType:e.smartPtrType})}}));return r.$$.count.value+=1,r.$$.deleteScheduled=!1,r}function vr(){this.$$.ptr||Ze(this),this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete&&Ye("Object already scheduled for deletion"),rr(this),tr(this.$$),this.$$.preservePointerOnDelete||(this.$$.smartPtr=void 0,this.$$.ptr=void 0)}function yr(){return!this.$$.ptr}function Er(){return this.$$.ptr||Ze(this),this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete&&Ye("Object already scheduled for deletion"),sr.push(this),1===sr.length&&ur&&ur(lr),this.$$.deleteScheduled=!0,this}function wr(){}function br(e,r,t){if(void 0===e[r].overloadTable){var n=e[r];e[r]=function(){return e[r].overloadTable.hasOwnProperty(arguments.length)||Ye("Function '"+t+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+e[r].overloadTable+")!"),e[r].overloadTable[arguments.length].apply(this,arguments)},e[r].overloadTable=[],e[r].overloadTable[n.argCount]=n}}function _r(e,r,t,n,o,i,a,s){this.name=e,this.constructor=r,this.instancePrototype=t,this.rawDestructor=n,this.baseClass=o,this.getActualType=i,this.upcast=a,this.downcast=s,this.pureVirtualFunctions=[]}function Tr(e,r,t){for(;r!==t;)r.upcast||Ye("Expected null or instance of "+t.name+", got an instance of "+r.name),e=r.upcast(e),r=r.baseClass;return e}function kr(e,r){if(null===r)return this.isReference&&Ye("null is not a valid "+this.name),0;r.$$||Ye('Cannot pass "'+qr(r)+'" as a '+this.name),r.$$.ptr||Ye("Cannot pass deleted object as a pointer of type "+this.name);var t=r.$$.ptrType.registeredClass;return Tr(r.$$.ptr,t,this.registeredClass)}function Sr(e,r){var t;if(null===r)return this.isReference&&Ye("null is not a valid "+this.name),this.isSmartPointer?(t=this.rawConstructor(),null!==e&&e.push(this.rawDestructor,t),t):0;r.$$||Ye('Cannot pass "'+qr(r)+'" as a '+this.name),r.$$.ptr||Ye("Cannot pass deleted object as a pointer of type "+this.name),!this.isConst&&r.$$.ptrType.isConst&&Ye("Cannot convert argument of type "+(r.$$.smartPtrType?r.$$.smartPtrType.name:r.$$.ptrType.name)+" to parameter type "+this.name);var n=r.$$.ptrType.registeredClass;if(t=Tr(r.$$.ptr,n,this.registeredClass),this.isSmartPointer)switch(void 0===r.$$.smartPtr&&Ye("Passing raw pointer to smart pointer is illegal"),this.sharingPolicy){case 0:r.$$.smartPtrType===this?t=r.$$.smartPtr:Ye("Cannot convert argument of type "+(r.$$.smartPtrType?r.$$.smartPtrType.name:r.$$.ptrType.name)+" to parameter type "+this.name);break;case 1:t=r.$$.smartPtr;break;case 2:if(r.$$.smartPtrType===this)t=r.$$.smartPtr;else{var o=r.clone();t=this.rawShare(t,Yr.toHandle((function(){o.delete()}))),null!==e&&e.push(this.rawDestructor,t)}break;default:Ye("Unsupporting sharing policy")}return t}function Cr(e,r){if(null===r)return this.isReference&&Ye("null is not a valid "+this.name),0;r.$$||Ye('Cannot pass "'+qr(r)+'" as a '+this.name),r.$$.ptr||Ye("Cannot pass deleted object as a pointer of type "+this.name),r.$$.ptrType.isConst&&Ye("Cannot convert argument of type "+r.$$.ptrType.name+" to parameter type "+this.name);var t=r.$$.ptrType.registeredClass;return Tr(r.$$.ptr,t,this.registeredClass)}function Pr(e){return this.fromWireType(W[e>>2])}function Ar(e){return this.rawGetPointee&&(e=this.rawGetPointee(e)),e}function Fr(e){this.rawDestructor&&this.rawDestructor(e)}function Dr(e){null!==e&&e.delete()}function Or(e,r,t,n,o,i,a,s,l,u,c){this.name=e,this.registeredClass=r,this.isReference=t,this.isConst=n,this.isSmartPointer=o,this.pointeeType=i,this.sharingPolicy=a,this.rawGetPointee=s,this.rawConstructor=l,this.rawShare=u,this.rawDestructor=c,o||void 0!==r.baseClass?this.toWireType=Sr:n?(this.toWireType=kr,this.destructorFunction=null):(this.toWireType=Cr,this.destructorFunction=null)}function Rr(e,t,n){return e.includes("j")?function(e,t,n){F("dynCall_"+e in r,"bad function pointer type - no table for sig '"+e+"'"),n&&n.length?F(n.length===e.substring(1).replace(/j/g,"--").length):F(1==e.length);var o=r["dynCall_"+e];return n&&n.length?o.apply(null,[t].concat(n)):o.call(null,t)}(e,t,n):(F(Ce(t),"missing table entry in dynCall: "+t),Ce(t).apply(null,n))}function Mr(e,r){var t=(e=Be(e)).includes("j")?function(e,r){F(e.includes("j"),"getDynCaller should only be called with i64 sigs");var t=[];return function(){return t.length=0,Object.assign(t,arguments),Rr(e,r,t)}}(e,r):Ce(r);return"function"!=typeof t&&Ye("unknown function pointer with signature "+e+": "+r),t}var Nr=void 0;function Ir(e){var r=Et(e),t=Be(r);return ht(r),t}function Lr(e,r){var t=[],n={};throw r.forEach((function e(r){n[r]||$e[r]||(We[r]?We[r].forEach(e):(t.push(r),n[r]=!0))})),new Nr(e+": "+t.map(Ir).join([", "]))}function xr(e,r){for(var t=[],n=0;n<e;n++)t.push($[(r>>2)+n]);return t}function Ur(e){for(;e.length;){var r=e.pop();e.pop()(r)}}function Br(e,r){if(!(e instanceof Function))throw new TypeError("new_ called with constructor type "+typeof e+" which is not a function");var t=He(e.name||"unknownFunctionName",(function(){}));t.prototype=e.prototype;var n=new t,o=e.apply(n,r);return o instanceof Object?o:n}function jr(e,r,t,n,o){var i=r.length;i<2&&Ye("argTypes array size mismatch! Must at least get return value and 'this' types!");for(var a=null!==r[1]&&null!==t,s=!1,l=1;l<r.length;++l)if(null!==r[l]&&void 0===r[l].destructorFunction){s=!0;break}var u="void"!==r[0].name,c="",d="";for(l=0;l<i-2;++l)c+=(0!==l?", ":"")+"arg"+l,d+=(0!==l?", ":"")+"arg"+l+"Wired";var f="return function "+ze(e)+"("+c+") {\nif (arguments.length !== "+(i-2)+") {\nthrowBindingError('function "+e+" called with ' + arguments.length + ' arguments, expected "+(i-2)+" args!');\n}\n";s&&(f+="var destructors = [];\n");var p=s?"destructors":"null",m=["throwBindingError","invoker","fn","runDestructors","retType","classParam"],h=[Ye,n,o,Ur,r[0],r[1]];a&&(f+="var thisWired = classParam.toWireType("+p+", this);\n");for(l=0;l<i-2;++l)f+="var arg"+l+"Wired = argType"+l+".toWireType("+p+", arg"+l+"); // "+r[l+2].name+"\n",m.push("argType"+l),h.push(r[l+2]);if(a&&(d="thisWired"+(d.length>0?", ":"")+d),f+=(u?"var rv = ":"")+"invoker(fn"+(d.length>0?", ":"")+d+");\n",s)f+="runDestructors(destructors);\n";else for(l=a?1:2;l<r.length;++l){var g=1===l?"thisWired":"arg"+(l-2)+"Wired";null!==r[l].destructorFunction&&(f+=g+"_dtor("+g+"); // "+r[l].name+"\n",m.push(g+"_dtor"),h.push(r[l].destructorFunction))}return u&&(f+="var ret = retType.fromWireType(rv);\nreturn ret;\n"),f+="}\n",m.push(f),Br(Function,m).apply(null,h)}function $r(e,r,t){return e instanceof Object||Ye(t+' with invalid "this": '+e),e instanceof r.registeredClass.constructor||Ye(t+' incompatible with "this" of type '+e.constructor.name),e.$$.ptr||Ye("cannot call emscripten binding method "+t+" on deleted object"),Tr(e.$$.ptr,e.$$.ptrType.registeredClass,r.registeredClass)}var Wr=[],zr=[{},{value:void 0},{value:null},{value:!0},{value:!1}];function Hr(e){e>4&&0==--zr[e].refcount&&(zr[e]=void 0,Wr.push(e))}function Gr(){for(var e=0,r=5;r<zr.length;++r)void 0!==zr[r]&&++e;return e}function Vr(){for(var e=5;e<zr.length;++e)if(void 0!==zr[e])return zr[e];return null}var Yr={toValue:e=>(e||Ye("Cannot use deleted val. handle = "+e),zr[e].value),toHandle:e=>{switch(e){case void 0:return 1;case null:return 2;case!0:return 3;case!1:return 4;default:var r=Wr.length?Wr.pop():zr.length;return zr[r]={refcount:1,value:e},r}}};function qr(e){if(null===e)return"null";var r=typeof e;return"object"===r||"array"===r||"function"===r?e.toString():""+e}function Xr(e,r){switch(r){case 2:return function(e){return this.fromWireType(z[e>>2])};case 3:return function(e){return this.fromWireType(H[e>>3])};default:throw new TypeError("Unknown float type: "+e)}}function Kr(e,r,t){switch(r){case 0:return t?function(e){return x[e]}:function(e){return U[e]};case 1:return t?function(e){return B[e>>1]}:function(e){return j[e>>1]};case 2:return t?function(e){return $[e>>2]}:function(e){return W[e>>2]};default:throw new TypeError("Unknown integer type: "+e)}}function Jr(e,r){var t=$e[e];return void 0===t&&Ye(r+" has unknown type "+Ir(e)),t}var Qr={};var Zr=[];var et=[];function rt(e,r){return F(r===(0|r)),(e>>>0)+4294967296*r}function tt(e,r){if(e<=0)return e;var t=r<=32?Math.abs(1<<r-1):Math.pow(2,r-1);return e>=t&&(r<=32||e>t)&&(e=-2*t+e),e}function nt(e,r){return e>=0?e:r<=32?2*Math.abs(1<<r-1)+e:Math.pow(2,r)+e}function ot(e,r){F(0==(3&r));var t=e,n=r;function o(e){var r;return n=function(e,r){return"double"===r||"i64"===r?7&e&&(F(4==(7&e)),e+=4):F(0==(3&e)),e}(n,e),"double"===e?(r=Number(H[n>>3]),n+=8):"i64"==e?(r=[$[n>>2],$[n+4>>2]],n+=8):(F(0==(3&n)),e="i32",r=$[n>>2],n+=4),r}for(var i,a,s,l,u,c,d=[];;){var f=t;if(0===(i=x[t>>0]))break;if(a=x[t+1>>0],37==i){var p=!1,m=!1,h=!1,g=!1,v=!1;e:for(;;){switch(a){case 43:p=!0;break;case 45:m=!0;break;case 35:h=!0;break;case 48:if(g)break e;g=!0;break;case 32:v=!0;break;default:break e}t++,a=x[t+1>>0]}var y=0;if(42==a)y=o("i32"),t++,a=x[t+1>>0];else for(;a>=48&&a<=57;)y=10*y+(a-48),t++,a=x[t+1>>0];var E,w=!1,b=-1;if(46==a){if(b=0,w=!0,t++,42==(a=x[t+1>>0]))b=o("i32"),t++;else for(;;){var _=x[t+1>>0];if(_<48||_>57)break;b=10*b+(_-48),t++}a=x[t+1>>0]}switch(b<0&&(b=6,w=!1),String.fromCharCode(a)){case"h":104==x[t+2>>0]?(t++,E=1):E=2;break;case"l":108==x[t+2>>0]?(t++,E=8):E=4;break;case"L":case"q":case"j":E=8;break;case"z":case"t":case"I":E=4;break;default:E=null}switch(E&&t++,a=x[t+1>>0],String.fromCharCode(a)){case"d":case"i":case"u":case"o":case"x":case"X":case"p":var T=100==a||105==a;if(s=o("i"+8*(E=E||4)),8==E&&(s=117==a?(u=s[0],c=s[1],(u>>>0)+4294967296*(c>>>0)):rt(s[0],s[1])),E<=4)s=(T?tt:nt)(s&Math.pow(256,E)-1,8*E);var k=Math.abs(s),S="";if(100==a||105==a)A=tt(s,8*E).toString(10);else if(117==a)A=nt(s,8*E).toString(10),s=Math.abs(s);else if(111==a)A=(h?"0":"")+k.toString(8);else if(120==a||88==a){if(S=h&&0!=s?"0x":"",s<0){s=-s,A=(k-1).toString(16);for(var C=[],P=0;P<A.length;P++)C.push((15-parseInt(A[P],16)).toString(16));for(A=C.join("");A.length<2*E;)A="f"+A}else A=k.toString(16);88==a&&(S=S.toUpperCase(),A=A.toUpperCase())}else 112==a&&(0===k?A="(nil)":(S="0x",A=k.toString(16)));if(w)for(;A.length<b;)A="0"+A;for(s>=0&&(p?S="+"+S:v&&(S=" "+S)),"-"==A.charAt(0)&&(S="-"+S,A=A.substr(1));S.length+A.length<y;)m?A+=" ":g?A="0"+A:S=" "+S;(A=S+A).split("").forEach((function(e){d.push(e.charCodeAt(0))}));break;case"f":case"F":case"e":case"E":case"g":case"G":var A;if(s=o("double"),isNaN(s))A="nan",g=!1;else if(isFinite(s)){var D=!1,O=Math.min(b,20);if(103==a||71==a){D=!0,b=b||1;var R=parseInt(s.toExponential(O).split("e")[1],10);b>R&&R>=-4?(a=(103==a?"f":"F").charCodeAt(0),b-=R+1):(a=(103==a?"e":"E").charCodeAt(0),b--),O=Math.min(b,20)}101==a||69==a?(A=s.toExponential(O),/[eE][-+]\d$/.test(A)&&(A=A.slice(0,-1)+"0"+A.slice(-1))):102!=a&&70!=a||(A=s.toFixed(O),0===s&&((l=s)<0||0===l&&1/l==-1/0)&&(A="-"+A));var M=A.split("e");if(D&&!h)for(;M[0].length>1&&M[0].includes(".")&&("0"==M[0].slice(-1)||"."==M[0].slice(-1));)M[0]=M[0].slice(0,-1);else for(h&&-1==A.indexOf(".")&&(M[0]+=".");b>O++;)M[0]+="0";A=M[0]+(M.length>1?"e"+M[1]:""),69==a&&(A=A.toUpperCase()),s>=0&&(p?A="+"+A:v&&(A=" "+A))}else A=(s<0?"-":"")+"inf",g=!1;for(;A.length<y;)m?A+=" ":A=!g||"-"!=A[0]&&"+"!=A[0]?(g?"0":" ")+A:A[0]+"0"+A.slice(1);a<97&&(A=A.toUpperCase()),A.split("").forEach((function(e){d.push(e.charCodeAt(0))}));break;case"s":var N=o("i8*"),I=N?vt(N):"(null)".length;if(w&&(I=Math.min(I,b)),!m)for(;I<y--;)d.push(32);if(N)for(P=0;P<I;P++)d.push(U[N++>>0]);else d=d.concat(pt("(null)".substr(0,I),!0));if(m)for(;I<y--;)d.push(32);break;case"c":for(m&&d.push(o("i8"));--y>0;)d.push(32);m||d.push(o("i8"));break;case"n":var L=o("i32*");$[L>>2]=d.length;break;case"%":d.push(i);break;default:for(P=f;P<t+2;P++)d.push(x[P>>0])}t+=2}else d.push(i),t+=1}return d}function it(e){if(!e||!e.callee||!e.callee.name)return[null,"",""];e.callee.toString();var r=e.callee.name,t="(",n=!0;for(var o in e){var i=e[o];n||(t+=", "),n=!1,t+="number"==typeof i||"string"==typeof i?i:"("+typeof i+")"}t+=")";var a=e.callee.caller;return n&&(t=""),[e=a?a.arguments:[],r,t]}function at(e,r){24&e&&(r=r.replace(/\s+$/,""),r+=(r.length>0?"\n":"")+function(e){var r=Pe(),t=r.lastIndexOf("_emscripten_log"),n=r.lastIndexOf("_emscripten_get_callstack"),o=r.indexOf("\n",Math.max(t,n))+1;r=r.slice(o),32&e&&T("EM_LOG_DEMANGLE is deprecated; ignoring"),8&e&&"undefined"==typeof emscripten_source_map&&(T('Source map information is not available, emscripten_log with EM_LOG_C_STACK will be ignored. Build with "--pre-js $EMSCRIPTEN/src/emscripten-source-map.min.js" linker flag to add source map loading to code.'),e^=8,e|=16);var i=null;if(128&e)for(i=it(arguments);i[1].includes("_emscripten_");)i=it(i[0]);var a=r.split("\n");r="";var s=new RegExp("\\s*(.*?)@(.*?):([0-9]+):([0-9]+)"),l=new RegExp("\\s*(.*?)@(.*):(.*)(:(.*))?"),u=new RegExp("\\s*at (.*?) \\((.*):(.*):(.*)\\)");for(var c in a){var d=a[c],f="",p="",m=0,h=0,g=u.exec(d);if(g&&5==g.length)f=g[1],p=g[2],m=g[3],h=g[4];else{if((g=s.exec(d))||(g=l.exec(d)),!(g&&g.length>=4)){r+=d+"\n";continue}f=g[1],p=g[2],m=g[3],h=0|g[4]}var v=!1;if(8&e){var y=emscripten_source_map.originalPositionFor({line:m,column:h});(v=y&&y.source)&&(64&e&&(y.source=y.source.substring(y.source.replace(/\\/g,"/").lastIndexOf("/")+1)),r+=" at "+f+" ("+y.source+":"+y.line+":"+y.column+")\n")}(16&e||!v)&&(64&e&&(p=p.substring(p.replace(/\\/g,"/").lastIndexOf("/")+1)),r+=(v?" = "+f:" at "+f)+" ("+p+":"+m+":"+h+")\n"),128&e&&i[0]&&(i[1]==f&&i[2].length>0&&(r=r.replace(/\s+$/,""),r+=" with values: "+i[1]+i[2]+"\n"),i=it(i[0]))}return r.replace(/\s+$/,"")}(e)),1&e?4&e?console.error(r):2&e?console.warn(r):512&e?console.info(r):256&e?console.debug(r):console.log(r):6&e?_(r):b(r)}function st(e){try{return w.grow(e-L.byteLength+65535>>>16),Z(w.buffer),1}catch(r){_("emscripten_realloc_buffer: Attempted to grow heap from "+L.byteLength+" bytes to "+e+" bytes, but got error: "+r)}}var lt={};function ut(){if(!ut.strings){var e={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"==typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:n||"./this.program"};for(var r in lt)void 0===lt[r]?delete e[r]:e[r]=lt[r];var t=[];for(var r in e)t.push(r+"="+e[r]);ut.strings=t}return ut.strings}var ct=function(e,r,t,n){e||(e=this),this.parent=e,this.mount=e.mount,this.mounted=null,this.id=Ie.nextInode++,this.name=r,this.mode=t,this.node_ops={},this.stream_ops={},this.rdev=n},dt=365,ft=146;function pt(e,r,t){var n=t>0?t:I(e)+1,o=new Array(n),i=M(e,o,0,o.length);return r&&(o.length=i),o}Object.defineProperties(ct.prototype,{read:{get:function(){return(this.mode&dt)===dt},set:function(e){e?this.mode|=dt:this.mode&=-366}},write:{get:function(){return(this.mode&ft)===ft},set:function(e){e?this.mode|=ft:this.mode&=-147}},isFolder:{get:function(){return Ie.isDir(this.mode)}},isDevice:{get:function(){return Ie.isChrdev(this.mode)}}}),Ie.FSNode=ct,Ie.staticInit(),Ne={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135},function(){for(var e=new Array(256),r=0;r<256;++r)e[r]=String.fromCharCode(r);Ue=e}(),Ve=r.BindingError=Ge(Error,"BindingError"),qe=r.InternalError=Ge(Error,"InternalError"),wr.prototype.isAliasOf=Qe,wr.prototype.clone=gr,wr.prototype.delete=vr,wr.prototype.isDeleted=yr,wr.prototype.deleteLater=Er,r.getInheritedInstanceCount=ir,r.getLiveInheritedInstances=ar,r.flushPendingDeletes=lr,r.setDelayFunction=cr,Or.prototype.getPointee=Ar,Or.prototype.destructor=Fr,Or.prototype.argPackAdvance=8,Or.prototype.readValueFromPointer=Pr,Or.prototype.deleteObject=Dr,Or.prototype.fromWireType=mr,Nr=r.UnboundTypeError=Ge(Error,"UnboundTypeError"),r.count_emval_handles=Gr,r.get_first_emval=Vr;var mt={__syscall_fcntl64:function(e,r,t){Le.varargs=t;try{var n=Le.getStreamFromFD(e);switch(r){case 0:return(o=Le.get())<0?-28:Ie.createStream(n,o).fd;case 1:case 2:case 6:case 7:return 0;case 3:return n.flags;case 4:var o=Le.get();return n.flags|=o,0;case 5:o=Le.get();return B[o+0>>1]=2,0;case 16:case 8:default:return-28;case 9:return i=28,$[yt()>>2]=i,-1}}catch(e){if(void 0===Ie||!(e instanceof Ie.ErrnoError))throw e;return-e.errno}var i},__syscall_openat:function(e,r,t,n){Le.varargs=n;try{r=Le.getStr(r),r=Le.calculateAt(e,r);var o=n?Le.get():0;return Ie.open(r,t,o).fd}catch(e){if(void 0===Ie||!(e instanceof Ie.ErrnoError))throw e;return-e.errno}},_embind_register_bigint:function(e,r,t,n,o){},_embind_register_bool:function(e,r,t,n,o){var i=xe(t);Je(e,{name:r=Be(r),fromWireType:function(e){return!!e},toWireType:function(e,r){return r?n:o},argPackAdvance:8,readValueFromPointer:function(e){var n;if(1===t)n=x;else if(2===t)n=B;else{if(4!==t)throw new TypeError("Unknown boolean type size: "+r);n=$}return this.fromWireType(n[e>>i])},destructorFunction:null})},_embind_register_class:function(e,t,n,o,i,a,s,l,u,c,d,f,p){d=Be(d),a=Mr(i,a),l&&(l=Mr(s,l)),c&&(c=Mr(u,c)),p=Mr(f,p);var m=ze(d);!function(e,t,n){r.hasOwnProperty(e)?((void 0===n||void 0!==r[e].overloadTable&&void 0!==r[e].overloadTable[n])&&Ye("Cannot register public name '"+e+"' twice"),br(r,e,e),r.hasOwnProperty(n)&&Ye("Cannot register multiple overloads of a function with the same number of arguments ("+n+")!"),r[e].overloadTable[n]=t):(r[e]=t,void 0!==n&&(r[e].numArguments=n))}(m,(function(){Lr("Cannot construct "+d+" due to unbound types",[o])})),Ke([e,t,n],o?[o]:[],(function(t){var n,i;t=t[0],i=o?(n=t.registeredClass).instancePrototype:wr.prototype;var s=He(m,(function(){if(Object.getPrototypeOf(this)!==u)throw new Ve("Use 'new' to construct "+d);if(void 0===f.constructor_body)throw new Ve(d+" has no accessible constructor");var e=f.constructor_body[arguments.length];if(void 0===e)throw new Ve("Tried to invoke ctor of "+d+" with invalid number of parameters ("+arguments.length+") - expected ("+Object.keys(f.constructor_body).toString()+") parameters instead!");return e.apply(this,arguments)})),u=Object.create(i,{constructor:{value:s}});s.prototype=u;var f=new _r(d,s,u,p,n,a,l,c),h=new Or(d,f,!0,!1,!1),g=new Or(d+"*",f,!1,!1,!1),v=new Or(d+" const*",f,!1,!0,!1);return or[e]={pointerType:g,constPointerType:v},function(e,t,n){r.hasOwnProperty(e)||Xe("Replacing nonexistant public symbol"),void 0!==r[e].overloadTable&&void 0!==n?r[e].overloadTable[n]=t:(r[e]=t,r[e].argCount=n)}(m,s),[h,g,v]}))},_embind_register_class_constructor:function(e,r,t,n,o,i){F(r>0);var a=xr(r,t);o=Mr(n,o),Ke([],[e],(function(e){var t="constructor "+(e=e[0]).name;if(void 0===e.registeredClass.constructor_body&&(e.registeredClass.constructor_body=[]),void 0!==e.registeredClass.constructor_body[r-1])throw new Ve("Cannot register multiple constructors with identical number of parameters ("+(r-1)+") for class '"+e.name+"'! Overload resolution is currently only performed using the parameter count, not actual type info!");return e.registeredClass.constructor_body[r-1]=()=>{Lr("Cannot construct "+e.name+" due to unbound types",a)},Ke([],a,(function(n){return n.splice(1,0,null),e.registeredClass.constructor_body[r-1]=jr(t,n,null,o,i),[]})),[]}))},_embind_register_class_function:function(e,r,t,n,o,i,a,s){var l=xr(t,n);r=Be(r),i=Mr(o,i),Ke([],[e],(function(e){var n=(e=e[0]).name+"."+r;function o(){Lr("Cannot call "+n+" due to unbound types",l)}r.startsWith("@@")&&(r=Symbol[r.substring(2)]),s&&e.registeredClass.pureVirtualFunctions.push(r);var u=e.registeredClass.instancePrototype,c=u[r];return void 0===c||void 0===c.overloadTable&&c.className!==e.name&&c.argCount===t-2?(o.argCount=t-2,o.className=e.name,u[r]=o):(br(u,r,n),u[r].overloadTable[t-2]=o),Ke([],l,(function(o){var s=jr(n,o,e,i,a);return void 0===u[r].overloadTable?(s.argCount=t-2,u[r]=s):u[r].overloadTable[t-2]=s,[]})),[]}))},_embind_register_class_property:function(e,r,t,n,o,i,a,s,l,u){r=Be(r),o=Mr(n,o),Ke([],[e],(function(e){var n=(e=e[0]).name+"."+r,c={get:function(){Lr("Cannot access "+n+" due to unbound types",[t,a])},enumerable:!0,configurable:!0};return c.set=l?()=>{Lr("Cannot access "+n+" due to unbound types",[t,a])}:e=>{Ye(n+" is a read-only property")},Object.defineProperty(e.registeredClass.instancePrototype,r,c),Ke([],l?[t,a]:[t],(function(t){var a=t[0],c={get:function(){var r=$r(this,e,n+" getter");return a.fromWireType(o(i,r))},enumerable:!0};if(l){l=Mr(s,l);var d=t[1];c.set=function(r){var t=$r(this,e,n+" setter"),o=[];l(u,t,d.toWireType(o,r)),Ur(o)}}return Object.defineProperty(e.registeredClass.instancePrototype,r,c),[]})),[]}))},_embind_register_emval:function(e,r){Je(e,{name:r=Be(r),fromWireType:function(e){var r=Yr.toValue(e);return Hr(e),r},toWireType:function(e,r){return Yr.toHandle(r)},argPackAdvance:8,readValueFromPointer:Pr,destructorFunction:null})},_embind_register_float:function(e,r,t){var n=xe(t);Je(e,{name:r=Be(r),fromWireType:function(e){return e},toWireType:function(e,r){if("number"!=typeof r&&"boolean"!=typeof r)throw new TypeError('Cannot convert "'+qr(r)+'" to '+this.name);return r},argPackAdvance:8,readValueFromPointer:Xr(r,n),destructorFunction:null})},_embind_register_integer:function(e,r,t,n,o){r=Be(r),-1===o&&(o=4294967295);var i=xe(t),a=e=>e;if(0===n){var s=32-8*t;a=e=>e<<s>>>s}var l=r.includes("unsigned"),u=(e,t)=>{if("number"!=typeof e&&"boolean"!=typeof e)throw new TypeError('Cannot convert "'+qr(e)+'" to '+t);if(e<n||e>o)throw new TypeError('Passing a number "'+qr(e)+'" from JS side to C/C++ side to an argument of type "'+r+'", which is outside the valid range ['+n+", "+o+"]!")};Je(e,{name:r,fromWireType:a,toWireType:l?function(e,r){return u(r,this.name),r>>>0}:function(e,r){return u(r,this.name),r},argPackAdvance:8,readValueFromPointer:Kr(r,i,0!==n),destructorFunction:null})},_embind_register_memory_view:function(e,r,t){var n=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][r];function o(e){var r=W,t=r[e>>=2],o=r[e+1];return new n(L,o,t)}Je(e,{name:t=Be(t),fromWireType:o,argPackAdvance:8,readValueFromPointer:o},{ignoreDuplicateRegistrations:!0})},_embind_register_std_string:function(e,r){var t="std::string"===(r=Be(r));Je(e,{name:r,fromWireType:function(e){var r,n=W[e>>2];if(t)for(var o=e+4,i=0;i<=n;++i){var a=e+4+i;if(i==n||0==U[a]){var s=R(o,a-o);void 0===r?r=s:(r+=String.fromCharCode(0),r+=s),o=a+1}}else{var l=new Array(n);for(i=0;i<n;++i)l[i]=String.fromCharCode(U[e+4+i]);r=l.join("")}return ht(e),r},toWireType:function(e,r){r instanceof ArrayBuffer&&(r=new Uint8Array(r));var n="string"==typeof r;n||r instanceof Uint8Array||r instanceof Uint8ClampedArray||r instanceof Int8Array||Ye("Cannot pass non-string to std::string");var o=(t&&n?()=>I(r):()=>r.length)(),i=gt(4+o+1);if(W[i>>2]=o,t&&n)N(r,i+4,o+1);else if(n)for(var a=0;a<o;++a){var s=r.charCodeAt(a);s>255&&(ht(i),Ye("String has UTF-16 code units that do not fit in 8 bits")),U[i+4+a]=s}else for(a=0;a<o;++a)U[i+4+a]=r[a];return null!==e&&e.push(ht,i),i},argPackAdvance:8,readValueFromPointer:Pr,destructorFunction:function(e){ht(e)}})},_embind_register_std_wstring:function(e,r,t){var n,o,i,a,s;t=Be(t),2===r?(n=V,o=Y,a=q,i=()=>j,s=1):4===r&&(n=X,o=K,a=J,i=()=>W,s=2),Je(e,{name:t,fromWireType:function(e){for(var t,o=W[e>>2],a=i(),l=e+4,u=0;u<=o;++u){var c=e+4+u*r;if(u==o||0==a[c>>s]){var d=n(l,c-l);void 0===t?t=d:(t+=String.fromCharCode(0),t+=d),l=c+r}}return ht(e),t},toWireType:function(e,n){"string"!=typeof n&&Ye("Cannot pass non-string to C++ string type "+t);var i=a(n),l=gt(4+i+r);return W[l>>2]=i>>s,o(n,l+4,i+r),null!==e&&e.push(ht,l),l},argPackAdvance:8,readValueFromPointer:Pr,destructorFunction:function(e){ht(e)}})},_embind_register_void:function(e,r){Je(e,{isVoid:!0,name:r=Be(r),argPackAdvance:0,fromWireType:function(){},toWireType:function(e,r){}})},_emscripten_date_now:function(){return Date.now()},_emval_as:function(e,r,t){e=Yr.toValue(e),r=Jr(r,"emval::as");var n=[],o=Yr.toHandle(n);return $[t>>2]=o,r.toWireType(n,e)},_emval_call_void_method:function(e,r,t,n){var o,i;(e=Zr[e])(r=Yr.toValue(r),t=void 0===(i=Qr[o=t])?Be(o):i,null,n)},_emval_decref:Hr,_emval_get_method_caller:function(e,r){var t=function(e,r){for(var t=new Array(e),n=0;n<e;++n)t[n]=Jr($[(r>>2)+n],"parameter "+n);return t}(e,r),n=t[0],o=n.name+"_$"+t.slice(1).map((function(e){return e.name})).join("_")+"$",i=et[o];if(void 0!==i)return i;for(var a=["retType"],s=[n],l="",u=0;u<e-1;++u)l+=(0!==u?", ":"")+"arg"+u,a.push("argType"+u),s.push(t[1+u]);var c="return function "+ze("methodCaller_"+o)+"(handle, name, destructors, args) {\n",d=0;for(u=0;u<e-1;++u)c+=" var arg"+u+" = argType"+u+".readValueFromPointer(args"+(d?"+"+d:"")+");\n",d+=t[u+1].argPackAdvance;for(c+=" var rv = handle[name]("+l+");\n",u=0;u<e-1;++u)t[u+1].deleteObject&&(c+=" argType"+u+".deleteObject(arg"+u+");\n");n.isVoid||(c+=" return retType.toWireType(destructors, rv);\n"),c+="};\n",a.push(c);var f,p,m=Br(Function,a).apply(null,s);return f=m,p=Zr.length,Zr.push(f),i=p,et[o]=i,i},_emval_incref:function(e){e>4&&(zr[e].refcount+=1)},_emval_run_destructors:function(e){Ur(Yr.toValue(e)),Hr(e)},_emval_take_value:function(e,r){var t=(e=Jr(e,"_emval_take_value")).readValueFromPointer(r);return Yr.toHandle(t)},_gmtime_js:function(e,r){var t=new Date(1e3*$[e>>2]);$[r>>2]=t.getUTCSeconds(),$[r+4>>2]=t.getUTCMinutes(),$[r+8>>2]=t.getUTCHours(),$[r+12>>2]=t.getUTCDate(),$[r+16>>2]=t.getUTCMonth(),$[r+20>>2]=t.getUTCFullYear()-1900,$[r+24>>2]=t.getUTCDay();var n=Date.UTC(t.getUTCFullYear(),0,1,0,0,0,0),o=(t.getTime()-n)/864e5|0;$[r+28>>2]=o},_localtime_js:function(e,r){var t=new Date(1e3*$[e>>2]);$[r>>2]=t.getSeconds(),$[r+4>>2]=t.getMinutes(),$[r+8>>2]=t.getHours(),$[r+12>>2]=t.getDate(),$[r+16>>2]=t.getMonth(),$[r+20>>2]=t.getFullYear()-1900,$[r+24>>2]=t.getDay();var n=new Date(t.getFullYear(),0,1),o=(t.getTime()-n.getTime())/864e5|0;$[r+28>>2]=o,$[r+36>>2]=-60*t.getTimezoneOffset();var i=new Date(t.getFullYear(),6,1).getTimezoneOffset(),a=n.getTimezoneOffset(),s=0|(i!=a&&t.getTimezoneOffset()==Math.min(a,i));$[r+32>>2]=s},_mktime_js:function(e){var r=new Date($[e+20>>2]+1900,$[e+16>>2],$[e+12>>2],$[e+8>>2],$[e+4>>2],$[e>>2],0),t=$[e+32>>2],n=r.getTimezoneOffset(),o=new Date(r.getFullYear(),0,1),i=new Date(r.getFullYear(),6,1).getTimezoneOffset(),a=o.getTimezoneOffset(),s=Math.min(a,i);if(t<0)$[e+32>>2]=Number(i!=a&&s==n);else if(t>0!=(s==n)){var l=Math.max(a,i),u=t>0?s:l;r.setTime(r.getTime()+6e4*(u-n))}$[e+24>>2]=r.getDay();var c=(r.getTime()-o.getTime())/864e5|0;return $[e+28>>2]=c,$[e>>2]=r.getSeconds(),$[e+4>>2]=r.getMinutes(),$[e+8>>2]=r.getHours(),$[e+12>>2]=r.getDate(),$[e+16>>2]=r.getMonth(),r.getTime()/1e3|0},_tzset_js:function e(r,t,n){e.called||(e.called=!0,function(e,r,t){var n=(new Date).getFullYear(),o=new Date(n,0,1),i=new Date(n,6,1),a=o.getTimezoneOffset(),s=i.getTimezoneOffset(),l=Math.max(a,s);function u(e){var r=e.toTimeString().match(/\(([A-Za-z ]+)\)$/);return r?r[1]:"GMT"}$[e>>2]=60*l,$[r>>2]=Number(a!=s);var c=u(o),d=u(i),f=Q(c),p=Q(d);s<a?($[t>>2]=f,$[t+4>>2]=p):($[t>>2]=p,$[t+4>>2]=f)}(r,t,n))},abort:function(){ge("native code called abort()")},emscripten_log:function(e,r,t){at(e,O(ot(r,t),0))},emscripten_resize_heap:function(e){var r=U.length;F((e>>>=0)>r);var t,n,o=2147483648;if(e>o)return _("Cannot enlarge memory, asked to go up to "+e+" bytes, but the limit is "+"2147483648 bytes!"),!1;for(var i=1;i<=4;i*=2){var a=r*(1+.2/i);a=Math.min(a,e+100663296);var s=Math.min(o,(t=Math.max(e,a))+((n=65536)-t%n)%n);if(st(s))return!0}return _("Failed to grow the heap from "+r+" bytes to "+s+" bytes, not enough memory!"),!1},environ_get:function(e,r){var t=0;return ut().forEach((function(n,o){var i=r+t;$[e+4*o>>2]=i,function(e,r,t){for(var n=0;n<e.length;++n)F(e.charCodeAt(n)===(255&e.charCodeAt(n))),x[r++>>0]=e.charCodeAt(n);t||(x[r>>0]=0)}(n,i),t+=n.length+1})),0},environ_sizes_get:function(e,r){var t=ut();$[e>>2]=t.length;var n=0;return t.forEach((function(e){n+=e.length+1})),$[r>>2]=n,0},fd_close:function(e){try{var r=Le.getStreamFromFD(e);return Ie.close(r),0}catch(e){if(void 0===Ie||!(e instanceof Ie.ErrnoError))throw e;return e.errno}},fd_fdstat_get:function(e,r){try{var t=Le.getStreamFromFD(e),n=t.tty?2:Ie.isDir(t.mode)?3:Ie.isLink(t.mode)?7:4;return x[r>>0]=n,0}catch(e){if(void 0===Ie||!(e instanceof Ie.ErrnoError))throw e;return e.errno}},fd_read:function(e,r,t,n){try{var o=Le.getStreamFromFD(e),i=Le.doReadv(o,r,t);return $[n>>2]=i,0}catch(e){if(void 0===Ie||!(e instanceof Ie.ErrnoError))throw e;return e.errno}},fd_seek:function(e,r,t,n,o){try{var i=Le.getStreamFromFD(e),a=4294967296*t+(r>>>0),s=9007199254740992;return a<=-s||a>=s?-61:(Ie.llseek(i,a,n),Ee=[i.position>>>0,(ye=i.position,+Math.abs(ye)>=1?ye>0?(0|Math.min(+Math.floor(ye/4294967296),4294967295))>>>0:~~+Math.ceil((ye-+(~~ye>>>0))/4294967296)>>>0:0)],$[o>>2]=Ee[0],$[o+4>>2]=Ee[1],i.getdents&&0===a&&0===n&&(i.getdents=null),0)}catch(e){if(void 0===Ie||!(e instanceof Ie.ErrnoError))throw e;return e.errno}},fd_write:function(e,r,t,n){try{var o=Le.getStreamFromFD(e),i=Le.doWritev(o,r,t);return $[n>>2]=i,0}catch(e){if(void 0===Ie||!(e instanceof Ie.ErrnoError))throw e;return e.errno}},setTempRet0:function(e){}};!function(){var e={env:mt,wasi_snapshot_preview1:mt};function t(e,t){var n,o=e.exports;r.asm=o,F(w=r.asm.memory,"memory not found in wasm exports"),Z(w.buffer),F(re=r.asm.__indirect_function_table,"table not found in wasm exports"),n=r.asm.__wasm_call_ctors,ae.unshift(n),he("wasm-instantiate")}me("wasm-instantiate");var n=r;function o(e){F(r===n,"the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?"),n=null,t(e.instance)}function i(r){return function(){if(!E&&(s||l)){if("function"==typeof fetch&&!be(ve))return fetch(ve,{credentials:"same-origin"}).then((function(e){if(!e.ok)throw"failed to load wasm binary file at '"+ve+"'";return e.arrayBuffer()})).catch((function(){return Te(ve)}));if(f)return new Promise((function(e,r){f(ve,(function(r){e(new Uint8Array(r))}),r)}))}return Promise.resolve().then((function(){return Te(ve)}))}().then((function(r){return WebAssembly.instantiate(r,e)})).then((function(e){return e})).then(r,(function(e){_("failed to asynchronously prepare wasm: "+e),be(ve)&&_("warning: Loading from a file URI ("+ve+") is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing"),ge(e)}))}if(r.instantiateWasm)try{return r.instantiateWasm(e,t)}catch(e){return _("Module.instantiateWasm callback failed with error: "+e),!1}E||"function"!=typeof WebAssembly.instantiateStreaming||we(ve)||be(ve)||"function"!=typeof fetch?i(o):fetch(ve,{credentials:"same-origin"}).then((function(r){return WebAssembly.instantiateStreaming(r,e).then(o,(function(e){return _("wasm streaming compile failed: "+e),_("falling back to ArrayBuffer instantiation"),i(o)}))}))}(),r.___wasm_call_ctors=_e("__wasm_call_ctors");var ht=r._free=_e("free"),gt=r._malloc=_e("malloc"),vt=r._strlen=_e("strlen"),yt=r.___errno_location=_e("__errno_location"),Et=r.___getTypeName=_e("__getTypeName");r.___embind_register_native_and_builtin_types=_e("__embind_register_native_and_builtin_types");var wt=r.___stdio_exit=_e("__stdio_exit"),bt=r._emscripten_builtin_memalign=_e("emscripten_builtin_memalign"),_t=r._emscripten_stack_init=function(){return(_t=r._emscripten_stack_init=r.asm.emscripten_stack_init).apply(null,arguments)};r._emscripten_stack_get_free=function(){return(r._emscripten_stack_get_free=r.asm.emscripten_stack_get_free).apply(null,arguments)},r._emscripten_stack_get_base=function(){return(r._emscripten_stack_get_base=r.asm.emscripten_stack_get_base).apply(null,arguments)};var Tt,kt=r._emscripten_stack_get_end=function(){return(kt=r._emscripten_stack_get_end=r.asm.emscripten_stack_get_end).apply(null,arguments)};function St(e){this.name="ExitStatus",this.message="Program terminated with exit("+e+")",this.status=e}function Ct(e){function t(){Tt||(Tt=!0,r.calledRun=!0,A||(oe(),F(!le),le=!0,r.noFSInit||Ie.init.initialized||Ie.init(),Ie.ignorePermissions=!1,ke(ae),r.onRuntimeInitialized&&r.onRuntimeInitialized(),F(!r._main,'compiled without a main, but one is present. if you added it from JS, use Module["onRuntimeInitialized"]'),function(){if(oe(),r.postRun)for("function"==typeof r.postRun&&(r.postRun=[r.postRun]);r.postRun.length;)e=r.postRun.shift(),se.unshift(e);var e;ke(se)}()))}ue>0||(_t(),ne(),function(){if(r.preRun)for("function"==typeof r.preRun&&(r.preRun=[r.preRun]);r.preRun.length;)e=r.preRun.shift(),ie.unshift(e);var e;ke(ie)}(),ue>0||(r.setStatus?(r.setStatus("Running..."),setTimeout((function(){setTimeout((function(){r.setStatus("")}),1),t()}),1)):t(),oe()))}if(r.stackSave=_e("stackSave"),r.stackRestore=_e("stackRestore"),r.stackAlloc=_e("stackAlloc"),r.dynCall_ijiii=_e("dynCall_ijiii"),r.dynCall_viiijj=_e("dynCall_viiijj"),r.dynCall_jij=_e("dynCall_jij"),r.dynCall_jii=_e("dynCall_jii"),r.dynCall_jiji=_e("dynCall_jiji"),r._ff_h264_cabac_tables=112940,P("intArrayFromString",!1),P("intArrayToString",!1),P("ccall",!1),P("cwrap",!1),P("setValue",!1),P("getValue",!1),P("allocate",!1),P("UTF8ArrayToString",!1),P("UTF8ToString",!1),P("stringToUTF8Array",!1),P("stringToUTF8",!1),P("lengthBytesUTF8",!1),P("stackTrace",!1),P("addOnPreRun",!1),P("addOnInit",!1),P("addOnPreMain",!1),P("addOnExit",!1),P("addOnPostRun",!1),P("writeStringToMemory",!1),P("writeArrayToMemory",!1),P("writeAsciiToMemory",!1),P("addRunDependency",!0),P("removeRunDependency",!0),P("FS_createFolder",!1),P("FS_createPath",!0),P("FS_createDataFile",!0),P("FS_createPreloadedFile",!0),P("FS_createLazyFile",!0),P("FS_createLink",!1),P("FS_createDevice",!0),P("FS_unlink",!0),P("getLEB",!1),P("getFunctionTables",!1),P("alignFunctionTables",!1),P("registerFunctions",!1),P("addFunction",!1),P("removeFunction",!1),P("prettyPrint",!1),P("dynCall",!1),P("getCompilerSetting",!1),P("print",!1),P("printErr",!1),P("getTempRet0",!1),P("setTempRet0",!1),P("callMain",!1),P("abort",!1),P("keepRuntimeAlive",!1),P("ptrToString",!1),P("zeroMemory",!1),P("stringToNewUTF8",!1),P("emscripten_realloc_buffer",!1),P("ENV",!1),P("ERRNO_CODES",!1),P("ERRNO_MESSAGES",!1),P("setErrNo",!1),P("inetPton4",!1),P("inetNtop4",!1),P("inetPton6",!1),P("inetNtop6",!1),P("readSockaddr",!1),P("writeSockaddr",!1),P("DNS",!1),P("getHostByName",!1),P("Protocols",!1),P("Sockets",!1),P("getRandomDevice",!1),P("traverseStack",!1),P("UNWIND_CACHE",!1),P("convertPCtoSourceLocation",!1),P("readAsmConstArgsArray",!1),P("readAsmConstArgs",!1),P("mainThreadEM_ASM",!1),P("jstoi_q",!1),P("jstoi_s",!1),P("getExecutableName",!1),P("listenOnce",!1),P("autoResumeAudioContext",!1),P("dynCallLegacy",!1),P("getDynCaller",!1),P("dynCall",!1),P("setWasmTableEntry",!1),P("getWasmTableEntry",!1),P("handleException",!1),P("runtimeKeepalivePush",!1),P("runtimeKeepalivePop",!1),P("callUserCallback",!1),P("maybeExit",!1),P("safeSetTimeout",!1),P("asmjsMangle",!1),P("asyncLoad",!1),P("alignMemory",!1),P("mmapAlloc",!1),P("reallyNegative",!1),P("unSign",!1),P("reSign",!1),P("formatString",!1),P("PATH",!1),P("PATH_FS",!1),P("SYSCALLS",!1),P("getSocketFromFD",!1),P("getSocketAddress",!1),P("JSEvents",!1),P("registerKeyEventCallback",!1),P("specialHTMLTargets",!1),P("maybeCStringToJsString",!1),P("findEventTarget",!1),P("findCanvasEventTarget",!1),P("getBoundingClientRect",!1),P("fillMouseEventData",!1),P("registerMouseEventCallback",!1),P("registerWheelEventCallback",!1),P("registerUiEventCallback",!1),P("registerFocusEventCallback",!1),P("fillDeviceOrientationEventData",!1),P("registerDeviceOrientationEventCallback",!1),P("fillDeviceMotionEventData",!1),P("registerDeviceMotionEventCallback",!1),P("screenOrientation",!1),P("fillOrientationChangeEventData",!1),P("registerOrientationChangeEventCallback",!1),P("fillFullscreenChangeEventData",!1),P("registerFullscreenChangeEventCallback",!1),P("registerRestoreOldStyle",!1),P("hideEverythingExceptGivenElement",!1),P("restoreHiddenElements",!1),P("setLetterbox",!1),P("currentFullscreenStrategy",!1),P("restoreOldWindowedStyle",!1),P("softFullscreenResizeWebGLRenderTarget",!1),P("doRequestFullscreen",!1),P("fillPointerlockChangeEventData",!1),P("registerPointerlockChangeEventCallback",!1),P("registerPointerlockErrorEventCallback",!1),P("requestPointerLock",!1),P("fillVisibilityChangeEventData",!1),P("registerVisibilityChangeEventCallback",!1),P("registerTouchEventCallback",!1),P("fillGamepadEventData",!1),P("registerGamepadEventCallback",!1),P("registerBeforeUnloadEventCallback",!1),P("fillBatteryEventData",!1),P("battery",!1),P("registerBatteryEventCallback",!1),P("setCanvasElementSize",!1),P("getCanvasElementSize",!1),P("demangle",!1),P("demangleAll",!1),P("jsStackTrace",!1),P("stackTrace",!1),P("getEnvStrings",!1),P("checkWasiClock",!1),P("writeI53ToI64",!1),P("writeI53ToI64Clamped",!1),P("writeI53ToI64Signaling",!1),P("writeI53ToU64Clamped",!1),P("writeI53ToU64Signaling",!1),P("readI53FromI64",!1),P("readI53FromU64",!1),P("convertI32PairToI53",!1),P("convertU32PairToI53",!1),P("dlopenMissingError",!1),P("setImmediateWrapped",!1),P("clearImmediateWrapped",!1),P("polyfillSetImmediate",!1),P("uncaughtExceptionCount",!1),P("exceptionLast",!1),P("exceptionCaught",!1),P("ExceptionInfo",!1),P("exception_addRef",!1),P("exception_decRef",!1),P("Browser",!1),P("setMainLoop",!1),P("wget",!1),P("FS",!1),P("MEMFS",!1),P("TTY",!1),P("PIPEFS",!1),P("SOCKFS",!1),P("_setNetworkCallback",!1),P("tempFixedLengthArray",!1),P("miniTempWebGLFloatBuffers",!1),P("heapObjectForWebGLType",!1),P("heapAccessShiftForWebGLHeap",!1),P("GL",!1),P("emscriptenWebGLGet",!1),P("computeUnpackAlignedImageSize",!1),P("emscriptenWebGLGetTexPixelData",!1),P("emscriptenWebGLGetUniform",!1),P("webglGetUniformLocation",!1),P("webglPrepareUniformLocationsBeforeFirstUse",!1),P("webglGetLeftBracePos",!1),P("emscriptenWebGLGetVertexAttrib",!1),P("writeGLArray",!1),P("AL",!1),P("SDL_unicode",!1),P("SDL_ttfContext",!1),P("SDL_audio",!1),P("SDL",!1),P("SDL_gfx",!1),P("GLUT",!1),P("EGL",!1),P("GLFW_Window",!1),P("GLFW",!1),P("GLEW",!1),P("IDBStore",!1),P("runAndAbortIfError",!1),P("InternalError",!1),P("BindingError",!1),P("UnboundTypeError",!1),P("PureVirtualError",!1),P("init_embind",!1),P("throwInternalError",!1),P("throwBindingError",!1),P("throwUnboundTypeError",!1),P("ensureOverloadTable",!1),P("exposePublicSymbol",!1),P("replacePublicSymbol",!1),P("extendError",!1),P("createNamedFunction",!1),P("registeredInstances",!1),P("getBasestPointer",!1),P("registerInheritedInstance",!1),P("unregisterInheritedInstance",!1),P("getInheritedInstance",!1),P("getInheritedInstanceCount",!1),P("getLiveInheritedInstances",!1),P("registeredTypes",!1),P("awaitingDependencies",!1),P("typeDependencies",!1),P("registeredPointers",!1),P("registerType",!1),P("whenDependentTypesAreResolved",!1),P("embind_charCodes",!1),P("embind_init_charCodes",!1),P("readLatin1String",!1),P("getTypeName",!1),P("heap32VectorToArray",!1),P("requireRegisteredType",!1),P("getShiftFromSize",!1),P("integerReadValueFromPointer",!1),P("enumReadValueFromPointer",!1),P("floatReadValueFromPointer",!1),P("simpleReadValueFromPointer",!1),P("runDestructors",!1),P("new_",!1),P("craftInvokerFunction",!1),P("embind__requireFunction",!1),P("tupleRegistrations",!1),P("structRegistrations",!1),P("genericPointerToWireType",!1),P("constNoSmartPtrRawPointerToWireType",!1),P("nonConstNoSmartPtrRawPointerToWireType",!1),P("init_RegisteredPointer",!1),P("RegisteredPointer",!1),P("RegisteredPointer_getPointee",!1),P("RegisteredPointer_destructor",!1),P("RegisteredPointer_deleteObject",!1),P("RegisteredPointer_fromWireType",!1),P("runDestructor",!1),P("releaseClassHandle",!1),P("finalizationRegistry",!1),P("detachFinalizer_deps",!1),P("detachFinalizer",!1),P("attachFinalizer",!1),P("makeClassHandle",!1),P("init_ClassHandle",!1),P("ClassHandle",!1),P("ClassHandle_isAliasOf",!1),P("throwInstanceAlreadyDeleted",!1),P("ClassHandle_clone",!1),P("ClassHandle_delete",!1),P("deletionQueue",!1),P("ClassHandle_isDeleted",!1),P("ClassHandle_deleteLater",!1),P("flushPendingDeletes",!1),P("delayFunction",!1),P("setDelayFunction",!1),P("RegisteredClass",!1),P("shallowCopyInternalPointer",!1),P("downcastPointer",!1),P("upcastPointer",!1),P("validateThis",!1),P("char_0",!1),P("char_9",!1),P("makeLegalFunctionName",!1),P("emval_handle_array",!1),P("emval_free_list",!1),P("emval_symbols",!1),P("init_emval",!1),P("count_emval_handles",!1),P("get_first_emval",!1),P("getStringOrSymbol",!1),P("Emval",!1),P("emval_newers",!1),P("craftEmvalAllocator",!1),P("emval_get_global",!1),P("emval_methodCallers",!1),P("emval_registeredMethods",!1),P("warnOnce",!1),P("stackSave",!1),P("stackRestore",!1),P("stackAlloc",!1),P("AsciiToString",!1),P("stringToAscii",!1),P("UTF16ToString",!1),P("stringToUTF16",!1),P("lengthBytesUTF16",!1),P("UTF32ToString",!1),P("stringToUTF32",!1),P("lengthBytesUTF32",!1),P("allocateUTF8",!1),P("allocateUTF8OnStack",!1),r.writeStackCookie=ne,r.checkStackCookie=oe,C("ALLOC_NORMAL",!1),C("ALLOC_STACK",!1),de=function e(){Tt||Ct(),Tt||(de=e)},r.run=Ct,r.preInit)for("function"==typeof r.preInit&&(r.preInit=[r.preInit]);r.preInit.length>0;)r.preInit.pop()();Ct(),e.exports=r}));const u=1e3,c=1e3,d=!1,f=!1,p=!1,m=!1,h="initVideo",g="render",v="playAudio",y="initAudio",E="audioCode",w="videoCode",b=1,_=2,T="init",k="decode",S="audioDecode",C="videoDecode",P="close",A="updateConfig",F="key",D="delta";s((function(e){!function(){var r="undefined"!=typeof window&&void 0!==window.document?window.document:{},t=e.exports,n=function(){for(var e,t=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError"]],n=0,o=t.length,i={};n<o;n++)if((e=t[n])&&e[1]in r){for(n=0;n<e.length;n++)i[t[0][n]]=e[n];return i}return!1}(),o={change:n.fullscreenchange,error:n.fullscreenerror},i={request:function(e,t){return new Promise(function(o,i){var a=function(){this.off("change",a),o()}.bind(this);this.on("change",a);var s=(e=e||r.documentElement)[n.requestFullscreen](t);s instanceof Promise&&s.then(a).catch(i)}.bind(this))},exit:function(){return new Promise(function(e,t){if(this.isFullscreen){var o=function(){this.off("change",o),e()}.bind(this);this.on("change",o);var i=r[n.exitFullscreen]();i instanceof Promise&&i.then(o).catch(t)}else e()}.bind(this))},toggle:function(e,r){return this.isFullscreen?this.exit():this.request(e,r)},onchange:function(e){this.on("change",e)},onerror:function(e){this.on("error",e)},on:function(e,t){var n=o[e];n&&r.addEventListener(n,t,!1)},off:function(e,t){var n=o[e];n&&r.removeEventListener(n,t,!1)},raw:n};n?(Object.defineProperties(i,{isFullscreen:{get:function(){return Boolean(r[n.fullscreenElement])}},element:{enumerable:!0,get:function(){return r[n.fullscreenElement]}},isEnabled:{enumerable:!0,get:function(){return Boolean(r[n.fullscreenEnabled])}}}),t?e.exports=i:window.screenfull=i):t?e.exports={isEnabled:!1}:window.screenfull={isEnabled:!1}}()})).isEnabled,(()=>{try{if("object"==typeof WebAssembly&&"function"==typeof WebAssembly.instantiate){const e=new WebAssembly.Module(Uint8Array.of(0,97,115,109,1,0,0,0));if(e instanceof WebAssembly.Module)return new WebAssembly.Instance(e)instanceof WebAssembly.Instance}}catch(e){}})(),Date.now||(Date.now=function(){return(new Date).getTime()}),l.postRun=function(){var e=[],r=[],t={};"VideoEncoder"in self&&(t={hasInit:!1,isEmitInfo:!1,offscreenCanvas:null,offscreenCanvasCtx:null,decoder:new VideoDecoder({output:function(e){t.isEmitInfo||(n.opt.debug&&console.log("Jessibuca: [worker] Webcodecs Video Decoder initSize"),postMessage({cmd:h,w:e.codedWidth,h:e.codedHeight}),t.isEmitInfo=!0,t.offscreenCanvas=new OffscreenCanvas(e.codedWidth,e.codedHeight),t.offscreenCanvasCtx=t.offscreenCanvas.getContext("2d")),t.offscreenCanvasCtx.drawImage(e,0,0,e.codedWidth,e.codedHeight);let r=t.offscreenCanvas.transferToImageBitmap();postMessage({cmd:g,buffer:r,delay:n.delay,ts:0},[r]),setTimeout((function(){e.close?e.close():e.destroy()}),100)},error:function(e){console.error(e)}}),decode:function(e,r){const o=e[0]>>4==1;if(t.hasInit){const n=new EncodedVideoChunk({data:e.slice(5),timestamp:r,type:o?F:D});t.decoder.decode(n)}else if(o&&0===e[1]){const r=15&e[0];n.setVideoCodec(r);const o=function(e){let r=e.subarray(1,4),t="avc1.";for(let e=0;e<3;e++){let n=r[e].toString(16);n.length<2&&(n="0"+n),t+=n}return{codec:t,description:e}}(e.slice(5));t.decoder.configure(o),t.hasInit=!0}},reset(){t.hasInit=!1,t.isEmitInfo=!1,t.offscreenCanvas=null,t.offscreenCanvasCtx=null}});var n={opt:{debug:d,useOffscreen:p,useWCS:f,videoBuffer:u,openWebglAlignment:m,videoBufferDelay:c},useOffscreen:function(){return n.opt.useOffscreen&&"undefined"!=typeof OffscreenCanvas},initAudioPlanar:function(e,t){postMessage({cmd:y,sampleRate:t,channels:e});var n=[],o=0;this.playAudioPlanar=function(t,i,a){for(var s=i,u=[],c=0,d=0;d<2;d++){var f=l.HEAPU32[(t>>2)+d]>>2;u[d]=l.HEAPF32.subarray(f,f+s)}if(o){if(!(s>=(i=1024-o)))return o+=s,r[0]=Float32Array.of(...r[0],...u[0]),void(2==e&&(r[1]=Float32Array.of(...r[1],...u[1])));n[0]=Float32Array.of(...r[0],...u[0].subarray(0,i)),2==e&&(n[1]=Float32Array.of(...r[1],...u[1].subarray(0,i))),postMessage({cmd:v,buffer:n,ts:a},n.map((e=>e.buffer))),c=i,s-=i}for(o=s;o>=1024;o-=1024)n[0]=u[0].slice(c,c+=1024),2==e&&(n[1]=u[1].slice(c-1024,c)),postMessage({cmd:v,buffer:n,ts:a},n.map((e=>e.buffer)));o&&(r[0]=u[0].slice(c),2==e&&(r[1]=u[1].slice(c)))}},setVideoCodec:function(e){postMessage({cmd:w,code:e})},setAudioCodec:function(e){postMessage({cmd:E,code:e})},setVideoSize:function(e,r){postMessage({cmd:h,w:e,h:r});var t=e*r,o=t>>2;n.useOffscreen()?(this.offscreenCanvas=new OffscreenCanvas(e,r),this.offscreenCanvasGL=this.offscreenCanvas.getContext("webgl"),this.webglObj=((e,r)=>{var t=["attribute vec4 vertexPos;","attribute vec4 texturePos;","varying vec2 textureCoord;","void main()","{","gl_Position = vertexPos;","textureCoord = texturePos.xy;","}"].join("\n"),n=["precision highp float;","varying highp vec2 textureCoord;","uniform sampler2D ySampler;","uniform sampler2D uSampler;","uniform sampler2D vSampler;","const mat4 YUV2RGB = mat4","(","1.1643828125, 0, 1.59602734375, -.87078515625,","1.1643828125, -.39176171875, -.81296875, .52959375,","1.1643828125, 2.017234375, 0, -1.081390625,","0, 0, 0, 1",");","void main(void) {","highp float y = texture2D(ySampler, textureCoord).r;","highp float u = texture2D(uSampler, textureCoord).r;","highp float v = texture2D(vSampler, textureCoord).r;","gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;","}"].join("\n");r&&e.pixelStorei(e.UNPACK_ALIGNMENT,1);var o=e.createShader(e.VERTEX_SHADER);e.shaderSource(o,t),e.compileShader(o),e.getShaderParameter(o,e.COMPILE_STATUS)||console.log("Vertex shader failed to compile: "+e.getShaderInfoLog(o));var i=e.createShader(e.FRAGMENT_SHADER);e.shaderSource(i,n),e.compileShader(i),e.getShaderParameter(i,e.COMPILE_STATUS)||console.log("Fragment shader failed to compile: "+e.getShaderInfoLog(i));var a=e.createProgram();e.attachShader(a,o),e.attachShader(a,i),e.linkProgram(a),e.getProgramParameter(a,e.LINK_STATUS)||console.log("Program failed to compile: "+e.getProgramInfoLog(a)),e.useProgram(a);var s=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,s),e.bufferData(e.ARRAY_BUFFER,new Float32Array([1,1,-1,1,1,-1,-1,-1]),e.STATIC_DRAW);var l=e.getAttribLocation(a,"vertexPos");e.enableVertexAttribArray(l),e.vertexAttribPointer(l,2,e.FLOAT,!1,0,0);var u=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,u),e.bufferData(e.ARRAY_BUFFER,new Float32Array([1,0,0,0,1,1,0,1]),e.STATIC_DRAW);var c=e.getAttribLocation(a,"texturePos");function d(r,t){var n=e.createTexture();return e.bindTexture(e.TEXTURE_2D,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.bindTexture(e.TEXTURE_2D,null),e.uniform1i(e.getUniformLocation(a,r),t),n}e.enableVertexAttribArray(c),e.vertexAttribPointer(c,2,e.FLOAT,!1,0,0);var f=d("ySampler",0),p=d("uSampler",1),m=d("vSampler",2);return{render:function(r,t,n,o,i){e.viewport(0,0,r,t),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,f),e.texImage2D(e.TEXTURE_2D,0,e.LUMINANCE,r,t,0,e.LUMINANCE,e.UNSIGNED_BYTE,n),e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,p),e.texImage2D(e.TEXTURE_2D,0,e.LUMINANCE,r/2,t/2,0,e.LUMINANCE,e.UNSIGNED_BYTE,o),e.activeTexture(e.TEXTURE2),e.bindTexture(e.TEXTURE_2D,m),e.texImage2D(e.TEXTURE_2D,0,e.LUMINANCE,r/2,t/2,0,e.LUMINANCE,e.UNSIGNED_BYTE,i),e.drawArrays(e.TRIANGLE_STRIP,0,4)},destroy:function(){try{e.deleteProgram(a),e.deleteBuffer(s),e.deleteBuffer(u),e.deleteTexture(f),e.deleteTexture(p),e.deleteTexture(m)}catch(e){}}}})(this.offscreenCanvasGL,n.opt.openWebglAlignment),this.draw=function(n,i,a,s){const u=l.HEAPU8.subarray(i,i+t),c=l.HEAPU8.subarray(a,a+o),d=l.HEAPU8.subarray(s,s+o);this.webglObj.render(e,r,u,c,d);let f=this.offscreenCanvas.transferToImageBitmap();postMessage({cmd:g,buffer:f,delay:this.delay,ts:n},[f])}):this.draw=function(e,r,n,i){const a=[Uint8Array.from(l.HEAPU8.subarray(r,r+t)),Uint8Array.from(l.HEAPU8.subarray(n,n+o)),Uint8Array.from(l.HEAPU8.subarray(i,i+o))];postMessage({cmd:g,output:a,delay:this.delay,ts:e},a.map((e=>e.buffer)))}},getDelay:function(e){if(!e)return-1;if(this.firstTimestamp){if(e){const r=Date.now()-this.startTimestamp,t=e-this.firstTimestamp;this.delay=r>=t?r-t:t-r}}else this.firstTimestamp=e,this.startTimestamp=Date.now(),this.delay=-1;return this.delay},resetDelay:function(){this.firstTimestamp=null,this.startTimestamp=null,this.delay=-1},init:function(){n.opt.debug&&console.log("Jessibuca: [worker] init");const r=e=>{n.opt.useWCS&&n.useOffscreen()&&e.type===_&&t.decode?t.decode(e.payload,e.ts):e.decoder.decode(e.payload,e.ts)};this.stopId=setInterval((()=>{if(e.length)if(this.dropping){for((t=e.shift()).type===b&&0===t.payload[1]&&r(t);!t.isIFrame&&e.length;)(t=e.shift()).type===b&&0===t.payload[1]&&r(t);t.isIFrame&&(this.dropping=!1,r(t))}else{var t=e[0];if(-1===this.getDelay(t.ts))e.shift(),r(t);else if(this.delay>n.opt.videoBuffer+n.opt.videoBufferDelay)this.resetDelay(),this.dropping=!0;else for(;e.length&&(t=e[0],this.getDelay(t.ts)>n.opt.videoBuffer);)e.shift(),r(t)}}),10)},close:function(){n.opt.debug&&console.log("Jessibuca: [worker]: close"),clearInterval(this.stopId),this.stopId=null,o.clear&&o.clear(),i.clear&&i.clear(),t.reset&&t.reset(),this.firstTimestamp=null,this.startTimestamp=null,this.delay=-1,this.dropping=!1,this.webglObj&&(this.webglObj.destroy(),this.offscreenCanvas=null,this.offscreenCanvasGL=null,this.offscreenCanvasCtx=null),e=[],r=[],delete this.playAudioPlanar,delete this.draw},pushBuffer:function(r,t){t.type===b?e.push({ts:t.ts,payload:r,decoder:o,type:b}):t.type===_&&e.push({ts:t.ts,payload:r,decoder:i,type:_,isIFrame:t.isIFrame})}},o=new l.AudioDecoder(n),i=new l.VideoDecoder(n);postMessage({cmd:T}),self.onmessage=function(e){var r=e.data;switch(r.cmd){case T:try{n.opt=Object.assign(n.opt,JSON.parse(r.opt))}catch(e){}o.sample_rate=r.sampleRate,n.init();break;case k:n.pushBuffer(r.buffer,r.options);break;case S:o.decode(r.buffer,r.ts);break;case C:i.decode(r.buffer,r.ts);break;case P:n.close();break;case A:n.opt[r.key]=r.value}}}}));
web_src/static/js/jessibuca/decoder.wasm
No preview for this file type
web_src/static/js/jessibuca/jessibuca.d.ts
@@ -62,7 +62,7 @@ declare namespace Jessibuca { @@ -62,7 +62,7 @@ declare namespace Jessibuca {
62 /** 62 /**
63 * 1. 当为`true`的时候:视频画面做等比缩放后,完全填充canvas区域,画面不被拉伸,没有黑边,但画面显示不全。等同于 `setScaleMode(2)` 63 * 1. 当为`true`的时候:视频画面做等比缩放后,完全填充canvas区域,画面不被拉伸,没有黑边,但画面显示不全。等同于 `setScaleMode(2)`
64 */ 64 */
65 - isFullSize?: boolean; 65 + isFullResize?: boolean;
66 /** 66 /**
67 * 1. 当为`true`的时候:ws协议不检验是否以.flv为依据,进行协议解析。 67 * 1. 当为`true`的时候:ws协议不检验是否以.flv为依据,进行协议解析。
68 */ 68 */
@@ -120,7 +120,7 @@ declare namespace Jessibuca { @@ -120,7 +120,7 @@ declare namespace Jessibuca {
120 /** 120 /**
121 * 加载过程中文案 121 * 加载过程中文案
122 */ 122 */
123 - loadingText?: boolean; 123 + loadingText?: string;
124 /** 124 /**
125 * 背景图片 125 * 背景图片
126 */ 126 */
web_src/static/js/jessibuca/jessibuca.js
1 -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).jessibuca=t()}(this,(function(){"use strict";var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function t(e,t){return e(t={exports:{}},t.exports),t.exports}var i,o=t((function(e){e.exports=function(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e},e.exports.__esModule=!0,e.exports.default=e.exports})),r=(i=o)&&i.__esModule&&Object.prototype.hasOwnProperty.call(i,"default")?i.default:i;const A=0,s=1,n="flv",a="m7s",d={videoBuffer:1e3,isResize:!0,isFullResize:!1,isFlv:!1,debug:!1,hotKey:!1,loadingTimeout:10,heartTimeout:5,timeout:10,loadingTimeoutReplay:!1,heartTimeoutReplay:!1,loadingTimeoutReplayTimes:3,heartTimeoutReplayTimes:3,supportDblclickFullscreen:!1,showBandwidth:!1,keepScreenOn:!1,isNotMute:!1,hasAudio:!0,hasVideo:!0,operateBtns:{fullscreen:!1,screenshot:!1,play:!1,audio:!1,record:!1},controlAutoHide:!1,hasControl:!1,loadingText:"",background:"",decoder:"decoder.js",url:"",rotate:0,forceNoOffscreen:!0,hiddenAutoPause:!1,protocol:s,demuxType:n,useWCS:!1,useMSE:!1,useOffscreen:!1,autoWasm:!0,wasmDecodeErrorReplay:!0,openWebglAlignment:!1},c="init",l="initVideo",u="render",h="playAudio",p="initAudio",m="audioCode",g="videoCode",f="wasmError",b="Invalid NAL unit size",y=1,v=2,w=8,S=9,E="init",B="decode",C="audioDecode",R="close",k="updateConfig",T={fullscreen:"fullscreen$2",webFullscreen:"webFullscreen",decoderWorkerInit:"decoderWorkerInit",play:"play",playing:"playing",pause:"pause",mute:"mute",load:"load",loading:"loading",videoInfo:"videoInfo",timeUpdate:"timeUpdate",audioInfo:"audioInfo",log:"log",error:"error",kBps:"kBps",timeout:"timeout",delayTimeout:"delayTimeout",loadingTimeout:"loadingTimeout",stats:"stats",performance:"performance",record:"record",recording:"recording",recordingTimestamp:"recordingTimestamp",recordStart:"recordStart",recordEnd:"recordEnd",recordCreateError:"recordCreateError",buffer:"buffer",videoFrame:"videoFrame",start:"start",metadata:"metadata",resize:"resize",streamEnd:"streamEnd",streamSuccess:"streamSuccess",streamMessage:"streamMessage",streamError:"streamError",volumechange:"volumechange",destroy:"destroy",mseSourceOpen:"mseSourceOpen",mseSourceClose:"mseSourceClose",mseSourceBufferError:"mseSourceBufferError",mseSourceBufferBusy:"mseSourceBufferBusy",videoWaiting:"videoWaiting",videoTimeUpdate:"videoTimeUpdate",videoSyncAudio:"videoSyncAudio",playToRenderTimes:"playToRenderTimes"},I={load:T.load,timeUpdate:T.timeUpdate,videoInfo:T.videoInfo,audioInfo:T.audioInfo,error:T.error,kBps:T.kBps,log:T.log,start:T.start,timeout:T.timeout,loadingTimeout:T.loadingTimeout,delayTimeout:T.delayTimeout,fullscreen:"fullscreen",play:T.play,pause:T.pause,mute:T.mute,stats:T.stats,performance:T.performance,recordingTimestamp:T.recordingTimestamp,recordStart:T.recordStart,recordEnd:T.recordEnd,playToRenderTimes:T.playToRenderTimes},x={playError:"playIsNotPauseOrUrlIsNull",fetchError:"fetchError",websocketError:"websocketError",webcodecsH265NotSupport:"webcodecsH265NotSupport",mediaSourceH265NotSupport:"mediaSourceH265NotSupport",wasmDecodeError:"wasmDecodeError"},D="notConnect",j="open",L="close",U="error",F={download:"download",base64:"base64",blob:"blob"},V={7:"H264(AVC)",12:"H265(HEVC)"},O=7,M=12,Q={10:"AAC",7:"ALAW",8:"MULAW"},W=32,G=33,J=34,N=0,P=1,z=2,Y="mp4",H="webm",X="webcodecs",Z="webgl",q="offscreen",K="key",_="delta",$='video/mp4; codecs="avc1.64002A"',ee="ended",te="open",ie="closed",oe=1e3,re=27,Ae=38,se=40;class ne{constructor(e){this.log=function(t){if(e._opt.debug){for(var i=arguments.length,o=new Array(i>1?i-1:0),r=1;r<i;r++)o[r-1]=arguments[r];console.log(`Jessibuca: [${t}]`,...o)}},this.warn=function(t){if(e._opt.debug){for(var i=arguments.length,o=new Array(i>1?i-1:0),r=1;r<i;r++)o[r-1]=arguments[r];console.warn(`Jessibuca: [${t}]`,...o)}},this.error=function(t){if(e._opt.debug){for(var i=arguments.length,o=new Array(i>1?i-1:0),r=1;r<i;r++)o[r-1]=arguments[r];console.error(`Jessibuca: [${t}]`,...o)}}}}class ae{constructor(e){this.destroys=[],this.proxy=this.proxy.bind(this),this.master=e}proxy(e,t,i){let o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};if(!e)return;if(Array.isArray(t))return t.map((t=>this.proxy(e,t,i,o)));e.addEventListener(t,i,o);const r=()=>e.removeEventListener(t,i,o);return this.destroys.push(r),r}destroy(){this.master.debug&&this.master.debug.log("Events","destroy"),this.destroys.forEach((e=>e()))}}var de=t((function(e){!function(){var t="undefined"!=typeof window&&void 0!==window.document?window.document:{},i=e.exports,o=function(){for(var e,i=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError"]],o=0,r=i.length,A={};o<r;o++)if((e=i[o])&&e[1]in t){for(o=0;o<e.length;o++)A[i[0][o]]=e[o];return A}return!1}(),r={change:o.fullscreenchange,error:o.fullscreenerror},A={request:function(e,i){return new Promise(function(r,A){var s=function(){this.off("change",s),r()}.bind(this);this.on("change",s);var n=(e=e||t.documentElement)[o.requestFullscreen](i);n instanceof Promise&&n.then(s).catch(A)}.bind(this))},exit:function(){return new Promise(function(e,i){if(this.isFullscreen){var r=function(){this.off("change",r),e()}.bind(this);this.on("change",r);var A=t[o.exitFullscreen]();A instanceof Promise&&A.then(r).catch(i)}else e()}.bind(this))},toggle:function(e,t){return this.isFullscreen?this.exit():this.request(e,t)},onchange:function(e){this.on("change",e)},onerror:function(e){this.on("error",e)},on:function(e,i){var o=r[e];o&&t.addEventListener(o,i,!1)},off:function(e,i){var o=r[e];o&&t.removeEventListener(o,i,!1)},raw:o};o?(Object.defineProperties(A,{isFullscreen:{get:function(){return Boolean(t[o.fullscreenElement])}},element:{enumerable:!0,get:function(){return t[o.fullscreenElement]}},isEnabled:{enumerable:!0,get:function(){return Boolean(t[o.fullscreenEnabled])}}}),i?e.exports=A:window.screenfull=A):i?e.exports={isEnabled:!1}:window.screenfull={isEnabled:!1}}()}));function ce(){}function le(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";const t=e.split(","),i=atob(t[1]),o=t[0].replace("data:","").replace(";base64","");let r=i.length,A=new Uint8Array(r);for(;r--;)A[r]=i.charCodeAt(r);return new File([A],"file",{type:o})}function ue(e,t){const i=document.createElement("a");i.download=t,i.href=URL.createObjectURL(e),i.click(),setTimeout((()=>{URL.revokeObjectURL(e)}),ve()?1e3:0)}function he(){return(new Date).getTime()}function pe(e,t,i){return Math.max(Math.min(e,Math.max(t,i)),Math.min(t,i))}function me(e,t,i){if(e)return"object"==typeof t&&Object.keys(t).forEach((i=>{me(e,i,t[i])})),e.style[t]=i,e}function ge(e,t){let i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(!e)return 0;const o=getComputedStyle(e,null).getPropertyValue(t);return i?parseFloat(o):o}function fe(){return performance&&"function"==typeof performance.now?performance.now():Date.now()}function be(e){let t=0,i=fe();return o=>{t+=o;const r=fe(),A=r-i;A>=1e3&&(e(t/A*1e3),i=r,t=0)}}function ye(){return/iphone|ipod|android.*mobile|windows.*phone|blackberry.*mobile/i.test(window.navigator.userAgent.toLowerCase())}function ve(){const e=window.navigator.userAgent.toLowerCase();return e&&/iphone|ipad|ipod|ios/.test(e)}function we(e){if(null==e||""===e)return"0 KB/S";let t=parseFloat(e);return t=t.toFixed(2),t+"KB/S"}function Se(e){return null==e}function Ee(e){return!Se(e)}de.isEnabled,(()=>{try{if("object"==typeof WebAssembly&&"function"==typeof WebAssembly.instantiate){const e=new WebAssembly.Module(Uint8Array.of(0,97,115,109,1,0,0,0));if(e instanceof WebAssembly.Module)return new WebAssembly.Instance(e)instanceof WebAssembly.Instance}}catch(e){}})();class Be{on(e,t,i){const o=this.e||(this.e={});return(o[e]||(o[e]=[])).push({fn:t,ctx:i}),this}once(e,t,i){const o=this;function r(){o.off(e,r);for(var A=arguments.length,s=new Array(A),n=0;n<A;n++)s[n]=arguments[n];t.apply(i,s)}return r._=t,this.on(e,r,i)}emit(e){const t=((this.e||(this.e={}))[e]||[]).slice();for(var i=arguments.length,o=new Array(i>1?i-1:0),r=1;r<i;r++)o[r-1]=arguments[r];for(let e=0;e<t.length;e+=1)t[e].fn.apply(t[e].ctx,o);return this}off(e,t){const i=this.e||(this.e={});if(!e)return Object.keys(i).forEach((e=>{delete i[e]})),void delete this.e;const o=i[e],r=[];if(o&&t)for(let e=0,i=o.length;e<i;e+=1)o[e].fn!==t&&o[e].fn._!==t&&r.push(o[e]);return r.length?i[e]=r:delete i[e],this}}class Ce extends Be{constructor(){super(),this.init=!1}updateVideoInfo(e){e.encTypeCode&&(this.videoInfo.encType=V[e.encTypeCode]),e.width&&(this.videoInfo.width=e.width),e.height&&(this.videoInfo.height=e.height),this.videoInfo.encType&&this.videoInfo.height&&this.videoInfo.width&&!this.init&&(this.player.emit(T.videoInfo,this.videoInfo),this.init=!0)}}class Re extends Ce{constructor(e){super(),this.player=e;const t=document.createElement("canvas");t.style.position="absolute",t.style.top=0,t.style.left=0,this.$videoElement=t,e.$container.appendChild(this.$videoElement),this.context2D=null,this.contextGl=null,this.contextGlRender=null,this.contextGlDestroy=null,this.bitmaprenderer=null,this.renderType=null,this.videoInfo={width:"",height:"",encType:""},this._initCanvasRender(),this.player.debug.log("CanvasVideo","init")}destroy(){this.contextGl&&(this.contextGl=null),this.context2D&&(this.context2D=null),this.contextGlRender&&(this.contextGlDestroy&&this.contextGlDestroy(),this.contextGlDestroy=null,this.contextGlRender=null),this.bitmaprenderer&&(this.bitmaprenderer=null),this.renderType=null,this.videoInfo={width:"",height:"",encType:"",encTypeCode:""},this.player.$container.removeChild(this.$videoElement),this.init=!1,this.off(),this.player.debug.log("CanvasVideoLoader","destroy")}_initContextGl(){this.contextGl=function(e){let t=null;const i=["webgl","experimental-webgl","moz-webgl","webkit-3d"];let o=0;for(;!t&&o<i.length;){const r=i[o];try{let i={preserveDrawingBuffer:!0};t=e.getContext(r,i)}catch(e){t=null}t&&"function"==typeof t.getParameter||(t=null),++o}return t}(this.$videoElement);const e=((e,t)=>{var i=["attribute vec4 vertexPos;","attribute vec4 texturePos;","varying vec2 textureCoord;","void main()","{","gl_Position = vertexPos;","textureCoord = texturePos.xy;","}"].join("\n"),o=["precision highp float;","varying highp vec2 textureCoord;","uniform sampler2D ySampler;","uniform sampler2D uSampler;","uniform sampler2D vSampler;","const mat4 YUV2RGB = mat4","(","1.1643828125, 0, 1.59602734375, -.87078515625,","1.1643828125, -.39176171875, -.81296875, .52959375,","1.1643828125, 2.017234375, 0, -1.081390625,","0, 0, 0, 1",");","void main(void) {","highp float y = texture2D(ySampler, textureCoord).r;","highp float u = texture2D(uSampler, textureCoord).r;","highp float v = texture2D(vSampler, textureCoord).r;","gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;","}"].join("\n");t&&e.pixelStorei(e.UNPACK_ALIGNMENT,1);var r=e.createShader(e.VERTEX_SHADER);e.shaderSource(r,i),e.compileShader(r),e.getShaderParameter(r,e.COMPILE_STATUS)||console.log("Vertex shader failed to compile: "+e.getShaderInfoLog(r));var A=e.createShader(e.FRAGMENT_SHADER);e.shaderSource(A,o),e.compileShader(A),e.getShaderParameter(A,e.COMPILE_STATUS)||console.log("Fragment shader failed to compile: "+e.getShaderInfoLog(A));var s=e.createProgram();e.attachShader(s,r),e.attachShader(s,A),e.linkProgram(s),e.getProgramParameter(s,e.LINK_STATUS)||console.log("Program failed to compile: "+e.getProgramInfoLog(s)),e.useProgram(s);var n=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,n),e.bufferData(e.ARRAY_BUFFER,new Float32Array([1,1,-1,1,1,-1,-1,-1]),e.STATIC_DRAW);var a=e.getAttribLocation(s,"vertexPos");e.enableVertexAttribArray(a),e.vertexAttribPointer(a,2,e.FLOAT,!1,0,0);var d=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,d),e.bufferData(e.ARRAY_BUFFER,new Float32Array([1,0,0,0,1,1,0,1]),e.STATIC_DRAW);var c=e.getAttribLocation(s,"texturePos");function l(t,i){var o=e.createTexture();return e.bindTexture(e.TEXTURE_2D,o),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.bindTexture(e.TEXTURE_2D,null),e.uniform1i(e.getUniformLocation(s,t),i),o}e.enableVertexAttribArray(c),e.vertexAttribPointer(c,2,e.FLOAT,!1,0,0);var u=l("ySampler",0),h=l("uSampler",1),p=l("vSampler",2);return{render:function(t,i,o,r,A){e.viewport(0,0,t,i),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,u),e.texImage2D(e.TEXTURE_2D,0,e.LUMINANCE,t,i,0,e.LUMINANCE,e.UNSIGNED_BYTE,o),e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,h),e.texImage2D(e.TEXTURE_2D,0,e.LUMINANCE,t/2,i/2,0,e.LUMINANCE,e.UNSIGNED_BYTE,r),e.activeTexture(e.TEXTURE2),e.bindTexture(e.TEXTURE_2D,p),e.texImage2D(e.TEXTURE_2D,0,e.LUMINANCE,t/2,i/2,0,e.LUMINANCE,e.UNSIGNED_BYTE,A),e.drawArrays(e.TRIANGLE_STRIP,0,4)},destroy:function(){try{e.deleteProgram(s),e.deleteBuffer(n),e.deleteBuffer(d),e.deleteTexture(u),e.deleteTexture(h),e.deleteBuffer(p)}catch(e){}}}})(this.contextGl,this.player._opt.openWebglAlignment);this.contextGlRender=e.render,this.contextGlDestroy=e.destroy}_initContext2D(){this.context2D=this.$videoElement.getContext("2d")}_initCanvasRender(){this.player._opt.useWCS&&!this._supportOffscreen()?(this.renderType=X,this._initContext2D()):this._supportOffscreen()?(this.renderType=q,this._bindOffscreen()):(this.renderType=Z,this._initContextGl())}_supportOffscreen(){return"function"==typeof this.$videoElement.transferControlToOffscreen&&this.player._opt.useOffscreen}_bindOffscreen(){this.bitmaprenderer=this.$videoElement.getContext("bitmaprenderer")}initCanvasViewSize(){this.$videoElement.width=this.videoInfo.width,this.$videoElement.height=this.videoInfo.height,this.resize()}render(e){switch(this.player.videoTimestamp=e.ts,this.renderType){case q:this.bitmaprenderer.transferFromImageBitmap(e.buffer);break;case Z:this.contextGlRender(this.$videoElement.width,this.$videoElement.height,e.output[0],e.output[1],e.output[2]);break;case X:this.context2D.drawImage(e.videoFrame,0,0,this.$videoElement.width,this.$videoElement.height)}}screenshot(e,t,i,o){e=e||he(),o=o||F.download;const r={png:"image/png",jpeg:"image/jpeg",webp:"image/webp"};let A=.92;!r[t]&&F[t]&&(o=t,t="png",i=void 0),"string"==typeof i&&(o=i,i=void 0),void 0!==i&&(A=Number(i));const s=this.$videoElement.toDataURL(r[t]||r.png,A),n=le(s);return o===F.base64?s:o===F.blob?n:void(o===F.download&&ue(n,e))}clearView(){switch(this.renderType){case q:(function(e,t){const i=document.createElement("canvas");return i.width=e,i.height=t,createImageBitmap(i,0,0,e,t)})(this.$videoElement.width,this.$videoElement.height).then((e=>{this.bitmaprenderer.transferFromImageBitmap(e)}));break;case Z:this.contextGl.clear(this.contextGl.COLOR_BUFFER_BIT);break;case X:this.context2D.clearRect(0,0,this.$videoElement.width,this.$videoElement.height)}}resize(){this.player.debug.log("canvasVideo","resize");const e=this.player._opt;let t=this.player.width,i=this.player.height;e.hasControl&&!e.controlAutoHide&&(ye()&&this.player.fullscreen?t-=38:i-=38);let o=this.$videoElement.width,r=this.$videoElement.height;const A=e.rotate;let s=(t-o)/2,n=(i-r)/2;270!==A&&90!==A||(o=this.$videoElement.height,r=this.$videoElement.width);const a=t/o,d=i/r;let c=a>d?d:a;e.isResize||a!==d&&(c=a+","+d),e.isFullResize&&(c=a>d?a:d);let l="scale("+c+")";A&&(l+=" rotate("+A+"deg)"),this.$videoElement.style.transform=l,this.$videoElement.style.left=s+"px",this.$videoElement.style.top=n+"px"}}class ke extends Ce{constructor(e){super(),this.player=e;const t=document.createElement("video");t.muted=!0,t.style.position="absolute",t.style.top=0,t.style.left=0,e.$container.appendChild(t),this.$videoElement=t,this.videoInfo={width:"",height:"",encType:""},this.resize();const{proxy:i}=this.player.events;i(this.$videoElement,"canplay",(()=>{this.player.debug.log("Video","canplay")})),i(this.$videoElement,"waiting",(()=>{this.player.emit(T.videoWaiting)})),i(this.$videoElement,"timeupdate",(e=>{})),this.player.debug.log("Video","init")}destroy(){this.player.$container.removeChild(this.$videoElement),this.$videoElement=null,this.init=!1,this.off(),this.player.debug.log("Video","destroy")}play(){this.$videoElement.play()}clearView(){}screenshot(e,t,i,o){e=e||he(),o=o||F.download;let r=.92;!{png:"image/png",jpeg:"image/jpeg",webp:"image/webp"}[t]&&F[t]&&(o=t,t="png",i=void 0),"string"==typeof i&&(o=i,i=void 0),void 0!==i&&(r=Number(i));const A=this.$videoElement;let s=document.createElement("canvas");s.width=A.videoWidth,s.height=A.videoHeight;s.getContext("2d").drawImage(A,0,0,s.width,s.height);const n=s.toDataURL(F[t]||F.png,r),a=le(n);return o===F.base64?n:o===F.blob?a:void(o===F.download&&ue(a,e))}initCanvasViewSize(){this.resize()}resize(){let e=this.player.width,t=this.player.height;const i=this.player._opt,o=i.rotate;i.hasControl&&!i.controlAutoHide&&(ye()&&this.player.fullscreen?e-=38:t-=38),this.$videoElement.width=e,this.$videoElement.height=t,270!==o&&90!==o||(this.$videoElement.width=t,this.$videoElement.height=e);let r=(e-this.$videoElement.width)/2,A=(t-this.$videoElement.height)/2,s="contain";i.isResize||(s="fill"),i.isFullResize&&(s="none"),this.$videoElement.style.objectFit=s,this.$videoElement.style.transform="rotate("+o+"deg)",this.$videoElement.style.left=r+"px",this.$videoElement.style.top=A+"px"}}class Te{constructor(e){return new(Te.getLoaderFactory(e._opt))(e)}static getLoaderFactory(e){return e.useMSE?ke:Re}}class Ie extends Be{constructor(e){super(),this.bufferList=[],this.player=e,this.scriptNode=null,this.hasInitScriptNode=!1,this.audioContextChannel=null,this.audioContext=new(window.AudioContext||window.webkitAudioContext),this.gainNode=this.audioContext.createGain();const t=this.audioContext.createBufferSource();t.buffer=this.audioContext.createBuffer(1,1,22050),t.connect(this.audioContext.destination),t.noteOn?t.noteOn(0):t.start(0),this.audioBufferSourceNode=t,this.mediaStreamAudioDestinationNode=this.audioContext.createMediaStreamDestination(),this.audioEnabled(!0),this.gainNode.gain.value=0,this.playing=!1,this.audioSyncVideoOption={diff:null},this.audioInfo={encType:"",channels:"",sampleRate:""},this.init=!1,this.hasAudio=!1,this.on(T.videoSyncAudio,(e=>{this.audioSyncVideoOption=e})),this.player.debug.log("AudioContext","init")}destroy(){this.closeAudio(),this.audioContext.close(),this.audioContext=null,this.gainNode=null,this.init=!1,this.hasAudio=!1,this.playing=!1,this.scriptNode&&(this.scriptNode.onaudioprocess=ce,this.scriptNode=null),this.audioBufferSourceNode=null,this.mediaStreamAudioDestinationNode=null,this.hasInitScriptNode=!1,this.audioSyncVideoOption={diff:null},this.audioInfo={encType:"",channels:"",sampleRate:""},this.off(),this.player.debug.log("AudioContext","destroy")}updateAudioInfo(e){e.encTypeCode&&(this.audioInfo.encType=Q[e.encTypeCode]),e.channels&&(this.audioInfo.channels=e.channels),e.sampleRate&&(this.audioInfo.sampleRate=e.sampleRate),this.audioInfo.sampleRate&&this.audioInfo.channels&&this.audioInfo.encType&&!this.init&&(this.player.emit(T.audioInfo,this.audioInfo),this.init=!0)}get isPlaying(){return this.playing}get isMute(){return 0===this.gainNode.gain.value||this.isStateSuspended()}get volume(){return this.gainNode.gain.value}get bufferSize(){return this.bufferList.length}initScriptNode(){if(this.playing=!0,this.hasInitScriptNode)return;const e=this.audioInfo.channels,t=this.audioContext.createScriptProcessor(1024,0,e);t.onaudioprocess=t=>{const i=t.outputBuffer;if(this.bufferList.length&&this.playing){if(!this.player._opt.useWCS&&!this.player._opt.useMSE){if(this.audioSyncVideoOption.diff>oe)return void this.player.debug.warn("AudioContext",`audioSyncVideoOption more than diff :${this.audioSyncVideoOption.diff}, waiting`);if(this.audioSyncVideoOption.diff<-1e3){this.player.debug.warn("AudioContext",`audioSyncVideoOption less than diff :${this.audioSyncVideoOption.diff}, dropping`);let e=this.bufferList.shift();for(;e.ts-this.player.videoTimestamp<-1e3&&this.bufferList.length>0;)e=this.bufferList.shift();if(0===this.bufferList.length)return}}if(0===this.bufferList.length)return;const t=this.bufferList.shift();t&&t.ts&&(this.player.audioTimestamp=t.ts);for(let o=0;o<e;o++){const e=t.buffer[o],r=i.getChannelData(o);for(let t=0;t<1024;t++)r[t]=e[t]||0}}},t.connect(this.gainNode),this.scriptNode=t,this.gainNode.connect(this.audioContext.destination),this.gainNode.connect(this.mediaStreamAudioDestinationNode),this.hasInitScriptNode=!0}mute(e){e?(this.isMute||this.player.emit(T.mute,e),this.setVolume(0),this.audioEnabled(!1),this.clear()):(this.isMute&&this.player.emit(T.mute,e),this.setVolume(.5),this.audioEnabled(!0))}setVolume(e){e=parseFloat(e).toFixed(2),isNaN(e)||(this.audioEnabled(!0),e=pe(e,0,1),this.gainNode.gain.value=e,this.gainNode.gain.setValueAtTime(e,this.audioContext.currentTime),this.player.emit(T.volumechange,this.player.volume))}closeAudio(){this.hasInitScriptNode&&(this.scriptNode&&this.scriptNode.disconnect(this.gainNode),this.gainNode&&this.gainNode.disconnect(this.audioContext.destination),this.gainNode&&this.gainNode.disconnect(this.mediaStreamAudioDestinationNode)),this.clear()}audioEnabled(e){e?"suspended"===this.audioContext.state&&this.audioContext.resume():"running"===this.audioContext.state&&this.audioContext.suspend()}isStateRunning(){return"running"===this.audioContext.state}isStateSuspended(){return"suspended"===this.audioContext.state}clear(){this.bufferList=[]}play(e,t){this.isMute||(this.hasAudio=!0,this.bufferList.push({buffer:e,ts:t}),this.bufferList.length>20&&(this.player.debug.warn("AudioContext",`bufferList is large: ${this.bufferList.length}`),this.bufferList.length>50&&this.bufferList.shift()))}pause(){this.audioSyncVideoOption={diff:null},this.playing=!1,this.clear()}resume(){this.playing=!0}}class xe{constructor(e){return new(xe.getLoaderFactory())(e)}static getLoaderFactory(){return Ie}}class De extends Be{constructor(e){super(),this.player=e,this.playing=!1,this.abortController=new AbortController,this.streamRate=be((t=>{e.emit(T.kBps,(t/1024).toFixed(2))})),e.debug.log("FetchStream","init")}destroy(){this.abort(),this.off(),this.streamRate=null,this.player.debug.log("FetchStream","destroy")}fetchStream(e){const{demux:t}=this.player;this.player._times.streamStart=he(),fetch(e,{signal:this.abortController.signal}).then((e=>{const i=e.body.getReader();this.emit(T.streamSuccess);const o=()=>{i.read().then((e=>{let{done:i,value:r}=e;i?t.close():(this.streamRate&&this.streamRate(r.byteLength),t.dispatch(r),o())})).catch((e=>{t.close(),this.emit(x.fetchError,e),this.player.emit(T.error,x.fetchError),this.abort()}))};o()})).catch((e=>{this.abort(),this.emit(x.fetchError,e),this.player.emit(T.error,x.fetchError)}))}abort(){this.abortController&&(this.abortController.abort(),this.abortController=null)}}class je extends Be{constructor(e){super(),this.player=e,this.socket=null,this.socketStatus=D,this.wsUrl=null,this.streamRate=be((t=>{e.emit(T.kBps,(t/1024).toFixed(2))}))}destroy(){this.socket&&(this.socket.close(),this.socket=null),this.socketStatus=D,this.streamRate=null,this.wsUrl=null,this.off(),this.player.debug.log("websocketLoader","destroy")}_createWebSocket(){const e=this.player,{debug:t,events:{proxy:i},demux:o}=e;this.socket=new WebSocket(this.wsUrl),this.socket.binaryType="arraybuffer",i(this.socket,"open",(()=>{this.emit(T.streamSuccess),t.log("websocketLoader","socket open"),this.socketStatus=j})),i(this.socket,"message",(e=>{this.streamRate&&this.streamRate(e.data.byteLength),this._handleMessage(e.data)})),i(this.socket,"close",(()=>{t.log("websocketLoader","socket close"),this.emit(T.streamEnd),this.socketStatus=L})),i(this.socket,"error",(e=>{t.log("websocketLoader","socket error"),this.emit(x.websocketError,e),this.player.emit(T.error,x.websocketError),this.socketStatus=U,o.close(),t.log("websocketLoader","socket error:",e)}))}_handleMessage(e){const{demux:t}=this.player;t?t.dispatch(e):this.player.debug.warn("websocketLoader","websocket handle message demux is null")}fetchStream(e){this.player._times.streamStart=he(),this.wsUrl=e,this._createWebSocket()}}class Le{constructor(e){return new(Le.getLoaderFactory(e._opt.protocol))(e)}static getLoaderFactory(e){return e===s?De:e===A?je:void 0}}var Ue=t((function(t){function i(e,t){if(!e)throw"First parameter is required.";t=new o(e,t=t||{type:"video"});var A=this;function s(i){i&&(t.initCallback=function(){i(),i=t.initCallback=null});var o=new r(e,t);(h=new o(e,t)).record(),u("recording"),t.disableLogs||console.log("Initialized recorderType:",h.constructor.name,"for output-type:",t.type)}function n(e){if(e=e||function(){},h){if("paused"===A.state)return A.resumeRecording(),void setTimeout((function(){n(e)}),1);"recording"===A.state||t.disableLogs||console.warn('Recording state should be: "recording", however current state is: ',A.state),t.disableLogs||console.log("Stopped recording "+t.type+" stream."),"gif"!==t.type?h.stop(i):(h.stop(),i()),u("stopped")}else m();function i(i){if(h){Object.keys(h).forEach((function(e){"function"!=typeof h[e]&&(A[e]=h[e])}));var o=h.blob;if(!o){if(!i)throw"Recording failed.";h.blob=o=i}if(o&&!t.disableLogs&&console.log(o.type,"->",b(o.size)),e){var r;try{r=l.createObjectURL(o)}catch(e){}"function"==typeof e.call?e.call(A,r):e(r)}t.autoWriteToDisk&&d((function(e){var i={};i[t.type+"Blob"]=e,x.Store(i)}))}else"function"==typeof e.call?e.call(A,""):e("")}}function a(e){postMessage((new FileReaderSync).readAsDataURL(e))}function d(e,i){if(!e)throw"Pass a callback function over getDataURL.";var o=i?i.blob:(h||{}).blob;if(!o)return t.disableLogs||console.warn("Blob encoder did not finish its job yet."),void setTimeout((function(){d(e,i)}),1e3);if("undefined"==typeof Worker||navigator.mozGetUserMedia){var r=new FileReader;r.readAsDataURL(o),r.onload=function(t){e(t.target.result)}}else{var A=function(e){try{var t=l.createObjectURL(new Blob([e.toString(),"this.onmessage = function (eee) {"+e.name+"(eee.data);}"],{type:"application/javascript"})),i=new Worker(t);return l.revokeObjectURL(t),i}catch(e){}}(a);A.onmessage=function(t){e(t.data)},A.postMessage(o)}}function c(e){e=e||0,"paused"!==A.state?"stopped"!==A.state&&(e>=A.recordingDuration?n(A.onRecordingStopped):(e+=1e3,setTimeout((function(){c(e)}),1e3))):setTimeout((function(){c(e)}),1e3)}function u(e){A&&(A.state=e,"function"==typeof A.onStateChanged.call?A.onStateChanged.call(A,e):A.onStateChanged(e))}var h,p='It seems that recorder is destroyed or "startRecording" is not invoked for '+t.type+" recorder.";function m(){!0!==t.disableLogs&&console.warn(p)}var g={startRecording:function(i){return t.disableLogs||console.log("RecordRTC version: ",A.version),i&&(t=new o(e,i)),t.disableLogs||console.log("started recording "+t.type+" stream."),h?(h.clearRecordedData(),h.record(),u("recording"),A.recordingDuration&&c(),A):(s((function(){A.recordingDuration&&c()})),A)},stopRecording:n,pauseRecording:function(){h?"recording"===A.state?(u("paused"),h.pause(),t.disableLogs||console.log("Paused recording.")):t.disableLogs||console.warn("Unable to pause the recording. Recording state: ",A.state):m()},resumeRecording:function(){h?"paused"===A.state?(u("recording"),h.resume(),t.disableLogs||console.log("Resumed recording.")):t.disableLogs||console.warn("Unable to resume the recording. Recording state: ",A.state):m()},initRecorder:s,setRecordingDuration:function(e,t){if(void 0===e)throw"recordingDuration is required.";if("number"!=typeof e)throw"recordingDuration must be a number.";return A.recordingDuration=e,A.onRecordingStopped=t||function(){},{onRecordingStopped:function(e){A.onRecordingStopped=e}}},clearRecordedData:function(){h?(h.clearRecordedData(),t.disableLogs||console.log("Cleared old recorded data.")):m()},getBlob:function(){if(h)return h.blob;m()},getDataURL:d,toURL:function(){if(h)return l.createObjectURL(h.blob);m()},getInternalRecorder:function(){return h},save:function(e){h?y(h.blob,e):m()},getFromDisk:function(e){h?i.getFromDisk(t.type,e):m()},setAdvertisementArray:function(e){t.advertisement=[];for(var i=e.length,o=0;o<i;o++)t.advertisement.push({duration:o,image:e[o]})},blob:null,bufferSize:0,sampleRate:0,buffer:null,reset:function(){"recording"!==A.state||t.disableLogs||console.warn("Stop an active recorder."),h&&"function"==typeof h.clearRecordedData&&h.clearRecordedData(),h=null,u("inactive"),A.blob=null},onStateChanged:function(e){t.disableLogs||console.log("Recorder state changed:",e)},state:"inactive",getState:function(){return A.state},destroy:function(){var e=t.disableLogs;t={disableLogs:!0},A.reset(),u("destroyed"),g=A=null,E.AudioContextConstructor&&(E.AudioContextConstructor.close(),E.AudioContextConstructor=null),t.disableLogs=e,t.disableLogs||console.log("RecordRTC is destroyed.")},version:"5.6.2"};if(!this)return A=g,g;for(var f in g)this[f]=g[f];return A=this,g}function o(e,t){return t.recorderType||t.type||(t.audio&&t.video?t.type="video":t.audio&&!t.video&&(t.type="audio")),t.recorderType&&!t.type&&(t.recorderType===T||t.recorderType===k||t.recorderType===U?t.type="video":t.recorderType===D?t.type="gif":t.recorderType===R?t.type="audio":t.recorderType===C&&(w(e,"audio").length&&w(e,"video").length||!w(e,"audio").length&&w(e,"video").length?t.type="video":w(e,"audio").length&&!w(e,"video").length&&(t.type="audio"))),"undefined"!=typeof MediaRecorder&&"requestData"in MediaRecorder.prototype&&(t.mimeType||(t.mimeType="video/webm"),t.type||(t.type=t.mimeType.split("/")[0]),t.bitsPerSecond),t.type||(t.mimeType&&(t.type=t.mimeType.split("/")[0]),t.type||(t.type="audio")),t}function r(e,t){var i;return(m||u||h)&&(i=R),"undefined"!=typeof MediaRecorder&&"requestData"in MediaRecorder.prototype&&!m&&(i=C),"video"===t.type&&(m||h)&&(i=T,"undefined"!=typeof ReadableStream&&(i=U)),"gif"===t.type&&(i=D),"canvas"===t.type&&(i=k),B()&&i!==k&&i!==D&&"undefined"!=typeof MediaRecorder&&"requestData"in MediaRecorder.prototype&&(w(e,"video").length||w(e,"audio").length)&&("audio"===t.type?"function"==typeof MediaRecorder.isTypeSupported&&MediaRecorder.isTypeSupported("audio/webm")&&(i=C):"function"==typeof MediaRecorder.isTypeSupported&&MediaRecorder.isTypeSupported("video/webm")&&(i=C)),e instanceof Array&&e.length&&(i=L),t.recorderType&&(i=t.recorderType),!t.disableLogs&&i&&i.name&&console.log("Using recorderType:",i.name||i.constructor.name),!i&&g&&(i=C),i}function A(e){this.addStream=function(t){t&&(e=t)},this.mediaType={audio:!0,video:!0},this.startRecording=function(){var t,o=this.mediaType,r=this.mimeType||{audio:null,video:null,gif:null};if("function"!=typeof o.audio&&B()&&!w(e,"audio").length&&(o.audio=!1),"function"!=typeof o.video&&B()&&!w(e,"video").length&&(o.video=!1),"function"!=typeof o.gif&&B()&&!w(e,"video").length&&(o.gif=!1),!o.audio&&!o.video&&!o.gif)throw"MediaStream must have either audio or video tracks.";if(o.audio&&(t=null,"function"==typeof o.audio&&(t=o.audio),this.audioRecorder=new i(e,{type:"audio",bufferSize:this.bufferSize,sampleRate:this.sampleRate,numberOfAudioChannels:this.numberOfAudioChannels||2,disableLogs:this.disableLogs,recorderType:t,mimeType:r.audio,timeSlice:this.timeSlice,onTimeStamp:this.onTimeStamp}),o.video||this.audioRecorder.startRecording()),o.video){t=null,"function"==typeof o.video&&(t=o.video);var A=e;if(B()&&o.audio&&"function"==typeof o.audio){var s=w(e,"video")[0];p?((A=new f).addTrack(s),t&&t===T&&(t=C)):(A=new f).addTrack(s)}this.videoRecorder=new i(A,{type:"video",video:this.video,canvas:this.canvas,frameInterval:this.frameInterval||10,disableLogs:this.disableLogs,recorderType:t,mimeType:r.video,timeSlice:this.timeSlice,onTimeStamp:this.onTimeStamp,workerPath:this.workerPath,webAssemblyPath:this.webAssemblyPath,frameRate:this.frameRate,bitrate:this.bitrate}),o.audio||this.videoRecorder.startRecording()}if(o.audio&&o.video){var n=this,a=!0===B();(o.audio instanceof R&&o.video||!0!==o.audio&&!0!==o.video&&o.audio!==o.video)&&(a=!1),!0===a?(n.audioRecorder=null,n.videoRecorder.startRecording()):n.videoRecorder.initRecorder((function(){n.audioRecorder.initRecorder((function(){n.videoRecorder.startRecording(),n.audioRecorder.startRecording()}))}))}o.gif&&(t=null,"function"==typeof o.gif&&(t=o.gif),this.gifRecorder=new i(e,{type:"gif",frameRate:this.frameRate||200,quality:this.quality||10,disableLogs:this.disableLogs,recorderType:t,mimeType:r.gif}),this.gifRecorder.startRecording())},this.stopRecording=function(e){e=e||function(){},this.audioRecorder&&this.audioRecorder.stopRecording((function(t){e(t,"audio")})),this.videoRecorder&&this.videoRecorder.stopRecording((function(t){e(t,"video")})),this.gifRecorder&&this.gifRecorder.stopRecording((function(t){e(t,"gif")}))},this.pauseRecording=function(){this.audioRecorder&&this.audioRecorder.pauseRecording(),this.videoRecorder&&this.videoRecorder.pauseRecording(),this.gifRecorder&&this.gifRecorder.pauseRecording()},this.resumeRecording=function(){this.audioRecorder&&this.audioRecorder.resumeRecording(),this.videoRecorder&&this.videoRecorder.resumeRecording(),this.gifRecorder&&this.gifRecorder.resumeRecording()},this.getBlob=function(e){var t={};return this.audioRecorder&&(t.audio=this.audioRecorder.getBlob()),this.videoRecorder&&(t.video=this.videoRecorder.getBlob()),this.gifRecorder&&(t.gif=this.gifRecorder.getBlob()),e&&e(t),t},this.destroy=function(){this.audioRecorder&&(this.audioRecorder.destroy(),this.audioRecorder=null),this.videoRecorder&&(this.videoRecorder.destroy(),this.videoRecorder=null),this.gifRecorder&&(this.gifRecorder.destroy(),this.gifRecorder=null)},this.getDataURL=function(e){function t(e,t){if("undefined"!=typeof Worker){var i=function(e){var t,i=l.createObjectURL(new Blob([e.toString(),"this.onmessage = function (eee) {"+e.name+"(eee.data);}"],{type:"application/javascript"})),o=new Worker(i);if(void 0!==l)t=l;else{if("undefined"==typeof webkitURL)throw"Neither URL nor webkitURL detected.";t=webkitURL}return t.revokeObjectURL(i),o}((function(e){postMessage((new FileReaderSync).readAsDataURL(e))}));i.onmessage=function(e){t(e.data)},i.postMessage(e)}else{var o=new FileReader;o.readAsDataURL(e),o.onload=function(e){t(e.target.result)}}}this.getBlob((function(i){i.audio&&i.video?t(i.audio,(function(o){t(i.video,(function(t){e({audio:o,video:t})}))})):i.audio?t(i.audio,(function(t){e({audio:t})})):i.video&&t(i.video,(function(t){e({video:t})}))}))},this.writeToDisk=function(){i.writeToDisk({audio:this.audioRecorder,video:this.videoRecorder,gif:this.gifRecorder})},this.save=function(e){(e=e||{audio:!0,video:!0,gif:!0}).audio&&this.audioRecorder&&this.audioRecorder.save("string"==typeof e.audio?e.audio:""),e.video&&this.videoRecorder&&this.videoRecorder.save("string"==typeof e.video?e.video:""),e.gif&&this.gifRecorder&&this.gifRecorder.save("string"==typeof e.gif?e.gif:"")}}i.version="5.6.2",t.exports=i,i.getFromDisk=function(e,t){if(!t)throw"callback is mandatory.";console.log("Getting recorded "+("all"===e?"blobs":e+" blob ")+" from disk!"),x.Fetch((function(i,o){"all"!==e&&o===e+"Blob"&&t&&t(i),"all"===e&&t&&t(i,o.replace("Blob",""))}))},i.writeToDisk=function(e){console.log("Writing recorded blob(s) to disk!"),(e=e||{}).audio&&e.video&&e.gif?e.audio.getDataURL((function(t){e.video.getDataURL((function(i){e.gif.getDataURL((function(e){x.Store({audioBlob:t,videoBlob:i,gifBlob:e})}))}))})):e.audio&&e.video?e.audio.getDataURL((function(t){e.video.getDataURL((function(e){x.Store({audioBlob:t,videoBlob:e})}))})):e.audio&&e.gif?e.audio.getDataURL((function(t){e.gif.getDataURL((function(e){x.Store({audioBlob:t,gifBlob:e})}))})):e.video&&e.gif?e.video.getDataURL((function(t){e.gif.getDataURL((function(e){x.Store({videoBlob:t,gifBlob:e})}))})):e.audio?e.audio.getDataURL((function(e){x.Store({audioBlob:e})})):e.video?e.video.getDataURL((function(e){x.Store({videoBlob:e})})):e.gif&&e.gif.getDataURL((function(e){x.Store({gifBlob:e})}))},A.getFromDisk=i.getFromDisk,A.writeToDisk=i.writeToDisk,i.MRecordRTC=A;var s;(s=void 0!==e?e:null)&&"undefined"==typeof window&&void 0!==e&&(e.navigator={userAgent:"Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45",getUserMedia:function(){}},e.console||(e.console={}),void 0!==e.console.log&&void 0!==e.console.error||(e.console.error=e.console.log=e.console.log||function(){console.log(arguments)}),"undefined"==typeof document&&(s.document={documentElement:{appendChild:function(){return""}}},document.createElement=document.captureStream=document.mozCaptureStream=function(){var e={getContext:function(){return e},play:function(){},pause:function(){},drawImage:function(){},toDataURL:function(){return""},style:{}};return e},s.HTMLVideoElement=function(){}),"undefined"==typeof location&&(s.location={protocol:"file:",href:"",hash:""}),"undefined"==typeof screen&&(s.screen={width:0,height:0}),void 0===l&&(s.URL={createObjectURL:function(){return""},revokeObjectURL:function(){return""}}),s.window=e);var n=window.requestAnimationFrame;if(void 0===n)if("undefined"!=typeof webkitRequestAnimationFrame)n=webkitRequestAnimationFrame;else if("undefined"!=typeof mozRequestAnimationFrame)n=mozRequestAnimationFrame;else if("undefined"!=typeof msRequestAnimationFrame)n=msRequestAnimationFrame;else if(void 0===n){var a=0;n=function(e,t){var i=(new Date).getTime(),o=Math.max(0,16-(i-a)),r=setTimeout((function(){e(i+o)}),o);return a=i+o,r}}var d=window.cancelAnimationFrame;void 0===d&&("undefined"!=typeof webkitCancelAnimationFrame?d=webkitCancelAnimationFrame:"undefined"!=typeof mozCancelAnimationFrame?d=mozCancelAnimationFrame:"undefined"!=typeof msCancelAnimationFrame?d=msCancelAnimationFrame:void 0===d&&(d=function(e){clearTimeout(e)}));var c=window.AudioContext;void 0===c&&("undefined"!=typeof webkitAudioContext&&(c=webkitAudioContext),"undefined"!=typeof mozAudioContext&&(c=mozAudioContext));var l=window.URL;void 0===l&&"undefined"!=typeof webkitURL&&(l=webkitURL),"undefined"!=typeof navigator&&void 0===navigator.getUserMedia&&(void 0!==navigator.webkitGetUserMedia&&(navigator.getUserMedia=navigator.webkitGetUserMedia),void 0!==navigator.mozGetUserMedia&&(navigator.getUserMedia=navigator.mozGetUserMedia));var u=!(-1===navigator.userAgent.indexOf("Edge")||!navigator.msSaveBlob&&!navigator.msSaveOrOpenBlob),h=!!window.opera||-1!==navigator.userAgent.indexOf("OPR/"),p=navigator.userAgent.toLowerCase().indexOf("firefox")>-1&&"netscape"in window&&/ rv:/.test(navigator.userAgent),m=!h&&!u&&!!navigator.webkitGetUserMedia||v()||-1!==navigator.userAgent.toLowerCase().indexOf("chrome/"),g=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);g&&!m&&-1!==navigator.userAgent.indexOf("CriOS")&&(g=!1,m=!0);var f=window.MediaStream;function b(e){if(0===e)return"0 Bytes";var t=parseInt(Math.floor(Math.log(e)/Math.log(1e3)),10);return(e/Math.pow(1e3,t)).toPrecision(3)+" "+["Bytes","KB","MB","GB","TB"][t]}function y(e,t){if(!e)throw"Blob object is required.";if(!e.type)try{e.type="video/webm"}catch(e){}var i=(e.type||"video/webm").split("/")[1];if(-1!==i.indexOf(";")&&(i=i.split(";")[0]),t&&-1!==t.indexOf(".")){var o=t.split(".");t=o[0],i=o[1]}var r=(t||Math.round(9999999999*Math.random())+888888888)+"."+i;if(void 0!==navigator.msSaveOrOpenBlob)return navigator.msSaveOrOpenBlob(e,r);if(void 0!==navigator.msSaveBlob)return navigator.msSaveBlob(e,r);var A=document.createElement("a");A.href=l.createObjectURL(e),A.download=r,A.style="display:none;opacity:0;color:transparent;",(document.body||document.documentElement).appendChild(A),"function"==typeof A.click?A.click():(A.target="_blank",A.dispatchEvent(new MouseEvent("click",{view:window,bubbles:!0,cancelable:!0}))),l.revokeObjectURL(A.href)}function v(){return"undefined"!=typeof window&&"object"==typeof window.process&&"renderer"===window.process.type||(!("undefined"==typeof process||"object"!=typeof process.versions||!process.versions.electron)||"object"==typeof navigator&&"string"==typeof navigator.userAgent&&navigator.userAgent.indexOf("Electron")>=0)}function w(e,t){return e&&e.getTracks?e.getTracks().filter((function(e){return e.kind===(t||"audio")})):[]}function S(e,t){"srcObject"in t?t.srcObject=e:"mozSrcObject"in t?t.mozSrcObject=e:t.srcObject=e}void 0===f&&"undefined"!=typeof webkitMediaStream&&(f=webkitMediaStream),void 0!==f&&void 0===f.prototype.stop&&(f.prototype.stop=function(){this.getTracks().forEach((function(e){e.stop()}))}),i.invokeSaveAsDialog=y,i.getTracks=w,i.getSeekableBlob=function(e,t){if("undefined"==typeof EBML)throw new Error("Please link: https://www.webrtc-experiment.com/EBML.js");var i=new EBML.Reader,o=new EBML.Decoder,r=EBML.tools,A=new FileReader;A.onload=function(e){o.decode(this.result).forEach((function(e){i.read(e)})),i.stop();var A=r.makeMetadataSeekable(i.metadatas,i.duration,i.cues),s=this.result.slice(i.metadataSize),n=new Blob([A,s],{type:"video/webm"});t(n)},A.readAsArrayBuffer(e)},i.bytesToSize=b,i.isElectron=v;var E={};function B(){if(p||g||u)return!0;var e,t,i=navigator.userAgent,o=""+parseFloat(navigator.appVersion),r=parseInt(navigator.appVersion,10);return(m||h)&&(e=i.indexOf("Chrome"),o=i.substring(e+7)),-1!==(t=o.indexOf(";"))&&(o=o.substring(0,t)),-1!==(t=o.indexOf(" "))&&(o=o.substring(0,t)),r=parseInt(""+o,10),isNaN(r)&&(o=""+parseFloat(navigator.appVersion),r=parseInt(navigator.appVersion,10)),r>=49}function C(e,t){var i=this;if(void 0===e)throw'First argument "MediaStream" is required.';if("undefined"==typeof MediaRecorder)throw"Your browser does not support the Media Recorder API. Please try other modules e.g. WhammyRecorder or StereoAudioRecorder.";if("audio"===(t=t||{mimeType:"video/webm"}).type){var o;if(w(e,"video").length&&w(e,"audio").length)navigator.mozGetUserMedia?(o=new f).addTrack(w(e,"audio")[0]):o=new f(w(e,"audio")),e=o;t.mimeType&&-1!==t.mimeType.toString().toLowerCase().indexOf("audio")||(t.mimeType=m?"audio/webm":"audio/ogg"),t.mimeType&&"audio/ogg"!==t.mimeType.toString().toLowerCase()&&navigator.mozGetUserMedia&&(t.mimeType="audio/ogg")}var r,A=[];function s(){i.timestamps.push((new Date).getTime()),"function"==typeof t.onTimeStamp&&t.onTimeStamp(i.timestamps[i.timestamps.length-1],i.timestamps)}function n(e){return r&&r.mimeType?r.mimeType:e.mimeType||"video/webm"}function a(){A=[],r=null,i.timestamps=[]}this.getArrayOfBlobs=function(){return A},this.record=function(){i.blob=null,i.clearRecordedData(),i.timestamps=[],d=[],A=[];var o=t;t.disableLogs||console.log("Passing following config over MediaRecorder API.",o),r&&(r=null),m&&!B()&&(o="video/vp8"),"function"==typeof MediaRecorder.isTypeSupported&&o.mimeType&&(MediaRecorder.isTypeSupported(o.mimeType)||(t.disableLogs||console.warn("MediaRecorder API seems unable to record mimeType:",o.mimeType),o.mimeType="audio"===t.type?"audio/webm":"video/webm"));try{r=new MediaRecorder(e,o),t.mimeType=o.mimeType}catch(t){r=new MediaRecorder(e)}o.mimeType&&!MediaRecorder.isTypeSupported&&"canRecordMimeType"in r&&!1===r.canRecordMimeType(o.mimeType)&&(t.disableLogs||console.warn("MediaRecorder API seems unable to record mimeType:",o.mimeType)),r.ondataavailable=function(e){if(e.data&&d.push("ondataavailable: "+b(e.data.size)),"number"!=typeof t.timeSlice)!e.data||!e.data.size||e.data.size<100||i.blob?i.recordingCallback&&(i.recordingCallback(new Blob([],{type:n(o)})),i.recordingCallback=null):(i.blob=t.getNativeBlob?e.data:new Blob([e.data],{type:n(o)}),i.recordingCallback&&(i.recordingCallback(i.blob),i.recordingCallback=null));else if(e.data&&e.data.size&&(A.push(e.data),s(),"function"==typeof t.ondataavailable)){var r=t.getNativeBlob?e.data:new Blob([e.data],{type:n(o)});t.ondataavailable(r)}},r.onstart=function(){d.push("started")},r.onpause=function(){d.push("paused")},r.onresume=function(){d.push("resumed")},r.onstop=function(){d.push("stopped")},r.onerror=function(e){e&&(e.name||(e.name="UnknownError"),d.push("error: "+e),t.disableLogs||(-1!==e.name.toString().toLowerCase().indexOf("invalidstate")?console.error("The MediaRecorder is not in a state in which the proposed operation is allowed to be executed.",e):-1!==e.name.toString().toLowerCase().indexOf("notsupported")?console.error("MIME type (",o.mimeType,") is not supported.",e):-1!==e.name.toString().toLowerCase().indexOf("security")?console.error("MediaRecorder security error",e):"OutOfMemory"===e.name?console.error("The UA has exhaused the available memory. User agents SHOULD provide as much additional information as possible in the message attribute.",e):"IllegalStreamModification"===e.name?console.error("A modification to the stream has occurred that makes it impossible to continue recording. An example would be the addition of a Track while recording is occurring. User agents SHOULD provide as much additional information as possible in the message attribute.",e):"OtherRecordingError"===e.name?console.error("Used for an fatal error other than those listed above. User agents SHOULD provide as much additional information as possible in the message attribute.",e):"GenericError"===e.name?console.error("The UA cannot provide the codec or recording option that has been requested.",e):console.error("MediaRecorder Error",e)),function(e){if(!i.manuallyStopped&&r&&"inactive"===r.state)return delete t.timeslice,void r.start(6e5);setTimeout(void 0,1e3)}(),"inactive"!==r.state&&"stopped"!==r.state&&r.stop())},"number"==typeof t.timeSlice?(s(),r.start(t.timeSlice)):r.start(36e5),t.initCallback&&t.initCallback()},this.timestamps=[],this.stop=function(e){e=e||function(){},i.manuallyStopped=!0,r&&(this.recordingCallback=e,"recording"===r.state&&r.stop(),"number"==typeof t.timeSlice&&setTimeout((function(){i.blob=new Blob(A,{type:n(t)}),i.recordingCallback(i.blob)}),100))},this.pause=function(){r&&"recording"===r.state&&r.pause()},this.resume=function(){r&&"paused"===r.state&&r.resume()},this.clearRecordedData=function(){r&&"recording"===r.state&&i.stop(a),a()},this.getInternalRecorder=function(){return r},this.blob=null,this.getState=function(){return r&&r.state||"inactive"};var d=[];this.getAllStates=function(){return d},void 0===t.checkForInactiveTracks&&(t.checkForInactiveTracks=!1);i=this;!function o(){if(r&&!1!==t.checkForInactiveTracks)return!1===function(){if("active"in e){if(!e.active)return!1}else if("ended"in e&&e.ended)return!1;return!0}()?(t.disableLogs||console.log("MediaStream seems stopped."),void i.stop()):void setTimeout(o,1e3)}(),this.name="MediaStreamRecorder",this.toString=function(){return this.name}}function R(e,t){if(!w(e,"audio").length)throw"Your stream has no audio tracks.";var o,r=this,A=[],s=[],n=!1,a=0,d=2,c=(t=t||{}).desiredSampRate;function u(){if(!1===t.checkForInactiveTracks)return!0;if("active"in e){if(!e.active)return!1}else if("ended"in e&&e.ended)return!1;return!0}function h(e,t){function i(e,t){var i,o=e.numberOfAudioChannels,r=e.leftBuffers.slice(0),A=e.rightBuffers.slice(0),s=e.sampleRate,n=e.internalInterleavedLength,a=e.desiredSampRate;function d(e,t,i){var o=Math.round(e.length*(t/i)),r=[],A=Number((e.length-1)/(o-1));r[0]=e[0];for(var s=1;s<o-1;s++){var n=s*A,a=Number(Math.floor(n)).toFixed(),d=Number(Math.ceil(n)).toFixed(),l=n-a;r[s]=c(e[a],e[d],l)}return r[o-1]=e[e.length-1],r}function c(e,t,i){return e+(t-e)*i}function l(e,t){for(var i=new Float64Array(t),o=0,r=e.length,A=0;A<r;A++){var s=e[A];i.set(s,o),o+=s.length}return i}function u(e,t,i){for(var o=i.length,r=0;r<o;r++)e.setUint8(t+r,i.charCodeAt(r))}2===o&&(r=l(r,n),A=l(A,n),a&&(r=d(r,a,s),A=d(A,a,s))),1===o&&(r=l(r,n),a&&(r=d(r,a,s))),a&&(s=a),2===o&&(i=function(e,t){for(var i=e.length+t.length,o=new Float64Array(i),r=0,A=0;A<i;)o[A++]=e[r],o[A++]=t[r],r++;return o}(r,A)),1===o&&(i=r);var h=i.length,p=new ArrayBuffer(44+2*h),m=new DataView(p);u(m,0,"RIFF"),m.setUint32(4,36+2*h,!0),u(m,8,"WAVE"),u(m,12,"fmt "),m.setUint32(16,16,!0),m.setUint16(20,1,!0),m.setUint16(22,o,!0),m.setUint32(24,s,!0),m.setUint32(28,s*o*2,!0),m.setUint16(32,2*o,!0),m.setUint16(34,16,!0),u(m,36,"data"),m.setUint32(40,2*h,!0);for(var g=h,f=44,b=0;b<g;b++)m.setInt16(f,32767*i[b],!0),f+=2;if(t)return t({buffer:p,view:m});postMessage({buffer:p,view:m})}if(e.noWorker)i(e,(function(e){t(e.buffer,e.view)}));else{var o,r,A,s=(o=i,r=l.createObjectURL(new Blob([o.toString(),";this.onmessage = function (eee) {"+o.name+"(eee.data);}"],{type:"application/javascript"})),(A=new Worker(r)).workerURL=r,A);s.onmessage=function(e){t(e.data.buffer,e.data.view),l.revokeObjectURL(s.workerURL),s.terminate()},s.postMessage(e)}}!0===t.leftChannel&&(d=1),1===t.numberOfAudioChannels&&(d=1),(!d||d<1)&&(d=2),t.disableLogs||console.log("StereoAudioRecorder is set to record number of channels: "+d),void 0===t.checkForInactiveTracks&&(t.checkForInactiveTracks=!0),this.record=function(){if(!1===u())throw"Please make sure MediaStream is active.";v(),E=y=!1,n=!0,void 0!==t.timeSlice&&C()},this.stop=function(e){e=e||function(){},n=!1,h({desiredSampRate:c,sampleRate:b,numberOfAudioChannels:d,internalInterleavedLength:a,leftBuffers:A,rightBuffers:1===d?[]:s,noWorker:t.noWorker},(function(t,i){r.blob=new Blob([i],{type:"audio/wav"}),r.buffer=new ArrayBuffer(i.buffer.byteLength),r.view=i,r.sampleRate=c||b,r.bufferSize=f,r.length=a,E=!1,e&&e(r.blob)}))},void 0===i.Storage&&(i.Storage={AudioContextConstructor:null,AudioContext:window.AudioContext||window.webkitAudioContext}),i.Storage.AudioContextConstructor&&"closed"!==i.Storage.AudioContextConstructor.state||(i.Storage.AudioContextConstructor=new i.Storage.AudioContext);var p=i.Storage.AudioContextConstructor,m=p.createMediaStreamSource(e),g=[0,256,512,1024,2048,4096,8192,16384],f=void 0===t.bufferSize?4096:t.bufferSize;if(-1===g.indexOf(f)&&(t.disableLogs||console.log("Legal values for buffer-size are "+JSON.stringify(g,null,"\t"))),p.createJavaScriptNode)o=p.createJavaScriptNode(f,d,d);else{if(!p.createScriptProcessor)throw"WebAudio API has no support on this browser.";o=p.createScriptProcessor(f,d,d)}m.connect(o),t.bufferSize||(f=o.bufferSize);var b=void 0!==t.sampleRate?t.sampleRate:p.sampleRate||44100;(b<22050||b>96e3)&&(t.disableLogs||console.log("sample-rate must be under range 22050 and 96000.")),t.disableLogs||t.desiredSampRate&&console.log("Desired sample-rate: "+t.desiredSampRate);var y=!1;function v(){A=[],s=[],a=0,E=!1,n=!1,y=!1,p=null,r.leftchannel=A,r.rightchannel=s,r.numberOfAudioChannels=d,r.desiredSampRate=c,r.sampleRate=b,r.recordingLength=a,B={left:[],right:[],recordingLength:0}}function S(){o&&(o.onaudioprocess=null,o.disconnect(),o=null),m&&(m.disconnect(),m=null),v()}this.pause=function(){y=!0},this.resume=function(){if(!1===u())throw"Please make sure MediaStream is active.";if(!n)return t.disableLogs||console.log("Seems recording has been restarted."),void this.record();y=!1},this.clearRecordedData=function(){t.checkForInactiveTracks=!1,n&&this.stop(S),S()},this.name="StereoAudioRecorder",this.toString=function(){return this.name};var E=!1;o.onaudioprocess=function(e){if(!y)if(!1===u()&&(t.disableLogs||console.log("MediaStream seems stopped."),o.disconnect(),n=!1),n){E||(E=!0,t.onAudioProcessStarted&&t.onAudioProcessStarted(),t.initCallback&&t.initCallback());var i=e.inputBuffer.getChannelData(0),c=new Float32Array(i);if(A.push(c),2===d){var l=e.inputBuffer.getChannelData(1),h=new Float32Array(l);s.push(h)}a+=f,r.recordingLength=a,void 0!==t.timeSlice&&(B.recordingLength+=f,B.left.push(c),2===d&&B.right.push(h))}else m&&(m.disconnect(),m=null)},p.createMediaStreamDestination?o.connect(p.createMediaStreamDestination()):o.connect(p.destination),this.leftchannel=A,this.rightchannel=s,this.numberOfAudioChannels=d,this.desiredSampRate=c,this.sampleRate=b,r.recordingLength=a;var B={left:[],right:[],recordingLength:0};function C(){n&&"function"==typeof t.ondataavailable&&void 0!==t.timeSlice&&(B.left.length?(h({desiredSampRate:c,sampleRate:b,numberOfAudioChannels:d,internalInterleavedLength:B.recordingLength,leftBuffers:B.left,rightBuffers:1===d?[]:B.right},(function(e,i){var o=new Blob([i],{type:"audio/wav"});t.ondataavailable(o),setTimeout(C,t.timeSlice)})),B={left:[],right:[],recordingLength:0}):setTimeout(C,t.timeSlice))}}function k(e,t){if("undefined"==typeof html2canvas)throw"Please link: https://www.webrtc-experiment.com/screenshot.js";(t=t||{}).frameInterval||(t.frameInterval=10);var i=!1;["captureStream","mozCaptureStream","webkitCaptureStream"].forEach((function(e){e in document.createElement("canvas")&&(i=!0)}));var o,r,A,s=!(!window.webkitRTCPeerConnection&&!window.webkitGetUserMedia||!window.chrome),n=50,a=navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);if(s&&a&&a[2]&&(n=parseInt(a[2],10)),s&&n<52&&(i=!1),t.useWhammyRecorder&&(i=!1),i)if(t.disableLogs||console.log("Your browser supports both MediRecorder API and canvas.captureStream!"),e instanceof HTMLCanvasElement)o=e;else{if(!(e instanceof CanvasRenderingContext2D))throw"Please pass either HTMLCanvasElement or CanvasRenderingContext2D.";o=e.canvas}else navigator.mozGetUserMedia&&(t.disableLogs||console.error("Canvas recording is NOT supported in Firefox."));this.record=function(){if(A=!0,i&&!t.useWhammyRecorder){var e;"captureStream"in o?e=o.captureStream(25):"mozCaptureStream"in o?e=o.mozCaptureStream(25):"webkitCaptureStream"in o&&(e=o.webkitCaptureStream(25));try{var s=new f;s.addTrack(w(e,"video")[0]),e=s}catch(e){}if(!e)throw"captureStream API are NOT available.";(r=new C(e,{mimeType:t.mimeType||"video/webm"})).record()}else h.frames=[],u=(new Date).getTime(),l();t.initCallback&&t.initCallback()},this.getWebPImages=function(i){if("canvas"===e.nodeName.toLowerCase()){var o=h.frames.length;h.frames.forEach((function(e,i){var r=o-i;t.disableLogs||console.log(r+"/"+o+" frames remaining"),t.onEncodingCallback&&t.onEncodingCallback(r,o);var A=e.image.toDataURL("image/webp",1);h.frames[i].image=A})),t.disableLogs||console.log("Generating WebM"),i()}else i()},this.stop=function(e){A=!1;var o=this;i&&r?r.stop(e):this.getWebPImages((function(){h.compile((function(i){t.disableLogs||console.log("Recording finished!"),o.blob=i,o.blob.forEach&&(o.blob=new Blob([],{type:"video/webm"})),e&&e(o.blob),h.frames=[]}))}))};var d=!1;function c(){h.frames=[],A=!1,d=!1}function l(){if(d)return u=(new Date).getTime(),setTimeout(l,500);if("canvas"===e.nodeName.toLowerCase()){var i=(new Date).getTime()-u;return u=(new Date).getTime(),h.frames.push({image:(o=document.createElement("canvas"),r=o.getContext("2d"),o.width=e.width,o.height=e.height,r.drawImage(e,0,0),o),duration:i}),void(A&&setTimeout(l,t.frameInterval))}var o,r;html2canvas(e,{grabMouse:void 0===t.showMousePointer||t.showMousePointer,onrendered:function(e){var i=(new Date).getTime()-u;if(!i)return setTimeout(l,t.frameInterval);u=(new Date).getTime(),h.frames.push({image:e.toDataURL("image/webp",1),duration:i}),A&&setTimeout(l,t.frameInterval)}})}this.pause=function(){d=!0,r instanceof C&&r.pause()},this.resume=function(){d=!1,r instanceof C?r.resume():A||this.record()},this.clearRecordedData=function(){A&&this.stop(c),c()},this.name="CanvasRecorder",this.toString=function(){return this.name};var u=(new Date).getTime(),h=new I.Video(100)}function T(e,t){function i(e){e=void 0!==e?e:10;var t=(new Date).getTime()-a;return t?A?(a=(new Date).getTime(),setTimeout(i,100)):(a=(new Date).getTime(),n.paused&&n.play(),l.drawImage(n,0,0,c.width,c.height),d.frames.push({duration:t,image:c.toDataURL("image/webp")}),void(r||setTimeout(i,e,e))):setTimeout(i,e,e)}function o(e,t,i,o,r){var A=document.createElement("canvas");A.width=c.width,A.height=c.height;var s,n,a,d=A.getContext("2d"),l=[],u=-1===t,h=t&&t>0&&t<=e.length?t:e.length,p=0,m=0,g=0,f=Math.sqrt(Math.pow(255,2)+Math.pow(255,2)+Math.pow(255,2)),b=i&&i>=0&&i<=1?i:0,y=o&&o>=0&&o<=1?o:0,v=!1;n=-1,a=(s={length:h,functionToLoop:function(t,i){var o,r,A,s=function(){!v&&A-o<=A*y||(u&&(v=!0),l.push(e[i])),t()};if(v)s();else{var n=new Image;n.onload=function(){d.drawImage(n,0,0,c.width,c.height);var e=d.getImageData(0,0,c.width,c.height);o=0,r=e.data.length,A=e.data.length/4;for(var t=0;t<r;t+=4){var i={r:e.data[t],g:e.data[t+1],b:e.data[t+2]};Math.sqrt(Math.pow(i.r-p,2)+Math.pow(i.g-m,2)+Math.pow(i.b-g,2))<=f*b&&o++}s()},n.src=e[i].image}},callback:function(){(l=l.concat(e.slice(h))).length<=0&&l.push(e[e.length-1]),r(l)}}).length,function e(){++n!==a?setTimeout((function(){s.functionToLoop(e,n)}),1):s.callback()}()}(t=t||{}).frameInterval||(t.frameInterval=10),t.disableLogs||console.log("Using frames-interval:",t.frameInterval),this.record=function(){t.width||(t.width=320),t.height||(t.height=240),t.video||(t.video={width:t.width,height:t.height}),t.canvas||(t.canvas={width:t.width,height:t.height}),c.width=t.canvas.width||320,c.height=t.canvas.height||240,l=c.getContext("2d"),t.video&&t.video instanceof HTMLVideoElement?(n=t.video.cloneNode(),t.initCallback&&t.initCallback()):(n=document.createElement("video"),S(e,n),n.onloadedmetadata=function(){t.initCallback&&t.initCallback()},n.width=t.video.width,n.height=t.video.height),n.muted=!0,n.play(),a=(new Date).getTime(),d=new I.Video,t.disableLogs||(console.log("canvas resolutions",c.width,"*",c.height),console.log("video width/height",n.width||c.width,"*",n.height||c.height)),i(t.frameInterval)};var r=!1;this.stop=function(e){e=e||function(){},r=!0;var i=this;setTimeout((function(){o(d.frames,-1,null,null,(function(o){d.frames=o,t.advertisement&&t.advertisement.length&&(d.frames=t.advertisement.concat(d.frames)),d.compile((function(t){i.blob=t,i.blob.forEach&&(i.blob=new Blob([],{type:"video/webm"})),e&&e(i.blob)}))}))}),10)};var A=!1;function s(){d.frames=[],r=!0,A=!1}this.pause=function(){A=!0},this.resume=function(){A=!1,r&&this.record()},this.clearRecordedData=function(){r||this.stop(s),s()},this.name="WhammyRecorder",this.toString=function(){return this.name};var n,a,d,c=document.createElement("canvas"),l=c.getContext("2d")}void 0!==c?E.AudioContext=c:"undefined"!=typeof webkitAudioContext&&(E.AudioContext=webkitAudioContext),i.Storage=E,i.MediaStreamRecorder=C,i.StereoAudioRecorder=R,i.CanvasRecorder=k,i.WhammyRecorder=T;var I=function(){function e(e){this.frames=[],this.duration=e||1,this.quality=.8}function t(e){function t(e,t,i){return[{data:e,id:231}].concat(i.map((function(e){var i=function(e){var t=0;e.keyframe&&(t|=128);e.invisible&&(t|=8);e.lacing&&(t|=e.lacing<<1);e.discardable&&(t|=1);if(e.trackNum>127)throw"TrackNumber > 127 not supported";return[128|e.trackNum,e.timecode>>8,255&e.timecode,t].map((function(e){return String.fromCharCode(e)})).join("")+e.frame}({discardable:0,frame:e.data.slice(4),invisible:0,keyframe:1,lacing:0,trackNum:1,timecode:Math.round(t)});return t+=e.duration,{data:i,id:163}})))}function i(e){for(var t=[];e>0;)t.push(255&e),e>>=8;return new Uint8Array(t.reverse())}function o(e){var t=[];e=(e.length%8?new Array(9-e.length%8).join("0"):"")+e;for(var i=0;i<e.length;i+=8)t.push(parseInt(e.substr(i,8),2));return new Uint8Array(t)}function r(e){for(var t=[],A=0;A<e.length;A++){var s=e[A].data;"object"==typeof s&&(s=r(s)),"number"==typeof s&&(s=o(s.toString(2))),"string"==typeof s&&(s=new Uint8Array(s.split("").map((function(e){return e.charCodeAt(0)}))));var n=s.size||s.byteLength||s.length,a=Math.ceil(Math.ceil(Math.log(n)/Math.log(2))/8),d=n.toString(2),c=new Array(7*a+7+1-d.length).join("0")+d,l=new Array(a).join("0")+"1"+c;t.push(i(e[A].id)),t.push(o(l)),t.push(s)}return new Blob(t,{type:"video/webm"})}function A(e,t){return parseInt(e.substr(t+4,4).split("").map((function(e){var t=e.charCodeAt(0).toString(2);return new Array(8-t.length+1).join("0")+t})).join(""),2)}function s(e){for(var t=0,i={};t<e.length;){var o=e.substr(t,4),r=A(e,t),n=e.substr(t+4+4,r);t+=8+r,i[o]=i[o]||[],"RIFF"===o||"LIST"===o?i[o].push(s(n)):i[o].push(n)}return i}var n=new function(e){var i=function(e){if(!e[0])return void postMessage({error:"Something went wrong. Maybe WebP format is not supported in the current browser."});for(var t=e[0].width,i=e[0].height,o=e[0].duration,r=1;r<e.length;r++)o+=e[r].duration;return{duration:o,width:t,height:i}}(e);if(!i)return[];for(var o,A=[{id:440786851,data:[{data:1,id:17030},{data:1,id:17143},{data:4,id:17138},{data:8,id:17139},{data:"webm",id:17026},{data:2,id:17031},{data:2,id:17029}]},{id:408125543,data:[{id:357149030,data:[{data:1e6,id:2807729},{data:"whammy",id:19840},{data:"whammy",id:22337},{data:(o=i.duration,[].slice.call(new Uint8Array(new Float64Array([o]).buffer),0).map((function(e){return String.fromCharCode(e)})).reverse().join("")),id:17545}]},{id:374648427,data:[{id:174,data:[{data:1,id:215},{data:1,id:29637},{data:0,id:156},{data:"und",id:2274716},{data:"V_VP8",id:134},{data:"VP8",id:2459272},{data:1,id:131},{id:224,data:[{data:i.width,id:176},{data:i.height,id:186}]}]}]}]}],s=0,n=0;s<e.length;){var a=[],d=0;do{a.push(e[s]),d+=e[s].duration,s++}while(s<e.length&&d<3e4);var c={id:524531317,data:t(n,0,a)};A[1].data.push(c),n+=d}return r(A)}(e.map((function(e){var t=function(e){for(var t=e.RIFF[0].WEBP[0],i=t.indexOf("*"),o=0,r=[];o<4;o++)r[o]=t.charCodeAt(i+3+o);return{width:16383&(r[1]<<8|r[0]),height:16383&(r[3]<<8|r[2]),data:t,riff:e}}(s(atob(e.image.slice(23))));return t.duration=e.duration,t})));postMessage(n)}return e.prototype.add=function(e,t){if("canvas"in e&&(e=e.canvas),"toDataURL"in e&&(e=e.toDataURL("image/webp",this.quality)),!/^data:image\/webp;base64,/gi.test(e))throw"Input must be formatted properly as a base64 encoded DataURI of type image/webp";this.frames.push({image:e,duration:t||this.duration})},e.prototype.compile=function(e){var i,o,r,A=(i=t,o=l.createObjectURL(new Blob([i.toString(),"this.onmessage = function (eee) {"+i.name+"(eee.data);}"],{type:"application/javascript"})),r=new Worker(o),l.revokeObjectURL(o),r);A.onmessage=function(t){t.data.error?console.error(t.data.error):e(t.data)},A.postMessage(this.frames)},{Video:e}}();i.Whammy=I;var x={init:function(){var e=this;if("undefined"!=typeof indexedDB&&void 0!==indexedDB.open){var t,i=this.dbName||location.href.replace(/\/|:|#|%|\.|\[|\]/g,""),o=indexedDB.open(i,1);o.onerror=e.onError,o.onsuccess=function(){((t=o.result).onerror=e.onError,t.setVersion)?1!==t.version?t.setVersion(1).onsuccess=function(){r(t),A()}:A():A()},o.onupgradeneeded=function(e){r(e.target.result)}}else console.error("IndexedDB API are not available in this browser.");function r(t){t.createObjectStore(e.dataStoreName)}function A(){var i=t.transaction([e.dataStoreName],"readwrite");function o(t){i.objectStore(e.dataStoreName).get(t).onsuccess=function(i){e.callback&&e.callback(i.target.result,t)}}e.videoBlob&&i.objectStore(e.dataStoreName).put(e.videoBlob,"videoBlob"),e.gifBlob&&i.objectStore(e.dataStoreName).put(e.gifBlob,"gifBlob"),e.audioBlob&&i.objectStore(e.dataStoreName).put(e.audioBlob,"audioBlob"),o("audioBlob"),o("videoBlob"),o("gifBlob")}},Fetch:function(e){return this.callback=e,this.init(),this},Store:function(e){return this.audioBlob=e.audioBlob,this.videoBlob=e.videoBlob,this.gifBlob=e.gifBlob,this.init(),this},onError:function(e){console.error(JSON.stringify(e,null,"\t"))},dataStoreName:"recordRTC",dbName:null};function D(e,t){if("undefined"==typeof GIFEncoder){var i=document.createElement("script");i.src="https://www.webrtc-experiment.com/gif-recorder.js",(document.body||document.documentElement).appendChild(i)}t=t||{};var o=e instanceof CanvasRenderingContext2D||e instanceof HTMLCanvasElement;this.record=function(){"undefined"!=typeof GIFEncoder&&a?(o||(t.width||(t.width=c.offsetWidth||320),t.height||(t.height=c.offsetHeight||240),t.video||(t.video={width:t.width,height:t.height}),t.canvas||(t.canvas={width:t.width,height:t.height}),A.width=t.canvas.width||320,A.height=t.canvas.height||240,c.width=t.video.width||320,c.height=t.video.height||240),(u=new GIFEncoder).setRepeat(0),u.setDelay(t.frameRate||200),u.setQuality(t.quality||10),u.start(),"function"==typeof t.onGifRecordingStarted&&t.onGifRecordingStarted(),h=n((function e(i){if(!0!==p.clearedRecordedData){if(r)return setTimeout((function(){e(i)}),100);h=n(e),void 0===typeof l&&(l=i),i-l<90||(!o&&c.paused&&c.play(),o||s.drawImage(c,0,0,A.width,A.height),t.onGifPreview&&t.onGifPreview(A.toDataURL("image/png")),u.addFrame(s),l=i)}})),t.initCallback&&t.initCallback()):setTimeout(p.record,1e3)},this.stop=function(e){e=e||function(){},h&&d(h),this.blob=new Blob([new Uint8Array(u.stream().bin)],{type:"image/gif"}),e(this.blob),u.stream().bin=[]};var r=!1;this.pause=function(){r=!0},this.resume=function(){r=!1},this.clearRecordedData=function(){p.clearedRecordedData=!0,u&&(u.stream().bin=[])},this.name="GifRecorder",this.toString=function(){return this.name};var A=document.createElement("canvas"),s=A.getContext("2d");o&&(e instanceof CanvasRenderingContext2D?A=(s=e).canvas:e instanceof HTMLCanvasElement&&(s=e.getContext("2d"),A=e));var a=!0;if(!o){var c=document.createElement("video");c.muted=!0,c.autoplay=!0,c.playsInline=!0,a=!1,c.onloadedmetadata=function(){a=!0},S(e,c),c.play()}var l,u,h=null,p=this}function j(e,t){t=t||"multi-streams-mixer";var i=[],o=!1,r=document.createElement("canvas"),A=r.getContext("2d");r.style.opacity=0,r.style.position="absolute",r.style.zIndex=-1,r.style.top="-1000em",r.style.left="-1000em",r.className=t,(document.body||document.documentElement).appendChild(r),this.disableLogs=!1,this.frameInterval=10,this.width=360,this.height=240,this.useGainNode=!0;var s=this,n=window.AudioContext;void 0===n&&("undefined"!=typeof webkitAudioContext&&(n=webkitAudioContext),"undefined"!=typeof mozAudioContext&&(n=mozAudioContext));var a=window.URL;void 0===a&&"undefined"!=typeof webkitURL&&(a=webkitURL),"undefined"!=typeof navigator&&void 0===navigator.getUserMedia&&(void 0!==navigator.webkitGetUserMedia&&(navigator.getUserMedia=navigator.webkitGetUserMedia),void 0!==navigator.mozGetUserMedia&&(navigator.getUserMedia=navigator.mozGetUserMedia));var d=window.MediaStream;void 0===d&&"undefined"!=typeof webkitMediaStream&&(d=webkitMediaStream),void 0!==d&&void 0===d.prototype.stop&&(d.prototype.stop=function(){this.getTracks().forEach((function(e){e.stop()}))});var c={};function l(){if(!o){var e=i.length,t=!1,A=[];if(i.forEach((function(e){e.stream||(e.stream={}),e.stream.fullcanvas?t=e:A.push(e)})),t)r.width=t.stream.width,r.height=t.stream.height;else if(A.length){r.width=e>1?2*A[0].width:A[0].width;var n=1;3!==e&&4!==e||(n=2),5!==e&&6!==e||(n=3),7!==e&&8!==e||(n=4),9!==e&&10!==e||(n=5),r.height=A[0].height*n}else r.width=s.width||360,r.height=s.height||240;t&&t instanceof HTMLVideoElement&&u(t),A.forEach((function(e,t){u(e,t)})),setTimeout(l,s.frameInterval)}}function u(e,t){if(!o){var i=0,r=0,s=e.width,n=e.height;1===t&&(i=e.width),2===t&&(r=e.height),3===t&&(i=e.width,r=e.height),4===t&&(r=2*e.height),5===t&&(i=e.width,r=2*e.height),6===t&&(r=3*e.height),7===t&&(i=e.width,r=3*e.height),void 0!==e.stream.left&&(i=e.stream.left),void 0!==e.stream.top&&(r=e.stream.top),void 0!==e.stream.width&&(s=e.stream.width),void 0!==e.stream.height&&(n=e.stream.height),A.drawImage(e,i,r,s,n),"function"==typeof e.stream.onRender&&e.stream.onRender(A,i,r,s,n,t)}}function h(e){var i=document.createElement("video");return function(e,t){"srcObject"in t?t.srcObject=e:"mozSrcObject"in t?t.mozSrcObject=e:t.srcObject=e}(e,i),i.className=t,i.muted=!0,i.volume=0,i.width=e.width||s.width||360,i.height=e.height||s.height||240,i.play(),i}function p(t){i=[],(t=t||e).forEach((function(e){if(e.getTracks().filter((function(e){return"video"===e.kind})).length){var t=h(e);t.stream=e,i.push(t)}}))}void 0!==n?c.AudioContext=n:"undefined"!=typeof webkitAudioContext&&(c.AudioContext=webkitAudioContext),this.startDrawingFrames=function(){l()},this.appendStreams=function(t){if(!t)throw"First parameter is required.";t instanceof Array||(t=[t]),t.forEach((function(t){var o=new d;if(t.getTracks().filter((function(e){return"video"===e.kind})).length){var r=h(t);r.stream=t,i.push(r),o.addTrack(t.getTracks().filter((function(e){return"video"===e.kind}))[0])}if(t.getTracks().filter((function(e){return"audio"===e.kind})).length){var A=s.audioContext.createMediaStreamSource(t);s.audioDestination=s.audioContext.createMediaStreamDestination(),A.connect(s.audioDestination),o.addTrack(s.audioDestination.stream.getTracks().filter((function(e){return"audio"===e.kind}))[0])}e.push(o)}))},this.releaseStreams=function(){i=[],o=!0,s.gainNode&&(s.gainNode.disconnect(),s.gainNode=null),s.audioSources.length&&(s.audioSources.forEach((function(e){e.disconnect()})),s.audioSources=[]),s.audioDestination&&(s.audioDestination.disconnect(),s.audioDestination=null),s.audioContext&&s.audioContext.close(),s.audioContext=null,A.clearRect(0,0,r.width,r.height),r.stream&&(r.stream.stop(),r.stream=null)},this.resetVideoStreams=function(e){!e||e instanceof Array||(e=[e]),p(e)},this.name="MultiStreamsMixer",this.toString=function(){return this.name},this.getMixedStream=function(){o=!1;var t=function(){var e;p(),"captureStream"in r?e=r.captureStream():"mozCaptureStream"in r?e=r.mozCaptureStream():s.disableLogs||console.error("Upgrade to latest Chrome or otherwise enable this flag: chrome://flags/#enable-experimental-web-platform-features");var t=new d;return e.getTracks().filter((function(e){return"video"===e.kind})).forEach((function(e){t.addTrack(e)})),r.stream=t,t}(),i=function(){c.AudioContextConstructor||(c.AudioContextConstructor=new c.AudioContext);s.audioContext=c.AudioContextConstructor,s.audioSources=[],!0===s.useGainNode&&(s.gainNode=s.audioContext.createGain(),s.gainNode.connect(s.audioContext.destination),s.gainNode.gain.value=0);var t=0;if(e.forEach((function(e){if(e.getTracks().filter((function(e){return"audio"===e.kind})).length){t++;var i=s.audioContext.createMediaStreamSource(e);!0===s.useGainNode&&i.connect(s.gainNode),s.audioSources.push(i)}})),!t)return;return s.audioDestination=s.audioContext.createMediaStreamDestination(),s.audioSources.forEach((function(e){e.connect(s.audioDestination)})),s.audioDestination.stream}();return i&&i.getTracks().filter((function(e){return"audio"===e.kind})).forEach((function(e){t.addTrack(e)})),e.forEach((function(e){e.fullcanvas})),t}}function L(e,t){e=e||[];var i,o,r=this;(t=t||{elementClass:"multi-streams-mixer",mimeType:"video/webm",video:{width:360,height:240}}).frameInterval||(t.frameInterval=10),t.video||(t.video={}),t.video.width||(t.video.width=360),t.video.height||(t.video.height=240),this.record=function(){var r;i=new j(e,t.elementClass||"multi-streams-mixer"),(r=[],e.forEach((function(e){w(e,"video").forEach((function(e){r.push(e)}))})),r).length&&(i.frameInterval=t.frameInterval||10,i.width=t.video.width||360,i.height=t.video.height||240,i.startDrawingFrames()),t.previewStream&&"function"==typeof t.previewStream&&t.previewStream(i.getMixedStream()),(o=new C(i.getMixedStream(),t)).record()},this.stop=function(e){o&&o.stop((function(t){r.blob=t,e(t),r.clearRecordedData()}))},this.pause=function(){o&&o.pause()},this.resume=function(){o&&o.resume()},this.clearRecordedData=function(){o&&(o.clearRecordedData(),o=null),i&&(i.releaseStreams(),i=null)},this.addStreams=function(r){if(!r)throw"First parameter is required.";r instanceof Array||(r=[r]),e.concat(r),o&&i&&(i.appendStreams(r),t.previewStream&&"function"==typeof t.previewStream&&t.previewStream(i.getMixedStream()))},this.resetVideoStreams=function(e){i&&(!e||e instanceof Array||(e=[e]),i.resetVideoStreams(e))},this.getMixer=function(){return i},this.name="MultiStreamRecorder",this.toString=function(){return this.name}}function U(e,t){var i,o,r;function A(){return new ReadableStream({start:function(o){var r=document.createElement("canvas"),A=document.createElement("video"),s=!0;A.srcObject=e,A.muted=!0,A.height=t.height,A.width=t.width,A.volume=0,A.onplaying=function(){r.width=t.width,r.height=t.height;var e=r.getContext("2d"),n=1e3/t.frameRate,a=setInterval((function(){if(i&&(clearInterval(a),o.close()),s&&(s=!1,t.onVideoProcessStarted&&t.onVideoProcessStarted()),e.drawImage(A,0,0),"closed"!==o._controlledReadableStream.state)try{o.enqueue(e.getImageData(0,0,t.width,t.height))}catch(e){}}),n)},A.play()}})}function s(e,a){if(!t.workerPath&&!a)return i=!1,void fetch("https://unpkg.com/webm-wasm@latest/dist/webm-worker.js").then((function(t){t.arrayBuffer().then((function(t){s(e,t)}))}));if(!t.workerPath&&a instanceof ArrayBuffer){var d=new Blob([a],{type:"text/javascript"});t.workerPath=l.createObjectURL(d)}t.workerPath||console.error("workerPath parameter is missing."),(o=new Worker(t.workerPath)).postMessage(t.webAssemblyPath||"https://unpkg.com/webm-wasm@latest/dist/webm-wasm.wasm"),o.addEventListener("message",(function(e){"READY"===e.data?(o.postMessage({width:t.width,height:t.height,bitrate:t.bitrate||1200,timebaseDen:t.frameRate||30,realtime:t.realtime}),A().pipeTo(new WritableStream({write:function(e){i?console.error("Got image, but recorder is finished!"):o.postMessage(e.data.buffer,[e.data.buffer])}}))):e.data&&(r||n.push(e.data))}))}"undefined"!=typeof ReadableStream&&"undefined"!=typeof WritableStream||console.error("Following polyfill is strongly recommended: https://unpkg.com/@mattiasbuelens/web-streams-polyfill/dist/polyfill.min.js"),(t=t||{}).width=t.width||640,t.height=t.height||480,t.frameRate=t.frameRate||30,t.bitrate=t.bitrate||1200,t.realtime=t.realtime||!0,this.record=function(){n=[],r=!1,this.blob=null,s(e),"function"==typeof t.initCallback&&t.initCallback()},this.pause=function(){r=!0},this.resume=function(){r=!1};var n=[];this.stop=function(e){i=!0;var t=this;!function(e){o?(o.addEventListener("message",(function(t){null===t.data&&(o.terminate(),o=null,e&&e())})),o.postMessage(null)):e&&e()}((function(){t.blob=new Blob(n,{type:"video/webm"}),e(t.blob)}))},this.name="WebAssemblyRecorder",this.toString=function(){return this.name},this.clearRecordedData=function(){n=[],r=!1,this.blob=null},this.blob=null}i.DiskStorage=x,i.GifRecorder=D,i.MultiStreamRecorder=L,i.RecordRTCPromisesHandler=function(e,t){if(!this)throw'Use "new RecordRTCPromisesHandler()"';if(void 0===e)throw'First argument "MediaStream" is required.';var o=this;o.recordRTC=new i(e,t),this.startRecording=function(){return new Promise((function(e,t){try{o.recordRTC.startRecording(),e()}catch(e){t(e)}}))},this.stopRecording=function(){return new Promise((function(e,t){try{o.recordRTC.stopRecording((function(i){o.blob=o.recordRTC.getBlob(),o.blob&&o.blob.size?e(i):t("Empty blob.",o.blob)}))}catch(e){t(e)}}))},this.pauseRecording=function(){return new Promise((function(e,t){try{o.recordRTC.pauseRecording(),e()}catch(e){t(e)}}))},this.resumeRecording=function(){return new Promise((function(e,t){try{o.recordRTC.resumeRecording(),e()}catch(e){t(e)}}))},this.getDataURL=function(e){return new Promise((function(e,t){try{o.recordRTC.getDataURL((function(t){e(t)}))}catch(e){t(e)}}))},this.getBlob=function(){return new Promise((function(e,t){try{e(o.recordRTC.getBlob())}catch(e){t(e)}}))},this.getInternalRecorder=function(){return new Promise((function(e,t){try{e(o.recordRTC.getInternalRecorder())}catch(e){t(e)}}))},this.reset=function(){return new Promise((function(e,t){try{e(o.recordRTC.reset())}catch(e){t(e)}}))},this.destroy=function(){return new Promise((function(e,t){try{e(o.recordRTC.destroy())}catch(e){t(e)}}))},this.getState=function(){return new Promise((function(e,t){try{e(o.recordRTC.getState())}catch(e){t(e)}}))},this.blob=null,this.version="5.6.2"},i.WebAssemblyRecorder=U}));class Fe extends Be{constructor(e){super(),this.player=e,this.fileName="",this.fileType=H,this.isRecording=!1,this.recordingTimestamp=0,this.recordingInterval=null,e.debug.log("Recorder","init")}destroy(){this._reset(),this.player.debug.log("Recorder","destroy")}setFileName(e,t){this.fileName=e,Y!==t&&H!==t||(this.fileType=t)}get recording(){return this.isRecording}get recordTime(){return this.recordingTimestamp}startRecord(){const e=this.player.debug,t={type:"video",mimeType:"video/webm;codecs=h264",onTimeStamp:t=>{e.log("Recorder","record timestamp :"+t)},disableLogs:!this.player._opt.debug};try{const e=this.player.video.$videoElement.captureStream(25);if(this.player.audio&&this.player.audio.mediaStreamAudioDestinationNode&&this.player.audio.mediaStreamAudioDestinationNode.stream&&!this.player.audio.isStateSuspended()&&this.player.audio.hasAudio&&this.player._opt.hasAudio){const t=this.player.audio.mediaStreamAudioDestinationNode.stream;if(t.getAudioTracks().length>0){const i=t.getAudioTracks()[0];i&&i.enabled&&e.addTrack(i)}}this.recorder=Ue(e,t)}catch(t){e.error("Recorder",t),this.emit(T.recordCreateError)}this.recorder&&(this.isRecording=!0,this.emit(T.recording,!0),this.recorder.startRecording(),e.log("Recorder","start recording"),this.player.emit(T.recordStart),this.recordingInterval=window.setInterval((()=>{this.recordingTimestamp+=1,this.player.emit(T.recordingTimestamp,this.recordingTimestamp)}),1e3))}stopRecordAndSave(){this.recorder&&this.isRecording&&this.recorder.stopRecording((()=>{this.player.debug.log("Recorder","stop recording"),this.player.emit(T.recordEnd),function(e,t,i){const o=window.URL.createObjectURL(e),r=document.createElement("a");r.href=o,r.download=(t||he())+"."+(i||H),r.click(),setTimeout((()=>{window.URL.revokeObjectURL(o)}),ve()?1e3:0)}(this.recorder.getBlob(),this.fileName,this.fileType),this._reset(),this.emit(T.recording,!1)}))}_reset(){this.isRecording=!1,this.recordingTimestamp=0,this.recorder&&(this.recorder.destroy(),this.recorder=null),this.fileName=null,this.recordingInterval&&clearInterval(this.recordingInterval),this.recordingInterval=null}}class Ve{constructor(e){return new(Ve.getLoaderFactory())(e)}static getLoaderFactory(){return Fe}}class Oe{constructor(e){this.player=e,this.decoderWorker=new Worker(e._opt.decoder),this._initDecoderWorker(),e.debug.log("decoderWorker","init")}destroy(){this.decoderWorker.postMessage({cmd:R}),this.decoderWorker.terminate(),this.decoderWorker=null,this.player.debug.log("decoderWorker","destroy")}_initDecoderWorker(){const{debug:e,events:{proxy:t}}=this.player;this.decoderWorker.onmessage=t=>{const i=t.data;switch(i.cmd){case c:e.log("decoderWorker","onmessage:",c),this.player.loaded||this.player.emit(T.load),this.player.emit(T.decoderWorkerInit),this._initWork();break;case g:e.log("decoderWorker","onmessage:",g,i.code),this.player._times.decodeStart||(this.player._times.decodeStart=he()),this.player.video.updateVideoInfo({encTypeCode:i.code});break;case m:e.log("decoderWorker","onmessage:",m,i.code),this.player.audio&&this.player.audio.updateAudioInfo({encTypeCode:i.code});break;case l:e.log("decoderWorker","onmessage:",l,`width:${i.w},height:${i.h}`),this.player.video.updateVideoInfo({width:i.w,height:i.h}),this.player.video.initCanvasViewSize();break;case p:e.log("decoderWorker","onmessage:",p,`channels:${i.channels},sampleRate:${i.sampleRate}`),this.player.audio&&(this.player.audio.updateAudioInfo(i),this.player.audio.initScriptNode(i));break;case u:this.player.handleRender(),this.player.video.render(i),this.player.emit(T.timeUpdate,i.ts),this.player.updateStats({fps:!0,ts:i.ts,buf:i.delay}),this.player._times.videoStart||(this.player._times.videoStart=he(),this.player.handlePlayToRenderTimes());break;case h:this.player.playing&&this.player.audio&&this.player.audio.play(i.buffer,i.ts);break;case f:i.message&&-1!==i.message.indexOf(b)&&(this.player.emit(T.error,x.wasmDecodeError),this.player.emit(x.wasmDecodeError));break;default:this.player[i.cmd]&&this.player[i.cmd](i)}}}_initWork(){const e={debug:this.player._opt.debug,forceNoOffscreen:this.player._opt.forceNoOffscreen,useWCS:this.player._opt.useWCS,videoBuffer:this.player._opt.videoBuffer,openWebglAlignment:this.player._opt.openWebglAlignment};this.decoderWorker.postMessage({cmd:E,opt:JSON.stringify(e),sampleRate:this.player.audio&&this.player.audio.audioContext.sampleRate||0})}decodeVideo(e,t,i){const o={type:v,ts:Math.max(t,0),isIFrame:i};this.decoderWorker.postMessage({cmd:B,buffer:e,options:o},[e.buffer])}decodeAudio(e,t){this.player._opt.useWCS&&!this.player._opt.useOffscreen||this.player._opt.useMSE?this._decodeAudioNoDelay(e,t):this._decodeAudio(e,t)}_decodeAudio(e,t){const i={type:y,ts:Math.max(t,0)};this.decoderWorker.postMessage({cmd:B,buffer:e,options:i},[e.buffer])}_decodeAudioNoDelay(e,t){this.decoderWorker.postMessage({cmd:C,buffer:e,ts:Math.max(t,0)},[e.buffer])}updateWorkConfig(e){this.decoderWorker.postMessage({cmd:k,key:e.key,value:e.value})}}class Me extends Be{constructor(e){super(),this.player=e,this.stopId=null,this.firstTimestamp=null,this.startTimestamp=null,this.delay=-1,this.bufferList=[],this.dropping=!1,this.initInterval()}destroy(){this.stopId&&(clearInterval(this.stopId),this.stopId=null),this.firstTimestamp=null,this.startTimestamp=null,this.delay=-1,this.bufferList=[],this.dropping=!1,this.off()}getDelay(e){return e?(this.firstTimestamp?e&&(this.delay=Date.now()-this.startTimestamp-(e-this.firstTimestamp)):(this.firstTimestamp=e,this.startTimestamp=Date.now(),this.delay=-1),this.delay):-1}resetDelay(){this.firstTimestamp=null,this.startTimestamp=null,this.delay=-1,this.dropping=!1}initInterval(){this.player.debug.log("common dumex","init Interval");let e=()=>{let e;const t=this.player._opt.videoBuffer;if(this.bufferList.length)if(this.dropping){for(e=this.bufferList.shift(),e.type===y&&0===e.payload[1]&&this._doDecoderDecode(e);!e.isIFrame&&this.bufferList.length;)e=this.bufferList.shift(),e.type===y&&0===e.payload[1]&&this._doDecoderDecode(e);e.isIFrame&&(this.dropping=!1,this._doDecoderDecode(e))}else if(e=this.bufferList[0],-1===this.getDelay(e.ts))this.bufferList.shift(),this._doDecoderDecode(e);else if(this.delay>t+1e3)this.resetDelay(),this.dropping=!0;else for(;this.bufferList.length&&(e=this.bufferList[0],this.getDelay(e.ts)>t);)this.bufferList.shift(),this._doDecoderDecode(e)};e(),this.stopId=setInterval(e,10)}_doDecode(e,t,i,o){const r=this.player;let A={ts:i,type:t,isIFrame:!1};r._opt.useWCS&&!r._opt.useOffscreen||r._opt.useMSE?(t===v&&(A.isIFrame=o),this.pushBuffer(e,A)):t===v?r.decoderWorker&&r.decoderWorker.decodeVideo(e,i,o):t===y&&r._opt.hasAudio&&r.decoderWorker&&r.decoderWorker.decodeAudio(e,i)}_doDecoderDecode(e){const t=this.player,{webcodecsDecoder:i,mseDecoder:o}=t;e.type===y?t._opt.hasAudio&&t.decoderWorker&&t.decoderWorker.decodeAudio(e.payload,e.ts):e.type===v&&(t._opt.useWCS&&!t._opt.useOffscreen?i.decodeVideo(e.payload,e.ts,e.isIFrame):t._opt.useMSE&&o.decodeVideo(e.payload,e.ts,e.isIFrame))}pushBuffer(e,t){t.type===y?this.bufferList.push({ts:t.ts,payload:e,type:y}):t.type===v&&this.bufferList.push({ts:t.ts,payload:e,type:v,isIFrame:t.isIFrame})}close(){}}class Qe extends Me{constructor(e){super(e),this.input=this._inputFlv(),this.flvDemux=this.dispatchFlvData(this.input),e.debug.log("FlvDemux","init")}destroy(){super.destroy(),this.input=null,this.flvDemux=null,this.player.debug.log("FlvDemux","destroy")}dispatch(e){this.flvDemux(e)}*_inputFlv(){yield 9;const e=new ArrayBuffer(4),t=new Uint8Array(e),i=new Uint32Array(e),o=this.player;for(;;){t[3]=0;const e=yield 15,r=e[4];t[0]=e[7],t[1]=e[6],t[2]=e[5];const A=i[0];t[0]=e[10],t[1]=e[9],t[2]=e[8];let s=i[0];16777215===s&&(t[3]=e[11],s=i[0]);const n=yield A;switch(r){case w:o._opt.hasAudio&&(o.updateStats({abps:n.byteLength}),n.byteLength>0&&this._doDecode(n,y,s));break;case S:if(o._times.demuxStart||(o._times.demuxStart=he()),o._opt.hasVideo){o.updateStats({vbps:n.byteLength});const e=n[0]>>4==1;n.byteLength>0&&this._doDecode(n,v,s,e)}}}}dispatchFlvData(e){let t=e.next(),i=null;return o=>{let r=new Uint8Array(o);if(i){let e=new Uint8Array(i.length+r.length);e.set(i),e.set(r,i.length),r=e,i=null}for(;r.length>=t.value;){let i=r.slice(t.value);t=e.next(r.slice(0,t.value)),r=i}r.length>0&&(i=r)}}close(){this.input&&this.input.return(null)}}class We extends Me{constructor(e){super(e),e.debug.log("M7sDemux","init")}destroy(){super.destroy(),this.player.debug.log("M7sDemux","destroy")}dispatch(e){const t=this.player,i=new DataView(e),o=i.getUint8(0),r=i.getUint32(1,!1);switch(o){case y:if(t._opt.hasAudio){const i=new Uint8Array(e,5);t.updateStats({abps:i.byteLength}),i.byteLength>0&&this._doDecode(i,o,r)}break;case v:if(t._opt.hasVideo&&(t._times.demuxStart||(t._times.demuxStart=he()),i.byteLength>5)){const A=new Uint8Array(e,5),s=i.getUint8(5)>>4==1;t.updateStats({vbps:A.byteLength}),A.byteLength>0&&this._doDecode(A,o,r,s)}}}}class Ge{constructor(e){return new(Ge.getLoaderFactory(e._opt.demuxType))(e)}static getLoaderFactory(e){return e===a?We:e===n?Qe:void 0}}class Je extends Be{constructor(e){super(),this.player=e,this.hasInit=!1,this.isInitInfo=!1,this.decoder=null,this.initDecoder(),e.debug.log("Webcodecs","init")}destroy(){this.decoder&&(this.decoder.close(),this.decoder=null),this.hasInit=!1,this.isInitInfo=!1,this.off(),this.player.debug.log("Webcodecs","destroy")}initDecoder(){const e=this;this.decoder=new VideoDecoder({output(t){e.handleDecode(t)},error(t){e.handleError(t)}})}handleDecode(e){this.isInitInfo||(this.player.video.updateVideoInfo({width:e.codedWidth,height:e.codedHeight}),this.player.video.initCanvasViewSize(),this.isInitInfo=!0),this.player._times.videoStart||(this.player._times.videoStart=he(),this.player.handlePlayToRenderTimes()),this.player.handleRender(),this.player.video.render({videoFrame:e}),this.player.updateStats({fps:!0,ts:0,buf:this.player.demux.delay}),setTimeout((function(){e.close?e.close():e.destroy()}),100)}handleError(e){this.player.debug.log("Webcodecs","VideoDecoder handleError",e)}decodeVideo(e,t,i){if(this.hasInit){const o=new EncodedVideoChunk({data:e.slice(5),timestamp:t,type:i?K:_});this.decoder.decode(o)}else if(i&&0===e[1]){const t=15&e[0];if(this.player.video.updateVideoInfo({encTypeCode:t}),t===M)return void this.emit(x.webcodecsH265NotSupport);this.player._times.decodeStart||(this.player._times.decodeStart=he());const i=function(e){let t=e.subarray(1,4),i="avc1.";for(let e=0;e<3;e++){let o=t[e].toString(16);o.length<2&&(o="0"+o),i+=o}return{codec:i,description:e}}(e.slice(5));this.decoder.configure(i),this.hasInit=!0}}}const Ne={play:"播放",pause:"暂停",audio:"",mute:"",screenshot:"截图",loading:"加载",fullscreen:"全屏",fullscreenExit:"退出全屏",record:"录制",recordStop:"停止录制"};var Pe=Object.keys(Ne).reduce(((e,t)=>(e[t]=`\n <i class="jessibuca-icon jessibuca-icon-${t}"></i>\n ${Ne[t]?`<span class="icon-title-tips"><span class="icon-title">${Ne[t]}</span></span>`:""}\n`,e)),{}),ze=(e,t)=>{const{events:{proxy:i}}=e,o=document.createElement("object");o.setAttribute("aria-hidden","true"),o.setAttribute("tabindex",-1),o.type="text/html",o.data="about:blank",me(o,{display:"block",position:"absolute",top:"0",left:"0",height:"100%",width:"100%",overflow:"hidden",pointerEvents:"none",zIndex:"-1"});let r=e.width,A=e.height;i(o,"load",(()=>{i(o.contentDocument.defaultView,"resize",(()=>{e.width===r&&e.height===A||(r=e.width,A=e.height,e.emit(T.resize))}))})),e.$container.appendChild(o),e.on(T.destroy,(()=>{e.$container.removeChild(o)})),e.on(T.volumechange,(()=>{!function(e){if(0===e)me(t.$volumeOn,"display","none"),me(t.$volumeOff,"display","flex"),me(t.$volumeHandle,"top","48px");else if(t.$volumeHandle&&t.$volumePanel){const i=ge(t.$volumePanel,"height")||60,o=ge(t.$volumeHandle,"height"),r=i-(i-o)*e-o;me(t.$volumeHandle,"top",`${r}px`),me(t.$volumeOn,"display","flex"),me(t.$volumeOff,"display","none")}t.$volumePanelText&&(t.$volumePanelText.innerHTML=parseInt(100*e))}(e.volume)})),e.on(T.loading,(e=>{me(t.$loading,"display",e?"flex":"none"),me(t.$poster,"display","none"),e&&me(t.$playBig,"display","none")}));const s=i=>{let o=!0===(r=i)||!1===r?i:e.fullscreen;var r;me(t.$fullscreenExit,"display",o?"flex":"none"),me(t.$fullscreen,"display",o?"none":"flex")};try{de.on("change",s),e.events.destroys.push((()=>{de.off("change",s)}))}catch(e){}e.on(T.webFullscreen,(e=>{s(e)})),e.on(T.recording,(()=>{me(t.$record,"display",e.recording?"none":"flex"),me(t.$recordStop,"display",e.recording?"flex":"none")})),e.on(T.recordingTimestamp,(e=>{})),e.on(T.playing,(e=>{me(t.$play,"display",e?"none":"flex"),me(t.$playBig,"display",e?"none":"block"),me(t.$pause,"display",e?"flex":"none"),me(t.$screenshot,"display",e?"flex":"none"),me(t.$record,"display",e?"flex":"none"),me(t.$fullscreen,"display",e?"flex":"none"),e||t.$speed&&(t.$speed.innerHTML=we(""))})),e.on(T.kBps,(e=>{const i=we(e);t.$speed&&(t.$speed.innerHTML=i)}))};function Ye(e,t){void 0===t&&(t={});var i=t.insertAt;if(e&&"undefined"!=typeof document){var o=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css","top"===i&&o.firstChild?o.insertBefore(r,o.firstChild):o.appendChild(r),r.styleSheet?r.styleSheet.cssText=e:r.appendChild(document.createTextNode(e))}}Ye('@keyframes rotation{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}.jessibuca-container .jessibuca-icon{cursor:pointer;width:16px;height:16px}.jessibuca-container .jessibuca-poster{position:absolute;z-index:10;left:0;top:0;right:0;bottom:0;height:100%;width:100%;background-position:50%;background-repeat:no-repeat;background-size:contain;pointer-events:none}.jessibuca-container .jessibuca-play-big{position:absolute;display:none;height:100%;width:100%;background:rgba(0,0,0,.4)}.jessibuca-container .jessibuca-play-big:after{cursor:pointer;content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:block;width:48px;height:48px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACgklEQVRoQ+3ZPYsTQRjA8eeZZCFlWttAwCIkZOaZJt8hlvkeHrlccuAFT6wEG0FQOeQQLCIWih6chQgKgkkKIyqKCVYip54IWmiQkTmyYhFvd3Zn3yDb7szu/7cv7GaDkPEFM94PK0DSZ9DzDAyHw7uI2HRDlVJX5/N5r9FoHCYdr/fvCRiNRmpJ6AEidoUQ15NG+AH8BgD2n9AHANAmohdJQfwAfgGA4xF4bjabnW21Whob62ILoKNfAsAGEd2PU2ATcNSNiDf0/cE5/xAHxDpgEf0NADaJ6HLUiKgAbvcjpdSGlPJZVJCoAUfdSqkLxWLxTLlc/mkbEgtgET1TSnWklLdtIuIEuN23crlcp16vv7cBSQKgu38AwBYRXQyLSArg3hsjRDxNRE+CQhIF/BN9qVAobFYqle+mkLQAdLd+8K0T0U0TRJoAbvc9fVkJId75gaQRoLv1C2STiPTb7rFLWgE6+g0RncwyYEJEtawCvjDGmpzzp5kD6NfxfD7frtVqB17xen2a7oG3ALBm+oMoFQBEPD+dTvtBfpImDXjIGFvjnD/3c7ksG5MU4HDxWeZa0HB3XhKAXcdxOn5vUi9gnIDXSqm2lHLPK8pkfVyAbSLqm4T5HRs1YB8RO0KIid8g03FRAT4rpbpSyh3TINPxUQB2GGM9zvkn05gg420CJovLZT9ISNA5tgB9ItoOGhFmnh/AcZ/X9xhj65zzV2Eiwsz1A1j2B8dHAOgS0W6YnduY6wkYj8d3lFKn/j66Ea84jtOrVqtfbQSE3YYnYDAY5Eql0hYAnNDv6kKIx2F3anO+J8DmzqLY1goQxVE12ebqDJgcrSjGrs5AFEfVZJt/AF0m+jHzUTtnAAAAAElFTkSuQmCC");background-repeat:no-repeat;background-position:50%}.jessibuca-container .jessibuca-play-big:hover:after{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACEElEQVRoQ+2ZXStEQRjH/3/yIXwDdz7J+i7kvdisXCk3SiFJW27kglBcSFFKbqwQSa4krykuKB09Naf2Yndn5jgzc06d53Znd36/mWfeniVyHsw5PwqB0DOonYEoijYBlOpAFwCMkHwLDS/9mwhEDUCfAAyTXA4tYSLwC6CtCegegH6S56FETAR+AHRoACcBTJAUWa+RloBAXwAYIrnt0yBNgZi7qtbHgw8RFwLC/QFglOScawlXAjH3gUqrE1cirgVi7mkAYyS/0xbxJSDcdwAGSa6nKeFTIOZeUyL3aYiEEBDuLwDjJGf+KxFKIOY+BdBL8iipSGiBmHtWbbuftiJZERBuOfgGSK7aSGRJIObeUml1ayKSRQHhlgtkiaTcdltGVgUE+ppkV54FaiS78yrwqlLoOI8Cch2XV548W7WRpTVwA6DP9kGUFYEpAOUkT9LQAvtq1M+0udKkQSgBqSlJWWYxKXj8vRACK+o6bbRIdYI+Ba7U7rKjg7L53JdAhWTZBsy0rWuBXZUuNVMg23auBF7UIl2yBbJt70JAoKV6/WwLk6R9mgKSJlJ1kLTxFmkJyCla8UZd15GJQKvyumyJ8gy8DAEvfZoINPqD41EtUjmUgoaJwAaAnjrKebVI34OSq85NBNqlCAWgE0CV5GEWwI3vQlmCbcSinYFCwPEIFDPgeIC1P1/MgHaIHDf4Aydx2TF7wnKeAAAAAElFTkSuQmCC")}.jessibuca-container .jessibuca-loading{display:none;flex-direction:column;justify-content:center;align-items:center;position:absolute;z-index:20;left:0;top:0;right:0;bottom:0;width:100%;height:100%;pointer-events:none}.jessibuca-container .jessibuca-loading-text{line-height:20px;font-size:13px;color:#fff;margin-top:10px}.jessibuca-container .jessibuca-controls{background-color:#161616;box-sizing:border-box;display:flex;flex-direction:column;justify-content:flex-end;position:absolute;z-index:40;left:0;right:0;bottom:0;height:38px;padding-left:13px;padding-right:13px;font-size:14px;color:#fff;opacity:0;visibility:hidden;transition:all .2s ease-in-out;-webkit-user-select:none;user-select:none;transition:width .5s ease-in}.jessibuca-container .jessibuca-controls .jessibuca-controls-item{position:relative;display:flex;justify-content:center;padding:0 8px}.jessibuca-container .jessibuca-controls .jessibuca-controls-item:hover .icon-title-tips{visibility:visible;opacity:1}.jessibuca-container .jessibuca-controls .jessibuca-fullscreen,.jessibuca-container .jessibuca-controls .jessibuca-fullscreen-exit,.jessibuca-container .jessibuca-controls .jessibuca-icon-audio,.jessibuca-container .jessibuca-controls .jessibuca-microphone-close,.jessibuca-container .jessibuca-controls .jessibuca-pause,.jessibuca-container .jessibuca-controls .jessibuca-play,.jessibuca-container .jessibuca-controls .jessibuca-record,.jessibuca-container .jessibuca-controls .jessibuca-record-stop,.jessibuca-container .jessibuca-controls .jessibuca-screenshot{display:none}.jessibuca-container .jessibuca-controls .jessibuca-icon-audio,.jessibuca-container .jessibuca-controls .jessibuca-icon-mute{z-index:1}.jessibuca-container .jessibuca-controls .jessibuca-controls-bottom{display:flex;justify-content:space-between;height:100%}.jessibuca-container .jessibuca-controls .jessibuca-controls-bottom .jessibuca-controls-left,.jessibuca-container .jessibuca-controls .jessibuca-controls-bottom .jessibuca-controls-right{display:flex;align-items:center}.jessibuca-container.jessibuca-controls-show .jessibuca-controls{opacity:1;visibility:visible}.jessibuca-container.jessibuca-controls-show-auto-hide .jessibuca-controls{opacity:.8;visibility:visible;display:none}.jessibuca-container.jessibuca-hide-cursor *{cursor:none!important}.jessibuca-container .jessibuca-icon-loading{width:50px;height:50px;background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%;animation:rotation 1s linear infinite}.jessibuca-container .jessibuca-icon-screenshot{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAE5UlEQVRoQ+1YW2sdVRT+1s7JxbsoVkEUrIIX0ouz15zYNA+N1RdtQfCltlUfvLbqL/BCwZ8grbHtizQqPojgBSr0JkiMmT2nxgapqBURtPVCq7HxJCeZJVPmxDlzZubMmXOSEsnAvOy917fXt9e39tp7E5b4R0vcfywTuNgRbBgBx3HuJqLVzPzmYjprjHkcwAlmLqXNm4XAISLaSESPaq2HF4OE67rbRGRYRA7btn1fbgLGmKsA/Azg0gBkGzO/vZAkHMd5hIiqc5wHcCMz/5k0Z2oExsfHV1QqldPAf8lORNu11m8tBAljzFYAYWxRSl1vWdZvuQj4RsYYF4AVBlgIOVVlE55HRIxt23ZuCfmGjuOsJ6LPoiAistW27XfaEYmIbOYhPc9bXywWR1oiEJDYQkR1zrYjEjGyqfqbKd8a7kJVtLgQ+30i8pht2wfyRKIdmJkJBPkQTbILfudJ7CTZNBvVpggEcgpvc/ML38zESbLJsxBNE/A9biX0rdjGyTQXgbxyapdsarb0PMlXtWnGoXbKpm0Essqp3bJpK4E0OXmed3+hUBDP8w5FI91M0rdcyLLILElOCbaZilSWeXMncRx4klTCY1spfG3dhZJWx3GcDUR0EEB3ZMw0ET2gtT6SZWWzjmlrBIJCl0hAKfWgZVmHszqXZVxbCSxpCS2JJA6umIhe8ZKKVLPbaBJ+S9toqVRa53nedgAbAKwIwH4FcAzAa0R0l4i8F7PPz189k6RFRA+LyNcAXojDV0oNW5b1eW4Cxpg9AHZkSaaa6hhzb065uDSCH2LmRB8Sk9gY4293g43Qo/1pV80m8yQMfZSZ781cB1zXHRKRZ2IMpgD8A+DamL4ZItqitX4/jbQx5iEA7wLoihn3V/ACckWMJN/QWj9b1x5tGBsbW6uUOh5pPy0iL3Z2dn6ilJqanp5ep5TaJSLhF4NppdRNaU8gPmapVLrO87yfIoXuWyJ6uVKp+HmFjo6OQSJ6FcBtYT+UUmstyxqvkWuUgDFmP4AnQu2/e563qlgs+u9DNZ8xZhRAX7VRRPbath0XuXk7Y8xeAE+FgL6fnJzsHRwcLIfBR0ZGLunq6poAsDLUvp+Zw7b1r9PGmJMAbg8Z7WDmoThZuK67WkS+DD18fcPMdzSQUBR/EzN/nIC/SUQ+DPXV4dclsTHmHAD/SfHCNzc3t7Kvr++HJKeMMacA3BL0nyuXyzcPDAxMxo0fHR29slAo/Ajg6qD/fE9Pzw29vb1/x42fmJi4vFwu+5G/LOg/y8zXNJLQ2dAES5JANMQ7mfn1jBI6ycx3NiMhItqstf4oAX+ziHwQ6qvDj5NQNIn/ALCKmX+JSeIvABRD7fuY+ekGBPYBeDI05tTMzExvf3+/vz2Hk91/ET8RSeI6/DoCpVJpjed5fmKGvzMAXpqdnT3oed5Ud3d3v4jsAqBr9Ei0Rmv9VRqBBPzvROQVETnq2xJRdRu9tRF+bCVOKWT+Kvl/TSIFk6SW/LAjKfjV5K8rZABi8dOOEv7FI7Z8x6zwEWbemLbyMfJr5qiSiJ96oclymBOR3bZtP9+M89WxxpjdAHY2sN3DzM8ljWl4I3Nd9x7/OE1ENcdpETnmH3e11n41zv0l4J8RkU+J6AAz+xtF4teQQG7PFslwmcAiLfSyhC72Qv9/I/Avns2OT7QJskoAAAAASUVORK5CYII=") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-screenshot:hover{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAED0lEQVRoQ+2ZycsdRRTFf2ejqHFAMQqiYBTUoElUHLNx3GgCgpuYRF2o0UT9CxwQ/BMkMSbZSKLiQgQHUDCJgjiAxiEiESdEcJbEedgcKaj3UV+/6q7u/jovPPkK3qbr1ql76p5bt6qemPKmKfefeQKHOoLFCNg+H1gi6fFJOmv7VmCvpD1N87Yh8ApwNXCzpB2TIGF7DRDm2inpmt4EbB8LfAMcGUHWSHryYJKwfRMwmuMP4BRJv9TN2RgB2wuB72BWsq+V9MTBIGF7NZBiGzhJ0o+9CIRBtt8FLqgADC6nRDbpVO9Iuqi3hCKB5cDrGZDVkp4aIhIV2aSQyyW9MScCkcQqIOfsnCORkc3I31b5VtyFRmg1IQ7dt0ja3icSQ2C2JhAjUU2ykd+dE7tBNp2i2olAJJFuc+nCt564QTadF6IzgUhiVGiqyinKaQjZpJP2ItBXTkPJZhACXeU0pGwGI9BWTkPLZlACBTldG4o5EA6E1dY66edcyNrs8Q36zg1vVaTazNs7iXPgDVJJzYs7VRvHRzaDEohyugJ4CTi84sg/wHWSdnVxsGQ7aQLXS9pZcqpL/6AEplpCU5HE8YpJ9YrXUKQ6baN1+HPaRm1fBqwFQnKGK2ZoPwCvAo8Ai4FnMpPMHMwapHUj8DFwbw3+Dklv9iZgexOwvktSRduxU2VDlErwmyXV+lCbxLbDdndlCT3TX3vV7JgnKfRuSVflfMkSsL0ZuDMz4E/gL+CETN+/wCpJzzaRtn0D8DRwWMbu1/gCcnSm7zFJd1W/jxGwvQx4r2IYnlbuA14GAomQFw8B6YtBKFSnNj2BxEJ3IvB1pdB9CjwQ8yqYhcg/DJxZ8WOZpA/SbzkC24DbEqOfgPMkBRKzmu23gEuSj1sk5SI3Y2J7C3BHMuZz4FxJf6fgto8APgIWJd+3SUrHjr9O294HnJUMWi8pSGqs2V4CvJ88fH0i6eyChKr4KyS9WIO/Ang+6RvDz0XgABCeFEdtkaQv65yy/QVweuwPY0+T9FuNQ8cAXwHHxf7wdHiypN9r7BfEl8GjYv9+SceXJLQ/mSDYTh2Baog3SHq0pYT2STqno4RWSnqhBn8l8FzSN4bfJol/jkn8bXUS228DFyfft0paVyCwFbg9sQkSDEkctueZZju8iO+tJPEYfo7A0piYKd73wP3xnB+20cvjNnphxdmlkj4sEMjhfwY8COyOY0fb6Bkl/K6FLKxS+M1KpDhJY8mvrG5doRwlf66QZfGbjhLh4pEt35kV3iUp/IvTunU8qtTil/7gaHOY2yjpntaez9b5RmBDYewmSXfX2RRvZLYvbThOh+NuqMa9Ww1+yLnXgO2SwkZR24oEens2oYHzBCa00PMSOtQL/f+NwH+Hg8hAnbrYgQAAAABJRU5ErkJggg==") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-play{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACgklEQVRoQ+3ZPYsTQRjA8eeZZCFlWttAwCIkZOaZJt8hlvkeHrlccuAFT6wEG0FQOeQQLCIWih6chQgKgkkKIyqKCVYip54IWmiQkTmyYhFvd3Zn3yDb7szu/7cv7GaDkPEFM94PK0DSZ9DzDAyHw7uI2HRDlVJX5/N5r9FoHCYdr/fvCRiNRmpJ6AEidoUQ15NG+AH8BgD2n9AHANAmohdJQfwAfgGA4xF4bjabnW21Whob62ILoKNfAsAGEd2PU2ATcNSNiDf0/cE5/xAHxDpgEf0NADaJ6HLUiKgAbvcjpdSGlPJZVJCoAUfdSqkLxWLxTLlc/mkbEgtgET1TSnWklLdtIuIEuN23crlcp16vv7cBSQKgu38AwBYRXQyLSArg3hsjRDxNRE+CQhIF/BN9qVAobFYqle+mkLQAdLd+8K0T0U0TRJoAbvc9fVkJId75gaQRoLv1C2STiPTb7rFLWgE6+g0RncwyYEJEtawCvjDGmpzzp5kD6NfxfD7frtVqB17xen2a7oG3ALBm+oMoFQBEPD+dTvtBfpImDXjIGFvjnD/3c7ksG5MU4HDxWeZa0HB3XhKAXcdxOn5vUi9gnIDXSqm2lHLPK8pkfVyAbSLqm4T5HRs1YB8RO0KIid8g03FRAT4rpbpSyh3TINPxUQB2GGM9zvkn05gg420CJovLZT9ISNA5tgB9ItoOGhFmnh/AcZ/X9xhj65zzV2Eiwsz1A1j2B8dHAOgS0W6YnduY6wkYj8d3lFKn/j66Ea84jtOrVqtfbQSE3YYnYDAY5Eql0hYAnNDv6kKIx2F3anO+J8DmzqLY1goQxVE12ebqDJgcrSjGrs5AFEfVZJt/AF0m+jHzUTtnAAAAAElFTkSuQmCC") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-play:hover{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACEElEQVRoQ+2ZXStEQRjH/3/yIXwDdz7J+i7kvdisXCk3SiFJW27kglBcSFFKbqwQSa4krykuKB09Naf2Yndn5jgzc06d53Znd36/mWfeniVyHsw5PwqB0DOonYEoijYBlOpAFwCMkHwLDS/9mwhEDUCfAAyTXA4tYSLwC6CtCegegH6S56FETAR+AHRoACcBTJAUWa+RloBAXwAYIrnt0yBNgZi7qtbHgw8RFwLC/QFglOScawlXAjH3gUqrE1cirgVi7mkAYyS/0xbxJSDcdwAGSa6nKeFTIOZeUyL3aYiEEBDuLwDjJGf+KxFKIOY+BdBL8iipSGiBmHtWbbuftiJZERBuOfgGSK7aSGRJIObeUml1ayKSRQHhlgtkiaTcdltGVgUE+ppkV54FaiS78yrwqlLoOI8Cch2XV548W7WRpTVwA6DP9kGUFYEpAOUkT9LQAvtq1M+0udKkQSgBqSlJWWYxKXj8vRACK+o6bbRIdYI+Ba7U7rKjg7L53JdAhWTZBsy0rWuBXZUuNVMg23auBF7UIl2yBbJt70JAoKV6/WwLk6R9mgKSJlJ1kLTxFmkJyCla8UZd15GJQKvyumyJ8gy8DAEvfZoINPqD41EtUjmUgoaJwAaAnjrKebVI34OSq85NBNqlCAWgE0CV5GEWwI3vQlmCbcSinYFCwPEIFDPgeIC1P1/MgHaIHDf4Aydx2TF7wnKeAAAAAElFTkSuQmCC") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-pause{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABA0lEQVRoQ+1YwQqCUBAcfWXXsLr2AXWTPXno8yVB8AP6Aa3oHI+kCDqYaawJljSe133uzO44bx0M/HEG/v1gAd9mkAyQgY4I/F8LJUlyrQFtD2AtIkcNoFEU+Z7n7QD4DfFHEVlocrVmgAUAIAOl3mILPcDgEFcUhyrUKMGUUcroc3NQRimj9XJBGaWMvvPydKN0o6/9QTdKN6rZANxj6EbpRulGuZnjYqs8BbyR8Ub2Izeys+u6yyAIDpo/ehzHM2NMDsA0xFsRmWhyfTIDWSXxCEBmrd2EYXjSHJqm6bQoii2AOYBL5Z0xgFxEVppcrQvQJO0zhgX0iXbdWWSADHRE4AZQ731AhEUeNwAAAABJRU5ErkJggg==") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-pause:hover{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAA7klEQVRoQ+2YSwrCQBBEX6HiVvxsPYDewfN7By/gD9ciQkvERQwJdBSiYs0mEDo96aruombEjy/9+P/jAj7NoBkwA28i8H8tFBFRA9oeWEo6ZgCNiDGwAYpn3TpKmmVytWbABQBmoNRbbqEHGB7iiuJYhRol2DJqGX1uDsuoZdRmLuNZSzGWUcuoZdRHSp/IylNgK2ErYSthK3FHwLcSvpXIjoLt9Jfa6TMwl3TIMBkRE2AH9BriL5KGmVyvWIltJXEfKN6tJJ0ym0bECFgDU+Ba+WZQFCdpkcnVuoBM0i5jXECXaNftZQbMwJsI3AAPN3dAQflHegAAAABJRU5ErkJggg==") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-record{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAC+UlEQVRoQ+1ZS2sTURT+zlDJYE3XSq219QHVuEjnJDT+Bff9Abqw2voAEfGxqygUqWhVFHGl/yMLu9BwByxk5SNI66ML6U7axjhHbmhgWiftncxoOiV3FcI53z3f/e65594zhIQPSnj86BBot4IdBToKRFyBnbeFlFIScVEiuYvIWC6Xe2YK8pcC7SYA4CMzH4mDQBXAqilQBDsLQLfPf9FxnF4i8kwwmypARI+Wl5dvmIBEsUmlUkNE9NaHsVCpVAZGR0d/m+A2JSAid3K53E0TkCg2pVKpz7KseR/GfKVSGYxMAMA0M1+JEpyJb6lUOm5ZVnkrAsVisaunp+esiByr1Wp3R0ZGvmifzZK4XQQWHMc52MgBpdQuAOcAXABwuB400ZTjONdaIjA7O5u2bVsnWU1EujzP+5nP5xdMVjvIJkCBD8x8VCm1G8AYgAkAAxt8Z5j5YmgCSqlTAJ4D2OcD/AXgATNfbYVEAIFPIvKKiE4D6GuCea8xX6gtpJT6DmBvECgRFRzHeROWRAABE4iWCbwHEFhkPM/L5vP5dyaz+23+KwHXdR3P854S0YG1ILSCuthNMfNM2OC1/RYENLY+ygcBnPfht6ZAA6BYLNr6dyqVokKhsGpaNQ2TWJstreXaE2aed133sojcj41AKyvdzCdAgSXLsk4MDw9/a/i4rntbRPxFNZoC/5jAV2be759DKTUJ4FZSFFi0bbs/k8noy2R9dAjEuWU2YgXkQOK3kD6BMsysi2Z9JC2Jdcw/ALzwPO+xvmcl7Rj177JVEbkO4BARjSflFDJJuW1dBxJPoCIiL4noDIB1BS0pW6j+oJmbm+uuVqvjRKQfLr0bZHnIzJf0f6HeAybahrUJqAPruhLlcnnPysqKfpXp11n/Gv62zoHAroS+AafT6QkiGrIsazKbzX7eVIHEt1US39gCkOzWYthkjNE+tuZujDGZQ8XRXn8N4KT5lLFZ6uaYPt+nwyDuvC80YdhvB9uOAu1WoaNAR4GIK/AHvdr+QAexB7EAAAAASUVORK5CYII=") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-record:hover{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACfUlEQVRoQ+2ZSYsUQRCFvycK4nJXXEbHBdwO4kn/gv9CD467ICIutxEFkREdFUU86T/xojcPntyQcT2INw+uISFVkD1Wd2dWlU7nUHlqisiX+fJFZGREi8yHMt8/HYG5VrBToFOg4QnMPxcyM2t4KE2nT0i6EwvylwIjQOCFpE1tEPgGfI0FamC3AFgazP8IrJL0KwZzkAI3gLMxIA1ttgCPA4w3wHpJP2NwBxG4KOlcDEgTGzNbA8wEGP57vA0CU5JONtlczFwz2wY8HUbAzBYCB4CtwCVJb33OIAXmioC70LoyBsxsEXAQOApsLIhelnS6FgEzW+5BBvwA/FS+SPJFa40KBZ5L2mxmS4AJ4IjHxCzwaUnHkgmY2V7gLrAyAPwOXJN0qg6DCgIvgQfAPsDjo2pcKddLciEz+wCs6AO6W9KjVBIVBGIgahN4BvRLMjslPYlZPbT53wR2AbeBtcUmXEFPdh5U06mbd/shBBzbr/Jx4FCAX0+BEsDMFocEYrNmFcE+BD4XsXZL0oyZnQCutkagzkn3m1NBwDe/Q9L74MAuFEqUn5op8I8JvJO0elacTALnc1HAH3Njkvwx+WeYWUegTa/pwaqIgexdyIN4uyRPmqULZRXEvulPwD3gpr+zcrtGQxfzRHYG2AAczuUWiom3kc4D2RN4BdwH9gM9CS0XFyoLGu9UuN974eIFVDiuSzruH5LqgRhtU20q8kBPV8LMlhVVmVdnYwX+SMdAZVeieAF7eeltmElJr4cpkH1bJfvGVvatxdR4bMu+teZuWxtKxWncXn8I7EldtQV7vz79fp9KwZp//9CksB8F206BuVahU6BToOEJ/Ab7+KdABdTt8AAAAABJRU5ErkJggg==") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-recordStop{background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-recordStop:hover{background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-fullscreen{background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-fullscreen:hover{background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-fullscreenExit{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAADd0lEQVRoQ+2Zz2sdVRTHv+fJBDW6anDVXen6wZszYxYBiYgtFGst3VSDunKjpS0GpUlqfjVpsVVs6aaL0or4YxMVFCJZ2ZLdPUP+gq5bQnTxtNAkfTnlhnnlkmQy9yV9780rudt77tzv5/y4v4bQ4Y06XD/2ANodwec/AiJygJnvtdvTWfPnRkBEJAiCN8rl8kMfiPn5+Ve7u7v3rays0Orq6lJfX99/PuN2auMDoAD+BvA2M6/mTWSMOUtE48D6AjHGzN/kjdlNvy+AnWOOmQ/lTSYiEwDOWzsimgrDcCRvzG76GwGw8/zJzO9sN6GInAMwbW1UdSSKoqndCMwb6wNwGsB39Q+p6h/M/C4R2dTa1AoHYBWKyCkA1+pqiWi2Wq0e7e/vf7yRoJAAKcQggMtuJKIoOtoxACnE0/xOi/SXMAxPuhCFjUBdpIjYVWXSEf0TM3/g9BeriDMKdSPEz8z8vrU1xgwT0YXCrEJZy1iSJKOqOub0/8jMA0mSfKKqNwoPkHp7ioiGHIhRIvpHVa93BEBa2JcAfOlALAHo6RgAKzRJkk9V1S6xL7kpV4idOM31taxaIKJHqmpPnMMA9hcOQES2PDJkAT1XAAC+ZebPfWB3auNzmLObVsNRUNUXVHUujuM7OxXnMy4XwOcj29mIyOuq+lapVGrYCelKpkEQ3CyXy4tbzdN0AGPMxr2iYZ+sra3FcRybtgCIiK2BKw2rdgaUSqWoUqlIkQAepFDdAF7cBq5ERI9rtdr1OI7tmE2t6SmUEYFHAEaexYW/1QC2EF+ru5GIvg7D0D2GNJxprQY4o6qv1I/b6SpzOYqiLxpWng5oOQAzXxWRWwA+dkRfYOb1p5hGW6sBJpn5KytSRG4D+KguWFXHoyhy7xdeLC0F2ChSRL4H8OFuINoKYIUbY34gogHH3eeZef1K6tPaDpCm068A3nMEDzHzxY4BUNWSiPxORO6z5aDPPlGICNQ9bYyZIaLjjudzIQoFkKbTbwCO+UI0HcB9J/LdeY0xs0R02IGYYObRrWqiFQCfEZEtSHsfmGZm+4qxbbM/hQD8BeBNa0hEM2EYnmgLgP3lFARBT1dXly4vL//b29tbzQNIU+llAHeJaLFSqRzJes5vegR8xGbZLCwsHKzVav8z8/0sm0ID+MDvAfh4qZk2exFopnd9vv0ELrXBQO7fD10AAAAASUVORK5CYII=") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-fullscreenExit:hover{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAC/ElEQVRoQ+2Zy49NQRCHvx+ReK6IlZ34E7CUiCAR4xEbTLCyQRATYswwb2IQZDYWgojHZpCQECts+ResiQwLj0RClNSkb9Lu3HtPz7mZc8+V6eXt6tP1VVV3VdcVbT7U5vozC9BqD/7/HjCzlZLet9rS9fbP9ICZvQPWSfqRAmFmS4ClMHm+JiR9S1mXVyYFwIBXwEZJv7I2MrPjQH8A6JN0OWtNM/OpAL7HS0mbsjYzswGgN8gNS+rJWtPM/HQAfJ9nkrY22tDMTgMjQaZH0nAzCmatTQE4ClyNPvQU2CbJQ2vKKB2Aa2hmR4DrkbbPgQ5Jv6sJSgkQILqA0dgTkjraBiBAxPHtPz2UtDuGKK0HKkqamd8qg5HS9yXtjebLdYjrHNRqiAeS9gQvnQGGSnML1bvGzOwc0BfN35PUaWYHgRulBwjW9ju+O4JwqM/AWFsABIgLwKkIYgJY1jYAAeJQuGIXVIVcKTKxh8WfBin9J+AVpx/eFWUEqFkyNACKp0rhgWYArkg6kQibSyylmPOklQdibijBX+fSLHFRJkDid+qKmdlaYENOI0zeEcBNSZ9qbVIEQHWuyGOTNZLetgrAz8ClPFpHa1ZL8rf5lFGEB2oBfAxQi4D5DeDmAP7mGJPka0oD4LnDr9imH/xFe8AP4vLIjBclxWXItCOtaIBjwOKo3HaFRyWdnLbmYUHhAJKumdkt4ECk9JCkSitmWixFAwxKOjt5uZvdBvZH2vZLit8XSSBFA/yjpJndAfY1A9FSgOCJu0BnBNErqfIkzfRCywECxCNgR6Rtt6TzmdqHBmyKXG4ZM4sTWc04NzNPWE+AuG3ZlZInSuGBinXMbBzYGVkrE6JUACGcHgPbUyGKAIj7REmZ18y897o5ghiQ5E/bltRChwE/kF7Xj0jyLkbDYWbzgBfA+iA4LmlXqwD8LydvszjAF0lfswBCKC0E3gBeP22p186f8RBKUbaejJmtAr5L+lBPptQAKfCzAClWmkmZWQ/MpHVTvv0X9iFAQGQyevIAAAAASUVORK5CYII=") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-audio{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACrUlEQVRoQ+2ZPYgTURCAZzbBXJnCeL2Cnb87b9MEtPBUrrMQFAtrtT5/ClGs9LBWWz0RtbBUFCF4oJDsbO68wsLA2YqQSmLlvpEHu7IuMdlLcus+yUKKhJfZ+ebnvZl5CJY/aLn+MAP41x7M1QPMfFtr/crzvHfTAs8FoNPp1LTWzwHgqIg0lFLvrQHwfX8BER8DwC6jNCIecF13wwoA3/dvIuKNpLJa60Oe560XGoCZd4rICiKeTCtaeABmPg4AJmRqg6xcaABmvg4At4aFRyEBhoVM4UMoCplHADCfJTEL5YEsIVNID5iQAYCHALCYxeq5b6PMfF5EBAAEESthGK7W6/XPRpFWq7W3VCqtZg2ZcT3g+/6i4zjzIlLSWn/yPO/DIGMNLCWY2Sj/+xGRK0qpZfNDEASnROTFVi0fr8+aA8z8Ld6KEfGt67oLYwMAwEUium8EREn7OgeAjwCwPyo/nrque3YSgAtE9GDaAM1mc65arc4Zuf1+P2w0Gt9jJZl5DQAORt+fENG5wgEw8zUAMB/zbBBRwyqAIAjuiMjlSOlNItpjFUCqWl0josMzgChR/9hGAWBbknjmAdPhDdqa0gfZzAMJKyVP4v8hhJYRcSni+0JEu63ahZj5anyQici6UuqIVQDdbrfS6/UqRulyufyTiH5sF8AlIro37VpoWEHIzGZ2tM+sEZFnSqkzk9RCS0R01wjIsZz+mug53hDRia0AnI4bGgDYISItz/M2jYC8Gpp2u30MEWuO4zha665Sqp0ZYFStX/iWchRAItFGzoHSsrJ2ZFl1mHg6bfVYJeGJv85CC++BpIJZ5kSFC6G0ha0e7mYJqcJ7IOkRay84UhD2XjHFIFZf8iW9YcYoYRi+tO6aNeupOs66iU/icV46zf/MAKZpzXFk/QL+JG1PUPhRiQAAAABJRU5ErkJggg==") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-audio:hover{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACSElEQVRoQ+2Zu4sUQRCHf5+C+gf4yBXMfMYHGvjCzEBQDIzV+HwEohipGKupD0QNDE8UEwUFTe68wEDhTMVUMFJ+0tArzbjs9u3Ojt0wBR0M9MzUV1XdXVWNKhcq1189wP/2YKcesH1d0nPgdVvgnQDY3iTpqaT9kuaAt9UA2D4o6aGkzVHpXcByFQC2r0q60lB2D7BUNIDtjZIeSDoyRNGyAWwfiiET4n6YlAtg+7Kka2PCozyAMSHT5CkLIIbMfUlbMhdmOQCZIVOeB2LI3JN0NNPq6bTZe8D2aUmOY72kN8DnoIXt7eF5FSEzkQdsB+OEsFwr6RPwbpixhqYStoPyqVwAbkaAY5KeTWD5wStZHrD9XdJgK34FhBP9H8kFOAvciQBhn3/RAcBHSTvjfx4DJ6cBOAPcbRvA9gZJYQT5DfwYKGl7UdLu+PwIOFUiwCVJYQRZBuZqA7gh6XxUegXYVhtAmq0uAnt7gLhQm9vorBZx74Hcc6D3QLKH/z2JGyVnlYs4pCfzEe4rsLW2XehicpAtAftqAwiZbhhBfgE/ZwVwDrjddi40KiG0HXpHO+KcJ8CJaXKheeBWBOgqnf6W1BwvgcOrATieFDTrJL0HViJAVwXNgVgPrJH0BfiQDTDKtREiNK7KLSnHASQLLacP1PxcVkWWq8PU3emq2yqJJ0b1Qsv2QKpdZp+orBBqmrfq5m5mSJXtgUZI1XnB0YCo94opCal6L/ka3ghtlIXqrllzT9VJ5k19Ek/y0zbf6QHatOYk3/oDujC8QMWgjf4AAAAASUVORK5CYII=") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-mute{background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-mute:hover{background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-text{font-size:14px;width:30px}.jessibuca-container .jessibuca-speed{font-size:14px;color:#fff}.jessibuca-container .jessibuca-quality-menu-list{position:absolute;left:50%;bottom:100%;visibility:hidden;opacity:0;transform:translateX(-50%);transition:visibility .3s,opacity .3s;background-color:rgba(0,0,0,.5);border-radius:4px}.jessibuca-container .jessibuca-quality-menu-list.jessibuca-quality-menu-shown{visibility:visible;opacity:1}.jessibuca-container .icon-title-tips{pointer-events:none;position:absolute;left:50%;bottom:100%;visibility:hidden;opacity:0;transform:translateX(-50%);transition:visibility .3s ease 0s,opacity .3s ease 0s;background-color:rgba(0,0,0,.5);border-radius:4px}.jessibuca-container .icon-title{display:inline-block;padding:5px 10px;font-size:12px;white-space:nowrap;color:#fff}.jessibuca-container .jessibuca-quality-menu{padding:8px 0}.jessibuca-container .jessibuca-quality-menu-item{display:block;height:25px;margin:0;padding:0 10px;cursor:pointer;font-size:14px;text-align:center;width:50px;color:hsla(0,0%,100%,.5);transition:color .3s,background-color .3s}.jessibuca-container .jessibuca-quality-menu-item:hover{background-color:hsla(0,0%,100%,.2)}.jessibuca-container .jessibuca-quality-menu-item:focus{outline:none}.jessibuca-container .jessibuca-quality-menu-item.jessibuca-quality-menu-item-active{color:#2298fc}.jessibuca-container .jessibuca-volume-panel-wrap{position:absolute;left:50%;bottom:100%;visibility:hidden;opacity:0;transform:translateX(-50%) translateY(22%);transition:visibility .3s,opacity .3s;background-color:rgba(0,0,0,.5);border-radius:4px;height:120px;width:50px;overflow:hidden}.jessibuca-container .jessibuca-volume-panel-wrap.jessibuca-volume-panel-wrap-show{visibility:visible;opacity:1}.jessibuca-container .jessibuca-volume-panel{cursor:pointer;position:absolute;top:21px;height:60px;width:50px;overflow:hidden}.jessibuca-container .jessibuca-volume-panel-text{position:absolute;left:0;top:0;width:50px;height:20px;line-height:20px;text-align:center;color:#fff;font-size:12px}.jessibuca-container .jessibuca-volume-panel-handle{position:absolute;top:48px;left:50%;width:12px;height:12px;border-radius:12px;margin-left:-6px;background:#fff}.jessibuca-container .jessibuca-volume-panel-handle:before{bottom:-54px;background:#fff}.jessibuca-container .jessibuca-volume-panel-handle:after{bottom:6px;background:hsla(0,0%,100%,.2)}.jessibuca-container .jessibuca-volume-panel-handle:after,.jessibuca-container .jessibuca-volume-panel-handle:before{content:"";position:absolute;display:block;left:50%;width:3px;margin-left:-1px;height:60px}.jessibuca-container.jessibuca-fullscreen-web .jessibuca-controls{width:100vh;transform:translateX(-13vw) translateY(-47.8vh) rotate(270deg);transition:width .5s ease-in}.jessibuca-container.jessibuca-fullscreen-web .jessibuca-play-big:after{transform:rotate(270deg)}.jessibuca-container.jessibuca-fullscreen-web .jessibuca-loading{flex-direction:row}.jessibuca-container.jessibuca-fullscreen-web .jessibuca-loading-text{transform:rotate(270deg)}');class He{constructor(e){var t;this.player=e,((e,t)=>{e._opt.hasControl&&e._opt.controlAutoHide?e.$container.classList.add("jessibuca-controls-show-auto-hide"):e.$container.classList.add("jessibuca-controls-show");const i=e._opt,o=i.operateBtns;e.$container.insertAdjacentHTML("beforeend",`\n ${i.background?`<div class="jessibuca-poster" style="background-image: url(${i.background})"></div>`:""}\n <div class="jessibuca-loading">\n ${Pe.loading}\n ${i.loadingText?`<div class="jessibuca-loading-text">${i.loadingText}</div>`:""}\n </div>\n ${i.hasControl&&o.play?'<div class="jessibuca-play-big"></div>':""}\n ${i.hasControl?`\n <div class="jessibuca-controls">\n <div class="jessibuca-controls-bottom">\n <div class="jessibuca-controls-left">\n ${i.showBandwidth?'<div class="jessibuca-controls-item jessibuca-speed"></div>':""}\n </div>\n <div class="jessibuca-controls-right">\n ${o.audio?`\n <div class="jessibuca-controls-item jessibuca-volume">\n ${Pe.audio}\n ${Pe.mute}\n <div class="jessibuca-volume-panel-wrap">\n <div class="jessibuca-volume-panel">\n <div class="jessibuca-volume-panel-handle"></div>\n </div>\n <div class="jessibuca-volume-panel-text"></div>\n </div>\n </div>\n `:""}\n ${o.play?`<div class="jessibuca-controls-item jessibuca-play">${Pe.play}</div><div class="jessibuca-controls-item jessibuca-pause">${Pe.pause}</div>`:""}\n ${o.screenshot?`<div class="jessibuca-controls-item jessibuca-screenshot">${Pe.screenshot}</div>`:""}\n ${o.record?` <div class="jessibuca-controls-item jessibuca-record">${Pe.record}</div><div class="jessibuca-controls-item jessibuca-record-stop">${Pe.recordStop}</div>`:""}\n ${o.fullscreen?`<div class="jessibuca-controls-item jessibuca-fullscreen">${Pe.fullscreen}</div><div class="jessibuca-controls-item jessibuca-fullscreen-exit">${Pe.fullscreenExit}</div>`:""}\n </div>\n </div>\n </div>\n `:""}\n\n `),Object.defineProperty(t,"$poster",{value:e.$container.querySelector(".jessibuca-poster")}),Object.defineProperty(t,"$loading",{value:e.$container.querySelector(".jessibuca-loading")}),Object.defineProperty(t,"$play",{value:e.$container.querySelector(".jessibuca-play")}),Object.defineProperty(t,"$playBig",{value:e.$container.querySelector(".jessibuca-play-big")}),Object.defineProperty(t,"$pause",{value:e.$container.querySelector(".jessibuca-pause")}),Object.defineProperty(t,"$controls",{value:e.$container.querySelector(".jessibuca-controls")}),Object.defineProperty(t,"$fullscreen",{value:e.$container.querySelector(".jessibuca-fullscreen")}),Object.defineProperty(t,"$fullscreen",{value:e.$container.querySelector(".jessibuca-fullscreen")}),Object.defineProperty(t,"$volume",{value:e.$container.querySelector(".jessibuca-volume")}),Object.defineProperty(t,"$volumePanelWrap",{value:e.$container.querySelector(".jessibuca-volume-panel-wrap")}),Object.defineProperty(t,"$volumePanelText",{value:e.$container.querySelector(".jessibuca-volume-panel-text")}),Object.defineProperty(t,"$volumePanel",{value:e.$container.querySelector(".jessibuca-volume-panel")}),Object.defineProperty(t,"$volumeHandle",{value:e.$container.querySelector(".jessibuca-volume-panel-handle")}),Object.defineProperty(t,"$volumeOn",{value:e.$container.querySelector(".jessibuca-icon-audio")}),Object.defineProperty(t,"$volumeOff",{value:e.$container.querySelector(".jessibuca-icon-mute")}),Object.defineProperty(t,"$fullscreen",{value:e.$container.querySelector(".jessibuca-fullscreen")}),Object.defineProperty(t,"$fullscreenExit",{value:e.$container.querySelector(".jessibuca-fullscreen-exit")}),Object.defineProperty(t,"$record",{value:e.$container.querySelector(".jessibuca-record")}),Object.defineProperty(t,"$recordStop",{value:e.$container.querySelector(".jessibuca-record-stop")}),Object.defineProperty(t,"$screenshot",{value:e.$container.querySelector(".jessibuca-screenshot")}),Object.defineProperty(t,"$speed",{value:e.$container.querySelector(".jessibuca-speed")})})(e,this),ze(e,this),t=this,Object.defineProperty(t,"controlsRect",{get:()=>t.$controls.getBoundingClientRect()}),((e,t)=>{const{events:{proxy:i},debug:o}=e;function r(e){const{bottom:i,height:o}=t.$volumePanel.getBoundingClientRect(),{height:r}=t.$volumeHandle.getBoundingClientRect();return pe(i-e.y-r/2,0,o-r/2)/(o-r)}i(window,["click","contextmenu"],(i=>{i.composedPath().indexOf(e.$container)>-1?t.isFocus=!0:t.isFocus=!1})),i(window,"orientationchange",(()=>{setTimeout((()=>{e.resize()}),300)})),i(t.$controls,"click",(e=>{e.stopPropagation()})),i(t.$pause,"click",(t=>{e.pause()})),i(t.$play,"click",(t=>{e.play()})),i(t.$playBig,"click",(t=>{e.play()})),i(t.$volume,"mouseover",(()=>{t.$volumePanelWrap.classList.add("jessibuca-volume-panel-wrap-show")})),i(t.$volume,"mouseout",(()=>{t.$volumePanelWrap.classList.remove("jessibuca-volume-panel-wrap-show")})),i(t.$volumeOn,"click",(i=>{i.stopPropagation(),me(t.$volumeOn,"display","none"),me(t.$volumeOff,"display","block"),e.lastVolume=e.volume,e.volume=0})),i(t.$volumeOff,"click",(i=>{i.stopPropagation(),me(t.$volumeOn,"display","block"),me(t.$volumeOff,"display","none"),e.volume=e.lastVolume||.5})),i(t.$screenshot,"click",(t=>{t.stopPropagation(),e.video.screenshot()})),i(t.$volumePanel,"click",(t=>{t.stopPropagation(),e.volume=r(t)})),i(t.$volumeHandle,"mousedown",(()=>{t.isVolumeDroging=!0})),i(t.$volumeHandle,"mousemove",(i=>{t.isVolumeDroging&&(e.volume=r(i))})),i(document,"mouseup",(()=>{t.isVolumeDroging&&(t.isVolumeDroging=!1)})),i(t.$record,"click",(t=>{t.stopPropagation(),e.recording=!0})),i(t.$recordStop,"click",(t=>{t.stopPropagation(),e.recording=!1})),i(t.$fullscreen,"click",(t=>{t.stopPropagation(),e.fullscreen=!0})),i(t.$fullscreenExit,"click",(t=>{t.stopPropagation(),e.fullscreen=!1})),e._opt.hasControl&&e._opt.controlAutoHide&&(i(e.$container,"mouseover",(()=>{e.fullscreen||me(t.$controls,"display","block")})),i(e.$container,"mouseout",(()=>{me(t.$controls,"display","none")})))})(e,this),e._opt.hotKey&&((e,t)=>{const{events:{proxy:i}}=e,o={};function r(e,t){o[e]?o[e].push(t):o[e]=[t]}r(re,(()=>{e.fullscreen&&(e.fullscreen=!1)})),r(Ae,(()=>{e.volume+=.05})),r(se,(()=>{e.volume-=.05})),i(window,"keydown",(e=>{if(t.isFocus){const t=document.activeElement.tagName.toUpperCase(),i=document.activeElement.getAttribute("contenteditable");if("INPUT"!==t&&"TEXTAREA"!==t&&""!==i&&"true"!==i){const t=o[e.keyCode];t&&(e.preventDefault(),t.forEach((e=>e())))}}}))})(e,this),this.player.debug.log("Control","init")}destroy(){this.$poster&&this.player.$container.removeChild(this.$poster),this.$loading&&this.player.$container.removeChild(this.$loading),this.$controls&&this.player.$container.removeChild(this.$controls),this.$playBig&&this.player.$container.removeChild(this.$playBig),this.player.debug.log("control","destroy")}autoSize(){const e=this.player;e.$container.style.padding="0 0";const t=e.width,i=e.height,o=t/i,r=e.video.$videoElement.width/e.video.$videoElement.height;if(o>r){const o=(t-i*r)/2;e.$container.style.padding=`0 ${o}px`}else{const o=(i-t/r)/2;e.$container.style.padding=`${o}px 0`}}}Ye(".jessibuca-container{position:relative;width:100%;height:100%;overflow:hidden}.jessibuca-container.jessibuca-fullscreen-web{position:fixed;z-index:9999;left:0;top:0;right:0;bottom:0;width:100vw!important;height:100vh!important;background:#000}");class Xe{static init(){Xe.types={avc1:[],avcC:[],hvc1:[],hvcC:[],btrt:[],dinf:[],dref:[],esds:[],ftyp:[],hdlr:[],mdat:[],mdhd:[],mdia:[],mfhd:[],minf:[],moof:[],moov:[],mp4a:[],mvex:[],mvhd:[],sdtp:[],stbl:[],stco:[],stsc:[],stsd:[],stsz:[],stts:[],tfdt:[],tfhd:[],traf:[],trak:[],trun:[],trex:[],tkhd:[],vmhd:[],smhd:[]};for(let e in Xe.types)Xe.types.hasOwnProperty(e)&&(Xe.types[e]=[e.charCodeAt(0),e.charCodeAt(1),e.charCodeAt(2),e.charCodeAt(3)]);let e=Xe.constants={};e.FTYP=new Uint8Array([105,115,111,109,0,0,0,1,105,115,111,109,97,118,99,49]),e.STSD_PREFIX=new Uint8Array([0,0,0,0,0,0,0,1]),e.STTS=new Uint8Array([0,0,0,0,0,0,0,0]),e.STSC=e.STCO=e.STTS,e.STSZ=new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]),e.HDLR_VIDEO=new Uint8Array([0,0,0,0,0,0,0,0,118,105,100,101,0,0,0,0,0,0,0,0,0,0,0,0,86,105,100,101,111,72,97,110,100,108,101,114,0]),e.HDLR_AUDIO=new Uint8Array([0,0,0,0,0,0,0,0,115,111,117,110,0,0,0,0,0,0,0,0,0,0,0,0,83,111,117,110,100,72,97,110,100,108,101,114,0]),e.DREF=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,12,117,114,108,32,0,0,0,1]),e.SMHD=new Uint8Array([0,0,0,0,0,0,0,0]),e.VMHD=new Uint8Array([0,0,0,1,0,0,0,0,0,0,0,0])}static box(e){let t=8,i=null,o=Array.prototype.slice.call(arguments,1),r=o.length;for(let e=0;e<r;e++)t+=o[e].byteLength;i=new Uint8Array(t),i[0]=t>>>24&255,i[1]=t>>>16&255,i[2]=t>>>8&255,i[3]=255&t,i.set(e,4);let A=8;for(let e=0;e<r;e++)i.set(o[e],A),A+=o[e].byteLength;return i}static generateInitSegment(e){let t=Xe.box(Xe.types.ftyp,Xe.constants.FTYP),i=Xe.moov(e),o=new Uint8Array(t.byteLength+i.byteLength);return o.set(t,0),o.set(i,t.byteLength),o}static moov(e){let t=Xe.mvhd(e.timescale,e.duration),i=Xe.trak(e),o=Xe.mvex(e);return Xe.box(Xe.types.moov,t,i,o)}static mvhd(e,t){return Xe.box(Xe.types.mvhd,new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,e>>>24&255,e>>>16&255,e>>>8&255,255&e,t>>>24&255,t>>>16&255,t>>>8&255,255&t,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255]))}static trak(e){return Xe.box(Xe.types.trak,Xe.tkhd(e),Xe.mdia(e))}static tkhd(e){let t=e.id,i=e.duration,o=e.presentWidth,r=e.presentHeight;return Xe.box(Xe.types.tkhd,new Uint8Array([0,0,0,7,0,0,0,0,0,0,0,0,t>>>24&255,t>>>16&255,t>>>8&255,255&t,0,0,0,0,i>>>24&255,i>>>16&255,i>>>8&255,255&i,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,o>>>8&255,255&o,0,0,r>>>8&255,255&r,0,0]))}static mdia(e){return Xe.box(Xe.types.mdia,Xe.mdhd(e),Xe.hdlr(e),Xe.minf(e))}static mdhd(e){let t=e.timescale,i=e.duration;return Xe.box(Xe.types.mdhd,new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,t>>>24&255,t>>>16&255,t>>>8&255,255&t,i>>>24&255,i>>>16&255,i>>>8&255,255&i,85,196,0,0]))}static hdlr(e){let t=null;return t="audio"===e.type?Xe.constants.HDLR_AUDIO:Xe.constants.HDLR_VIDEO,Xe.box(Xe.types.hdlr,t)}static minf(e){let t=null;return t="audio"===e.type?Xe.box(Xe.types.smhd,Xe.constants.SMHD):Xe.box(Xe.types.vmhd,Xe.constants.VMHD),Xe.box(Xe.types.minf,t,Xe.dinf(),Xe.stbl(e))}static dinf(){return Xe.box(Xe.types.dinf,Xe.box(Xe.types.dref,Xe.constants.DREF))}static stbl(e){return Xe.box(Xe.types.stbl,Xe.stsd(e),Xe.box(Xe.types.stts,Xe.constants.STTS),Xe.box(Xe.types.stsc,Xe.constants.STSC),Xe.box(Xe.types.stsz,Xe.constants.STSZ),Xe.box(Xe.types.stco,Xe.constants.STCO))}static stsd(e){return"audio"===e.type?Xe.box(Xe.types.stsd,Xe.constants.STSD_PREFIX,Xe.mp4a(e)):"avc"===e.videoType?Xe.box(Xe.types.stsd,Xe.constants.STSD_PREFIX,Xe.avc1(e)):Xe.box(Xe.types.stsd,Xe.constants.STSD_PREFIX,Xe.hvc1(e))}static mp4a(e){let t=e.channelCount,i=e.audioSampleRate,o=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,t,0,16,0,0,0,0,i>>>8&255,255&i,0,0]);return Xe.box(Xe.types.mp4a,o,Xe.esds(e))}static esds(e){let t=e.config||[],i=t.length,o=new Uint8Array([0,0,0,0,3,23+i,0,1,0,4,15+i,64,21,0,0,0,0,0,0,0,0,0,0,0,5].concat([i]).concat(t).concat([6,1,2]));return Xe.box(Xe.types.esds,o)}static avc1(e){let t=e.avcc;const i=e.codecWidth,o=e.codecHeight;let r=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,i>>>8&255,255&i,o>>>8&255,255&o,0,72,0,0,0,72,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,255,255]);return Xe.box(Xe.types.avc1,r,Xe.box(Xe.types.avcC,t))}static hvc1(e){let t=e.avcc;const i=e.codecWidth,o=e.codecHeight;let r=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,i>>>8&255,255&i,o>>>8&255,255&o,0,72,0,0,0,72,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,255,255]);return Xe.box(Xe.types.hvc1,r,Xe.box(Xe.types.hvcC,t))}static mvex(e){return Xe.box(Xe.types.mvex,Xe.trex(e))}static trex(e){let t=e.id,i=new Uint8Array([0,0,0,0,t>>>24&255,t>>>16&255,t>>>8&255,255&t,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1]);return Xe.box(Xe.types.trex,i)}static moof(e,t){return Xe.box(Xe.types.moof,Xe.mfhd(e.sequenceNumber),Xe.traf(e,t))}static mfhd(e){let t=new Uint8Array([0,0,0,0,e>>>24&255,e>>>16&255,e>>>8&255,255&e]);return Xe.box(Xe.types.mfhd,t)}static traf(e,t){let i=e.id,o=Xe.box(Xe.types.tfhd,new Uint8Array([0,0,0,0,i>>>24&255,i>>>16&255,i>>>8&255,255&i])),r=Xe.box(Xe.types.tfdt,new Uint8Array([0,0,0,0,t>>>24&255,t>>>16&255,t>>>8&255,255&t])),A=Xe.sdtp(e),s=Xe.trun(e,A.byteLength+16+16+8+16+8+8);return Xe.box(Xe.types.traf,o,r,s,A)}static sdtp(e){let t=new Uint8Array(5),i=e.flags;return t[4]=i.isLeading<<6|i.dependsOn<<4|i.isDependedOn<<2|i.hasRedundancy,Xe.box(Xe.types.sdtp,t)}static trun(e,t){let i=new Uint8Array(28);t+=36,i.set([0,0,15,1,0,0,0,1,t>>>24&255,t>>>16&255,t>>>8&255,255&t],0);let o=e.duration,r=e.size,A=e.flags,s=e.cts;return i.set([o>>>24&255,o>>>16&255,o>>>8&255,255&o,r>>>24&255,r>>>16&255,r>>>8&255,255&r,A.isLeading<<2|A.dependsOn,A.isDependedOn<<6|A.hasRedundancy<<4|A.isNonSync,0,0,s>>>24&255,s>>>16&255,s>>>8&255,255&s],12),Xe.box(Xe.types.trun,i)}static mdat(e){return Xe.box(Xe.types.mdat,e)}}Xe.init();class Ze{constructor(e){this.TAG="ExpGolomb",this._buffer=e,this._buffer_index=0,this._total_bytes=e.byteLength,this._total_bits=8*e.byteLength,this._current_word=0,this._current_word_bits_left=0}destroy(){this._buffer=null}_fillCurrentWord(){let e=this._total_bytes-this._buffer_index,t=Math.min(4,e),i=new Uint8Array(4);i.set(this._buffer.subarray(this._buffer_index,this._buffer_index+t)),this._current_word=new DataView(i.buffer).getUint32(0,!1),this._buffer_index+=t,this._current_word_bits_left=8*t}readBits(e){if(e<=this._current_word_bits_left){let t=this._current_word>>>32-e;return this._current_word<<=e,this._current_word_bits_left-=e,t}let t=this._current_word_bits_left?this._current_word:0;t>>>=32-this._current_word_bits_left;let i=e-this._current_word_bits_left;this._fillCurrentWord();let o=Math.min(i,this._current_word_bits_left),r=this._current_word>>>32-o;return this._current_word<<=o,this._current_word_bits_left-=o,t=t<<o|r,t}readBool(){return 1===this.readBits(1)}readByte(){return this.readBits(8)}_skipLeadingZero(){let e;for(e=0;e<this._current_word_bits_left;e++)if(0!=(this._current_word&2147483648>>>e))return this._current_word<<=e,this._current_word_bits_left-=e,e;return this._fillCurrentWord(),e+this._skipLeadingZero()}readUEG(){let e=this._skipLeadingZero();return this.readBits(e+1)-1}readSEG(){let e=this.readUEG();return 1&e?e+1>>>1:-1*(e>>>1)}}class qe{static _ebsp2rbsp(e){let t=e,i=t.byteLength,o=new Uint8Array(i),r=0;for(let e=0;e<i;e++)e>=2&&3===t[e]&&0===t[e-1]&&0===t[e-2]||(o[r]=t[e],r++);return new Uint8Array(o.buffer,0,r)}static parseSPS(e){let t=qe._ebsp2rbsp(e),i=new Ze(t);i.readByte();let o=i.readByte();i.readByte();let r=i.readByte();i.readUEG();let A=qe.getProfileString(o),s=qe.getLevelString(r),n=1,a=420,d=[0,420,422,444],c=8;if((100===o||110===o||122===o||244===o||44===o||83===o||86===o||118===o||128===o||138===o||144===o)&&(n=i.readUEG(),3===n&&i.readBits(1),n<=3&&(a=d[n]),c=i.readUEG()+8,i.readUEG(),i.readBits(1),i.readBool())){let e=3!==n?8:12;for(let t=0;t<e;t++)i.readBool()&&(t<6?qe._skipScalingList(i,16):qe._skipScalingList(i,64))}i.readUEG();let l=i.readUEG();if(0===l)i.readUEG();else if(1===l){i.readBits(1),i.readSEG(),i.readSEG();let e=i.readUEG();for(let t=0;t<e;t++)i.readSEG()}let u=i.readUEG();i.readBits(1);let h=i.readUEG(),p=i.readUEG(),m=i.readBits(1);0===m&&i.readBits(1),i.readBits(1);let g=0,f=0,b=0,y=0;i.readBool()&&(g=i.readUEG(),f=i.readUEG(),b=i.readUEG(),y=i.readUEG());let v=1,w=1,S=0,E=!0,B=0,C=0;if(i.readBool()){if(i.readBool()){let e=i.readByte(),t=[1,12,10,16,40,24,20,32,80,18,15,64,160,4,3,2],o=[1,11,11,11,33,11,11,11,33,11,11,33,99,3,2,1];e>0&&e<16?(v=t[e-1],w=o[e-1]):255===e&&(v=i.readByte()<<8|i.readByte(),w=i.readByte()<<8|i.readByte())}if(i.readBool()&&i.readBool(),i.readBool()&&(i.readBits(4),i.readBool()&&i.readBits(24)),i.readBool()&&(i.readUEG(),i.readUEG()),i.readBool()){let e=i.readBits(32),t=i.readBits(32);E=i.readBool(),B=t,C=2*e,S=B/C}}let R=1;1===v&&1===w||(R=v/w);let k=0,T=0;if(0===n)k=1,T=2-m;else{k=3===n?1:2,T=(1===n?2:1)*(2-m)}let I=16*(h+1),x=16*(p+1)*(2-m);I-=(g+f)*k,x-=(b+y)*T;let D=Math.ceil(I*R);return i.destroy(),i=null,{profile_string:A,level_string:s,bit_depth:c,ref_frames:u,chroma_format:a,chroma_format_string:qe.getChromaFormatString(a),frame_rate:{fixed:E,fps:S,fps_den:C,fps_num:B},sar_ratio:{width:v,height:w},codec_size:{width:I,height:x},present_size:{width:D,height:x}}}static _skipScalingList(e,t){let i=8,o=8,r=0;for(let A=0;A<t;A++)0!==o&&(r=e.readSEG(),o=(i+r+256)%256),i=0===o?i:o}static getProfileString(e){switch(e){case 66:return"Baseline";case 77:return"Main";case 88:return"Extended";case 100:return"High";case 110:return"High10";case 122:return"High422";case 244:return"High444";default:return"Unknown"}}static getLevelString(e){return(e/10).toFixed(1)}static getChromaFormatString(e){switch(e){case 420:return"4:2:0";case 422:return"4:2:2";case 444:return"4:4:4";default:return"Unknown"}}}class Ke extends Be{constructor(e){super(),this.player=e,this.isAvc=!0,this.mediaSource=new window.MediaSource,this.sourceBuffer=null,this.hasInit=!1,this.isInitInfo=!1,this.cacheTrack={},this.timeInit=!1,this.sequenceNumber=0,this.mediaSourceOpen=!1,this.bufferList=[],this.dropping=!1,this.player.video.$videoElement.src=window.URL.createObjectURL(this.mediaSource);const{debug:t,events:{proxy:i}}=e;i(this.mediaSource,"sourceopen",(()=>{this.mediaSourceOpen=!0,this.player.emit(T.mseSourceOpen)})),i(this.mediaSource,"sourceclose",(()=>{this.player.emit(T.mseSourceClose)})),e.debug.log("MediaSource","init")}destroy(){this.stop(),this.bufferList=[],this.mediaSource=null,this.mediaSourceOpen=!1,this.sourceBuffer=null,this.hasInit=!1,this.isInitInfo=!1,this.sequenceNumber=0,this.cacheTrack=null,this.timeInit=!1,this.off(),this.player.debug.log("MediaSource","destroy")}get state(){return this.mediaSource.readyState}get isStateOpen(){return this.state===te}get isStateClosed(){return this.state===ie}get isStateEnded(){return this.state===ee}get duration(){return this.mediaSource.duration}set duration(e){this.mediaSource.duration=e}decodeVideo(e,t,i){const o=this.player;if(this.hasInit)this._decodeVideo(e,t,i);else if(i&&0===e[1]){const r=15&e[0];if(o.video.updateVideoInfo({encTypeCode:r}),r===M)return void this.emit(x.mediaSourceH265NotSupport);o._times.decodeStart||(o._times.decodeStart=he()),this._decodeConfigurationRecord(e,t,i,r),this.hasInit=!0}}_doDecode(){const e=this.bufferList.shift();e&&this._decodeVideo(e.payload,e.ts,e.isIframe)}_decodeConfigurationRecord(e,t,i,o){let r=e.slice(5),A={};o===O?A=function(e){const t={},i=new DataView(e.buffer);let o=i.getUint8(0),r=i.getUint8(1);if(i.getUint8(2),i.getUint8(3),1!==o||0===r)return;const A=1+(3&i.getUint8(4));if(3!==A&&4!==A)return;let s=31&i.getUint8(5);if(0===s)return;let n=6;for(let o=0;o<s;o++){let r=i.getUint16(n,!1);if(n+=2,0===r)continue;let A=new Uint8Array(e.buffer,n,r);n+=r;let s=qe.parseSPS(A);if(0!==o)continue;t.codecWidth=s.codec_size.width,t.codecHeight=s.codec_size.height,t.presentWidth=s.present_size.width,t.presentHeight=s.present_size.height,t.profile=s.profile_string,t.level=s.level_string,t.bitDepth=s.bit_depth,t.chromaFormat=s.chroma_format,t.sarRatio=s.sar_ratio,t.frameRate=s.frame_rate,!1!==s.frame_rate.fixed&&0!==s.frame_rate.fps_num&&0!==s.frame_rate.fps_den||(t.frameRate={});let a=t.frameRate.fps_den,d=t.frameRate.fps_num;t.refSampleDuration=t.timescale*(a/d);let c=A.subarray(1,4),l="avc1.";for(let e=0;e<3;e++){let t=c[e].toString(16);t.length<2&&(t="0"+t),l+=t}t.codec=l}let a=i.getUint8(n);if(0!==a){n++;for(let t=0;t<a;t++){let t=i.getUint16(n,!1);n+=2,0!==t&&(new Uint8Array(e.buffer,n,t),n+=t)}return t.videoType="avc",t}}(r):o===M&&(A=function(e){const t={videoType:"hevc"};let i=23;if(e[i]!==W)return t;i+=2,i+=1;const o=e[i+1]|e[i]<<8;i+=2;const r=e.slice(i,i+o);if(console.log(Uint8Array.from(r)),i+=o,e[i]!==G)return t;i+=2,i+=1;const A=e[i+1]|e[i]<<8;i+=2;const s=e.slice(i,i+A);if(console.log(Uint8Array.from(s)),i+=A,e[i]!==J)return t;i+=2,i+=1;const n=e[i+1]|e[i]<<8;i+=2;const a=e.slice(i,i+n);console.log(Uint8Array.from(a));let d=Uint8Array.from(s),c=class{static parseSPS(e){}}.parseSPS(d);return t.codecWidth=c.codec_size.width,t.codecHeight=c.codec_size.height,t.presentWidth=c.present_size.width,t.presentHeight=c.present_size.height,t.profile=c.profile_string,t.level=c.level_string,t.bitDepth=c.bit_depth,t.chromaFormat=c.chroma_format,t.sarRatio=c.sar_ratio,t}(r));const s={id:1,type:"video",timescale:1e3,duration:0,avcc:r,codecWidth:A.codecWidth,codecHeight:A.codecHeight,videoType:A.videoType},n=Xe.generateInitSegment(s);this.isAvc=!0,this.appendBuffer(n.buffer),this.sequenceNumber=0,this.cacheTrack=null,this.timeInit=!1}_decodeVideo(e,t,i){const o=this.player;let r=e.slice(5),A=r.byteLength,s=t;const n=o.video.$videoElement;if(n.buffered.length>1&&(this.removeBuffer(n.buffered.start(0),n.buffered.end(0)),this.timeInit=!1),this.dropping&&s-this.cacheTrack.dts>1e3)this.dropping=!1,this.cacheTrack={};else if(this.cacheTrack&&s>this.cacheTrack.dts){let e=8+this.cacheTrack.size,i=new Uint8Array(e);i[0]=e>>>24&255,i[1]=e>>>16&255,i[2]=e>>>8&255,i[3]=255&e,i.set(Xe.types.mdat,4),i.set(this.cacheTrack.data,8),this.cacheTrack.duration=s-this.cacheTrack.dts;let r=Xe.moof(this.cacheTrack,this.cacheTrack.dts),A=new Uint8Array(r.byteLength+i.byteLength);A.set(r,0),A.set(i,r.byteLength),this.appendBuffer(A.buffer),o.handleRender(),o.updateStats({fps:!0,ts:t,buf:o.demux.delay}),o._times.videoStart||(o._times.videoStart=he(),o.handlePlayToRenderTimes())}else o.debug.log("MediaSource","timeInit set false , cacheTrack = {}"),this.timeInit=!1,this.cacheTrack={};this.cacheTrack.id=1,this.cacheTrack.sequenceNumber=++this.sequenceNumber,this.cacheTrack.size=A,this.cacheTrack.dts=s,this.cacheTrack.cts=0,this.cacheTrack.isKeyframe=i,this.cacheTrack.data=r,this.cacheTrack.flags={isLeading:0,dependsOn:i?2:1,isDependedOn:i?1:0,hasRedundancy:0,isNonSync:i?0:1},this.timeInit||1!==n.buffered.length||(o.debug.log("MediaSource","timeInit set true"),this.timeInit=!0,n.currentTime=n.buffered.end(0)),!this.isInitInfo&&n.videoWidth>0&&n.videoHeight>0&&(o.debug.log("MediaSource",`updateVideoInfo: ${n.videoWidth},${n.videoHeight}`),o.video.updateVideoInfo({width:n.videoWidth,height:n.videoHeight}),o.video.initCanvasViewSize(),this.isInitInfo=!0)}appendBuffer(e){const{debug:t,events:{proxy:i}}=this.player;null===this.sourceBuffer&&(this.sourceBuffer=this.mediaSource.addSourceBuffer($),i(this.sourceBuffer,"error",(e=>{this.player.emit(T.mseSourceBufferError,e)}))),!1===this.sourceBuffer.updating&&this.isStateOpen?this.sourceBuffer.appendBuffer(e):this.isStateClosed?this.player.emit(T.mseSourceBufferError,"mediaSource is not attached to video or mediaSource is closed"):this.isStateEnded?this.player.emit(T.mseSourceBufferError,"mediaSource is closed"):!0===this.sourceBuffer.updating&&this.player.emit(T.mseSourceBufferBusy)}stop(){this.isStateOpen&&this.sourceBuffer&&this.sourceBuffer.abort(),this.endOfStream()}dropSourceBuffer(e){const t=this.player.video.$videoElement;this.dropping=e,t.buffered.length>0&&t.buffered.end(0)-t.currentTime>1&&(t.currentTime=t.buffered.end(0))}removeBuffer(e,t){if(this.isStateOpen&&!1===this.sourceBuffer.updating)try{this.sourceBuffer.remove(e,t)}catch(e){console.error(e)}}endOfStream(){this.isStateOpen&&this.mediaSource.endOfStream()}}const _e=()=>"undefined"!=typeof navigator&&parseFloat((""+(/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_",".").replace("_",""))<10&&!window.MSStream,$e=()=>"wakeLock"in navigator;class et{constructor(e){if(this.player=e,this.enabled=!1,$e()){this._wakeLock=null;const e=()=>{null!==this._wakeLock&&"visible"===document.visibilityState&&this.enable()};document.addEventListener("visibilitychange",e),document.addEventListener("fullscreenchange",e)}else _e()?this.noSleepTimer=null:(this.noSleepVideo=document.createElement("video"),this.noSleepVideo.setAttribute("title","No Sleep"),this.noSleepVideo.setAttribute("playsinline",""),this._addSourceToVideo(this.noSleepVideo,"webm","data:video/webm;base64,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"),this._addSourceToVideo(this.noSleepVideo,"mp4","data:video/mp4;base64,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"),this.noSleepVideo.addEventListener("loadedmetadata",(()=>{this.noSleepVideo.duration<=1?this.noSleepVideo.setAttribute("loop",""):this.noSleepVideo.addEventListener("timeupdate",(()=>{this.noSleepVideo.currentTime>.5&&(this.noSleepVideo.currentTime=Math.random())}))})))}_addSourceToVideo(e,t,i){var o=document.createElement("source");o.src=i,o.type=`video/${t}`,e.appendChild(o)}get isEnabled(){return this.enabled}enable(){const e=this.player.debug;if($e())return navigator.wakeLock.request("screen").then((t=>{this._wakeLock=t,this.enabled=!0,e.log("wakeLock","Wake Lock active."),this._wakeLock.addEventListener("release",(()=>{e.log("wakeLock","Wake Lock released.")}))})).catch((t=>{throw this.enabled=!1,e.error("wakeLock",`${t.name}, ${t.message}`),t}));if(_e())return this.disable(),this.noSleepTimer=window.setInterval((()=>{document.hidden||(window.location.href=window.location.href.split("#")[0],window.setTimeout(window.stop,0))}),15e3),this.enabled=!0,Promise.resolve();return this.noSleepVideo.play().then((e=>(this.enabled=!0,e))).catch((e=>{throw this.enabled=!1,e}))}disable(){const e=this.player.debug;$e()?(this._wakeLock&&this._wakeLock.release(),this._wakeLock=null):_e()?this.noSleepTimer&&(e.warn("wakeLock","NoSleep now disabled for older iOS devices."),window.clearInterval(this.noSleepTimer),this.noSleepTimer=null):this.noSleepVideo.pause(),this.enabled=!1}}class tt extends Be{constructor(e,t){var i;super(),this.$container=e,this._opt=Object.assign({},d,t),this.debug=new ne(this),this._opt.useWCS&&(this._opt.useWCS="VideoEncoder"in window),this._opt.useMSE&&(this._opt.useMSE=window.MediaSource&&window.MediaSource.isTypeSupported($)),this._opt.useMSE?(this._opt.useWCS&&this.debug.log("Player","useWCS set true->false"),this._opt.forceNoOffscreen||this.debug.log("Player","forceNoOffscreen set false->true"),this._opt.useWCS=!1,this._opt.forceNoOffscreen=!0):this._opt.useWCS,this._opt.forceNoOffscreen||("undefined"==typeof OffscreenCanvas?(this._opt.forceNoOffscreen=!0,this._opt.useOffscreen=!1):this._opt.useOffscreen=!0),this._opt.hasAudio||(this._opt.operateBtns.audio=!1),this._opt.hasControl=this._hasControl(),this._loading=!1,this._playing=!1,this._hasLoaded=!1,this._checkHeartTimeout=null,this._checkLoadingTimeout=null,this._startBpsTime=null,this._isPlayingBeforePageHidden=!1,this._stats={buf:0,fps:0,abps:0,vbps:0,ts:0},this._times={playInitStart:"",playStart:"",streamStart:"",streamResponse:"",demuxStart:"",decodeStart:"",videoStart:"",playTimestamp:"",streamTimestamp:"",streamResponseTimestamp:"",demuxTimestamp:"",decodeTimestamp:"",videoTimestamp:"",allTimestamp:""},this._videoTimestamp=0,this._audioTimestamp=0,i=this,Object.defineProperty(i,"rect",{get:()=>{const e=i.$container.getBoundingClientRect();return e.width=Math.max(e.width,i.$container.clientWidth),e.height=Math.max(e.height,i.$container.clientHeight),e}}),["bottom","height","left","right","top","width"].forEach((e=>{Object.defineProperty(i,e,{get:()=>i.rect[e]})})),this.events=new ae(this),this.video=new Te(this),this._opt.hasAudio&&(this.audio=new xe(this)),this.recorder=new Ve(this),this._onlyMseOrWcsVideo()?this.loaded=!0:this.decoderWorker=new Oe(this),this.stream=null,this.demux=null,this._opt.useWCS&&(this.webcodecsDecoder=new Je(this)),this._opt.useMSE&&(this.mseDecoder=new Ke(this)),this.control=new He(this),this.keepScreenOn=new et(this),(e=>{try{const t=()=>{e.emit(I.fullscreen,e.fullscreen),e.fullscreen?e._opt.useMSE&&e.resize():e.resize()};de.on("change",t),e.events.destroys.push((()=>{de.off("change",t)}))}catch(e){}if(e.on(T.decoderWorkerInit,(()=>{e.debug.log("player","has loaded"),e.loaded=!0})),e.on(T.play,(()=>{e.loading=!1})),e.on(T.fullscreen,(t=>{if(t)try{de.request(e.$container).then((()=>{})).catch((t=>{e.webFullscreen=!0}))}catch(t){e.webFullscreen=!0}else try{de.exit().then((()=>{})).catch((()=>{e.webFullscreen=!1}))}catch(t){e.webFullscreen=!1}})),e.on(T.webFullscreen,(t=>{t?e.$container.classList.add("jessibuca-fullscreen-web"):e.$container.classList.remove("jessibuca-fullscreen-web")})),e.on(T.resize,(()=>{e.video.resize()})),e._opt.debug){const t=[T.timeUpdate];Object.keys(T).forEach((i=>{e.on(T[i],(o=>{t.includes(i)||e.debug.log("player events",T[i],o)}))})),Object.keys(x).forEach((t=>{e.on(x[t],(i=>{e.debug.log("player event error",x[t],i)}))}))}})(this),(e=>{const{_opt:t,debug:i,events:{proxy:o}}=e;t.supportDblclickFullscreen&&o(e.$container,"dblclick",(()=>{e.fullscreen=!e.fullscreen})),o(document,"visibilitychange",(()=>{t.hiddenAutoPause&&(i.log("visibilitychange",document.visibilityState,e._isPlayingBeforePageHidden),"visible"===document.visibilityState?e._isPlayingBeforePageHidden&&e.play():(e._isPlayingBeforePageHidden=e.playing,e.playing&&e.pause()))})),o(window,"fullscreenchange",(()=>{null!==e.keepScreenOn&&"visible"===document.visibilityState&&e.enableWakeLock()}))})(this),this._opt.useWCS&&this.debug.log("Player","use WCS"),this._opt.useMSE&&this.debug.log("Player","use MSE"),this._opt.useOffscreen&&this.debug.log("Player","use offscreen"),this.debug.log("Player options",this._opt)}destroy(){this._loading=!1,this._playing=!1,this._hasLoaded=!1,this._times={playInitStart:"",playStart:"",streamStart:"",streamResponse:"",demuxStart:"",decodeStart:"",videoStart:"",playTimestamp:"",streamTimestamp:"",streamResponseTimestamp:"",demuxTimestamp:"",decodeTimestamp:"",videoTimestamp:"",allTimestamp:""},this.decoderWorker&&(this.decoderWorker.destroy(),this.decoderWorker=null),this.video&&(this.video.destroy(),this.video=null),this.audio&&(this.audio.destroy(),this.audio=null),this.stream&&(this.stream.destroy(),this.stream=null),this.recorder&&(this.recorder.destroy(),this.recorder=null),this.control&&(this.control.destroy(),this.control=null),this.webcodecsDecoder&&(this.webcodecsDecoder.destroy(),this.webcodecsDecoder=null),this.mseDecoder&&(this.mseDecoder.destroy(),this.mseDecoder=null),this.demux&&(this.demux.destroy(),this.demux=null),this.events&&(this.events.destroy(),this.events=null),this.clearCheckHeartTimeout(),this.clearCheckLoadingTimeout(),this.releaseWakeLock(),this.keepScreenOn=null,this.resetStats(),this._audioTimestamp=0,this._videoTimestamp=0,this.emit("destroy"),this.off(),this.debug.log("play","destroy end")}set fullscreen(e){ye()?(this.emit(T.webFullscreen,e),setTimeout((()=>{this.updateOption({rotate:e?270:0}),this.resize()}),10)):this.emit(T.fullscreen,e)}get fullscreen(){return document.isFullScreen||document.mozIsFullScreen||document.webkitIsFullScreen||this.webFullscreen}set webFullscreen(e){this.emit(T.webFullscreen,e)}get webFullscreen(){return this.$container.classList.contains("jessibuca-fullscreen-web")}set loaded(e){this._hasLoaded=e}get loaded(){return this._hasLoaded}set playing(e){e&&(this.loading=!1),this.playing!==e&&(this._playing=e,this.emit(T.playing,e),this.emit(T.volumechange,this.volume),e?this.emit(T.play):this.emit(T.pause))}get playing(){return this._playing}get volume(){return this.audio&&this.audio.volume||0}set volume(e){this.audio&&this.audio.setVolume(e)}set loading(e){this.loading!==e&&(this._loading=e,this.emit(T.loading,this._loading))}get loading(){return this._loading}set recording(e){this.playing&&(e?this.recorder.startRecord():this.recorder.stopRecordAndSave())}get recording(){return this.recorder&&this.recorder.recording}set audioTimestamp(e){null!==e&&(this._audioTimestamp=e)}get audioTimestamp(){return this._audioTimestamp}set videoTimestamp(e){null!==e&&(this._videoTimestamp=e,this._opt.useWCS||this._opt.useMSE||this.audioTimestamp&&this.videoTimestamp&&this.audio&&this.audio.emit(T.videoSyncAudio,{audioTimestamp:this.audioTimestamp,videoTimestamp:this.videoTimestamp,diff:this.audioTimestamp-this.videoTimestamp}))}get videoTimestamp(){return this._videoTimestamp}updateOption(e){this._opt=Object.assign({},this._opt,e)}init(){return new Promise(((e,t)=>{this.stream||(this.stream=new Le(this)),this.demux||(this.demux=new Ge(this)),this._opt.useWCS&&(this.webcodecsDecoder||(this.webcodecsDecoder=new Je(this))),this._opt.useMSE&&(this.mseDecoder||(this.mseDecoder=new Ke(this))),this.decoderWorker||this._onlyMseOrWcsVideo()?e():(this.decoderWorker=new Oe(this),this.once(T.decoderWorkerInit,(()=>{e()})))}))}play(e){return new Promise(((t,i)=>{if(!e&&!this._opt.url)return i();this.loading=!0,this.playing=!1,this._times.playInitStart=he(),e||(e=this._opt.url),this._opt.url=e,this.clearCheckHeartTimeout(),this.init().then((()=>{this._times.playStart=he(),this._opt.isNotMute&&this.mute(!1),this.webcodecsDecoder&&this.webcodecsDecoder.once(x.webcodecsH265NotSupport,(()=>{this.emit(x.webcodecsH265NotSupport),this._opt.autoWasm||this.emit(T.error,x.webcodecsH265NotSupport)})),this.mseDecoder&&this.mseDecoder.once(x.mediaSourceH265NotSupport,(()=>{this.emit(x.mediaSourceH265NotSupport),this._opt.autoWasm||this.emit(T.error,x.mediaSourceH265NotSupport)})),this.enableWakeLock(),this.stream.fetchStream(e),this.checkLoadingTimeout(),this.stream.once(x.fetchError,(e=>{i(e)})),this.stream.once(x.websocketError,(e=>{i(e)})),this.stream.once(T.streamSuccess,(()=>{t(),this._times.streamResponse=he(),this._opt.useMSE&&this.video.play()}))})).catch((e=>{i(e)}))}))}close(){return new Promise(((e,t)=>{this._close().then((()=>{this.video.clearView(),e()}))}))}_close(){return new Promise(((e,t)=>{this.stream&&(this.stream.destroy(),this.stream=null),this.demux&&(this.demux.destroy(),this.demux=null),this.decoderWorker&&(this.decoderWorker.destroy(),this.decoderWorker=null),this.webcodecsDecoder&&(this.webcodecsDecoder.destroy(),this.webcodecsDecoder=null),this.mseDecoder&&(this.mseDecoder.destroy(),this.mseDecoder=null),this.clearCheckHeartTimeout(),this.clearCheckLoadingTimeout(),this.playing=!1,this.loading=!1,this.recording=!1,this.audio&&this.audio.pause(),this.releaseWakeLock(),this.resetStats(),this._audioTimestamp=0,this._videoTimestamp=0,this._times={playInitStart:"",playStart:"",streamStart:"",streamResponse:"",demuxStart:"",decodeStart:"",videoStart:"",playTimestamp:"",streamTimestamp:"",streamResponseTimestamp:"",demuxTimestamp:"",decodeTimestamp:"",videoTimestamp:"",allTimestamp:""},setTimeout((()=>{e()}),0)}))}pause(e){return e?this.close():this._close()}mute(e){this.audio&&this.audio.mute(e)}resize(){this.video.resize()}startRecord(e,t){this.recording||(this.recorder.setFileName(e,t),this.recording=!0)}stopRecordAndSave(){this.recording&&(this.recording=!1)}_hasControl(){let e=!1,t=!1;return Object.keys(this._opt.operateBtns).forEach((e=>{this._opt.operateBtns[e]&&(t=!0)})),(this._opt.showBandwidth||this._opt.text||t)&&(e=!0),e}_onlyMseOrWcsVideo(){return!1===this._opt.hasAudio&&(this._opt.useMSE||this._opt.useWCS&&!this._opt.useOffscreen)}checkHeart(){this.clearCheckHeartTimeout(),this.checkHeartTimeout()}checkHeartTimeout(){this._checkHeartTimeout=setTimeout((()=>{this.pause(!1).then((()=>{this.emit(T.timeout,T.delayTimeout),this.emit(T.delayTimeout)}))}),1e3*this._opt.heartTimeout)}clearCheckHeartTimeout(){this._checkHeartTimeout&&(clearTimeout(this._checkHeartTimeout),this._checkHeartTimeout=null)}checkLoadingTimeout(){this._checkLoadingTimeout=setTimeout((()=>{this.pause(!1).then((()=>{this.emit(T.timeout,T.loadingTimeout),this.emit(T.loadingTimeout)}))}),1e3*this._opt.loadingTimeout)}clearCheckLoadingTimeout(){this._checkLoadingTimeout&&(clearTimeout(this._checkLoadingTimeout),this._checkLoadingTimeout=null)}handleRender(){this.loading&&(this.emit(T.start),this.loading=!1,this.clearCheckLoadingTimeout()),this.playing||(this.playing=!0),this.checkHeart()}updateStats(e){e=e||{},this._startBpsTime||(this._startBpsTime=he()),Ee(e.ts)&&(this._stats.ts=e.ts),Ee(e.buf)&&(this._stats.buf=e.buf),e.fps&&(this._stats.fps+=1),e.abps&&(this._stats.abps+=e.abps),e.vbps&&(this._stats.vbps+=e.vbps);const t=he();t-this._startBpsTime<1e3||(this.emit(T.stats,this._stats),this.emit(T.performance,function(e){let t=0;return e>=24?t=2:e>=15&&(t=1),t}(this._stats.fps)),this._stats.fps=0,this._stats.abps=0,this._stats.vbps=0,this._startBpsTime=t)}resetStats(){this._startBpsTime=null,this._stats={buf:0,fps:0,abps:0,vbps:0,ts:0}}enableWakeLock(){this._opt.keepScreenOn&&this.keepScreenOn.enable()}releaseWakeLock(){this._opt.keepScreenOn&&this.keepScreenOn.disable()}handlePlayToRenderTimes(){const e=this._times;e.playTimestamp=e.playStart-e.playInitStart,e.streamTimestamp=e.streamStart-e.playStart,e.streamResponseTimestamp=e.streamResponse-e.streamStart,e.demuxTimestamp=e.demuxStart-e.streamResponse,e.decodeTimestamp=e.decodeStart-e.demuxStart,e.videoTimestamp=e.videoStart-e.decodeStart,e.allTimestamp=e.videoStart-e.playInitStart,this.emit(T.playToRenderTimes,e)}}class it extends Be{constructor(e){super();let t=e,i=e.container;if("string"==typeof e.container&&(i=document.querySelector(e.container)),!i)throw new Error("Jessibuca need container option");i.classList.add("jessibuca-container"),delete t.container,Ee(t.videoBuffer)&&(t.videoBuffer=1e3*Number(t.videoBuffer)),Ee(t.timeout)&&(Se(t.loadingTimeout)&&(t.loadingTimeout=t.timeout),Se(t.heartTimeout)&&(t.heartTimeout=t.timeout)),this._opt=t,this.$container=i,this._loadingTimeoutReplayTimes=0,this._heartTimeoutReplayTimes=0,this.events=new ae(this),this._initPlayer(i,t)}destroy(){this.events&&(this.events.destroy(),this.events=null),this.player&&(this.player.destroy(),this.player=null),this.$container=null,this._opt=null,this._loadingTimeoutReplayTimes=0,this._heartTimeoutReplayTimes=0,this.off()}_initPlayer(e,t){this.player=new tt(e,t),this._bindEvents()}_resetPlayer(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.player.destroy(),this.player=null;const t=Object.assign(this._opt,e);this._initPlayer(this.$container,t)}_bindEvents(){Object.keys(I).forEach((e=>{this.player.on(I[e],(t=>{this.emit(e,t)}))}))}setDebug(e){this.player.updateOption({isDebug:!!e})}mute(){this.player.mute(!0)}cancelMute(){this.player.mute(!1)}setVolume(e){this.player.volume=e}audioResume(){this.player.audio&&this.player.audio.audioEnabled(!0)}setTimeout(e){e=Number(e),this.player.updateOption({timeout:e,loadingTimeout:e,heartTimeout:e})}setScaleMode(e){let t={isFullResize:!1,isResize:!1};switch(e=Number(e)){case N:t.isFullResize=!1,t.isResize=!1;break;case P:t.isFullResize=!1,t.isResize=!0;break;case z:t.isFullResize=!0,t.isResize=!0}this.player.updateOption(t),this.resize()}pause(){return this.player.pause()}close(){return this._opt.url="",this.player.close()}clearView(){this.player.video.clearView()}play(e){return new Promise(((t,i)=>{if(!e&&!this._opt.url)return this.emit(T.error,x.playError),void i();if(e){if(!this._opt.url)return this._play(e);e===this._opt.url?this.player.playing?t():(this.clearView(),this.player.play(this._opt.url).then((()=>{t()})).catch((()=>{this.player.pause().then((()=>{i()}))}))):this.player.pause().then((()=>(this.clearView(),this._play(e)))).catch((()=>{i()}))}else this.player.play(this._opt.url).then((()=>{t()})).catch((()=>{this.player.pause().then((()=>{i()}))}))}))}_play(e){return new Promise(((t,i)=>{this._opt.url=e;const o=0===e.indexOf("http"),r=o?s:A,d=o||-1!==e.indexOf(".flv")||this._opt.isFlv?n:a;this.player.updateOption({protocol:r,demuxType:d}),this.player.once(x.mediaSourceH265NotSupport,(()=>{this.close().then((()=>{this.player._opt.autoWasm&&(this.player.debug.log("Jessibuca","auto wasm [mse-> wasm] reset player and play"),this._resetPlayer({useMSE:!1}),this.play(e).then((()=>{this.player.debug.log("Jessibuca","auto wasm [mse-> wasm] reset player and play success")})).catch((()=>{this.player.debug.log("Jessibuca","auto wasm [mse-> wasm] reset player and play error")})))}))})),this.player.once(x.webcodecsH265NotSupport,(()=>{this.close().then((()=>{this.player._opt.autoWasm&&(this.player.debug.log("Jessibuca","auto wasm [wcs-> wasm] reset player and play"),this._resetPlayer({useWCS:!1}),this.play(e).then((()=>{this.player.debug.log("Jessibuca","auto wasm [wcs-> wasm] reset player and play success")})).catch((()=>{this.player.debug.log("Jessibuca","auto wasm [wcs-> wasm] reset player and play error")})))}))})),this.player.once(x.wasmDecodeError,(()=>{this.player._opt.wasmDecodeErrorReplay&&this.close().then((()=>{this.player.debug.log("Jessibuca","wasm decode error and reset player and play"),this._resetPlayer({useWCS:!1}),this.play(e).then((()=>{this.player.debug.log("Jessibuca","wasm decode error and reset player and play success")})).catch((()=>{this.player.debug.log("Jessibuca","wasm decode error and reset player and play error")}))}))})),this.player.once(T.delayTimeout,(()=>{this.player._opt.heartTimeoutReplay&&this._heartTimeoutReplayTimes<this.player._opt.heartTimeoutReplayTimes&&(this._heartTimeoutReplayTimes+=1,this.play(e).then((()=>{this._heartTimeoutReplayTimes=0})).catch((()=>{})))})),this.player.once(T.loadingTimeout,(()=>{this.player._opt.loadingTimeoutReplay&&this._loadingTimeoutReplayTimes<this.player._opt.loadingTimeoutReplayTimes&&(this._loadingTimeoutReplayTimes+=1,this.play(e).then((()=>{this._loadingTimeoutReplayTimes=0})).catch((()=>{})))})),this.hasLoaded()?this.player.play(e).then((()=>{t()})).catch((()=>{this.player.pause().then((()=>{i()}))})):this.player.once(T.decoderWorkerInit,(()=>{this.player.play(e).then((()=>{t()})).catch((()=>{this.player.pause().then((()=>{i()}))}))}))}))}resize(){this.player.resize()}setBufferTime(e){e=Number(e),this.player.updateOption({videoBuffer:1e3*e}),this.player.decoderWorker&&this.player.decoderWorker.updateWorkConfig({key:"videoBuffer",value:1e3*e})}setRotate(e){e=parseInt(e,10);this._opt.rotate!==e&&-1!==[0,90,270].indexOf(e)&&(this.player.updateOption({rotate:e}),this.resize())}hasLoaded(){return this.player.loaded}setKeepScreenOn(){this.player.updateOption({keepScreenOn:!0})}setFullscreen(e){const t=!!e;this.player.fullscreen!==t&&(this.player.fullscreen=t)}screenshot(e,t,i,o){return this.player.video.screenshot(e,t,i,o)}startRecord(e,t){return new Promise(((i,o)=>{this.player.playing?(this.player.startRecord(e,t),i()):o()}))}stopRecordAndSave(){this.player.recording&&this.player.stopRecordAndSave()}isPlaying(){return this.player.playing}isMute(){return!this.player.audio||this.player.audio.isMute}isRecording(){return this.player.recorder.recording}}return r(it,"ERROR",x),r(it,"TIMEOUT",{loadingTimeout:T.loadingTimeout,delayTimeout:T.delayTimeout}),window.Jessibuca=it,it})); 1 +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).jessibuca=t()}(this,(function(){"use strict";var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function t(e,t){return e(t={exports:{}},t.exports),t.exports}var i,o=t((function(e){e.exports=function(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e},e.exports.__esModule=!0,e.exports.default=e.exports})),r=(i=o)&&i.__esModule&&Object.prototype.hasOwnProperty.call(i,"default")?i.default:i;const s=0,a=1,n="flv",A="m7s",d="mp4",c="webm",l={videoBuffer:1e3,videoBufferDelay:1e3,isResize:!0,isFullResize:!1,isFlv:!1,debug:!1,hotKey:!1,loadingTimeout:10,heartTimeout:5,timeout:10,loadingTimeoutReplay:!0,heartTimeoutReplay:!1,loadingTimeoutReplayTimes:3,heartTimeoutReplayTimes:3,supportDblclickFullscreen:!1,showBandwidth:!1,keepScreenOn:!1,isNotMute:!1,hasAudio:!0,hasVideo:!0,operateBtns:{fullscreen:!1,screenshot:!1,play:!1,audio:!1,record:!1},controlAutoHide:!1,hasControl:!1,loadingText:"",background:"",decoder:"decoder.js",url:"",rotate:0,forceNoOffscreen:!0,hiddenAutoPause:!1,protocol:a,demuxType:n,useWCS:!1,wcsUseVideoRender:!0,useMSE:!1,useOffscreen:!1,autoWasm:!0,wasmDecodeErrorReplay:!0,openWebglAlignment:!1,wasmDecodeAudioSyncVideo:!1,recordType:c,useWebFullScreen:!1},u="init",h="initVideo",p="render",m="playAudio",g="initAudio",f="audioCode",b="videoCode",y="wasmError",v="Invalid NAL unit size",w=1,S=2,E=8,B=9,C="init",R="decode",k="audioDecode",T="close",I="updateConfig",x={fullscreen:"fullscreen$2",webFullscreen:"webFullscreen",decoderWorkerInit:"decoderWorkerInit",play:"play",playing:"playing",pause:"pause",mute:"mute",load:"load",loading:"loading",videoInfo:"videoInfo",timeUpdate:"timeUpdate",audioInfo:"audioInfo",log:"log",error:"error",kBps:"kBps",timeout:"timeout",delayTimeout:"delayTimeout",loadingTimeout:"loadingTimeout",stats:"stats",performance:"performance",record:"record",recording:"recording",recordingTimestamp:"recordingTimestamp",recordStart:"recordStart",recordEnd:"recordEnd",recordCreateError:"recordCreateError",buffer:"buffer",videoFrame:"videoFrame",start:"start",metadata:"metadata",resize:"resize",streamEnd:"streamEnd",streamSuccess:"streamSuccess",streamMessage:"streamMessage",streamError:"streamError",volumechange:"volumechange",destroy:"destroy",mseSourceOpen:"mseSourceOpen",mseSourceClose:"mseSourceClose",mseSourceBufferError:"mseSourceBufferError",mseSourceBufferBusy:"mseSourceBufferBusy",mseSourceBufferFull:"mseSourceBufferFull",videoWaiting:"videoWaiting",videoTimeUpdate:"videoTimeUpdate",videoSyncAudio:"videoSyncAudio",playToRenderTimes:"playToRenderTimes"},D={load:x.load,timeUpdate:x.timeUpdate,videoInfo:x.videoInfo,audioInfo:x.audioInfo,error:x.error,kBps:x.kBps,log:x.log,start:x.start,timeout:x.timeout,loadingTimeout:x.loadingTimeout,delayTimeout:x.delayTimeout,fullscreen:"fullscreen",webFullscreen:x.webFullscreen,play:x.play,pause:x.pause,mute:x.mute,stats:x.stats,performance:x.performance,recordingTimestamp:x.recordingTimestamp,recordStart:x.recordStart,recordEnd:x.recordEnd,playToRenderTimes:x.playToRenderTimes},j={playError:"playIsNotPauseOrUrlIsNull",fetchError:"fetchError",websocketError:"websocketError",webcodecsH265NotSupport:"webcodecsH265NotSupport",webcodecsDecodeError:"webcodecsDecodeError",webcodecsWidthOrHeightChange:"webcodecsWidthOrHeightChange",mediaSourceH265NotSupport:"mediaSourceH265NotSupport",mediaSourceFull:x.mseSourceBufferFull,mseSourceBufferError:x.mseSourceBufferError,mediaSourceAppendBufferError:"mediaSourceAppendBufferError",mediaSourceBufferListLarge:"mediaSourceBufferListLarge",mediaSourceAppendBufferEndTimeout:"mediaSourceAppendBufferEndTimeout",wasmDecodeError:"wasmDecodeError",webglAlignmentError:"webglAlignmentError"},L="notConnect",F="open",O="close",V="error",M={download:"download",base64:"base64",blob:"blob"},U={7:"H264(AVC)",12:"H265(HEVC)"},Q=12,W={10:"AAC",7:"ALAW",8:"MULAW"},J=38,P=0,G=1,N=2,z="webcodecs",H="webgl",Y="offscreen",X="key",q="delta",Z='video/mp4; codecs="avc1.64002A"',K="ended",_="open",$="closed",ee=1e3,te=27,ie=38,oe=40,re="A key frame is required after configure() or flush()",se="The user aborted a request",ae="AbortError",ne="AbortError";class Ae{constructor(e){this.log=function(t){if(e._opt.debug){for(var i=arguments.length,o=new Array(i>1?i-1:0),r=1;r<i;r++)o[r-1]=arguments[r];console.log(`Jessibuca: [${t}]`,...o)}},this.warn=function(t){if(e._opt.debug){for(var i=arguments.length,o=new Array(i>1?i-1:0),r=1;r<i;r++)o[r-1]=arguments[r];console.warn(`Jessibuca: [${t}]`,...o)}},this.error=function(e){for(var t=arguments.length,i=new Array(t>1?t-1:0),o=1;o<t;o++)i[o-1]=arguments[o];console.error(`Jessibuca: [${e}]`,...i)}}}class de{constructor(e){this.destroys=[],this.proxy=this.proxy.bind(this),this.master=e}proxy(e,t,i){let o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};if(!e)return;if(Array.isArray(t))return t.map((t=>this.proxy(e,t,i,o)));e.addEventListener(t,i,o);const r=()=>e.removeEventListener(t,i,o);return this.destroys.push(r),r}destroy(){this.master.debug&&this.master.debug.log("Events","destroy"),this.destroys.forEach((e=>e()))}}var ce=t((function(e){!function(){var t="undefined"!=typeof window&&void 0!==window.document?window.document:{},i=e.exports,o=function(){for(var e,i=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError"]],o=0,r=i.length,s={};o<r;o++)if((e=i[o])&&e[1]in t){for(o=0;o<e.length;o++)s[i[0][o]]=e[o];return s}return!1}(),r={change:o.fullscreenchange,error:o.fullscreenerror},s={request:function(e,i){return new Promise(function(r,s){var a=function(){this.off("change",a),r()}.bind(this);this.on("change",a);var n=(e=e||t.documentElement)[o.requestFullscreen](i);n instanceof Promise&&n.then(a).catch(s)}.bind(this))},exit:function(){return new Promise(function(e,i){if(this.isFullscreen){var r=function(){this.off("change",r),e()}.bind(this);this.on("change",r);var s=t[o.exitFullscreen]();s instanceof Promise&&s.then(r).catch(i)}else e()}.bind(this))},toggle:function(e,t){return this.isFullscreen?this.exit():this.request(e,t)},onchange:function(e){this.on("change",e)},onerror:function(e){this.on("error",e)},on:function(e,i){var o=r[e];o&&t.addEventListener(o,i,!1)},off:function(e,i){var o=r[e];o&&t.removeEventListener(o,i,!1)},raw:o};o?(Object.defineProperties(s,{isFullscreen:{get:function(){return Boolean(t[o.fullscreenElement])}},element:{enumerable:!0,get:function(){return t[o.fullscreenElement]}},isEnabled:{enumerable:!0,get:function(){return Boolean(t[o.fullscreenEnabled])}}}),i?e.exports=s:window.screenfull=s):i?e.exports={isEnabled:!1}:window.screenfull={isEnabled:!1}}()}));function le(){}function ue(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";const t=e.split(","),i=atob(t[1]),o=t[0].replace("data:","").replace(";base64","");let r=i.length,s=new Uint8Array(r);for(;r--;)s[r]=i.charCodeAt(r);return new File([s],"file",{type:o})}function he(){return(new Date).getTime()}function pe(e,t,i){return Math.max(Math.min(e,Math.max(t,i)),Math.min(t,i))}function me(e,t,i){if(e)return"object"==typeof t&&Object.keys(t).forEach((i=>{me(e,i,t[i])})),e.style[t]=i,e}function ge(e,t){let i=!(arguments.length>2&&void 0!==arguments[2])||arguments[2];if(!e)return 0;const o=getComputedStyle(e,null).getPropertyValue(t);return i?parseFloat(o):o}function fe(){return performance&&"function"==typeof performance.now?performance.now():Date.now()}function be(e){let t=0,i=fe();return o=>{t+=o;const r=fe(),s=r-i;s>=1e3&&(e(t/s*1e3),i=r,t=0)}}function ye(){return/iphone|ipod|android.*mobile|windows.*phone|blackberry.*mobile/i.test(window.navigator.userAgent.toLowerCase())}function ve(e){if(null==e||""===e||0===parseInt(e)||isNaN(parseInt(e)))return"0KB/s";let t=parseFloat(e);return t=t.toFixed(2),t+"KB/s"}function we(e){return null==e}function Se(e){return!we(e)}function Ee(e){const t=e||window.event;return t.target||t.srcElement}ce.isEnabled,(()=>{try{if("object"==typeof WebAssembly&&"function"==typeof WebAssembly.instantiate){const e=new WebAssembly.Module(Uint8Array.of(0,97,115,109,1,0,0,0));if(e instanceof WebAssembly.Module)return new WebAssembly.Instance(e)instanceof WebAssembly.Instance}}catch(e){}})();class Be{on(e,t,i){const o=this.e||(this.e={});return(o[e]||(o[e]=[])).push({fn:t,ctx:i}),this}once(e,t,i){const o=this;function r(){o.off(e,r);for(var s=arguments.length,a=new Array(s),n=0;n<s;n++)a[n]=arguments[n];t.apply(i,a)}return r._=t,this.on(e,r,i)}emit(e){const t=((this.e||(this.e={}))[e]||[]).slice();for(var i=arguments.length,o=new Array(i>1?i-1:0),r=1;r<i;r++)o[r-1]=arguments[r];for(let e=0;e<t.length;e+=1)t[e].fn.apply(t[e].ctx,o);return this}off(e,t){const i=this.e||(this.e={});if(!e)return Object.keys(i).forEach((e=>{delete i[e]})),void delete this.e;const o=i[e],r=[];if(o&&t)for(let e=0,i=o.length;e<i;e+=1)o[e].fn!==t&&o[e].fn._!==t&&r.push(o[e]);return r.length?i[e]=r:delete i[e],this}}class Ce extends Be{constructor(){super(),this.init=!1}resetInit(){this.init=!1,this.videoInfo={width:"",height:"",encType:"",encTypeCode:""}}destroy(){this.resetInit(),this.player.$container.removeChild(this.$videoElement),this.off()}updateVideoInfo(e){e.encTypeCode&&(this.videoInfo.encType=U[e.encTypeCode]),e.width&&(this.videoInfo.width=e.width),e.height&&(this.videoInfo.height=e.height),this.videoInfo.encType&&this.videoInfo.height&&this.videoInfo.width&&!this.init&&(this.player.emit(x.videoInfo,this.videoInfo),this.init=!0)}play(){}pause(){}clearView(){}}var Re="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0;function ke(e,t,i){var o=new XMLHttpRequest;o.open("GET",e),o.responseType="blob",o.onload=function(){De(o.response,t,i)},o.onerror=function(){console.error("could not download file")},o.send()}function Te(e){var t=new XMLHttpRequest;t.open("HEAD",e,!1);try{t.send()}catch(e){}return t.status>=200&&t.status<=299}function Ie(e){try{e.dispatchEvent(new MouseEvent("click"))}catch(i){var t=document.createEvent("MouseEvents");t.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),e.dispatchEvent(t)}}var xe=Re.navigator&&/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),De="object"!=typeof window||window!==Re?function(){}:"download"in HTMLAnchorElement.prototype&&!xe?function(e,t,i){var o=Re.URL||Re.webkitURL,r=document.createElementNS("http://www.w3.org/1999/xhtml","a");t=t||e.name||"download",r.download=t,r.rel="noopener","string"==typeof e?(r.href=e,r.origin!==location.origin?Te(r.href)?ke(e,t,i):Ie(r,r.target="_blank"):Ie(r)):(r.href=o.createObjectURL(e),setTimeout((function(){o.revokeObjectURL(r.href)}),4e4),setTimeout((function(){Ie(r)}),0))}:"msSaveOrOpenBlob"in navigator?function(e,t,i){if(t=t||e.name||"download","string"==typeof e)if(Te(e))ke(e,t,i);else{var o=document.createElement("a");o.href=e,o.target="_blank",setTimeout((function(){Ie(o)}))}else navigator.msSaveOrOpenBlob(function(e,t){return void 0===t?t={autoBom:!1}:"object"!=typeof t&&(console.warn("Deprecated: Expected third argument to be a object"),t={autoBom:!t}),t.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)?new Blob([String.fromCharCode(65279),e],{type:e.type}):e}(e,i),t)}:function(e,t,i,o){if((o=o||open("","_blank"))&&(o.document.title=o.document.body.innerText="downloading..."),"string"==typeof e)return ke(e,t,i);var r="application/octet-stream"===e.type,s=/constructor/i.test(Re.HTMLElement)||Re.safari,a=/CriOS\/[\d]+/.test(navigator.userAgent);if((a||r&&s||xe)&&"undefined"!=typeof FileReader){var n=new FileReader;n.onloadend=function(){var e=n.result;e=a?e:e.replace(/^data:[^;]*;/,"data:attachment/file;"),o?o.location.href=e:location=e,o=null},n.readAsDataURL(e)}else{var A=Re.URL||Re.webkitURL,d=A.createObjectURL(e);o?o.location=d:location.href=d,o=null,setTimeout((function(){A.revokeObjectURL(d)}),4e4)}};class je extends Ce{constructor(e){super(),this.player=e;const t=document.createElement("canvas");t.style.position="absolute",t.style.top=0,t.style.left=0,this.$videoElement=t,e.$container.appendChild(this.$videoElement),this.context2D=null,this.contextGl=null,this.contextGlRender=null,this.contextGlDestroy=null,this.bitmaprenderer=null,this.renderType=null,this.videoInfo={width:"",height:"",encType:""},this._initCanvasRender(),this.player.debug.log("CanvasVideo","init")}destroy(){super.destroy(),this.contextGl&&(this.contextGl=null),this.context2D&&(this.context2D=null),this.contextGlRender&&(this.contextGlDestroy&&this.contextGlDestroy(),this.contextGlDestroy=null,this.contextGlRender=null),this.bitmaprenderer&&(this.bitmaprenderer=null),this.renderType=null,this.player.debug.log("CanvasVideoLoader","destroy")}_initContextGl(){this.contextGl=function(e){let t=null;const i=["webgl","experimental-webgl","moz-webgl","webkit-3d"];let o=0;for(;!t&&o<i.length;){const r=i[o];try{let i={preserveDrawingBuffer:!0};t=e.getContext(r,i)}catch(e){t=null}t&&"function"==typeof t.getParameter||(t=null),++o}return t}(this.$videoElement);const e=((e,t)=>{var i=["attribute vec4 vertexPos;","attribute vec4 texturePos;","varying vec2 textureCoord;","void main()","{","gl_Position = vertexPos;","textureCoord = texturePos.xy;","}"].join("\n"),o=["precision highp float;","varying highp vec2 textureCoord;","uniform sampler2D ySampler;","uniform sampler2D uSampler;","uniform sampler2D vSampler;","const mat4 YUV2RGB = mat4","(","1.1643828125, 0, 1.59602734375, -.87078515625,","1.1643828125, -.39176171875, -.81296875, .52959375,","1.1643828125, 2.017234375, 0, -1.081390625,","0, 0, 0, 1",");","void main(void) {","highp float y = texture2D(ySampler, textureCoord).r;","highp float u = texture2D(uSampler, textureCoord).r;","highp float v = texture2D(vSampler, textureCoord).r;","gl_FragColor = vec4(y, u, v, 1) * YUV2RGB;","}"].join("\n");t&&e.pixelStorei(e.UNPACK_ALIGNMENT,1);var r=e.createShader(e.VERTEX_SHADER);e.shaderSource(r,i),e.compileShader(r),e.getShaderParameter(r,e.COMPILE_STATUS)||console.log("Vertex shader failed to compile: "+e.getShaderInfoLog(r));var s=e.createShader(e.FRAGMENT_SHADER);e.shaderSource(s,o),e.compileShader(s),e.getShaderParameter(s,e.COMPILE_STATUS)||console.log("Fragment shader failed to compile: "+e.getShaderInfoLog(s));var a=e.createProgram();e.attachShader(a,r),e.attachShader(a,s),e.linkProgram(a),e.getProgramParameter(a,e.LINK_STATUS)||console.log("Program failed to compile: "+e.getProgramInfoLog(a)),e.useProgram(a);var n=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,n),e.bufferData(e.ARRAY_BUFFER,new Float32Array([1,1,-1,1,1,-1,-1,-1]),e.STATIC_DRAW);var A=e.getAttribLocation(a,"vertexPos");e.enableVertexAttribArray(A),e.vertexAttribPointer(A,2,e.FLOAT,!1,0,0);var d=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,d),e.bufferData(e.ARRAY_BUFFER,new Float32Array([1,0,0,0,1,1,0,1]),e.STATIC_DRAW);var c=e.getAttribLocation(a,"texturePos");function l(t,i){var o=e.createTexture();return e.bindTexture(e.TEXTURE_2D,o),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.bindTexture(e.TEXTURE_2D,null),e.uniform1i(e.getUniformLocation(a,t),i),o}e.enableVertexAttribArray(c),e.vertexAttribPointer(c,2,e.FLOAT,!1,0,0);var u=l("ySampler",0),h=l("uSampler",1),p=l("vSampler",2);return{render:function(t,i,o,r,s){e.viewport(0,0,t,i),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,u),e.texImage2D(e.TEXTURE_2D,0,e.LUMINANCE,t,i,0,e.LUMINANCE,e.UNSIGNED_BYTE,o),e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,h),e.texImage2D(e.TEXTURE_2D,0,e.LUMINANCE,t/2,i/2,0,e.LUMINANCE,e.UNSIGNED_BYTE,r),e.activeTexture(e.TEXTURE2),e.bindTexture(e.TEXTURE_2D,p),e.texImage2D(e.TEXTURE_2D,0,e.LUMINANCE,t/2,i/2,0,e.LUMINANCE,e.UNSIGNED_BYTE,s),e.drawArrays(e.TRIANGLE_STRIP,0,4)},destroy:function(){try{e.deleteProgram(a),e.deleteBuffer(n),e.deleteBuffer(d),e.deleteTexture(u),e.deleteTexture(h),e.deleteTexture(p)}catch(e){}}}})(this.contextGl,this.player._opt.openWebglAlignment);this.contextGlRender=e.render,this.contextGlDestroy=e.destroy}_initContext2D(){this.context2D=this.$videoElement.getContext("2d")}_initCanvasRender(){this.player._opt.useWCS&&!this._supportOffscreen()?(this.renderType=z,this._initContext2D()):this._supportOffscreen()?(this.renderType=Y,this._bindOffscreen()):(this.renderType=H,this._initContextGl())}_supportOffscreen(){return"function"==typeof this.$videoElement.transferControlToOffscreen&&this.player._opt.useOffscreen}_bindOffscreen(){this.bitmaprenderer=this.$videoElement.getContext("bitmaprenderer")}initCanvasViewSize(){this.$videoElement.width=this.videoInfo.width,this.$videoElement.height=this.videoInfo.height,this.resize()}render(e){switch(this.player.videoTimestamp=e.ts,this.renderType){case Y:this.bitmaprenderer.transferFromImageBitmap(e.buffer);break;case H:this.contextGlRender(this.$videoElement.width,this.$videoElement.height,e.output[0],e.output[1],e.output[2]);break;case z:this.context2D.drawImage(e.videoFrame,0,0,this.$videoElement.width,this.$videoElement.height),(t=e.videoFrame).close?t.close():t.destroy&&t.destroy()}var t}screenshot(e,t,i,o){e=e||he(),o=o||M.download;const r={png:"image/png",jpeg:"image/jpeg",webp:"image/webp"};let s=.92;!r[t]&&M[t]&&(o=t,t="png",i=void 0),"string"==typeof i&&(o=i,i=void 0),void 0!==i&&(s=Number(i));const a=this.$videoElement.toDataURL(r[t]||r.png,s);if(o===M.base64)return a;{const t=ue(a);if(o===M.blob)return t;o===M.download&&De(t,e)}}clearView(){switch(this.renderType){case Y:(function(e,t){const i=document.createElement("canvas");return i.width=e,i.height=t,window.createImageBitmap(i,0,0,e,t)})(this.$videoElement.width,this.$videoElement.height).then((e=>{this.bitmaprenderer.transferFromImageBitmap(e)}));break;case H:this.contextGl.clear(this.contextGl.COLOR_BUFFER_BIT);break;case z:this.context2D.clearRect(0,0,this.$videoElement.width,this.$videoElement.height)}}resize(){this.player.debug.log("canvasVideo","resize");const e=this.player._opt;let t=this.player.width,i=this.player.height;e.hasControl&&!e.controlAutoHide&&(ye()&&this.player.fullscreen&&e.useWebFullScreen?t-=J:i-=J);let o=this.$videoElement.width,r=this.$videoElement.height;const s=e.rotate;let a=(t-o)/2,n=(i-r)/2;270!==s&&90!==s||(o=this.$videoElement.height,r=this.$videoElement.width);const A=t/o,d=i/r;let c=A>d?d:A;e.isResize||A!==d&&(c=A+","+d),e.isFullResize&&(c=A>d?A:d);let l="scale("+c+")";s&&(l+=" rotate("+s+"deg)"),this.$videoElement.style.transform=l,this.$videoElement.style.left=a+"px",this.$videoElement.style.top=n+"px"}}class Le extends Ce{constructor(e){super(),this.player=e;const t=document.createElement("video"),i=document.createElement("canvas");t.muted=!0,t.style.position="absolute",t.style.top=0,t.style.left=0,this._delayPlay=!1,e.$container.appendChild(t),this.videoInfo={width:"",height:"",encType:""};const o=this.player._opt;o.useWCS&&o.wcsUseVideoRender&&(this.trackGenerator=new MediaStreamTrackGenerator({kind:"video"}),t.srcObject=new MediaStream([this.trackGenerator]),this.vwriter=this.trackGenerator.writable.getWriter()),this.$videoElement=t,this.$canvasElement=i,this.canvasContext=i.getContext("2d"),this.fixChromeVideoFlashBug(),this.resize();const{proxy:r}=this.player.events;r(this.$videoElement,"canplay",(()=>{this.player.debug.log("Video","canplay"),this._delayPlay&&this._play()})),r(this.$videoElement,"waiting",(()=>{this.player.emit(x.videoWaiting)})),r(this.$videoElement,"timeupdate",(e=>{const t=parseInt(e.timeStamp,10);this.player.emit(x.timeUpdate,t),this.isPlaying()||this.$videoElement.play()})),this.player.debug.log("Video","init")}destroy(){super.destroy(),this.$canvasElement=null,this.canvasContext=null,this.$videoElement&&(this.$videoElement.pause(),this.$videoElement.currentTime=0,this.$videoElement.src="",this.$videoElement.removeAttribute("src"),this.$videoElement=null),this.trackGenerator&&(this.trackGenerator.stop(),this.trackGenerator=null),this.vwriter&&(this.vwriter.close(),this.vwriter=null),this.player.debug.log("Video","destroy")}fixChromeVideoFlashBug(){const e=function(){const e=navigator.userAgent.toLowerCase(),t={},i={IE:window.ActiveXObject||"ActiveXObject"in window,Chrome:e.indexOf("chrome")>-1&&e.indexOf("safari")>-1,Firefox:e.indexOf("firefox")>-1,Opera:e.indexOf("opera")>-1,Safari:e.indexOf("safari")>-1&&-1==e.indexOf("chrome"),Edge:e.indexOf("edge")>-1,QQBrowser:/qqbrowser/.test(e),WeixinBrowser:/MicroMessenger/i.test(e)};for(let o in i)if(i[o]){let i="";if("IE"===o)i=e.match(/(msie\s|trident.*rv:)([\w.]+)/)[2];else if("Chrome"===o){for(let e in navigator.mimeTypes)"application/360softmgrplugin"===navigator.mimeTypes[e].type&&(o="360");i=e.match(/chrome\/([\d.]+)/)[1]}else"Firefox"===o?i=e.match(/firefox\/([\d.]+)/)[1]:"Opera"===o?i=e.match(/opera\/([\d.]+)/)[1]:"Safari"===o?i=e.match(/version\/([\d.]+)/)[1]:"Edge"===o?i=e.match(/edge\/([\d.]+)/)[1]:"QQBrowser"===o&&(i=e.match(/qqbrowser\/([\d.]+)/)[1]);t.type=o,t.version=parseInt(i)}return t}().type.toLowerCase();if("chrome"===e||"edge"===e){const e=this.player.$container;e.style.backdropFilter="blur(0px)",e.style.translateZ="0"}}play(){if(this.$videoElement){const e=this._getVideoReadyState();if(this.player.debug.log("Video",`play and readyState: ${e}`),0===e)return this.player.debug.warn("Video","readyState is 0 and set _delayPlay to true"),void(this._delayPlay=!0);this._play()}}_getVideoReadyState(){let e=0;return this.$videoElement&&(e=this.$videoElement.readyState),e}_play(){this.$videoElement&&this.$videoElement.play().then((()=>{this._delayPlay=!1,this.player.debug.log("Video","_play success"),setTimeout((()=>{this.isPlaying()||(this.player.debug.warn("Video","play failed and retry play"),this._play())}),100)})).catch((e=>{this.player.debug.error("Video","_play error",e)}))}pause(e){e?this.$videoElement&&this.$videoElement.pause():setTimeout((()=>{this.$videoElement&&this.$videoElement.pause()}),100)}clearView(){}screenshot(e,t,i,o){e=e||he(),o=o||M.download;const r={png:"image/png",jpeg:"image/jpeg",webp:"image/webp"};let s=.92;!r[t]&&M[t]&&(o=t,t="png",i=void 0),"string"==typeof i&&(o=i,i=void 0),void 0!==i&&(s=Number(i));const a=this.$videoElement;let n=this.$canvasElement;n.width=a.videoWidth,n.height=a.videoHeight,this.canvasContext.drawImage(a,0,0,n.width,n.height);const A=n.toDataURL(r[t]||r.png,s);if(this.canvasContext.clearRect(0,0,n.width,n.height),n.width=0,n.height=0,o===M.base64)return A;{const t=ue(A);if(o===M.blob)return t;o===M.download&&De(t,e)}}initCanvasViewSize(){this.resize()}render(e){this.vwriter&&this.vwriter.write(e.videoFrame)}resize(){let e=this.player.width,t=this.player.height;const i=this.player._opt,o=i.rotate;i.hasControl&&!i.controlAutoHide&&(ye()&&this.player.fullscreen&&i.useWebFullScreen?e-=J:t-=J),this.$videoElement.width=e,this.$videoElement.height=t,270!==o&&90!==o||(this.$videoElement.width=t,this.$videoElement.height=e);let r=(e-this.$videoElement.width)/2,s=(t-this.$videoElement.height)/2,a="contain";i.isResize||(a="fill"),i.isFullResize&&(a="none"),this.$videoElement.style.objectFit=a,this.$videoElement.style.transform="rotate("+o+"deg)",this.$videoElement.style.left=r+"px",this.$videoElement.style.top=s+"px"}isPlaying(){return this.$videoElement&&!this.$videoElement.paused}}class Fe{constructor(e){return new(Fe.getLoaderFactory(e._opt))(e)}static getLoaderFactory(e){return e.useMSE||e.useWCS&&!e.useOffscreen&&e.wcsUseVideoRender?Le:je}}class Oe extends Be{constructor(e){super(),this.bufferList=[],this.player=e,this.scriptNode=null,this.hasInitScriptNode=!1,this.audioContextChannel=null,this.audioContext=new(window.AudioContext||window.webkitAudioContext),this.gainNode=this.audioContext.createGain();const t=this.audioContext.createBufferSource();t.buffer=this.audioContext.createBuffer(1,1,22050),t.connect(this.audioContext.destination),t.noteOn?t.noteOn(0):t.start(0),this.audioBufferSourceNode=t,this.mediaStreamAudioDestinationNode=this.audioContext.createMediaStreamDestination(),this.audioEnabled(!0),this.gainNode.gain.value=0,this.playing=!1,this.audioSyncVideoOption={diff:null},this.audioInfo={encType:"",channels:"",sampleRate:""},this.init=!1,this.hasAudio=!1,this.on(x.videoSyncAudio,(e=>{this.audioSyncVideoOption=e})),this.player.debug.log("AudioContext","init")}resetInit(){this.init=!1,this.audioInfo={encType:"",channels:"",sampleRate:""}}destroy(){this.closeAudio(),this.resetInit(),this.audioContext.close(),this.audioContext=null,this.gainNode=null,this.hasAudio=!1,this.playing=!1,this.scriptNode&&(this.scriptNode.onaudioprocess=le,this.scriptNode=null),this.audioBufferSourceNode=null,this.mediaStreamAudioDestinationNode=null,this.hasInitScriptNode=!1,this.audioSyncVideoOption={diff:null},this.off(),this.player.debug.log("AudioContext","destroy")}updateAudioInfo(e){e.encTypeCode&&(this.audioInfo.encType=W[e.encTypeCode]),e.channels&&(this.audioInfo.channels=e.channels),e.sampleRate&&(this.audioInfo.sampleRate=e.sampleRate),this.audioInfo.sampleRate&&this.audioInfo.channels&&this.audioInfo.encType&&!this.init&&(this.player.emit(x.audioInfo,this.audioInfo),this.init=!0)}get isPlaying(){return this.playing}get isMute(){return 0===this.gainNode.gain.value||this.isStateSuspended()}get volume(){return this.gainNode.gain.value}get bufferSize(){return this.bufferList.length}initScriptNode(){if(this.playing=!0,this.hasInitScriptNode)return;const e=this.audioInfo.channels,t=this.audioContext.createScriptProcessor(1024,0,e);t.onaudioprocess=t=>{const i=t.outputBuffer;if(this.bufferList.length&&this.playing){if(!this.player._opt.useWCS&&!this.player._opt.useMSE&&this.player._opt.wasmDecodeAudioSyncVideo){if(this.audioSyncVideoOption.diff>ee)return void this.player.debug.warn("AudioContext",`audioSyncVideoOption more than diff :${this.audioSyncVideoOption.diff}, waiting`);if(this.audioSyncVideoOption.diff<-1e3){this.player.debug.warn("AudioContext",`audioSyncVideoOption less than diff :${this.audioSyncVideoOption.diff}, dropping`);let e=this.bufferList.shift();for(;e.ts-this.player.videoTimestamp<-1e3&&this.bufferList.length>0;)e=this.bufferList.shift();if(0===this.bufferList.length)return}}if(0===this.bufferList.length)return;const t=this.bufferList.shift();t&&t.ts&&(this.player.audioTimestamp=t.ts);for(let o=0;o<e;o++){const e=t.buffer[o],r=i.getChannelData(o);for(let t=0;t<1024;t++)r[t]=e[t]||0}}},t.connect(this.gainNode),this.scriptNode=t,this.gainNode.connect(this.audioContext.destination),this.gainNode.connect(this.mediaStreamAudioDestinationNode),this.hasInitScriptNode=!0}mute(e){e?(this.isMute||this.player.emit(x.mute,e),this.setVolume(0),this.audioEnabled(!1),this.clear()):(this.isMute&&this.player.emit(x.mute,e),this.setVolume(.5),this.audioEnabled(!0))}setVolume(e){e=parseFloat(e).toFixed(2),isNaN(e)||(this.audioEnabled(!0),e=pe(e,0,1),this.gainNode.gain.value=e,this.gainNode.gain.setValueAtTime(e,this.audioContext.currentTime),this.player.emit(x.volumechange,this.player.volume))}closeAudio(){this.hasInitScriptNode&&(this.scriptNode&&this.scriptNode.disconnect(this.gainNode),this.gainNode&&this.gainNode.disconnect(this.audioContext.destination),this.gainNode&&this.gainNode.disconnect(this.mediaStreamAudioDestinationNode)),this.clear()}audioEnabled(e){e?"suspended"===this.audioContext.state&&this.audioContext.resume():"running"===this.audioContext.state&&this.audioContext.suspend()}isStateRunning(){return"running"===this.audioContext.state}isStateSuspended(){return"suspended"===this.audioContext.state}clear(){this.bufferList=[]}play(e,t){this.isMute||(this.hasAudio=!0,this.bufferList.push({buffer:e,ts:t}),this.bufferList.length>20&&(this.player.debug.warn("AudioContext",`bufferList is large: ${this.bufferList.length}`),this.bufferList.length>50&&this.bufferList.shift()))}pause(){this.audioSyncVideoOption={diff:null},this.playing=!1,this.clear()}resume(){this.playing=!0}}class Ve{constructor(e){return new(Ve.getLoaderFactory())(e)}static getLoaderFactory(){return Oe}}class Me extends Be{constructor(e){super(),this.player=e,this.playing=!1,this.abortController=new AbortController,this.streamRate=be((t=>{e.emit(x.kBps,(t/1024).toFixed(2))})),e.debug.log("FetchStream","init")}destroy(){this.abort(),this.off(),this.streamRate=null,this.player.debug.log("FetchStream","destroy")}fetchStream(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const{demux:i}=this.player;this.player._times.streamStart=he();const o=Object.assign({signal:this.abortController.signal},{headers:t.headers||{}});fetch(e,o).then((e=>{const t=e.body.getReader();this.emit(x.streamSuccess);const o=()=>{t.read().then((e=>{let{done:t,value:r}=e;t?i.close():(this.streamRate&&this.streamRate(r.byteLength),i.dispatch(r),o())})).catch((e=>{i.close();const t=e.toString();-1===t.indexOf(se)&&-1===t.indexOf(ae)&&e.name!==ne&&(this.abort(),this.emit(j.fetchError,e),this.player.emit(x.error,j.fetchError))}))};o()})).catch((e=>{"AbortError"!==e.name&&(i.close(),this.abort(),this.emit(j.fetchError,e),this.player.emit(x.error,j.fetchError))}))}abort(){this.abortController&&(this.abortController.abort(),this.abortController=null)}}class Ue extends Be{constructor(e){super(),this.player=e,this.socket=null,this.socketStatus=L,this.wsUrl=null,this.streamRate=be((t=>{e.emit(x.kBps,(t/1024).toFixed(2))})),e.debug.log("WebsocketLoader","init")}destroy(){this.socket&&(this.socket.close(),this.socket=null),this.socketStatus=L,this.streamRate=null,this.wsUrl=null,this.off(),this.player.debug.log("websocketLoader","destroy")}_createWebSocket(){const e=this.player,{debug:t,events:{proxy:i},demux:o}=e;this.socket=new WebSocket(this.wsUrl),this.socket.binaryType="arraybuffer",i(this.socket,"open",(()=>{this.emit(x.streamSuccess),t.log("websocketLoader","socket open"),this.socketStatus=F})),i(this.socket,"message",(e=>{this.streamRate&&this.streamRate(e.data.byteLength),this._handleMessage(e.data)})),i(this.socket,"close",(()=>{t.log("websocketLoader","socket close"),this.emit(x.streamEnd),this.socketStatus=O})),i(this.socket,"error",(e=>{t.log("websocketLoader","socket error"),this.emit(j.websocketError,e),this.player.emit(x.error,j.websocketError),this.socketStatus=V,o.close(),t.log("websocketLoader","socket error:",e)}))}_handleMessage(e){const{demux:t}=this.player;t?t.dispatch(e):this.player.debug.warn("websocketLoader","websocket handle message demux is null")}fetchStream(e,t){this.player._times.streamStart=he(),this.wsUrl=e,this._createWebSocket()}}class Qe{constructor(e){return new(Qe.getLoaderFactory(e._opt.protocol))(e)}static getLoaderFactory(e){return e===a?Me:e===s?Ue:void 0}}var We=t((function(t){function i(e,t){if(!e)throw"First parameter is required.";t=new o(e,t=t||{type:"video"});var s=this;function a(i){i&&(t.initCallback=function(){i(),i=t.initCallback=null});var o=new r(e,t);(h=new o(e,t)).record(),u("recording"),t.disableLogs||console.log("Initialized recorderType:",h.constructor.name,"for output-type:",t.type)}function n(e){if(e=e||function(){},h){if("paused"===s.state)return s.resumeRecording(),void setTimeout((function(){n(e)}),1);"recording"===s.state||t.disableLogs||console.warn('Recording state should be: "recording", however current state is: ',s.state),t.disableLogs||console.log("Stopped recording "+t.type+" stream."),"gif"!==t.type?h.stop(i):(h.stop(),i()),u("stopped")}else m();function i(i){if(h){Object.keys(h).forEach((function(e){"function"!=typeof h[e]&&(s[e]=h[e])}));var o=h.blob;if(!o){if(!i)throw"Recording failed.";h.blob=o=i}if(o&&!t.disableLogs&&console.log(o.type,"->",b(o.size)),e){var r;try{r=l.createObjectURL(o)}catch(e){}"function"==typeof e.call?e.call(s,r):e(r)}t.autoWriteToDisk&&d((function(e){var i={};i[t.type+"Blob"]=e,x.Store(i)}))}else"function"==typeof e.call?e.call(s,""):e("")}}function A(e){postMessage((new FileReaderSync).readAsDataURL(e))}function d(e,i){if(!e)throw"Pass a callback function over getDataURL.";var o=i?i.blob:(h||{}).blob;if(!o)return t.disableLogs||console.warn("Blob encoder did not finish its job yet."),void setTimeout((function(){d(e,i)}),1e3);if("undefined"==typeof Worker||navigator.mozGetUserMedia){var r=new FileReader;r.readAsDataURL(o),r.onload=function(t){e(t.target.result)}}else{var s=function(e){try{var t=l.createObjectURL(new Blob([e.toString(),"this.onmessage = function (eee) {"+e.name+"(eee.data);}"],{type:"application/javascript"})),i=new Worker(t);return l.revokeObjectURL(t),i}catch(e){}}(A);s.onmessage=function(t){e(t.data)},s.postMessage(o)}}function c(e){e=e||0,"paused"!==s.state?"stopped"!==s.state&&(e>=s.recordingDuration?n(s.onRecordingStopped):(e+=1e3,setTimeout((function(){c(e)}),1e3))):setTimeout((function(){c(e)}),1e3)}function u(e){s&&(s.state=e,"function"==typeof s.onStateChanged.call?s.onStateChanged.call(s,e):s.onStateChanged(e))}var h,p='It seems that recorder is destroyed or "startRecording" is not invoked for '+t.type+" recorder.";function m(){!0!==t.disableLogs&&console.warn(p)}var g={startRecording:function(i){return t.disableLogs||console.log("RecordRTC version: ",s.version),i&&(t=new o(e,i)),t.disableLogs||console.log("started recording "+t.type+" stream."),h?(h.clearRecordedData(),h.record(),u("recording"),s.recordingDuration&&c(),s):(a((function(){s.recordingDuration&&c()})),s)},stopRecording:n,pauseRecording:function(){h?"recording"===s.state?(u("paused"),h.pause(),t.disableLogs||console.log("Paused recording.")):t.disableLogs||console.warn("Unable to pause the recording. Recording state: ",s.state):m()},resumeRecording:function(){h?"paused"===s.state?(u("recording"),h.resume(),t.disableLogs||console.log("Resumed recording.")):t.disableLogs||console.warn("Unable to resume the recording. Recording state: ",s.state):m()},initRecorder:a,setRecordingDuration:function(e,t){if(void 0===e)throw"recordingDuration is required.";if("number"!=typeof e)throw"recordingDuration must be a number.";return s.recordingDuration=e,s.onRecordingStopped=t||function(){},{onRecordingStopped:function(e){s.onRecordingStopped=e}}},clearRecordedData:function(){h?(h.clearRecordedData(),t.disableLogs||console.log("Cleared old recorded data.")):m()},getBlob:function(){if(h)return h.blob;m()},getDataURL:d,toURL:function(){if(h)return l.createObjectURL(h.blob);m()},getInternalRecorder:function(){return h},save:function(e){h?y(h.blob,e):m()},getFromDisk:function(e){h?i.getFromDisk(t.type,e):m()},setAdvertisementArray:function(e){t.advertisement=[];for(var i=e.length,o=0;o<i;o++)t.advertisement.push({duration:o,image:e[o]})},blob:null,bufferSize:0,sampleRate:0,buffer:null,reset:function(){"recording"!==s.state||t.disableLogs||console.warn("Stop an active recorder."),h&&"function"==typeof h.clearRecordedData&&h.clearRecordedData(),h=null,u("inactive"),s.blob=null},onStateChanged:function(e){t.disableLogs||console.log("Recorder state changed:",e)},state:"inactive",getState:function(){return s.state},destroy:function(){var e=t.disableLogs;t={disableLogs:!0},s.reset(),u("destroyed"),g=s=null,E.AudioContextConstructor&&(E.AudioContextConstructor.close(),E.AudioContextConstructor=null),t.disableLogs=e,t.disableLogs||console.log("RecordRTC is destroyed.")},version:"5.6.2"};if(!this)return s=g,g;for(var f in g)this[f]=g[f];return s=this,g}function o(e,t){return t.recorderType||t.type||(t.audio&&t.video?t.type="video":t.audio&&!t.video&&(t.type="audio")),t.recorderType&&!t.type&&(t.recorderType===T||t.recorderType===k||t.recorderType===F?t.type="video":t.recorderType===D?t.type="gif":t.recorderType===R?t.type="audio":t.recorderType===C&&(w(e,"audio").length&&w(e,"video").length||!w(e,"audio").length&&w(e,"video").length?t.type="video":w(e,"audio").length&&!w(e,"video").length&&(t.type="audio"))),"undefined"!=typeof MediaRecorder&&"requestData"in MediaRecorder.prototype&&(t.mimeType||(t.mimeType="video/webm"),t.type||(t.type=t.mimeType.split("/")[0]),t.bitsPerSecond),t.type||(t.mimeType&&(t.type=t.mimeType.split("/")[0]),t.type||(t.type="audio")),t}function r(e,t){var i;return(m||u||h)&&(i=R),"undefined"!=typeof MediaRecorder&&"requestData"in MediaRecorder.prototype&&!m&&(i=C),"video"===t.type&&(m||h)&&(i=T,"undefined"!=typeof ReadableStream&&(i=F)),"gif"===t.type&&(i=D),"canvas"===t.type&&(i=k),B()&&i!==k&&i!==D&&"undefined"!=typeof MediaRecorder&&"requestData"in MediaRecorder.prototype&&(w(e,"video").length||w(e,"audio").length)&&("audio"===t.type?"function"==typeof MediaRecorder.isTypeSupported&&MediaRecorder.isTypeSupported("audio/webm")&&(i=C):"function"==typeof MediaRecorder.isTypeSupported&&MediaRecorder.isTypeSupported("video/webm")&&(i=C)),e instanceof Array&&e.length&&(i=L),t.recorderType&&(i=t.recorderType),!t.disableLogs&&i&&i.name&&console.log("Using recorderType:",i.name||i.constructor.name),!i&&g&&(i=C),i}function s(e){this.addStream=function(t){t&&(e=t)},this.mediaType={audio:!0,video:!0},this.startRecording=function(){var t,o=this.mediaType,r=this.mimeType||{audio:null,video:null,gif:null};if("function"!=typeof o.audio&&B()&&!w(e,"audio").length&&(o.audio=!1),"function"!=typeof o.video&&B()&&!w(e,"video").length&&(o.video=!1),"function"!=typeof o.gif&&B()&&!w(e,"video").length&&(o.gif=!1),!o.audio&&!o.video&&!o.gif)throw"MediaStream must have either audio or video tracks.";if(o.audio&&(t=null,"function"==typeof o.audio&&(t=o.audio),this.audioRecorder=new i(e,{type:"audio",bufferSize:this.bufferSize,sampleRate:this.sampleRate,numberOfAudioChannels:this.numberOfAudioChannels||2,disableLogs:this.disableLogs,recorderType:t,mimeType:r.audio,timeSlice:this.timeSlice,onTimeStamp:this.onTimeStamp}),o.video||this.audioRecorder.startRecording()),o.video){t=null,"function"==typeof o.video&&(t=o.video);var s=e;if(B()&&o.audio&&"function"==typeof o.audio){var a=w(e,"video")[0];p?((s=new f).addTrack(a),t&&t===T&&(t=C)):(s=new f).addTrack(a)}this.videoRecorder=new i(s,{type:"video",video:this.video,canvas:this.canvas,frameInterval:this.frameInterval||10,disableLogs:this.disableLogs,recorderType:t,mimeType:r.video,timeSlice:this.timeSlice,onTimeStamp:this.onTimeStamp,workerPath:this.workerPath,webAssemblyPath:this.webAssemblyPath,frameRate:this.frameRate,bitrate:this.bitrate}),o.audio||this.videoRecorder.startRecording()}if(o.audio&&o.video){var n=this,A=!0===B();(o.audio instanceof R&&o.video||!0!==o.audio&&!0!==o.video&&o.audio!==o.video)&&(A=!1),!0===A?(n.audioRecorder=null,n.videoRecorder.startRecording()):n.videoRecorder.initRecorder((function(){n.audioRecorder.initRecorder((function(){n.videoRecorder.startRecording(),n.audioRecorder.startRecording()}))}))}o.gif&&(t=null,"function"==typeof o.gif&&(t=o.gif),this.gifRecorder=new i(e,{type:"gif",frameRate:this.frameRate||200,quality:this.quality||10,disableLogs:this.disableLogs,recorderType:t,mimeType:r.gif}),this.gifRecorder.startRecording())},this.stopRecording=function(e){e=e||function(){},this.audioRecorder&&this.audioRecorder.stopRecording((function(t){e(t,"audio")})),this.videoRecorder&&this.videoRecorder.stopRecording((function(t){e(t,"video")})),this.gifRecorder&&this.gifRecorder.stopRecording((function(t){e(t,"gif")}))},this.pauseRecording=function(){this.audioRecorder&&this.audioRecorder.pauseRecording(),this.videoRecorder&&this.videoRecorder.pauseRecording(),this.gifRecorder&&this.gifRecorder.pauseRecording()},this.resumeRecording=function(){this.audioRecorder&&this.audioRecorder.resumeRecording(),this.videoRecorder&&this.videoRecorder.resumeRecording(),this.gifRecorder&&this.gifRecorder.resumeRecording()},this.getBlob=function(e){var t={};return this.audioRecorder&&(t.audio=this.audioRecorder.getBlob()),this.videoRecorder&&(t.video=this.videoRecorder.getBlob()),this.gifRecorder&&(t.gif=this.gifRecorder.getBlob()),e&&e(t),t},this.destroy=function(){this.audioRecorder&&(this.audioRecorder.destroy(),this.audioRecorder=null),this.videoRecorder&&(this.videoRecorder.destroy(),this.videoRecorder=null),this.gifRecorder&&(this.gifRecorder.destroy(),this.gifRecorder=null)},this.getDataURL=function(e){function t(e,t){if("undefined"!=typeof Worker){var i=function(e){var t,i=l.createObjectURL(new Blob([e.toString(),"this.onmessage = function (eee) {"+e.name+"(eee.data);}"],{type:"application/javascript"})),o=new Worker(i);if(void 0!==l)t=l;else{if("undefined"==typeof webkitURL)throw"Neither URL nor webkitURL detected.";t=webkitURL}return t.revokeObjectURL(i),o}((function(e){postMessage((new FileReaderSync).readAsDataURL(e))}));i.onmessage=function(e){t(e.data)},i.postMessage(e)}else{var o=new FileReader;o.readAsDataURL(e),o.onload=function(e){t(e.target.result)}}}this.getBlob((function(i){i.audio&&i.video?t(i.audio,(function(o){t(i.video,(function(t){e({audio:o,video:t})}))})):i.audio?t(i.audio,(function(t){e({audio:t})})):i.video&&t(i.video,(function(t){e({video:t})}))}))},this.writeToDisk=function(){i.writeToDisk({audio:this.audioRecorder,video:this.videoRecorder,gif:this.gifRecorder})},this.save=function(e){(e=e||{audio:!0,video:!0,gif:!0}).audio&&this.audioRecorder&&this.audioRecorder.save("string"==typeof e.audio?e.audio:""),e.video&&this.videoRecorder&&this.videoRecorder.save("string"==typeof e.video?e.video:""),e.gif&&this.gifRecorder&&this.gifRecorder.save("string"==typeof e.gif?e.gif:"")}}i.version="5.6.2",t.exports=i,i.getFromDisk=function(e,t){if(!t)throw"callback is mandatory.";console.log("Getting recorded "+("all"===e?"blobs":e+" blob ")+" from disk!"),x.Fetch((function(i,o){"all"!==e&&o===e+"Blob"&&t&&t(i),"all"===e&&t&&t(i,o.replace("Blob",""))}))},i.writeToDisk=function(e){console.log("Writing recorded blob(s) to disk!"),(e=e||{}).audio&&e.video&&e.gif?e.audio.getDataURL((function(t){e.video.getDataURL((function(i){e.gif.getDataURL((function(e){x.Store({audioBlob:t,videoBlob:i,gifBlob:e})}))}))})):e.audio&&e.video?e.audio.getDataURL((function(t){e.video.getDataURL((function(e){x.Store({audioBlob:t,videoBlob:e})}))})):e.audio&&e.gif?e.audio.getDataURL((function(t){e.gif.getDataURL((function(e){x.Store({audioBlob:t,gifBlob:e})}))})):e.video&&e.gif?e.video.getDataURL((function(t){e.gif.getDataURL((function(e){x.Store({videoBlob:t,gifBlob:e})}))})):e.audio?e.audio.getDataURL((function(e){x.Store({audioBlob:e})})):e.video?e.video.getDataURL((function(e){x.Store({videoBlob:e})})):e.gif&&e.gif.getDataURL((function(e){x.Store({gifBlob:e})}))},s.getFromDisk=i.getFromDisk,s.writeToDisk=i.writeToDisk,i.MRecordRTC=s;var a;(a=void 0!==e?e:null)&&"undefined"==typeof window&&void 0!==e&&(e.navigator={userAgent:"Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45",getUserMedia:function(){}},e.console||(e.console={}),void 0!==e.console.log&&void 0!==e.console.error||(e.console.error=e.console.log=e.console.log||function(){console.log(arguments)}),"undefined"==typeof document&&(a.document={documentElement:{appendChild:function(){return""}}},document.createElement=document.captureStream=document.mozCaptureStream=function(){var e={getContext:function(){return e},play:function(){},pause:function(){},drawImage:function(){},toDataURL:function(){return""},style:{}};return e},a.HTMLVideoElement=function(){}),"undefined"==typeof location&&(a.location={protocol:"file:",href:"",hash:""}),"undefined"==typeof screen&&(a.screen={width:0,height:0}),void 0===l&&(a.URL={createObjectURL:function(){return""},revokeObjectURL:function(){return""}}),a.window=e);var n=window.requestAnimationFrame;if(void 0===n)if("undefined"!=typeof webkitRequestAnimationFrame)n=webkitRequestAnimationFrame;else if("undefined"!=typeof mozRequestAnimationFrame)n=mozRequestAnimationFrame;else if("undefined"!=typeof msRequestAnimationFrame)n=msRequestAnimationFrame;else if(void 0===n){var A=0;n=function(e,t){var i=(new Date).getTime(),o=Math.max(0,16-(i-A)),r=setTimeout((function(){e(i+o)}),o);return A=i+o,r}}var d=window.cancelAnimationFrame;void 0===d&&("undefined"!=typeof webkitCancelAnimationFrame?d=webkitCancelAnimationFrame:"undefined"!=typeof mozCancelAnimationFrame?d=mozCancelAnimationFrame:"undefined"!=typeof msCancelAnimationFrame?d=msCancelAnimationFrame:void 0===d&&(d=function(e){clearTimeout(e)}));var c=window.AudioContext;void 0===c&&("undefined"!=typeof webkitAudioContext&&(c=webkitAudioContext),"undefined"!=typeof mozAudioContext&&(c=mozAudioContext));var l=window.URL;void 0===l&&"undefined"!=typeof webkitURL&&(l=webkitURL),"undefined"!=typeof navigator&&void 0===navigator.getUserMedia&&(void 0!==navigator.webkitGetUserMedia&&(navigator.getUserMedia=navigator.webkitGetUserMedia),void 0!==navigator.mozGetUserMedia&&(navigator.getUserMedia=navigator.mozGetUserMedia));var u=!(-1===navigator.userAgent.indexOf("Edge")||!navigator.msSaveBlob&&!navigator.msSaveOrOpenBlob),h=!!window.opera||-1!==navigator.userAgent.indexOf("OPR/"),p=navigator.userAgent.toLowerCase().indexOf("firefox")>-1&&"netscape"in window&&/ rv:/.test(navigator.userAgent),m=!h&&!u&&!!navigator.webkitGetUserMedia||v()||-1!==navigator.userAgent.toLowerCase().indexOf("chrome/"),g=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);g&&!m&&-1!==navigator.userAgent.indexOf("CriOS")&&(g=!1,m=!0);var f=window.MediaStream;function b(e){if(0===e)return"0 Bytes";var t=parseInt(Math.floor(Math.log(e)/Math.log(1e3)),10);return(e/Math.pow(1e3,t)).toPrecision(3)+" "+["Bytes","KB","MB","GB","TB"][t]}function y(e,t){if(!e)throw"Blob object is required.";if(!e.type)try{e.type="video/webm"}catch(e){}var i=(e.type||"video/webm").split("/")[1];if(-1!==i.indexOf(";")&&(i=i.split(";")[0]),t&&-1!==t.indexOf(".")){var o=t.split(".");t=o[0],i=o[1]}var r=(t||Math.round(9999999999*Math.random())+888888888)+"."+i;if(void 0!==navigator.msSaveOrOpenBlob)return navigator.msSaveOrOpenBlob(e,r);if(void 0!==navigator.msSaveBlob)return navigator.msSaveBlob(e,r);var s=document.createElement("a");s.href=l.createObjectURL(e),s.download=r,s.style="display:none;opacity:0;color:transparent;",(document.body||document.documentElement).appendChild(s),"function"==typeof s.click?s.click():(s.target="_blank",s.dispatchEvent(new MouseEvent("click",{view:window,bubbles:!0,cancelable:!0}))),l.revokeObjectURL(s.href)}function v(){return"undefined"!=typeof window&&"object"==typeof window.process&&"renderer"===window.process.type||(!("undefined"==typeof process||"object"!=typeof process.versions||!process.versions.electron)||"object"==typeof navigator&&"string"==typeof navigator.userAgent&&navigator.userAgent.indexOf("Electron")>=0)}function w(e,t){return e&&e.getTracks?e.getTracks().filter((function(e){return e.kind===(t||"audio")})):[]}function S(e,t){"srcObject"in t?t.srcObject=e:"mozSrcObject"in t?t.mozSrcObject=e:t.srcObject=e}void 0===f&&"undefined"!=typeof webkitMediaStream&&(f=webkitMediaStream),void 0!==f&&void 0===f.prototype.stop&&(f.prototype.stop=function(){this.getTracks().forEach((function(e){e.stop()}))}),i.invokeSaveAsDialog=y,i.getTracks=w,i.getSeekableBlob=function(e,t){if("undefined"==typeof EBML)throw new Error("Please link: https://www.webrtc-experiment.com/EBML.js");var i=new EBML.Reader,o=new EBML.Decoder,r=EBML.tools,s=new FileReader;s.onload=function(e){o.decode(this.result).forEach((function(e){i.read(e)})),i.stop();var s=r.makeMetadataSeekable(i.metadatas,i.duration,i.cues),a=this.result.slice(i.metadataSize),n=new Blob([s,a],{type:"video/webm"});t(n)},s.readAsArrayBuffer(e)},i.bytesToSize=b,i.isElectron=v;var E={};function B(){if(p||g||u)return!0;var e,t,i=navigator.userAgent,o=""+parseFloat(navigator.appVersion),r=parseInt(navigator.appVersion,10);return(m||h)&&(e=i.indexOf("Chrome"),o=i.substring(e+7)),-1!==(t=o.indexOf(";"))&&(o=o.substring(0,t)),-1!==(t=o.indexOf(" "))&&(o=o.substring(0,t)),r=parseInt(""+o,10),isNaN(r)&&(o=""+parseFloat(navigator.appVersion),r=parseInt(navigator.appVersion,10)),r>=49}function C(e,t){var i=this;if(void 0===e)throw'First argument "MediaStream" is required.';if("undefined"==typeof MediaRecorder)throw"Your browser does not support the Media Recorder API. Please try other modules e.g. WhammyRecorder or StereoAudioRecorder.";if("audio"===(t=t||{mimeType:"video/webm"}).type){var o;if(w(e,"video").length&&w(e,"audio").length)navigator.mozGetUserMedia?(o=new f).addTrack(w(e,"audio")[0]):o=new f(w(e,"audio")),e=o;t.mimeType&&-1!==t.mimeType.toString().toLowerCase().indexOf("audio")||(t.mimeType=m?"audio/webm":"audio/ogg"),t.mimeType&&"audio/ogg"!==t.mimeType.toString().toLowerCase()&&navigator.mozGetUserMedia&&(t.mimeType="audio/ogg")}var r,s=[];function a(){i.timestamps.push((new Date).getTime()),"function"==typeof t.onTimeStamp&&t.onTimeStamp(i.timestamps[i.timestamps.length-1],i.timestamps)}function n(e){return r&&r.mimeType?r.mimeType:e.mimeType||"video/webm"}function A(){s=[],r=null,i.timestamps=[]}this.getArrayOfBlobs=function(){return s},this.record=function(){i.blob=null,i.clearRecordedData(),i.timestamps=[],d=[],s=[];var o=t;t.disableLogs||console.log("Passing following config over MediaRecorder API.",o),r&&(r=null),m&&!B()&&(o="video/vp8"),"function"==typeof MediaRecorder.isTypeSupported&&o.mimeType&&(MediaRecorder.isTypeSupported(o.mimeType)||(t.disableLogs||console.warn("MediaRecorder API seems unable to record mimeType:",o.mimeType),o.mimeType="audio"===t.type?"audio/webm":"video/webm"));try{r=new MediaRecorder(e,o),t.mimeType=o.mimeType}catch(t){r=new MediaRecorder(e)}o.mimeType&&!MediaRecorder.isTypeSupported&&"canRecordMimeType"in r&&!1===r.canRecordMimeType(o.mimeType)&&(t.disableLogs||console.warn("MediaRecorder API seems unable to record mimeType:",o.mimeType)),r.ondataavailable=function(e){if(e.data&&d.push("ondataavailable: "+b(e.data.size)),"number"!=typeof t.timeSlice)!e.data||!e.data.size||e.data.size<100||i.blob?i.recordingCallback&&(i.recordingCallback(new Blob([],{type:n(o)})),i.recordingCallback=null):(i.blob=t.getNativeBlob?e.data:new Blob([e.data],{type:n(o)}),i.recordingCallback&&(i.recordingCallback(i.blob),i.recordingCallback=null));else if(e.data&&e.data.size&&(s.push(e.data),a(),"function"==typeof t.ondataavailable)){var r=t.getNativeBlob?e.data:new Blob([e.data],{type:n(o)});t.ondataavailable(r)}},r.onstart=function(){d.push("started")},r.onpause=function(){d.push("paused")},r.onresume=function(){d.push("resumed")},r.onstop=function(){d.push("stopped")},r.onerror=function(e){e&&(e.name||(e.name="UnknownError"),d.push("error: "+e),t.disableLogs||(-1!==e.name.toString().toLowerCase().indexOf("invalidstate")?console.error("The MediaRecorder is not in a state in which the proposed operation is allowed to be executed.",e):-1!==e.name.toString().toLowerCase().indexOf("notsupported")?console.error("MIME type (",o.mimeType,") is not supported.",e):-1!==e.name.toString().toLowerCase().indexOf("security")?console.error("MediaRecorder security error",e):"OutOfMemory"===e.name?console.error("The UA has exhaused the available memory. User agents SHOULD provide as much additional information as possible in the message attribute.",e):"IllegalStreamModification"===e.name?console.error("A modification to the stream has occurred that makes it impossible to continue recording. An example would be the addition of a Track while recording is occurring. User agents SHOULD provide as much additional information as possible in the message attribute.",e):"OtherRecordingError"===e.name?console.error("Used for an fatal error other than those listed above. User agents SHOULD provide as much additional information as possible in the message attribute.",e):"GenericError"===e.name?console.error("The UA cannot provide the codec or recording option that has been requested.",e):console.error("MediaRecorder Error",e)),function(e){if(!i.manuallyStopped&&r&&"inactive"===r.state)return delete t.timeslice,void r.start(6e5);setTimeout(void 0,1e3)}(),"inactive"!==r.state&&"stopped"!==r.state&&r.stop())},"number"==typeof t.timeSlice?(a(),r.start(t.timeSlice)):r.start(36e5),t.initCallback&&t.initCallback()},this.timestamps=[],this.stop=function(e){e=e||function(){},i.manuallyStopped=!0,r&&(this.recordingCallback=e,"recording"===r.state&&r.stop(),"number"==typeof t.timeSlice&&setTimeout((function(){i.blob=new Blob(s,{type:n(t)}),i.recordingCallback(i.blob)}),100))},this.pause=function(){r&&"recording"===r.state&&r.pause()},this.resume=function(){r&&"paused"===r.state&&r.resume()},this.clearRecordedData=function(){r&&"recording"===r.state&&i.stop(A),A()},this.getInternalRecorder=function(){return r},this.blob=null,this.getState=function(){return r&&r.state||"inactive"};var d=[];this.getAllStates=function(){return d},void 0===t.checkForInactiveTracks&&(t.checkForInactiveTracks=!1);i=this;!function o(){if(r&&!1!==t.checkForInactiveTracks)return!1===function(){if("active"in e){if(!e.active)return!1}else if("ended"in e&&e.ended)return!1;return!0}()?(t.disableLogs||console.log("MediaStream seems stopped."),void i.stop()):void setTimeout(o,1e3)}(),this.name="MediaStreamRecorder",this.toString=function(){return this.name}}function R(e,t){if(!w(e,"audio").length)throw"Your stream has no audio tracks.";var o,r=this,s=[],a=[],n=!1,A=0,d=2,c=(t=t||{}).desiredSampRate;function u(){if(!1===t.checkForInactiveTracks)return!0;if("active"in e){if(!e.active)return!1}else if("ended"in e&&e.ended)return!1;return!0}function h(e,t){function i(e,t){var i,o=e.numberOfAudioChannels,r=e.leftBuffers.slice(0),s=e.rightBuffers.slice(0),a=e.sampleRate,n=e.internalInterleavedLength,A=e.desiredSampRate;function d(e,t,i){var o=Math.round(e.length*(t/i)),r=[],s=Number((e.length-1)/(o-1));r[0]=e[0];for(var a=1;a<o-1;a++){var n=a*s,A=Number(Math.floor(n)).toFixed(),d=Number(Math.ceil(n)).toFixed(),l=n-A;r[a]=c(e[A],e[d],l)}return r[o-1]=e[e.length-1],r}function c(e,t,i){return e+(t-e)*i}function l(e,t){for(var i=new Float64Array(t),o=0,r=e.length,s=0;s<r;s++){var a=e[s];i.set(a,o),o+=a.length}return i}function u(e,t,i){for(var o=i.length,r=0;r<o;r++)e.setUint8(t+r,i.charCodeAt(r))}2===o&&(r=l(r,n),s=l(s,n),A&&(r=d(r,A,a),s=d(s,A,a))),1===o&&(r=l(r,n),A&&(r=d(r,A,a))),A&&(a=A),2===o&&(i=function(e,t){for(var i=e.length+t.length,o=new Float64Array(i),r=0,s=0;s<i;)o[s++]=e[r],o[s++]=t[r],r++;return o}(r,s)),1===o&&(i=r);var h=i.length,p=new ArrayBuffer(44+2*h),m=new DataView(p);u(m,0,"RIFF"),m.setUint32(4,36+2*h,!0),u(m,8,"WAVE"),u(m,12,"fmt "),m.setUint32(16,16,!0),m.setUint16(20,1,!0),m.setUint16(22,o,!0),m.setUint32(24,a,!0),m.setUint32(28,a*o*2,!0),m.setUint16(32,2*o,!0),m.setUint16(34,16,!0),u(m,36,"data"),m.setUint32(40,2*h,!0);for(var g=h,f=44,b=0;b<g;b++)m.setInt16(f,32767*i[b],!0),f+=2;if(t)return t({buffer:p,view:m});postMessage({buffer:p,view:m})}if(e.noWorker)i(e,(function(e){t(e.buffer,e.view)}));else{var o,r,s,a=(o=i,r=l.createObjectURL(new Blob([o.toString(),";this.onmessage = function (eee) {"+o.name+"(eee.data);}"],{type:"application/javascript"})),(s=new Worker(r)).workerURL=r,s);a.onmessage=function(e){t(e.data.buffer,e.data.view),l.revokeObjectURL(a.workerURL),a.terminate()},a.postMessage(e)}}!0===t.leftChannel&&(d=1),1===t.numberOfAudioChannels&&(d=1),(!d||d<1)&&(d=2),t.disableLogs||console.log("StereoAudioRecorder is set to record number of channels: "+d),void 0===t.checkForInactiveTracks&&(t.checkForInactiveTracks=!0),this.record=function(){if(!1===u())throw"Please make sure MediaStream is active.";v(),E=y=!1,n=!0,void 0!==t.timeSlice&&C()},this.stop=function(e){e=e||function(){},n=!1,h({desiredSampRate:c,sampleRate:b,numberOfAudioChannels:d,internalInterleavedLength:A,leftBuffers:s,rightBuffers:1===d?[]:a,noWorker:t.noWorker},(function(t,i){r.blob=new Blob([i],{type:"audio/wav"}),r.buffer=new ArrayBuffer(i.buffer.byteLength),r.view=i,r.sampleRate=c||b,r.bufferSize=f,r.length=A,E=!1,e&&e(r.blob)}))},void 0===i.Storage&&(i.Storage={AudioContextConstructor:null,AudioContext:window.AudioContext||window.webkitAudioContext}),i.Storage.AudioContextConstructor&&"closed"!==i.Storage.AudioContextConstructor.state||(i.Storage.AudioContextConstructor=new i.Storage.AudioContext);var p=i.Storage.AudioContextConstructor,m=p.createMediaStreamSource(e),g=[0,256,512,1024,2048,4096,8192,16384],f=void 0===t.bufferSize?4096:t.bufferSize;if(-1===g.indexOf(f)&&(t.disableLogs||console.log("Legal values for buffer-size are "+JSON.stringify(g,null,"\t"))),p.createJavaScriptNode)o=p.createJavaScriptNode(f,d,d);else{if(!p.createScriptProcessor)throw"WebAudio API has no support on this browser.";o=p.createScriptProcessor(f,d,d)}m.connect(o),t.bufferSize||(f=o.bufferSize);var b=void 0!==t.sampleRate?t.sampleRate:p.sampleRate||44100;(b<22050||b>96e3)&&(t.disableLogs||console.log("sample-rate must be under range 22050 and 96000.")),t.disableLogs||t.desiredSampRate&&console.log("Desired sample-rate: "+t.desiredSampRate);var y=!1;function v(){s=[],a=[],A=0,E=!1,n=!1,y=!1,p=null,r.leftchannel=s,r.rightchannel=a,r.numberOfAudioChannels=d,r.desiredSampRate=c,r.sampleRate=b,r.recordingLength=A,B={left:[],right:[],recordingLength:0}}function S(){o&&(o.onaudioprocess=null,o.disconnect(),o=null),m&&(m.disconnect(),m=null),v()}this.pause=function(){y=!0},this.resume=function(){if(!1===u())throw"Please make sure MediaStream is active.";if(!n)return t.disableLogs||console.log("Seems recording has been restarted."),void this.record();y=!1},this.clearRecordedData=function(){t.checkForInactiveTracks=!1,n&&this.stop(S),S()},this.name="StereoAudioRecorder",this.toString=function(){return this.name};var E=!1;o.onaudioprocess=function(e){if(!y)if(!1===u()&&(t.disableLogs||console.log("MediaStream seems stopped."),o.disconnect(),n=!1),n){E||(E=!0,t.onAudioProcessStarted&&t.onAudioProcessStarted(),t.initCallback&&t.initCallback());var i=e.inputBuffer.getChannelData(0),c=new Float32Array(i);if(s.push(c),2===d){var l=e.inputBuffer.getChannelData(1),h=new Float32Array(l);a.push(h)}A+=f,r.recordingLength=A,void 0!==t.timeSlice&&(B.recordingLength+=f,B.left.push(c),2===d&&B.right.push(h))}else m&&(m.disconnect(),m=null)},p.createMediaStreamDestination?o.connect(p.createMediaStreamDestination()):o.connect(p.destination),this.leftchannel=s,this.rightchannel=a,this.numberOfAudioChannels=d,this.desiredSampRate=c,this.sampleRate=b,r.recordingLength=A;var B={left:[],right:[],recordingLength:0};function C(){n&&"function"==typeof t.ondataavailable&&void 0!==t.timeSlice&&(B.left.length?(h({desiredSampRate:c,sampleRate:b,numberOfAudioChannels:d,internalInterleavedLength:B.recordingLength,leftBuffers:B.left,rightBuffers:1===d?[]:B.right},(function(e,i){var o=new Blob([i],{type:"audio/wav"});t.ondataavailable(o),setTimeout(C,t.timeSlice)})),B={left:[],right:[],recordingLength:0}):setTimeout(C,t.timeSlice))}}function k(e,t){if("undefined"==typeof html2canvas)throw"Please link: https://www.webrtc-experiment.com/screenshot.js";(t=t||{}).frameInterval||(t.frameInterval=10);var i=!1;["captureStream","mozCaptureStream","webkitCaptureStream"].forEach((function(e){e in document.createElement("canvas")&&(i=!0)}));var o,r,s,a=!(!window.webkitRTCPeerConnection&&!window.webkitGetUserMedia||!window.chrome),n=50,A=navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);if(a&&A&&A[2]&&(n=parseInt(A[2],10)),a&&n<52&&(i=!1),t.useWhammyRecorder&&(i=!1),i)if(t.disableLogs||console.log("Your browser supports both MediRecorder API and canvas.captureStream!"),e instanceof HTMLCanvasElement)o=e;else{if(!(e instanceof CanvasRenderingContext2D))throw"Please pass either HTMLCanvasElement or CanvasRenderingContext2D.";o=e.canvas}else navigator.mozGetUserMedia&&(t.disableLogs||console.error("Canvas recording is NOT supported in Firefox."));this.record=function(){if(s=!0,i&&!t.useWhammyRecorder){var e;"captureStream"in o?e=o.captureStream(25):"mozCaptureStream"in o?e=o.mozCaptureStream(25):"webkitCaptureStream"in o&&(e=o.webkitCaptureStream(25));try{var a=new f;a.addTrack(w(e,"video")[0]),e=a}catch(e){}if(!e)throw"captureStream API are NOT available.";(r=new C(e,{mimeType:t.mimeType||"video/webm"})).record()}else h.frames=[],u=(new Date).getTime(),l();t.initCallback&&t.initCallback()},this.getWebPImages=function(i){if("canvas"===e.nodeName.toLowerCase()){var o=h.frames.length;h.frames.forEach((function(e,i){var r=o-i;t.disableLogs||console.log(r+"/"+o+" frames remaining"),t.onEncodingCallback&&t.onEncodingCallback(r,o);var s=e.image.toDataURL("image/webp",1);h.frames[i].image=s})),t.disableLogs||console.log("Generating WebM"),i()}else i()},this.stop=function(e){s=!1;var o=this;i&&r?r.stop(e):this.getWebPImages((function(){h.compile((function(i){t.disableLogs||console.log("Recording finished!"),o.blob=i,o.blob.forEach&&(o.blob=new Blob([],{type:"video/webm"})),e&&e(o.blob),h.frames=[]}))}))};var d=!1;function c(){h.frames=[],s=!1,d=!1}function l(){if(d)return u=(new Date).getTime(),setTimeout(l,500);if("canvas"===e.nodeName.toLowerCase()){var i=(new Date).getTime()-u;return u=(new Date).getTime(),h.frames.push({image:(o=document.createElement("canvas"),r=o.getContext("2d"),o.width=e.width,o.height=e.height,r.drawImage(e,0,0),o),duration:i}),void(s&&setTimeout(l,t.frameInterval))}var o,r;html2canvas(e,{grabMouse:void 0===t.showMousePointer||t.showMousePointer,onrendered:function(e){var i=(new Date).getTime()-u;if(!i)return setTimeout(l,t.frameInterval);u=(new Date).getTime(),h.frames.push({image:e.toDataURL("image/webp",1),duration:i}),s&&setTimeout(l,t.frameInterval)}})}this.pause=function(){d=!0,r instanceof C&&r.pause()},this.resume=function(){d=!1,r instanceof C?r.resume():s||this.record()},this.clearRecordedData=function(){s&&this.stop(c),c()},this.name="CanvasRecorder",this.toString=function(){return this.name};var u=(new Date).getTime(),h=new I.Video(100)}function T(e,t){function i(e){e=void 0!==e?e:10;var t=(new Date).getTime()-A;return t?s?(A=(new Date).getTime(),setTimeout(i,100)):(A=(new Date).getTime(),n.paused&&n.play(),l.drawImage(n,0,0,c.width,c.height),d.frames.push({duration:t,image:c.toDataURL("image/webp")}),void(r||setTimeout(i,e,e))):setTimeout(i,e,e)}function o(e,t,i,o,r){var s=document.createElement("canvas");s.width=c.width,s.height=c.height;var a,n,A,d=s.getContext("2d"),l=[],u=-1===t,h=t&&t>0&&t<=e.length?t:e.length,p=0,m=0,g=0,f=Math.sqrt(Math.pow(255,2)+Math.pow(255,2)+Math.pow(255,2)),b=i&&i>=0&&i<=1?i:0,y=o&&o>=0&&o<=1?o:0,v=!1;n=-1,A=(a={length:h,functionToLoop:function(t,i){var o,r,s,a=function(){!v&&s-o<=s*y||(u&&(v=!0),l.push(e[i])),t()};if(v)a();else{var n=new Image;n.onload=function(){d.drawImage(n,0,0,c.width,c.height);var e=d.getImageData(0,0,c.width,c.height);o=0,r=e.data.length,s=e.data.length/4;for(var t=0;t<r;t+=4){var i={r:e.data[t],g:e.data[t+1],b:e.data[t+2]};Math.sqrt(Math.pow(i.r-p,2)+Math.pow(i.g-m,2)+Math.pow(i.b-g,2))<=f*b&&o++}a()},n.src=e[i].image}},callback:function(){(l=l.concat(e.slice(h))).length<=0&&l.push(e[e.length-1]),r(l)}}).length,function e(){++n!==A?setTimeout((function(){a.functionToLoop(e,n)}),1):a.callback()}()}(t=t||{}).frameInterval||(t.frameInterval=10),t.disableLogs||console.log("Using frames-interval:",t.frameInterval),this.record=function(){t.width||(t.width=320),t.height||(t.height=240),t.video||(t.video={width:t.width,height:t.height}),t.canvas||(t.canvas={width:t.width,height:t.height}),c.width=t.canvas.width||320,c.height=t.canvas.height||240,l=c.getContext("2d"),t.video&&t.video instanceof HTMLVideoElement?(n=t.video.cloneNode(),t.initCallback&&t.initCallback()):(n=document.createElement("video"),S(e,n),n.onloadedmetadata=function(){t.initCallback&&t.initCallback()},n.width=t.video.width,n.height=t.video.height),n.muted=!0,n.play(),A=(new Date).getTime(),d=new I.Video,t.disableLogs||(console.log("canvas resolutions",c.width,"*",c.height),console.log("video width/height",n.width||c.width,"*",n.height||c.height)),i(t.frameInterval)};var r=!1;this.stop=function(e){e=e||function(){},r=!0;var i=this;setTimeout((function(){o(d.frames,-1,null,null,(function(o){d.frames=o,t.advertisement&&t.advertisement.length&&(d.frames=t.advertisement.concat(d.frames)),d.compile((function(t){i.blob=t,i.blob.forEach&&(i.blob=new Blob([],{type:"video/webm"})),e&&e(i.blob)}))}))}),10)};var s=!1;function a(){d.frames=[],r=!0,s=!1}this.pause=function(){s=!0},this.resume=function(){s=!1,r&&this.record()},this.clearRecordedData=function(){r||this.stop(a),a()},this.name="WhammyRecorder",this.toString=function(){return this.name};var n,A,d,c=document.createElement("canvas"),l=c.getContext("2d")}void 0!==c?E.AudioContext=c:"undefined"!=typeof webkitAudioContext&&(E.AudioContext=webkitAudioContext),i.Storage=E,i.MediaStreamRecorder=C,i.StereoAudioRecorder=R,i.CanvasRecorder=k,i.WhammyRecorder=T;var I=function(){function e(e){this.frames=[],this.duration=e||1,this.quality=.8}function t(e){function t(e,t,i){return[{data:e,id:231}].concat(i.map((function(e){var i=function(e){var t=0;e.keyframe&&(t|=128);e.invisible&&(t|=8);e.lacing&&(t|=e.lacing<<1);e.discardable&&(t|=1);if(e.trackNum>127)throw"TrackNumber > 127 not supported";return[128|e.trackNum,e.timecode>>8,255&e.timecode,t].map((function(e){return String.fromCharCode(e)})).join("")+e.frame}({discardable:0,frame:e.data.slice(4),invisible:0,keyframe:1,lacing:0,trackNum:1,timecode:Math.round(t)});return t+=e.duration,{data:i,id:163}})))}function i(e){for(var t=[];e>0;)t.push(255&e),e>>=8;return new Uint8Array(t.reverse())}function o(e){var t=[];e=(e.length%8?new Array(9-e.length%8).join("0"):"")+e;for(var i=0;i<e.length;i+=8)t.push(parseInt(e.substr(i,8),2));return new Uint8Array(t)}function r(e){for(var t=[],s=0;s<e.length;s++){var a=e[s].data;"object"==typeof a&&(a=r(a)),"number"==typeof a&&(a=o(a.toString(2))),"string"==typeof a&&(a=new Uint8Array(a.split("").map((function(e){return e.charCodeAt(0)}))));var n=a.size||a.byteLength||a.length,A=Math.ceil(Math.ceil(Math.log(n)/Math.log(2))/8),d=n.toString(2),c=new Array(7*A+7+1-d.length).join("0")+d,l=new Array(A).join("0")+"1"+c;t.push(i(e[s].id)),t.push(o(l)),t.push(a)}return new Blob(t,{type:"video/webm"})}function s(e,t){return parseInt(e.substr(t+4,4).split("").map((function(e){var t=e.charCodeAt(0).toString(2);return new Array(8-t.length+1).join("0")+t})).join(""),2)}function a(e){for(var t=0,i={};t<e.length;){var o=e.substr(t,4),r=s(e,t),n=e.substr(t+4+4,r);t+=8+r,i[o]=i[o]||[],"RIFF"===o||"LIST"===o?i[o].push(a(n)):i[o].push(n)}return i}var n=new function(e){var i=function(e){if(!e[0])return void postMessage({error:"Something went wrong. Maybe WebP format is not supported in the current browser."});for(var t=e[0].width,i=e[0].height,o=e[0].duration,r=1;r<e.length;r++)o+=e[r].duration;return{duration:o,width:t,height:i}}(e);if(!i)return[];for(var o,s=[{id:440786851,data:[{data:1,id:17030},{data:1,id:17143},{data:4,id:17138},{data:8,id:17139},{data:"webm",id:17026},{data:2,id:17031},{data:2,id:17029}]},{id:408125543,data:[{id:357149030,data:[{data:1e6,id:2807729},{data:"whammy",id:19840},{data:"whammy",id:22337},{data:(o=i.duration,[].slice.call(new Uint8Array(new Float64Array([o]).buffer),0).map((function(e){return String.fromCharCode(e)})).reverse().join("")),id:17545}]},{id:374648427,data:[{id:174,data:[{data:1,id:215},{data:1,id:29637},{data:0,id:156},{data:"und",id:2274716},{data:"V_VP8",id:134},{data:"VP8",id:2459272},{data:1,id:131},{id:224,data:[{data:i.width,id:176},{data:i.height,id:186}]}]}]}]}],a=0,n=0;a<e.length;){var A=[],d=0;do{A.push(e[a]),d+=e[a].duration,a++}while(a<e.length&&d<3e4);var c={id:524531317,data:t(n,0,A)};s[1].data.push(c),n+=d}return r(s)}(e.map((function(e){var t=function(e){for(var t=e.RIFF[0].WEBP[0],i=t.indexOf("*"),o=0,r=[];o<4;o++)r[o]=t.charCodeAt(i+3+o);return{width:16383&(r[1]<<8|r[0]),height:16383&(r[3]<<8|r[2]),data:t,riff:e}}(a(atob(e.image.slice(23))));return t.duration=e.duration,t})));postMessage(n)}return e.prototype.add=function(e,t){if("canvas"in e&&(e=e.canvas),"toDataURL"in e&&(e=e.toDataURL("image/webp",this.quality)),!/^data:image\/webp;base64,/gi.test(e))throw"Input must be formatted properly as a base64 encoded DataURI of type image/webp";this.frames.push({image:e,duration:t||this.duration})},e.prototype.compile=function(e){var i,o,r,s=(i=t,o=l.createObjectURL(new Blob([i.toString(),"this.onmessage = function (eee) {"+i.name+"(eee.data);}"],{type:"application/javascript"})),r=new Worker(o),l.revokeObjectURL(o),r);s.onmessage=function(t){t.data.error?console.error(t.data.error):e(t.data)},s.postMessage(this.frames)},{Video:e}}();i.Whammy=I;var x={init:function(){var e=this;if("undefined"!=typeof indexedDB&&void 0!==indexedDB.open){var t,i=this.dbName||location.href.replace(/\/|:|#|%|\.|\[|\]/g,""),o=indexedDB.open(i,1);o.onerror=e.onError,o.onsuccess=function(){((t=o.result).onerror=e.onError,t.setVersion)?1!==t.version?t.setVersion(1).onsuccess=function(){r(t),s()}:s():s()},o.onupgradeneeded=function(e){r(e.target.result)}}else console.error("IndexedDB API are not available in this browser.");function r(t){t.createObjectStore(e.dataStoreName)}function s(){var i=t.transaction([e.dataStoreName],"readwrite");function o(t){i.objectStore(e.dataStoreName).get(t).onsuccess=function(i){e.callback&&e.callback(i.target.result,t)}}e.videoBlob&&i.objectStore(e.dataStoreName).put(e.videoBlob,"videoBlob"),e.gifBlob&&i.objectStore(e.dataStoreName).put(e.gifBlob,"gifBlob"),e.audioBlob&&i.objectStore(e.dataStoreName).put(e.audioBlob,"audioBlob"),o("audioBlob"),o("videoBlob"),o("gifBlob")}},Fetch:function(e){return this.callback=e,this.init(),this},Store:function(e){return this.audioBlob=e.audioBlob,this.videoBlob=e.videoBlob,this.gifBlob=e.gifBlob,this.init(),this},onError:function(e){console.error(JSON.stringify(e,null,"\t"))},dataStoreName:"recordRTC",dbName:null};function D(e,t){if("undefined"==typeof GIFEncoder){var i=document.createElement("script");i.src="https://www.webrtc-experiment.com/gif-recorder.js",(document.body||document.documentElement).appendChild(i)}t=t||{};var o=e instanceof CanvasRenderingContext2D||e instanceof HTMLCanvasElement;this.record=function(){"undefined"!=typeof GIFEncoder&&A?(o||(t.width||(t.width=c.offsetWidth||320),t.height||(t.height=c.offsetHeight||240),t.video||(t.video={width:t.width,height:t.height}),t.canvas||(t.canvas={width:t.width,height:t.height}),s.width=t.canvas.width||320,s.height=t.canvas.height||240,c.width=t.video.width||320,c.height=t.video.height||240),(u=new GIFEncoder).setRepeat(0),u.setDelay(t.frameRate||200),u.setQuality(t.quality||10),u.start(),"function"==typeof t.onGifRecordingStarted&&t.onGifRecordingStarted(),h=n((function e(i){if(!0!==p.clearedRecordedData){if(r)return setTimeout((function(){e(i)}),100);h=n(e),void 0===typeof l&&(l=i),i-l<90||(!o&&c.paused&&c.play(),o||a.drawImage(c,0,0,s.width,s.height),t.onGifPreview&&t.onGifPreview(s.toDataURL("image/png")),u.addFrame(a),l=i)}})),t.initCallback&&t.initCallback()):setTimeout(p.record,1e3)},this.stop=function(e){e=e||function(){},h&&d(h),this.blob=new Blob([new Uint8Array(u.stream().bin)],{type:"image/gif"}),e(this.blob),u.stream().bin=[]};var r=!1;this.pause=function(){r=!0},this.resume=function(){r=!1},this.clearRecordedData=function(){p.clearedRecordedData=!0,u&&(u.stream().bin=[])},this.name="GifRecorder",this.toString=function(){return this.name};var s=document.createElement("canvas"),a=s.getContext("2d");o&&(e instanceof CanvasRenderingContext2D?s=(a=e).canvas:e instanceof HTMLCanvasElement&&(a=e.getContext("2d"),s=e));var A=!0;if(!o){var c=document.createElement("video");c.muted=!0,c.autoplay=!0,c.playsInline=!0,A=!1,c.onloadedmetadata=function(){A=!0},S(e,c),c.play()}var l,u,h=null,p=this}function j(e,t){t=t||"multi-streams-mixer";var i=[],o=!1,r=document.createElement("canvas"),s=r.getContext("2d");r.style.opacity=0,r.style.position="absolute",r.style.zIndex=-1,r.style.top="-1000em",r.style.left="-1000em",r.className=t,(document.body||document.documentElement).appendChild(r),this.disableLogs=!1,this.frameInterval=10,this.width=360,this.height=240,this.useGainNode=!0;var a=this,n=window.AudioContext;void 0===n&&("undefined"!=typeof webkitAudioContext&&(n=webkitAudioContext),"undefined"!=typeof mozAudioContext&&(n=mozAudioContext));var A=window.URL;void 0===A&&"undefined"!=typeof webkitURL&&(A=webkitURL),"undefined"!=typeof navigator&&void 0===navigator.getUserMedia&&(void 0!==navigator.webkitGetUserMedia&&(navigator.getUserMedia=navigator.webkitGetUserMedia),void 0!==navigator.mozGetUserMedia&&(navigator.getUserMedia=navigator.mozGetUserMedia));var d=window.MediaStream;void 0===d&&"undefined"!=typeof webkitMediaStream&&(d=webkitMediaStream),void 0!==d&&void 0===d.prototype.stop&&(d.prototype.stop=function(){this.getTracks().forEach((function(e){e.stop()}))});var c={};function l(){if(!o){var e=i.length,t=!1,s=[];if(i.forEach((function(e){e.stream||(e.stream={}),e.stream.fullcanvas?t=e:s.push(e)})),t)r.width=t.stream.width,r.height=t.stream.height;else if(s.length){r.width=e>1?2*s[0].width:s[0].width;var n=1;3!==e&&4!==e||(n=2),5!==e&&6!==e||(n=3),7!==e&&8!==e||(n=4),9!==e&&10!==e||(n=5),r.height=s[0].height*n}else r.width=a.width||360,r.height=a.height||240;t&&t instanceof HTMLVideoElement&&u(t),s.forEach((function(e,t){u(e,t)})),setTimeout(l,a.frameInterval)}}function u(e,t){if(!o){var i=0,r=0,a=e.width,n=e.height;1===t&&(i=e.width),2===t&&(r=e.height),3===t&&(i=e.width,r=e.height),4===t&&(r=2*e.height),5===t&&(i=e.width,r=2*e.height),6===t&&(r=3*e.height),7===t&&(i=e.width,r=3*e.height),void 0!==e.stream.left&&(i=e.stream.left),void 0!==e.stream.top&&(r=e.stream.top),void 0!==e.stream.width&&(a=e.stream.width),void 0!==e.stream.height&&(n=e.stream.height),s.drawImage(e,i,r,a,n),"function"==typeof e.stream.onRender&&e.stream.onRender(s,i,r,a,n,t)}}function h(e){var i=document.createElement("video");return function(e,t){"srcObject"in t?t.srcObject=e:"mozSrcObject"in t?t.mozSrcObject=e:t.srcObject=e}(e,i),i.className=t,i.muted=!0,i.volume=0,i.width=e.width||a.width||360,i.height=e.height||a.height||240,i.play(),i}function p(t){i=[],(t=t||e).forEach((function(e){if(e.getTracks().filter((function(e){return"video"===e.kind})).length){var t=h(e);t.stream=e,i.push(t)}}))}void 0!==n?c.AudioContext=n:"undefined"!=typeof webkitAudioContext&&(c.AudioContext=webkitAudioContext),this.startDrawingFrames=function(){l()},this.appendStreams=function(t){if(!t)throw"First parameter is required.";t instanceof Array||(t=[t]),t.forEach((function(t){var o=new d;if(t.getTracks().filter((function(e){return"video"===e.kind})).length){var r=h(t);r.stream=t,i.push(r),o.addTrack(t.getTracks().filter((function(e){return"video"===e.kind}))[0])}if(t.getTracks().filter((function(e){return"audio"===e.kind})).length){var s=a.audioContext.createMediaStreamSource(t);a.audioDestination=a.audioContext.createMediaStreamDestination(),s.connect(a.audioDestination),o.addTrack(a.audioDestination.stream.getTracks().filter((function(e){return"audio"===e.kind}))[0])}e.push(o)}))},this.releaseStreams=function(){i=[],o=!0,a.gainNode&&(a.gainNode.disconnect(),a.gainNode=null),a.audioSources.length&&(a.audioSources.forEach((function(e){e.disconnect()})),a.audioSources=[]),a.audioDestination&&(a.audioDestination.disconnect(),a.audioDestination=null),a.audioContext&&a.audioContext.close(),a.audioContext=null,s.clearRect(0,0,r.width,r.height),r.stream&&(r.stream.stop(),r.stream=null)},this.resetVideoStreams=function(e){!e||e instanceof Array||(e=[e]),p(e)},this.name="MultiStreamsMixer",this.toString=function(){return this.name},this.getMixedStream=function(){o=!1;var t=function(){var e;p(),"captureStream"in r?e=r.captureStream():"mozCaptureStream"in r?e=r.mozCaptureStream():a.disableLogs||console.error("Upgrade to latest Chrome or otherwise enable this flag: chrome://flags/#enable-experimental-web-platform-features");var t=new d;return e.getTracks().filter((function(e){return"video"===e.kind})).forEach((function(e){t.addTrack(e)})),r.stream=t,t}(),i=function(){c.AudioContextConstructor||(c.AudioContextConstructor=new c.AudioContext);a.audioContext=c.AudioContextConstructor,a.audioSources=[],!0===a.useGainNode&&(a.gainNode=a.audioContext.createGain(),a.gainNode.connect(a.audioContext.destination),a.gainNode.gain.value=0);var t=0;if(e.forEach((function(e){if(e.getTracks().filter((function(e){return"audio"===e.kind})).length){t++;var i=a.audioContext.createMediaStreamSource(e);!0===a.useGainNode&&i.connect(a.gainNode),a.audioSources.push(i)}})),!t)return;return a.audioDestination=a.audioContext.createMediaStreamDestination(),a.audioSources.forEach((function(e){e.connect(a.audioDestination)})),a.audioDestination.stream}();return i&&i.getTracks().filter((function(e){return"audio"===e.kind})).forEach((function(e){t.addTrack(e)})),e.forEach((function(e){e.fullcanvas})),t}}function L(e,t){e=e||[];var i,o,r=this;(t=t||{elementClass:"multi-streams-mixer",mimeType:"video/webm",video:{width:360,height:240}}).frameInterval||(t.frameInterval=10),t.video||(t.video={}),t.video.width||(t.video.width=360),t.video.height||(t.video.height=240),this.record=function(){var r;i=new j(e,t.elementClass||"multi-streams-mixer"),(r=[],e.forEach((function(e){w(e,"video").forEach((function(e){r.push(e)}))})),r).length&&(i.frameInterval=t.frameInterval||10,i.width=t.video.width||360,i.height=t.video.height||240,i.startDrawingFrames()),t.previewStream&&"function"==typeof t.previewStream&&t.previewStream(i.getMixedStream()),(o=new C(i.getMixedStream(),t)).record()},this.stop=function(e){o&&o.stop((function(t){r.blob=t,e(t),r.clearRecordedData()}))},this.pause=function(){o&&o.pause()},this.resume=function(){o&&o.resume()},this.clearRecordedData=function(){o&&(o.clearRecordedData(),o=null),i&&(i.releaseStreams(),i=null)},this.addStreams=function(r){if(!r)throw"First parameter is required.";r instanceof Array||(r=[r]),e.concat(r),o&&i&&(i.appendStreams(r),t.previewStream&&"function"==typeof t.previewStream&&t.previewStream(i.getMixedStream()))},this.resetVideoStreams=function(e){i&&(!e||e instanceof Array||(e=[e]),i.resetVideoStreams(e))},this.getMixer=function(){return i},this.name="MultiStreamRecorder",this.toString=function(){return this.name}}function F(e,t){var i,o,r;function s(){return new ReadableStream({start:function(o){var r=document.createElement("canvas"),s=document.createElement("video"),a=!0;s.srcObject=e,s.muted=!0,s.height=t.height,s.width=t.width,s.volume=0,s.onplaying=function(){r.width=t.width,r.height=t.height;var e=r.getContext("2d"),n=1e3/t.frameRate,A=setInterval((function(){if(i&&(clearInterval(A),o.close()),a&&(a=!1,t.onVideoProcessStarted&&t.onVideoProcessStarted()),e.drawImage(s,0,0),"closed"!==o._controlledReadableStream.state)try{o.enqueue(e.getImageData(0,0,t.width,t.height))}catch(e){}}),n)},s.play()}})}function a(e,A){if(!t.workerPath&&!A)return i=!1,void fetch("https://unpkg.com/webm-wasm@latest/dist/webm-worker.js").then((function(t){t.arrayBuffer().then((function(t){a(e,t)}))}));if(!t.workerPath&&A instanceof ArrayBuffer){var d=new Blob([A],{type:"text/javascript"});t.workerPath=l.createObjectURL(d)}t.workerPath||console.error("workerPath parameter is missing."),(o=new Worker(t.workerPath)).postMessage(t.webAssemblyPath||"https://unpkg.com/webm-wasm@latest/dist/webm-wasm.wasm"),o.addEventListener("message",(function(e){"READY"===e.data?(o.postMessage({width:t.width,height:t.height,bitrate:t.bitrate||1200,timebaseDen:t.frameRate||30,realtime:t.realtime}),s().pipeTo(new WritableStream({write:function(e){i?console.error("Got image, but recorder is finished!"):o.postMessage(e.data.buffer,[e.data.buffer])}}))):e.data&&(r||n.push(e.data))}))}"undefined"!=typeof ReadableStream&&"undefined"!=typeof WritableStream||console.error("Following polyfill is strongly recommended: https://unpkg.com/@mattiasbuelens/web-streams-polyfill/dist/polyfill.min.js"),(t=t||{}).width=t.width||640,t.height=t.height||480,t.frameRate=t.frameRate||30,t.bitrate=t.bitrate||1200,t.realtime=t.realtime||!0,this.record=function(){n=[],r=!1,this.blob=null,a(e),"function"==typeof t.initCallback&&t.initCallback()},this.pause=function(){r=!0},this.resume=function(){r=!1};var n=[];this.stop=function(e){i=!0;var t=this;!function(e){o?(o.addEventListener("message",(function(t){null===t.data&&(o.terminate(),o=null,e&&e())})),o.postMessage(null)):e&&e()}((function(){t.blob=new Blob(n,{type:"video/webm"}),e(t.blob)}))},this.name="WebAssemblyRecorder",this.toString=function(){return this.name},this.clearRecordedData=function(){n=[],r=!1,this.blob=null},this.blob=null}i.DiskStorage=x,i.GifRecorder=D,i.MultiStreamRecorder=L,i.RecordRTCPromisesHandler=function(e,t){if(!this)throw'Use "new RecordRTCPromisesHandler()"';if(void 0===e)throw'First argument "MediaStream" is required.';var o=this;o.recordRTC=new i(e,t),this.startRecording=function(){return new Promise((function(e,t){try{o.recordRTC.startRecording(),e()}catch(e){t(e)}}))},this.stopRecording=function(){return new Promise((function(e,t){try{o.recordRTC.stopRecording((function(i){o.blob=o.recordRTC.getBlob(),o.blob&&o.blob.size?e(i):t("Empty blob.",o.blob)}))}catch(e){t(e)}}))},this.pauseRecording=function(){return new Promise((function(e,t){try{o.recordRTC.pauseRecording(),e()}catch(e){t(e)}}))},this.resumeRecording=function(){return new Promise((function(e,t){try{o.recordRTC.resumeRecording(),e()}catch(e){t(e)}}))},this.getDataURL=function(e){return new Promise((function(e,t){try{o.recordRTC.getDataURL((function(t){e(t)}))}catch(e){t(e)}}))},this.getBlob=function(){return new Promise((function(e,t){try{e(o.recordRTC.getBlob())}catch(e){t(e)}}))},this.getInternalRecorder=function(){return new Promise((function(e,t){try{e(o.recordRTC.getInternalRecorder())}catch(e){t(e)}}))},this.reset=function(){return new Promise((function(e,t){try{e(o.recordRTC.reset())}catch(e){t(e)}}))},this.destroy=function(){return new Promise((function(e,t){try{e(o.recordRTC.destroy())}catch(e){t(e)}}))},this.getState=function(){return new Promise((function(e,t){try{e(o.recordRTC.getState())}catch(e){t(e)}}))},this.blob=null,this.version="5.6.2"},i.WebAssemblyRecorder=F}));class Je extends Be{constructor(e){super(),this.player=e,this.fileName="",this.fileType=e._opt.recordType||c,this.isRecording=!1,this.recordingTimestamp=0,this.recordingInterval=null,e.debug.log("Recorder","init")}destroy(){this._reset(),this.player.debug.log("Recorder","destroy")}setFileName(e,t){this.fileName=e,d!==t&&c!==t||(this.fileType=t)}get recording(){return this.isRecording}get recordTime(){return this.recordingTimestamp}startRecord(){const e=this.player.debug,t={type:"video",mimeType:"video/webm;codecs=h264",onTimeStamp:t=>{e.log("Recorder","record timestamp :"+t)},disableLogs:!this.player._opt.debug};try{const e=this.player.video.$videoElement.captureStream(25);if(this.player.audio&&this.player.audio.mediaStreamAudioDestinationNode&&this.player.audio.mediaStreamAudioDestinationNode.stream&&!this.player.audio.isStateSuspended()&&this.player.audio.hasAudio&&this.player._opt.hasAudio){const t=this.player.audio.mediaStreamAudioDestinationNode.stream;if(t.getAudioTracks().length>0){const i=t.getAudioTracks()[0];i&&i.enabled&&e.addTrack(i)}}this.recorder=We(e,t)}catch(t){e.error("Recorder","startRecord error",t),this.emit(x.recordCreateError)}this.recorder&&(this.isRecording=!0,this.player.emit(x.recording,!0),this.recorder.startRecording(),e.log("Recorder","start recording"),this.player.emit(x.recordStart),this.recordingInterval=window.setInterval((()=>{this.recordingTimestamp+=1,this.player.emit(x.recordingTimestamp,this.recordingTimestamp)}),1e3))}stopRecordAndSave(){this.recorder&&this.isRecording&&this.recorder.stopRecording((()=>{this.player.debug.log("Recorder","stop recording"),this.player.emit(x.recordEnd);const e=(this.fileName||he())+"."+(this.fileType||c);De(this.recorder.getBlob(),e),this._reset(),this.player.emit(x.recording,!1)}))}_reset(){this.isRecording=!1,this.recordingTimestamp=0,this.recorder&&(this.recorder.destroy(),this.recorder=null),this.fileName=null,this.recordingInterval&&clearInterval(this.recordingInterval),this.recordingInterval=null}}class Pe{constructor(e){return new(Pe.getLoaderFactory())(e)}static getLoaderFactory(){return Je}}class Ge{constructor(e){this.player=e,this.decoderWorker=new Worker(e._opt.decoder),this._initDecoderWorker(),e.debug.log("decoderWorker","init")}destroy(){this.decoderWorker.postMessage({cmd:T}),this.decoderWorker.terminate(),this.decoderWorker=null,this.player.debug.log("decoderWorker","destroy")}_initDecoderWorker(){const{debug:e,events:{proxy:t}}=this.player;this.decoderWorker.onmessage=t=>{const i=t.data;switch(i.cmd){case u:e.log("decoderWorker","onmessage:",u),this.player.loaded||this.player.emit(x.load),this.player.emit(x.decoderWorkerInit),this._initWork();break;case b:e.log("decoderWorker","onmessage:",b,i.code),this.player._times.decodeStart||(this.player._times.decodeStart=he()),this.player.video.updateVideoInfo({encTypeCode:i.code});break;case f:e.log("decoderWorker","onmessage:",f,i.code),this.player.audio&&this.player.audio.updateAudioInfo({encTypeCode:i.code});break;case h:if(e.log("decoderWorker","onmessage:",h,`width:${i.w},height:${i.h}`),this.player.video.updateVideoInfo({width:i.w,height:i.h}),!this.player._opt.openWebglAlignment&&i.w/2%4!=0)return void this.player.emit(j.webglAlignmentError);this.player.video.initCanvasViewSize();break;case g:e.log("decoderWorker","onmessage:",g,`channels:${i.channels},sampleRate:${i.sampleRate}`),this.player.audio&&(this.player.audio.updateAudioInfo(i),this.player.audio.initScriptNode(i));break;case p:this.player.handleRender(),this.player.video.render(i),this.player.emit(x.timeUpdate,i.ts),this.player.updateStats({fps:!0,ts:i.ts,buf:i.delay}),this.player._times.videoStart||(this.player._times.videoStart=he(),this.player.handlePlayToRenderTimes());break;case m:this.player.playing&&this.player.audio&&this.player.audio.play(i.buffer,i.ts);break;case y:i.message&&-1!==i.message.indexOf(v)&&(this.player.emit(x.error,j.wasmDecodeError),this.player.emit(j.wasmDecodeError));break;default:this.player[i.cmd]&&this.player[i.cmd](i)}}}_initWork(){const e={debug:this.player._opt.debug,useOffscreen:this.player._opt.useOffscreen,useWCS:this.player._opt.useWCS,videoBuffer:this.player._opt.videoBuffer,videoBufferDelay:this.player._opt.videoBufferDelay,openWebglAlignment:this.player._opt.openWebglAlignment};this.decoderWorker.postMessage({cmd:C,opt:JSON.stringify(e),sampleRate:this.player.audio&&this.player.audio.audioContext.sampleRate||0})}decodeVideo(e,t,i){const o={type:S,ts:Math.max(t,0),isIFrame:i};this.decoderWorker.postMessage({cmd:R,buffer:e,options:o},[e.buffer])}decodeAudio(e,t){this.player._opt.useWCS||this.player._opt.useMSE?this._decodeAudioNoDelay(e,t):this._decodeAudio(e,t)}_decodeAudio(e,t){const i={type:w,ts:Math.max(t,0)};this.decoderWorker.postMessage({cmd:R,buffer:e,options:i},[e.buffer])}_decodeAudioNoDelay(e,t){this.decoderWorker.postMessage({cmd:k,buffer:e,ts:Math.max(t,0)},[e.buffer])}updateWorkConfig(e){this.decoderWorker.postMessage({cmd:I,key:e.key,value:e.value})}}class Ne extends Be{constructor(e){super(),this.player=e,this.stopId=null,this.firstTimestamp=null,this.startTimestamp=null,this.delay=-1,this.bufferList=[],this.dropping=!1,this.initInterval()}destroy(){this.stopId&&(clearInterval(this.stopId),this.stopId=null),this.firstTimestamp=null,this.startTimestamp=null,this.delay=-1,this.bufferList=[],this.dropping=!1,this.off(),this.player.debug.log("CommonDemux","destroy")}getDelay(e){if(!e)return-1;if(this.firstTimestamp){if(e){const t=Date.now()-this.startTimestamp,i=e-this.firstTimestamp;this.delay=t>=i?t-i:i-t}}else this.firstTimestamp=e,this.startTimestamp=Date.now(),this.delay=-1;return this.delay}resetDelay(){this.firstTimestamp=null,this.startTimestamp=null,this.delay=-1,this.dropping=!1}initInterval(){this.player.debug.log("common dumex","init Interval");let e=()=>{let e;const t=this.player._opt.videoBuffer,i=this.player._opt.videoBufferDelay;if(this.bufferList.length)if(this.dropping){for(e=this.bufferList.shift(),e.type===w&&0===e.payload[1]&&this._doDecoderDecode(e);!e.isIFrame&&this.bufferList.length;)e=this.bufferList.shift(),e.type===w&&0===e.payload[1]&&this._doDecoderDecode(e);e.isIFrame&&this.getDelay(e.ts)<=Math.min(t,200)&&(this.dropping=!1,this._doDecoderDecode(e))}else e=this.bufferList[0],-1===this.getDelay(e.ts)?(this.bufferList.shift(),this._doDecoderDecode(e)):this.delay>t+i?(this.resetDelay(),this.dropping=!0):(e=this.bufferList[0],this.getDelay(e.ts)>t&&(this.bufferList.shift(),this._doDecoderDecode(e)))};e(),this.stopId=setInterval(e,10)}_doDecode(e,t,i,o,r){const s=this.player;let a={ts:i,cts:r,type:t,isIFrame:!1};s._opt.useWCS&&!s._opt.useOffscreen||s._opt.useMSE?(t===S&&(a.isIFrame=o),this.pushBuffer(e,a)):t===S?s.decoderWorker&&s.decoderWorker.decodeVideo(e,i,o):t===w&&s._opt.hasAudio&&s.decoderWorker&&s.decoderWorker.decodeAudio(e,i)}_doDecoderDecode(e){const t=this.player,{webcodecsDecoder:i,mseDecoder:o}=t;e.type===w?t._opt.hasAudio&&t.decoderWorker&&t.decoderWorker.decodeAudio(e.payload,e.ts):e.type===S&&(t._opt.useWCS&&!t._opt.useOffscreen?i.decodeVideo(e.payload,e.ts,e.isIFrame):t._opt.useMSE&&o.decodeVideo(e.payload,e.ts,e.isIFrame,e.cts))}pushBuffer(e,t){t.type===w?this.bufferList.push({ts:t.ts,payload:e,type:w}):t.type===S&&this.bufferList.push({ts:t.ts,cts:t.cts,payload:e,type:S,isIFrame:t.isIFrame})}close(){}}class ze extends Ne{constructor(e){super(e),this.input=this._inputFlv(),this.flvDemux=this.dispatchFlvData(this.input),e.debug.log("FlvDemux","init")}destroy(){super.destroy(),this.input=null,this.flvDemux=null,this.player.debug.log("FlvDemux","destroy")}dispatch(e){this.flvDemux(e)}*_inputFlv(){yield 9;const e=new ArrayBuffer(4),t=new Uint8Array(e),i=new Uint32Array(e),o=this.player;for(;;){t[3]=0;const e=yield 15,r=e[4];t[0]=e[7],t[1]=e[6],t[2]=e[5];const s=i[0];t[0]=e[10],t[1]=e[9],t[2]=e[8];let a=i[0];16777215===a&&(t[3]=e[11],a=i[0]);const n=yield s;switch(r){case E:o._opt.hasAudio&&(o.updateStats({abps:n.byteLength}),n.byteLength>0&&this._doDecode(n,w,a));break;case B:if(o._times.demuxStart||(o._times.demuxStart=he()),o._opt.hasVideo){o.updateStats({vbps:n.byteLength});const e=n[0]>>4==1;if(n.byteLength>0){i[0]=n[4],i[1]=n[3],i[2]=n[2],i[3]=0;let t=i[0];this._doDecode(n,S,a,e,t)}}}}}dispatchFlvData(e){let t=e.next(),i=null;return o=>{let r=new Uint8Array(o);if(i){let e=new Uint8Array(i.length+r.length);e.set(i),e.set(r,i.length),r=e,i=null}for(;r.length>=t.value;){let i=r.slice(t.value);t=e.next(r.slice(0,t.value)),r=i}r.length>0&&(i=r)}}close(){this.input&&this.input.return(null)}}class He extends Ne{constructor(e){super(e),e.debug.log("M7sDemux","init")}destroy(){super.destroy(),this.player.debug.log("M7sDemux","destroy"),this.player=null}dispatch(e){const t=this.player,i=new DataView(e),o=i.getUint8(0),r=i.getUint32(1,!1);switch(o){case w:if(t._opt.hasAudio){const i=new Uint8Array(e,5);t.updateStats({abps:i.byteLength}),i.byteLength>0&&this._doDecode(i,o,r)}break;case S:if(t._opt.hasVideo)if(t._times.demuxStart||(t._times.demuxStart=he()),i.byteLength>5){const s=new Uint8Array(e,5),a=i.getUint8(5)>>4==1;t.updateStats({vbps:s.byteLength}),s.byteLength>0&&this._doDecode(s,o,r,a)}else this.player.debug.warn("M7sDemux","dispatch","dv byteLength is",i.byteLength)}}}class Ye{constructor(e){return new(Ye.getLoaderFactory(e._opt.demuxType))(e)}static getLoaderFactory(e){return e===A?He:e===n?ze:void 0}}class Xe{constructor(e){this.TAG="ExpGolomb",this._buffer=e,this._buffer_index=0,this._total_bytes=e.byteLength,this._total_bits=8*e.byteLength,this._current_word=0,this._current_word_bits_left=0}destroy(){this._buffer=null}_fillCurrentWord(){let e=this._total_bytes-this._buffer_index,t=Math.min(4,e),i=new Uint8Array(4);i.set(this._buffer.subarray(this._buffer_index,this._buffer_index+t)),this._current_word=new DataView(i.buffer).getUint32(0,!1),this._buffer_index+=t,this._current_word_bits_left=8*t}readBits(e){if(e<=this._current_word_bits_left){let t=this._current_word>>>32-e;return this._current_word<<=e,this._current_word_bits_left-=e,t}let t=this._current_word_bits_left?this._current_word:0;t>>>=32-this._current_word_bits_left;let i=e-this._current_word_bits_left;this._fillCurrentWord();let o=Math.min(i,this._current_word_bits_left),r=this._current_word>>>32-o;return this._current_word<<=o,this._current_word_bits_left-=o,t=t<<o|r,t}readBool(){return 1===this.readBits(1)}readByte(){return this.readBits(8)}_skipLeadingZero(){let e;for(e=0;e<this._current_word_bits_left;e++)if(0!=(this._current_word&2147483648>>>e))return this._current_word<<=e,this._current_word_bits_left-=e,e;return this._fillCurrentWord(),e+this._skipLeadingZero()}readUEG(){let e=this._skipLeadingZero();return this.readBits(e+1)-1}readSEG(){let e=this.readUEG();return 1&e?e+1>>>1:-1*(e>>>1)}}class qe{static _ebsp2rbsp(e){let t=e,i=t.byteLength,o=new Uint8Array(i),r=0;for(let e=0;e<i;e++)e>=2&&3===t[e]&&0===t[e-1]&&0===t[e-2]||(o[r]=t[e],r++);return new Uint8Array(o.buffer,0,r)}static parseSPS(e){let t=qe._ebsp2rbsp(e),i=new Xe(t);i.readByte();let o=i.readByte();i.readByte();let r=i.readByte();i.readUEG();let s=qe.getProfileString(o),a=qe.getLevelString(r),n=1,A=420,d=[0,420,422,444],c=8;if((100===o||110===o||122===o||244===o||44===o||83===o||86===o||118===o||128===o||138===o||144===o)&&(n=i.readUEG(),3===n&&i.readBits(1),n<=3&&(A=d[n]),c=i.readUEG()+8,i.readUEG(),i.readBits(1),i.readBool())){let e=3!==n?8:12;for(let t=0;t<e;t++)i.readBool()&&(t<6?qe._skipScalingList(i,16):qe._skipScalingList(i,64))}i.readUEG();let l=i.readUEG();if(0===l)i.readUEG();else if(1===l){i.readBits(1),i.readSEG(),i.readSEG();let e=i.readUEG();for(let t=0;t<e;t++)i.readSEG()}let u=i.readUEG();i.readBits(1);let h=i.readUEG(),p=i.readUEG(),m=i.readBits(1);0===m&&i.readBits(1),i.readBits(1);let g=0,f=0,b=0,y=0;i.readBool()&&(g=i.readUEG(),f=i.readUEG(),b=i.readUEG(),y=i.readUEG());let v=1,w=1,S=0,E=!0,B=0,C=0;if(i.readBool()){if(i.readBool()){let e=i.readByte(),t=[1,12,10,16,40,24,20,32,80,18,15,64,160,4,3,2],o=[1,11,11,11,33,11,11,11,33,11,11,33,99,3,2,1];e>0&&e<16?(v=t[e-1],w=o[e-1]):255===e&&(v=i.readByte()<<8|i.readByte(),w=i.readByte()<<8|i.readByte())}if(i.readBool()&&i.readBool(),i.readBool()&&(i.readBits(4),i.readBool()&&i.readBits(24)),i.readBool()&&(i.readUEG(),i.readUEG()),i.readBool()){let e=i.readBits(32),t=i.readBits(32);E=i.readBool(),B=t,C=2*e,S=B/C}}let R=1;1===v&&1===w||(R=v/w);let k=0,T=0;if(0===n)k=1,T=2-m;else{k=3===n?1:2,T=(1===n?2:1)*(2-m)}let I=16*(h+1),x=16*(p+1)*(2-m);I-=(g+f)*k,x-=(b+y)*T;let D=Math.ceil(I*R);return i.destroy(),i=null,{profile_string:s,level_string:a,bit_depth:c,ref_frames:u,chroma_format:A,chroma_format_string:qe.getChromaFormatString(A),frame_rate:{fixed:E,fps:S,fps_den:C,fps_num:B},sar_ratio:{width:v,height:w},codec_size:{width:I,height:x},present_size:{width:D,height:x}}}static _skipScalingList(e,t){let i=8,o=8,r=0;for(let s=0;s<t;s++)0!==o&&(r=e.readSEG(),o=(i+r+256)%256),i=0===o?i:o}static getProfileString(e){switch(e){case 66:return"Baseline";case 77:return"Main";case 88:return"Extended";case 100:return"High";case 110:return"High10";case 122:return"High422";case 244:return"High444";default:return"Unknown"}}static getLevelString(e){return(e/10).toFixed(1)}static getChromaFormatString(e){switch(e){case 420:return"4:2:0";case 422:return"4:2:2";case 444:return"4:4:4";default:return"Unknown"}}}function Ze(e){const t={},i=new DataView(e.buffer);let o=i.getUint8(0),r=i.getUint8(1);if(i.getUint8(2),i.getUint8(3),1!==o||0===r)return t;const s=1+(3&i.getUint8(4));if(3!==s&&4!==s)return t;let a=31&i.getUint8(5);if(0===a)return;let n=6;for(let o=0;o<a;o++){let r=i.getUint16(n,!1);if(n+=2,0===r)continue;let s=new Uint8Array(e.buffer,n,r);n+=r;let a=qe.parseSPS(s);if(0!==o)continue;t.codecWidth=a.codec_size.width,t.codecHeight=a.codec_size.height,t.presentWidth=a.present_size.width,t.presentHeight=a.present_size.height,t.profile=a.profile_string,t.level=a.level_string,t.bitDepth=a.bit_depth,t.chromaFormat=a.chroma_format,t.sarRatio=a.sar_ratio,t.frameRate=a.frame_rate,!1!==a.frame_rate.fixed&&0!==a.frame_rate.fps_num&&0!==a.frame_rate.fps_den||(t.frameRate={});let A=t.frameRate.fps_den,d=t.frameRate.fps_num;t.refSampleDuration=t.timescale*(A/d);let c=s.subarray(1,4),l="avc1.";for(let e=0;e<3;e++){let t=c[e].toString(16);t.length<2&&(t="0"+t),l+=t}t.codec=l}let A=i.getUint8(n);if(0===A)return t;n++;for(let t=0;t<A;t++){let t=i.getUint16(n,!1);n+=2,0!==t&&(new Uint8Array(e.buffer,n,t),n+=t)}return t.videoType="avc",t}class Ke extends Be{constructor(e){super(),this.player=e,this.hasInit=!1,this.isDecodeFirstIIframe=!1,this.isInitInfo=!1,this.decoder=null,this.initDecoder(),e.debug.log("Webcodecs","init")}destroy(){this.decoder&&("closed"!==this.decoder.state&&this.decoder.close(),this.decoder=null),this.hasInit=!1,this.isInitInfo=!1,this.isDecodeFirstIIframe=!1,this.off(),this.player.debug.log("Webcodecs","destroy")}initDecoder(){const e=this;this.decoder=new VideoDecoder({output(t){e.handleDecode(t)},error(t){e.handleError(t)}})}handleDecode(e){this.isInitInfo||(this.player.video.updateVideoInfo({width:e.codedWidth,height:e.codedHeight}),this.player.video.initCanvasViewSize(),this.isInitInfo=!0),this.player._times.videoStart||(this.player._times.videoStart=he(),this.player.handlePlayToRenderTimes()),this.player.handleRender(),this.player.video.render({videoFrame:e}),this.player.updateStats({fps:!0,ts:0,buf:this.player.demux.delay})}handleError(e){this.player.debug.error("Webcodecs","VideoDecoder handleError",e)}decodeVideo(e,t,i){if(this.hasInit){if(i&&0===e[1]){const t=Ze(e.slice(5)),i=this.player.video.videoInfo;if(t.codecWidth!==i.width||t.codecHeight!==i.height)return this.player.debug.log("Webcodecs",`width or height is update, width ${i.width}-> ${t.codecWidth}, height ${i.height}-> ${t.codecHeight}`),void this.player.emit(j.webcodecsWidthOrHeightChange)}if(!this.isDecodeFirstIIframe&&i&&(this.isDecodeFirstIIframe=!0),this.isDecodeFirstIIframe){const o=new EncodedVideoChunk({data:e.slice(5),timestamp:t,type:i?X:q});this.player.emit(x.timeUpdate,t);try{this.decoder.decode(o)}catch(e){this.player.debug.error("Webcodecs","VideoDecoder",e),-1!==e.toString().indexOf(re)&&this.player.emit(j.webcodecsDecodeError)}}else this.player.debug.warn("Webcodecs","VideoDecoder isDecodeFirstIIframe false")}else if(i&&0===e[1]){const t=15&e[0];if(this.player.video.updateVideoInfo({encTypeCode:t}),t===Q)return void this.emit(j.webcodecsH265NotSupport);this.player._times.decodeStart||(this.player._times.decodeStart=he());const i=function(e){let t=e.subarray(1,4),i="avc1.";for(let e=0;e<3;e++){let o=t[e].toString(16);o.length<2&&(o="0"+o),i+=o}return{codec:i,description:e}}(e.slice(5));this.decoder.configure(i),this.hasInit=!0}}}const _e={play:"播放",pause:"暂停",audio:"",mute:"",screenshot:"截图",loading:"加载",fullscreen:"全屏",fullscreenExit:"退出全屏",record:"录制",recordStop:"停止录制"};var $e=Object.keys(_e).reduce(((e,t)=>(e[t]=`\n <i class="jessibuca-icon jessibuca-icon-${t}"></i>\n ${_e[t]?`<span class="icon-title-tips"><span class="icon-title">${_e[t]}</span></span>`:""}\n`,e)),{}),et=(e,t)=>{const{events:{proxy:i}}=e,o=document.createElement("object");o.setAttribute("aria-hidden","true"),o.setAttribute("tabindex",-1),o.type="text/html",o.data="about:blank",me(o,{display:"block",position:"absolute",top:"0",left:"0",height:"100%",width:"100%",overflow:"hidden",pointerEvents:"none",zIndex:"-1"});let r=e.width,s=e.height;i(o,"load",(()=>{i(o.contentDocument.defaultView,"resize",(()=>{e.width===r&&e.height===s||(r=e.width,s=e.height,e.emit(x.resize),n())}))})),e.$container.appendChild(o),e.on(x.destroy,(()=>{e.$container.removeChild(o)})),e.on(x.volumechange,(()=>{!function(e){if(0===e)me(t.$volumeOn,"display","none"),me(t.$volumeOff,"display","flex"),me(t.$volumeHandle,"top","48px");else if(t.$volumeHandle&&t.$volumePanel){const i=ge(t.$volumePanel,"height")||60,o=ge(t.$volumeHandle,"height"),r=i-(i-o)*e-o;me(t.$volumeHandle,"top",`${r}px`),me(t.$volumeOn,"display","flex"),me(t.$volumeOff,"display","none")}t.$volumePanelText&&(t.$volumePanelText.innerHTML=parseInt(100*e))}(e.volume)})),e.on(x.loading,(e=>{me(t.$loading,"display",e?"flex":"none"),me(t.$poster,"display","none"),e&&me(t.$playBig,"display","none")}));const a=i=>{let o=!0===(r=i)||!1===r?i:e.fullscreen;var r;me(t.$fullscreenExit,"display",o?"flex":"none"),me(t.$fullscreen,"display",o?"none":"flex")},n=()=>{ye()&&t.$controls&&e._opt.useWebFullScreen&&setTimeout((()=>{if(e.fullscreen){let i=e.height/2-e.width+19,o=e.height/2-19;t.$controls.style.transform=`translateX(${-i}px) translateY(-${o}px) rotate(-90deg)`}else t.$controls.style.transform="translateX(0) translateY(0) rotate(0)"}),10)};try{ce.on("change",a),e.events.destroys.push((()=>{ce.off("change",a)}))}catch(e){}e.on(x.webFullscreen,(e=>{a(e),n()})),e.on(x.recording,(()=>{me(t.$record,"display",e.recording?"none":"flex"),me(t.$recordStop,"display",e.recording?"flex":"none"),me(t.$recording,"display",e.recording?"flex":"none")})),e.on(x.recordingTimestamp,(e=>{t.$recordingTime&&(t.$recordingTime.innerHTML=function(e){var t;if(e>-1){var i=Math.floor(e/3600),o=Math.floor(e/60)%60,r=e%60;t=i<10?"0"+i+":":i+":",o<10&&(t+="0"),t+=o+":",(r=Math.round(r))<10&&(t+="0"),t+=r.toFixed(0)}return t}(e))})),e.on(x.playing,(e=>{me(t.$play,"display",e?"none":"flex"),me(t.$playBig,"display",e?"none":"block"),me(t.$pause,"display",e?"flex":"none"),me(t.$screenshot,"display",e?"flex":"none"),me(t.$record,"display",e?"flex":"none"),me(t.$qualityMenu,"display",e?"flex":"none"),me(t.$volume,"display",e?"flex":"none"),a(),e||t.$speed&&(t.$speed.innerHTML=ve(""))})),e.on(x.kBps,(e=>{const i=ve(e);t.$speed&&(t.$speed.innerHTML=i)}))};function tt(e,t){void 0===t&&(t={});var i=t.insertAt;if(e&&"undefined"!=typeof document){var o=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css","top"===i&&o.firstChild?o.insertBefore(r,o.firstChild):o.appendChild(r),r.styleSheet?r.styleSheet.cssText=e:r.appendChild(document.createTextNode(e))}}tt('@keyframes rotation{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes magentaPulse{0%{background-color:#630030;-webkit-box-shadow:0 0 9px #333}50%{background-color:#a9014b;-webkit-box-shadow:0 0 18px #a9014b}to{background-color:#630030;-webkit-box-shadow:0 0 9px #333}}.jessibuca-container .jessibuca-icon{cursor:pointer;width:16px;height:16px}.jessibuca-container .jessibuca-poster{position:absolute;z-index:10;left:0;top:0;right:0;bottom:0;height:100%;width:100%;background-position:50%;background-repeat:no-repeat;background-size:contain;pointer-events:none}.jessibuca-container .jessibuca-play-big{position:absolute;display:none;height:100%;width:100%;background:rgba(0,0,0,.4)}.jessibuca-container .jessibuca-play-big:after{cursor:pointer;content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:block;width:48px;height:48px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACgklEQVRoQ+3ZPYsTQRjA8eeZZCFlWttAwCIkZOaZJt8hlvkeHrlccuAFT6wEG0FQOeQQLCIWih6chQgKgkkKIyqKCVYip54IWmiQkTmyYhFvd3Zn3yDb7szu/7cv7GaDkPEFM94PK0DSZ9DzDAyHw7uI2HRDlVJX5/N5r9FoHCYdr/fvCRiNRmpJ6AEidoUQ15NG+AH8BgD2n9AHANAmohdJQfwAfgGA4xF4bjabnW21Whob62ILoKNfAsAGEd2PU2ATcNSNiDf0/cE5/xAHxDpgEf0NADaJ6HLUiKgAbvcjpdSGlPJZVJCoAUfdSqkLxWLxTLlc/mkbEgtgET1TSnWklLdtIuIEuN23crlcp16vv7cBSQKgu38AwBYRXQyLSArg3hsjRDxNRE+CQhIF/BN9qVAobFYqle+mkLQAdLd+8K0T0U0TRJoAbvc9fVkJId75gaQRoLv1C2STiPTb7rFLWgE6+g0RncwyYEJEtawCvjDGmpzzp5kD6NfxfD7frtVqB17xen2a7oG3ALBm+oMoFQBEPD+dTvtBfpImDXjIGFvjnD/3c7ksG5MU4HDxWeZa0HB3XhKAXcdxOn5vUi9gnIDXSqm2lHLPK8pkfVyAbSLqm4T5HRs1YB8RO0KIid8g03FRAT4rpbpSyh3TINPxUQB2GGM9zvkn05gg420CJovLZT9ISNA5tgB9ItoOGhFmnh/AcZ/X9xhj65zzV2Eiwsz1A1j2B8dHAOgS0W6YnduY6wkYj8d3lFKn/j66Ea84jtOrVqtfbQSE3YYnYDAY5Eql0hYAnNDv6kKIx2F3anO+J8DmzqLY1goQxVE12ebqDJgcrSjGrs5AFEfVZJt/AF0m+jHzUTtnAAAAAElFTkSuQmCC");background-repeat:no-repeat;background-position:50%}.jessibuca-container .jessibuca-play-big:hover:after{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACEElEQVRoQ+2ZXStEQRjH/3/yIXwDdz7J+i7kvdisXCk3SiFJW27kglBcSFFKbqwQSa4krykuKB09Naf2Yndn5jgzc06d53Znd36/mWfeniVyHsw5PwqB0DOonYEoijYBlOpAFwCMkHwLDS/9mwhEDUCfAAyTXA4tYSLwC6CtCegegH6S56FETAR+AHRoACcBTJAUWa+RloBAXwAYIrnt0yBNgZi7qtbHgw8RFwLC/QFglOScawlXAjH3gUqrE1cirgVi7mkAYyS/0xbxJSDcdwAGSa6nKeFTIOZeUyL3aYiEEBDuLwDjJGf+KxFKIOY+BdBL8iipSGiBmHtWbbuftiJZERBuOfgGSK7aSGRJIObeUml1ayKSRQHhlgtkiaTcdltGVgUE+ppkV54FaiS78yrwqlLoOI8Cch2XV548W7WRpTVwA6DP9kGUFYEpAOUkT9LQAvtq1M+0udKkQSgBqSlJWWYxKXj8vRACK+o6bbRIdYI+Ba7U7rKjg7L53JdAhWTZBsy0rWuBXZUuNVMg23auBF7UIl2yBbJt70JAoKV6/WwLk6R9mgKSJlJ1kLTxFmkJyCla8UZd15GJQKvyumyJ8gy8DAEvfZoINPqD41EtUjmUgoaJwAaAnjrKebVI34OSq85NBNqlCAWgE0CV5GEWwI3vQlmCbcSinYFCwPEIFDPgeIC1P1/MgHaIHDf4Aydx2TF7wnKeAAAAAElFTkSuQmCC")}.jessibuca-container .jessibuca-recording{display:none;position:absolute;left:50%;top:0;padding:0 3px;transform:translateX(-50%);justify-content:space-around;align-items:center;width:95px;height:20px;background:#000;opacity:1;border-radius:0 0 8px 8px;z-index:1}.jessibuca-container .jessibuca-recording .jessibuca-recording-red-point{width:8px;height:8px;background:#ff1f1f;border-radius:50%;animation:magentaPulse 1s linear infinite}.jessibuca-container .jessibuca-recording .jessibuca-recording-time{font-size:14px;font-weight:500;color:#ddd}.jessibuca-container .jessibuca-recording .jessibuca-icon-recordStop{width:16px;height:16px;cursor:pointer}.jessibuca-container .jessibuca-loading{display:none;flex-direction:column;justify-content:center;align-items:center;position:absolute;z-index:20;left:0;top:0;right:0;bottom:0;width:100%;height:100%;pointer-events:none}.jessibuca-container .jessibuca-loading-text{line-height:20px;font-size:13px;color:#fff;margin-top:10px}.jessibuca-container .jessibuca-controls{background-color:#161616;box-sizing:border-box;display:flex;flex-direction:column;justify-content:flex-end;position:absolute;z-index:40;left:0;right:0;bottom:0;height:38px;width:100%;padding-left:13px;padding-right:13px;font-size:14px;color:#fff;opacity:0;visibility:hidden;transition:all .2s ease-in-out;-webkit-user-select:none;user-select:none;transition:width .5s ease-in}.jessibuca-container .jessibuca-controls .jessibuca-controls-item{position:relative;display:flex;justify-content:center;padding:0 8px}.jessibuca-container .jessibuca-controls .jessibuca-controls-item:hover .icon-title-tips{visibility:visible;opacity:1}.jessibuca-container .jessibuca-controls .jessibuca-fullscreen,.jessibuca-container .jessibuca-controls .jessibuca-fullscreen-exit,.jessibuca-container .jessibuca-controls .jessibuca-icon-audio,.jessibuca-container .jessibuca-controls .jessibuca-microphone-close,.jessibuca-container .jessibuca-controls .jessibuca-pause,.jessibuca-container .jessibuca-controls .jessibuca-play,.jessibuca-container .jessibuca-controls .jessibuca-record,.jessibuca-container .jessibuca-controls .jessibuca-record-stop,.jessibuca-container .jessibuca-controls .jessibuca-screenshot{display:none}.jessibuca-container .jessibuca-controls .jessibuca-icon-audio,.jessibuca-container .jessibuca-controls .jessibuca-icon-mute{z-index:1}.jessibuca-container .jessibuca-controls .jessibuca-controls-bottom{display:flex;justify-content:space-between;height:100%}.jessibuca-container .jessibuca-controls .jessibuca-controls-bottom .jessibuca-controls-left,.jessibuca-container .jessibuca-controls .jessibuca-controls-bottom .jessibuca-controls-right{display:flex;align-items:center}.jessibuca-container.jessibuca-controls-show .jessibuca-controls{opacity:1;visibility:visible}.jessibuca-container.jessibuca-controls-show-auto-hide .jessibuca-controls{opacity:.8;visibility:visible;display:none}.jessibuca-container.jessibuca-hide-cursor *{cursor:none!important}.jessibuca-container .jessibuca-icon-loading{width:50px;height:50px;background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%;animation:rotation 1s linear infinite}.jessibuca-container .jessibuca-icon-screenshot{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAE5UlEQVRoQ+1YW2sdVRT+1s7JxbsoVkEUrIIX0ouz15zYNA+N1RdtQfCltlUfvLbqL/BCwZ8grbHtizQqPojgBSr0JkiMmT2nxgapqBURtPVCq7HxJCeZJVPmxDlzZubMmXOSEsnAvOy917fXt9e39tp7E5b4R0vcfywTuNgRbBgBx3HuJqLVzPzmYjprjHkcwAlmLqXNm4XAISLaSESPaq2HF4OE67rbRGRYRA7btn1fbgLGmKsA/Azg0gBkGzO/vZAkHMd5hIiqc5wHcCMz/5k0Z2oExsfHV1QqldPAf8lORNu11m8tBAljzFYAYWxRSl1vWdZvuQj4RsYYF4AVBlgIOVVlE55HRIxt23ZuCfmGjuOsJ6LPoiAistW27XfaEYmIbOYhPc9bXywWR1oiEJDYQkR1zrYjEjGyqfqbKd8a7kJVtLgQ+30i8pht2wfyRKIdmJkJBPkQTbILfudJ7CTZNBvVpggEcgpvc/ML38zESbLJsxBNE/A9biX0rdjGyTQXgbxyapdsarb0PMlXtWnGoXbKpm0Essqp3bJpK4E0OXmed3+hUBDP8w5FI91M0rdcyLLILElOCbaZilSWeXMncRx4klTCY1spfG3dhZJWx3GcDUR0EEB3ZMw0ET2gtT6SZWWzjmlrBIJCl0hAKfWgZVmHszqXZVxbCSxpCS2JJA6umIhe8ZKKVLPbaBJ+S9toqVRa53nedgAbAKwIwH4FcAzAa0R0l4i8F7PPz189k6RFRA+LyNcAXojDV0oNW5b1eW4Cxpg9AHZkSaaa6hhzb065uDSCH2LmRB8Sk9gY4293g43Qo/1pV80m8yQMfZSZ781cB1zXHRKRZ2IMpgD8A+DamL4ZItqitX4/jbQx5iEA7wLoihn3V/ACckWMJN/QWj9b1x5tGBsbW6uUOh5pPy0iL3Z2dn6ilJqanp5ep5TaJSLhF4NppdRNaU8gPmapVLrO87yfIoXuWyJ6uVKp+HmFjo6OQSJ6FcBtYT+UUmstyxqvkWuUgDFmP4AnQu2/e563qlgs+u9DNZ8xZhRAX7VRRPbath0XuXk7Y8xeAE+FgL6fnJzsHRwcLIfBR0ZGLunq6poAsDLUvp+Zw7b1r9PGmJMAbg8Z7WDmoThZuK67WkS+DD18fcPMdzSQUBR/EzN/nIC/SUQ+DPXV4dclsTHmHAD/SfHCNzc3t7Kvr++HJKeMMacA3BL0nyuXyzcPDAxMxo0fHR29slAo/Ajg6qD/fE9Pzw29vb1/x42fmJi4vFwu+5G/LOg/y8zXNJLQ2dAES5JANMQ7mfn1jBI6ycx3NiMhItqstf4oAX+ziHwQ6qvDj5NQNIn/ALCKmX+JSeIvABRD7fuY+ekGBPYBeDI05tTMzExvf3+/vz2Hk91/ET8RSeI6/DoCpVJpjed5fmKGvzMAXpqdnT3oed5Ud3d3v4jsAqBr9Ei0Rmv9VRqBBPzvROQVETnq2xJRdRu9tRF+bCVOKWT+Kvl/TSIFk6SW/LAjKfjV5K8rZABi8dOOEv7FI7Z8x6zwEWbemLbyMfJr5qiSiJ96oclymBOR3bZtP9+M89WxxpjdAHY2sN3DzM8ljWl4I3Nd9x7/OE1ENcdpETnmH3e11n41zv0l4J8RkU+J6AAz+xtF4teQQG7PFslwmcAiLfSyhC72Qv9/I/Avns2OT7QJskoAAAAASUVORK5CYII=") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-screenshot:hover{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAED0lEQVRoQ+2ZycsdRRTFf2ejqHFAMQqiYBTUoElUHLNx3GgCgpuYRF2o0UT9CxwQ/BMkMSbZSKLiQgQHUDCJgjiAxiEiESdEcJbEedgcKaj3UV+/6q7u/jovPPkK3qbr1ql76p5bt6qemPKmKfefeQKHOoLFCNg+H1gi6fFJOmv7VmCvpD1N87Yh8ApwNXCzpB2TIGF7DRDm2inpmt4EbB8LfAMcGUHWSHryYJKwfRMwmuMP4BRJv9TN2RgB2wuB72BWsq+V9MTBIGF7NZBiGzhJ0o+9CIRBtt8FLqgADC6nRDbpVO9Iuqi3hCKB5cDrGZDVkp4aIhIV2aSQyyW9MScCkcQqIOfsnCORkc3I31b5VtyFRmg1IQ7dt0ja3icSQ2C2JhAjUU2ykd+dE7tBNp2i2olAJJFuc+nCt564QTadF6IzgUhiVGiqyinKaQjZpJP2ItBXTkPJZhACXeU0pGwGI9BWTkPLZlACBTldG4o5EA6E1dY66edcyNrs8Q36zg1vVaTazNs7iXPgDVJJzYs7VRvHRzaDEohyugJ4CTi84sg/wHWSdnVxsGQ7aQLXS9pZcqpL/6AEplpCU5HE8YpJ9YrXUKQ6baN1+HPaRm1fBqwFQnKGK2ZoPwCvAo8Ai4FnMpPMHMwapHUj8DFwbw3+Dklv9iZgexOwvktSRduxU2VDlErwmyXV+lCbxLbDdndlCT3TX3vV7JgnKfRuSVflfMkSsL0ZuDMz4E/gL+CETN+/wCpJzzaRtn0D8DRwWMbu1/gCcnSm7zFJd1W/jxGwvQx4r2IYnlbuA14GAomQFw8B6YtBKFSnNj2BxEJ3IvB1pdB9CjwQ8yqYhcg/DJxZ8WOZpA/SbzkC24DbEqOfgPMkBRKzmu23gEuSj1sk5SI3Y2J7C3BHMuZz4FxJf6fgto8APgIWJd+3SUrHjr9O294HnJUMWi8pSGqs2V4CvJ88fH0i6eyChKr4KyS9WIO/Ang+6RvDz0XgABCeFEdtkaQv65yy/QVweuwPY0+T9FuNQ8cAXwHHxf7wdHiypN9r7BfEl8GjYv9+SceXJLQ/mSDYTh2Baog3SHq0pYT2STqno4RWSnqhBn8l8FzSN4bfJol/jkn8bXUS228DFyfft0paVyCwFbg9sQkSDEkctueZZju8iO+tJPEYfo7A0piYKd73wP3xnB+20cvjNnphxdmlkj4sEMjhfwY8COyOY0fb6Bkl/K6FLKxS+M1KpDhJY8mvrG5doRwlf66QZfGbjhLh4pEt35kV3iUp/IvTunU8qtTil/7gaHOY2yjpntaez9b5RmBDYewmSXfX2RRvZLYvbThOh+NuqMa9Ww1+yLnXgO2SwkZR24oEens2oYHzBCa00PMSOtQL/f+NwH+Hg8hAnbrYgQAAAABJRU5ErkJggg==") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-play{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACgklEQVRoQ+3ZPYsTQRjA8eeZZCFlWttAwCIkZOaZJt8hlvkeHrlccuAFT6wEG0FQOeQQLCIWih6chQgKgkkKIyqKCVYip54IWmiQkTmyYhFvd3Zn3yDb7szu/7cv7GaDkPEFM94PK0DSZ9DzDAyHw7uI2HRDlVJX5/N5r9FoHCYdr/fvCRiNRmpJ6AEidoUQ15NG+AH8BgD2n9AHANAmohdJQfwAfgGA4xF4bjabnW21Whob62ILoKNfAsAGEd2PU2ATcNSNiDf0/cE5/xAHxDpgEf0NADaJ6HLUiKgAbvcjpdSGlPJZVJCoAUfdSqkLxWLxTLlc/mkbEgtgET1TSnWklLdtIuIEuN23crlcp16vv7cBSQKgu38AwBYRXQyLSArg3hsjRDxNRE+CQhIF/BN9qVAobFYqle+mkLQAdLd+8K0T0U0TRJoAbvc9fVkJId75gaQRoLv1C2STiPTb7rFLWgE6+g0RncwyYEJEtawCvjDGmpzzp5kD6NfxfD7frtVqB17xen2a7oG3ALBm+oMoFQBEPD+dTvtBfpImDXjIGFvjnD/3c7ksG5MU4HDxWeZa0HB3XhKAXcdxOn5vUi9gnIDXSqm2lHLPK8pkfVyAbSLqm4T5HRs1YB8RO0KIid8g03FRAT4rpbpSyh3TINPxUQB2GGM9zvkn05gg420CJovLZT9ISNA5tgB9ItoOGhFmnh/AcZ/X9xhj65zzV2Eiwsz1A1j2B8dHAOgS0W6YnduY6wkYj8d3lFKn/j66Ea84jtOrVqtfbQSE3YYnYDAY5Eql0hYAnNDv6kKIx2F3anO+J8DmzqLY1goQxVE12ebqDJgcrSjGrs5AFEfVZJt/AF0m+jHzUTtnAAAAAElFTkSuQmCC") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-play:hover{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACEElEQVRoQ+2ZXStEQRjH/3/yIXwDdz7J+i7kvdisXCk3SiFJW27kglBcSFFKbqwQSa4krykuKB09Naf2Yndn5jgzc06d53Znd36/mWfeniVyHsw5PwqB0DOonYEoijYBlOpAFwCMkHwLDS/9mwhEDUCfAAyTXA4tYSLwC6CtCegegH6S56FETAR+AHRoACcBTJAUWa+RloBAXwAYIrnt0yBNgZi7qtbHgw8RFwLC/QFglOScawlXAjH3gUqrE1cirgVi7mkAYyS/0xbxJSDcdwAGSa6nKeFTIOZeUyL3aYiEEBDuLwDjJGf+KxFKIOY+BdBL8iipSGiBmHtWbbuftiJZERBuOfgGSK7aSGRJIObeUml1ayKSRQHhlgtkiaTcdltGVgUE+ppkV54FaiS78yrwqlLoOI8Cch2XV548W7WRpTVwA6DP9kGUFYEpAOUkT9LQAvtq1M+0udKkQSgBqSlJWWYxKXj8vRACK+o6bbRIdYI+Ba7U7rKjg7L53JdAhWTZBsy0rWuBXZUuNVMg23auBF7UIl2yBbJt70JAoKV6/WwLk6R9mgKSJlJ1kLTxFmkJyCla8UZd15GJQKvyumyJ8gy8DAEvfZoINPqD41EtUjmUgoaJwAaAnjrKebVI34OSq85NBNqlCAWgE0CV5GEWwI3vQlmCbcSinYFCwPEIFDPgeIC1P1/MgHaIHDf4Aydx2TF7wnKeAAAAAElFTkSuQmCC") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-pause{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAABA0lEQVRoQ+1YwQqCUBAcfWXXsLr2AXWTPXno8yVB8AP6Aa3oHI+kCDqYaawJljSe133uzO44bx0M/HEG/v1gAd9mkAyQgY4I/F8LJUlyrQFtD2AtIkcNoFEU+Z7n7QD4DfFHEVlocrVmgAUAIAOl3mILPcDgEFcUhyrUKMGUUcroc3NQRimj9XJBGaWMvvPydKN0o6/9QTdKN6rZANxj6EbpRulGuZnjYqs8BbyR8Ub2Izeys+u6yyAIDpo/ehzHM2NMDsA0xFsRmWhyfTIDWSXxCEBmrd2EYXjSHJqm6bQoii2AOYBL5Z0xgFxEVppcrQvQJO0zhgX0iXbdWWSADHRE4AZQ731AhEUeNwAAAABJRU5ErkJggg==") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-pause:hover{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAA7klEQVRoQ+2YSwrCQBBEX6HiVvxsPYDewfN7By/gD9ciQkvERQwJdBSiYs0mEDo96aruombEjy/9+P/jAj7NoBkwA28i8H8tFBFRA9oeWEo6ZgCNiDGwAYpn3TpKmmVytWbABQBmoNRbbqEHGB7iiuJYhRol2DJqGX1uDsuoZdRmLuNZSzGWUcuoZdRHSp/IylNgK2ErYSthK3FHwLcSvpXIjoLt9Jfa6TMwl3TIMBkRE2AH9BriL5KGmVyvWIltJXEfKN6tJJ0ym0bECFgDU+Ba+WZQFCdpkcnVuoBM0i5jXECXaNftZQbMwJsI3AAPN3dAQflHegAAAABJRU5ErkJggg==") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-record{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAC+UlEQVRoQ+1ZS2sTURT+zlDJYE3XSq219QHVuEjnJDT+Bff9Abqw2voAEfGxqygUqWhVFHGl/yMLu9BwByxk5SNI66ML6U7axjhHbmhgWiftncxoOiV3FcI53z3f/e65594zhIQPSnj86BBot4IdBToKRFyBnbeFlFIScVEiuYvIWC6Xe2YK8pcC7SYA4CMzH4mDQBXAqilQBDsLQLfPf9FxnF4i8kwwmypARI+Wl5dvmIBEsUmlUkNE9NaHsVCpVAZGR0d/m+A2JSAid3K53E0TkCg2pVKpz7KseR/GfKVSGYxMAMA0M1+JEpyJb6lUOm5ZVnkrAsVisaunp+esiByr1Wp3R0ZGvmifzZK4XQQWHMc52MgBpdQuAOcAXABwuB400ZTjONdaIjA7O5u2bVsnWU1EujzP+5nP5xdMVjvIJkCBD8x8VCm1G8AYgAkAAxt8Z5j5YmgCSqlTAJ4D2OcD/AXgATNfbYVEAIFPIvKKiE4D6GuCea8xX6gtpJT6DmBvECgRFRzHeROWRAABE4iWCbwHEFhkPM/L5vP5dyaz+23+KwHXdR3P854S0YG1ILSCuthNMfNM2OC1/RYENLY+ygcBnPfht6ZAA6BYLNr6dyqVokKhsGpaNQ2TWJstreXaE2aed133sojcj41AKyvdzCdAgSXLsk4MDw9/a/i4rntbRPxFNZoC/5jAV2be759DKTUJ4FZSFFi0bbs/k8noy2R9dAjEuWU2YgXkQOK3kD6BMsysi2Z9JC2Jdcw/ALzwPO+xvmcl7Rj177JVEbkO4BARjSflFDJJuW1dBxJPoCIiL4noDIB1BS0pW6j+oJmbm+uuVqvjRKQfLr0bZHnIzJf0f6HeAybahrUJqAPruhLlcnnPysqKfpXp11n/Gv62zoHAroS+AafT6QkiGrIsazKbzX7eVIHEt1US39gCkOzWYthkjNE+tuZujDGZQ8XRXn8N4KT5lLFZ6uaYPt+nwyDuvC80YdhvB9uOAu1WoaNAR4GIK/AHvdr+QAexB7EAAAAASUVORK5CYII=") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-record:hover{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACfUlEQVRoQ+2ZSYsUQRCFvycK4nJXXEbHBdwO4kn/gv9CD467ICIutxEFkREdFUU86T/xojcPntyQcT2INw+uISFVkD1Wd2dWlU7nUHlqisiX+fJFZGREi8yHMt8/HYG5VrBToFOg4QnMPxcyM2t4KE2nT0i6EwvylwIjQOCFpE1tEPgGfI0FamC3AFgazP8IrJL0KwZzkAI3gLMxIA1ttgCPA4w3wHpJP2NwBxG4KOlcDEgTGzNbA8wEGP57vA0CU5JONtlczFwz2wY8HUbAzBYCB4CtwCVJb33OIAXmioC70LoyBsxsEXAQOApsLIhelnS6FgEzW+5BBvwA/FS+SPJFa40KBZ5L2mxmS4AJ4IjHxCzwaUnHkgmY2V7gLrAyAPwOXJN0qg6DCgIvgQfAPsDjo2pcKddLciEz+wCs6AO6W9KjVBIVBGIgahN4BvRLMjslPYlZPbT53wR2AbeBtcUmXEFPdh5U06mbd/shBBzbr/Jx4FCAX0+BEsDMFocEYrNmFcE+BD4XsXZL0oyZnQCutkagzkn3m1NBwDe/Q9L74MAuFEqUn5op8I8JvJO0elacTALnc1HAH3Njkvwx+WeYWUegTa/pwaqIgexdyIN4uyRPmqULZRXEvulPwD3gpr+zcrtGQxfzRHYG2AAczuUWiom3kc4D2RN4BdwH9gM9CS0XFyoLGu9UuN974eIFVDiuSzruH5LqgRhtU20q8kBPV8LMlhVVmVdnYwX+SMdAZVeieAF7eeltmElJr4cpkH1bJfvGVvatxdR4bMu+teZuWxtKxWncXn8I7EldtQV7vz79fp9KwZp//9CksB8F206BuVahU6BToOEJ/Ab7+KdABdTt8AAAAABJRU5ErkJggg==") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-recordStop{background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-recordStop:hover{background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-fullscreen{background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-fullscreen:hover{background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-fullscreenExit{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAADd0lEQVRoQ+2Zz2sdVRTHv+fJBDW6anDVXen6wZszYxYBiYgtFGst3VSDunKjpS0GpUlqfjVpsVVs6aaL0or4YxMVFCJZ2ZLdPUP+gq5bQnTxtNAkfTnlhnnlkmQy9yV9780rudt77tzv5/y4v4bQ4Y06XD/2ANodwec/AiJygJnvtdvTWfPnRkBEJAiCN8rl8kMfiPn5+Ve7u7v3rays0Orq6lJfX99/PuN2auMDoAD+BvA2M6/mTWSMOUtE48D6AjHGzN/kjdlNvy+AnWOOmQ/lTSYiEwDOWzsimgrDcCRvzG76GwGw8/zJzO9sN6GInAMwbW1UdSSKoqndCMwb6wNwGsB39Q+p6h/M/C4R2dTa1AoHYBWKyCkA1+pqiWi2Wq0e7e/vf7yRoJAAKcQggMtuJKIoOtoxACnE0/xOi/SXMAxPuhCFjUBdpIjYVWXSEf0TM3/g9BeriDMKdSPEz8z8vrU1xgwT0YXCrEJZy1iSJKOqOub0/8jMA0mSfKKqNwoPkHp7ioiGHIhRIvpHVa93BEBa2JcAfOlALAHo6RgAKzRJkk9V1S6xL7kpV4idOM31taxaIKJHqmpPnMMA9hcOQES2PDJkAT1XAAC+ZebPfWB3auNzmLObVsNRUNUXVHUujuM7OxXnMy4XwOcj29mIyOuq+lapVGrYCelKpkEQ3CyXy4tbzdN0AGPMxr2iYZ+sra3FcRybtgCIiK2BKw2rdgaUSqWoUqlIkQAepFDdAF7cBq5ERI9rtdr1OI7tmE2t6SmUEYFHAEaexYW/1QC2EF+ru5GIvg7D0D2GNJxprQY4o6qv1I/b6SpzOYqiLxpWng5oOQAzXxWRWwA+dkRfYOb1p5hGW6sBJpn5KytSRG4D+KguWFXHoyhy7xdeLC0F2ChSRL4H8OFuINoKYIUbY34gogHH3eeZef1K6tPaDpCm068A3nMEDzHzxY4BUNWSiPxORO6z5aDPPlGICNQ9bYyZIaLjjudzIQoFkKbTbwCO+UI0HcB9J/LdeY0xs0R02IGYYObRrWqiFQCfEZEtSHsfmGZm+4qxbbM/hQD8BeBNa0hEM2EYnmgLgP3lFARBT1dXly4vL//b29tbzQNIU+llAHeJaLFSqRzJes5vegR8xGbZLCwsHKzVav8z8/0sm0ID+MDvAfh4qZk2exFopnd9vv0ELrXBQO7fD10AAAAASUVORK5CYII=") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-fullscreenExit:hover{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAC/ElEQVRoQ+2Zy49NQRCHvx+ReK6IlZ34E7CUiCAR4xEbTLCyQRATYswwb2IQZDYWgojHZpCQECts+ResiQwLj0RClNSkb9Lu3HtPz7mZc8+V6eXt6tP1VVV3VdcVbT7U5vozC9BqD/7/HjCzlZLet9rS9fbP9ICZvQPWSfqRAmFmS4ClMHm+JiR9S1mXVyYFwIBXwEZJv7I2MrPjQH8A6JN0OWtNM/OpAL7HS0mbsjYzswGgN8gNS+rJWtPM/HQAfJ9nkrY22tDMTgMjQaZH0nAzCmatTQE4ClyNPvQU2CbJQ2vKKB2Aa2hmR4DrkbbPgQ5Jv6sJSgkQILqA0dgTkjraBiBAxPHtPz2UtDuGKK0HKkqamd8qg5HS9yXtjebLdYjrHNRqiAeS9gQvnQGGSnML1bvGzOwc0BfN35PUaWYHgRulBwjW9ju+O4JwqM/AWFsABIgLwKkIYgJY1jYAAeJQuGIXVIVcKTKxh8WfBin9J+AVpx/eFWUEqFkyNACKp0rhgWYArkg6kQibSyylmPOklQdibijBX+fSLHFRJkDid+qKmdlaYENOI0zeEcBNSZ9qbVIEQHWuyGOTNZLetgrAz8ClPFpHa1ZL8rf5lFGEB2oBfAxQi4D5DeDmAP7mGJPka0oD4LnDr9imH/xFe8AP4vLIjBclxWXItCOtaIBjwOKo3HaFRyWdnLbmYUHhAJKumdkt4ECk9JCkSitmWixFAwxKOjt5uZvdBvZH2vZLit8XSSBFA/yjpJndAfY1A9FSgOCJu0BnBNErqfIkzfRCywECxCNgR6Rtt6TzmdqHBmyKXG4ZM4sTWc04NzNPWE+AuG3ZlZInSuGBinXMbBzYGVkrE6JUACGcHgPbUyGKAIj7REmZ18y897o5ghiQ5E/bltRChwE/kF7Xj0jyLkbDYWbzgBfA+iA4LmlXqwD8LydvszjAF0lfswBCKC0E3gBeP22p186f8RBKUbaejJmtAr5L+lBPptQAKfCzAClWmkmZWQ/MpHVTvv0X9iFAQGQyevIAAAAASUVORK5CYII=") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-audio{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACrUlEQVRoQ+2ZPYgTURCAZzbBXJnCeL2Cnb87b9MEtPBUrrMQFAtrtT5/ClGs9LBWWz0RtbBUFCF4oJDsbO68wsLA2YqQSmLlvpEHu7IuMdlLcus+yUKKhJfZ+ebnvZl5CJY/aLn+MAP41x7M1QPMfFtr/crzvHfTAs8FoNPp1LTWzwHgqIg0lFLvrQHwfX8BER8DwC6jNCIecF13wwoA3/dvIuKNpLJa60Oe560XGoCZd4rICiKeTCtaeABmPg4AJmRqg6xcaABmvg4At4aFRyEBhoVM4UMoCplHADCfJTEL5YEsIVNID5iQAYCHALCYxeq5b6PMfF5EBAAEESthGK7W6/XPRpFWq7W3VCqtZg2ZcT3g+/6i4zjzIlLSWn/yPO/DIGMNLCWY2Sj/+xGRK0qpZfNDEASnROTFVi0fr8+aA8z8Ld6KEfGt67oLYwMAwEUium8EREn7OgeAjwCwPyo/nrque3YSgAtE9GDaAM1mc65arc4Zuf1+P2w0Gt9jJZl5DQAORt+fENG5wgEw8zUAMB/zbBBRwyqAIAjuiMjlSOlNItpjFUCqWl0josMzgChR/9hGAWBbknjmAdPhDdqa0gfZzAMJKyVP4v8hhJYRcSni+0JEu63ahZj5anyQici6UuqIVQDdbrfS6/UqRulyufyTiH5sF8AlIro37VpoWEHIzGZ2tM+sEZFnSqkzk9RCS0R01wjIsZz+mug53hDRia0AnI4bGgDYISItz/M2jYC8Gpp2u30MEWuO4zha665Sqp0ZYFStX/iWchRAItFGzoHSsrJ2ZFl1mHg6bfVYJeGJv85CC++BpIJZ5kSFC6G0ha0e7mYJqcJ7IOkRay84UhD2XjHFIFZf8iW9YcYoYRi+tO6aNeupOs66iU/icV46zf/MAKZpzXFk/QL+JG1PUPhRiQAAAABJRU5ErkJggg==") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-audio:hover{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACSElEQVRoQ+2Zu4sUQRCHf5+C+gf4yBXMfMYHGvjCzEBQDIzV+HwEohipGKupD0QNDE8UEwUFTe68wEDhTMVUMFJ+0tArzbjs9u3Ojt0wBR0M9MzUV1XdXVWNKhcq1189wP/2YKcesH1d0nPgdVvgnQDY3iTpqaT9kuaAt9UA2D4o6aGkzVHpXcByFQC2r0q60lB2D7BUNIDtjZIeSDoyRNGyAWwfiiET4n6YlAtg+7Kka2PCozyAMSHT5CkLIIbMfUlbMhdmOQCZIVOeB2LI3JN0NNPq6bTZe8D2aUmOY72kN8DnoIXt7eF5FSEzkQdsB+OEsFwr6RPwbpixhqYStoPyqVwAbkaAY5KeTWD5wStZHrD9XdJgK34FhBP9H8kFOAvciQBhn3/RAcBHSTvjfx4DJ6cBOAPcbRvA9gZJYQT5DfwYKGl7UdLu+PwIOFUiwCVJYQRZBuZqA7gh6XxUegXYVhtAmq0uAnt7gLhQm9vorBZx74Hcc6D3QLKH/z2JGyVnlYs4pCfzEe4rsLW2XehicpAtAftqAwiZbhhBfgE/ZwVwDrjddi40KiG0HXpHO+KcJ8CJaXKheeBWBOgqnf6W1BwvgcOrATieFDTrJL0HViJAVwXNgVgPrJH0BfiQDTDKtREiNK7KLSnHASQLLacP1PxcVkWWq8PU3emq2yqJJ0b1Qsv2QKpdZp+orBBqmrfq5m5mSJXtgUZI1XnB0YCo94opCal6L/ka3ghtlIXqrllzT9VJ5k19Ek/y0zbf6QHatOYk3/oDujC8QMWgjf4AAAAASUVORK5CYII=") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-mute{background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-mute:hover{background:url("data:image/png;base64,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") no-repeat 50%;background-size:100% 100%}.jessibuca-container .jessibuca-icon-text{font-size:14px;width:30px}.jessibuca-container .jessibuca-speed{font-size:14px;color:#fff}.jessibuca-container .jessibuca-quality-menu-list{position:absolute;left:50%;bottom:100%;visibility:hidden;opacity:0;transform:translateX(-50%);transition:visibility .3s,opacity .3s;background-color:rgba(0,0,0,.5);border-radius:4px}.jessibuca-container .jessibuca-quality-menu-list.jessibuca-quality-menu-shown{visibility:visible;opacity:1}.jessibuca-container .icon-title-tips{pointer-events:none;position:absolute;left:50%;bottom:100%;visibility:hidden;opacity:0;transform:translateX(-50%);transition:visibility .3s ease 0s,opacity .3s ease 0s;background-color:rgba(0,0,0,.5);border-radius:4px}.jessibuca-container .icon-title{display:inline-block;padding:5px 10px;font-size:12px;white-space:nowrap;color:#fff}.jessibuca-container .jessibuca-quality-menu{padding:8px 0}.jessibuca-container .jessibuca-quality-menu-item{display:block;height:25px;margin:0;padding:0 10px;cursor:pointer;font-size:14px;text-align:center;width:50px;color:hsla(0,0%,100%,.5);transition:color .3s,background-color .3s}.jessibuca-container .jessibuca-quality-menu-item:hover{background-color:hsla(0,0%,100%,.2)}.jessibuca-container .jessibuca-quality-menu-item:focus{outline:none}.jessibuca-container .jessibuca-quality-menu-item.jessibuca-quality-menu-item-active{color:#2298fc}.jessibuca-container .jessibuca-volume-panel-wrap{position:absolute;left:50%;bottom:100%;visibility:hidden;opacity:0;transform:translateX(-50%) translateY(22%);transition:visibility .3s,opacity .3s;background-color:rgba(0,0,0,.5);border-radius:4px;height:120px;width:50px;overflow:hidden}.jessibuca-container .jessibuca-volume-panel-wrap.jessibuca-volume-panel-wrap-show{visibility:visible;opacity:1}.jessibuca-container .jessibuca-volume-panel{cursor:pointer;position:absolute;top:21px;height:60px;width:50px;overflow:hidden}.jessibuca-container .jessibuca-volume-panel-text{position:absolute;left:0;top:0;width:50px;height:20px;line-height:20px;text-align:center;color:#fff;font-size:12px}.jessibuca-container .jessibuca-volume-panel-handle{position:absolute;top:48px;left:50%;width:12px;height:12px;border-radius:12px;margin-left:-6px;background:#fff}.jessibuca-container .jessibuca-volume-panel-handle:before{bottom:-54px;background:#fff}.jessibuca-container .jessibuca-volume-panel-handle:after{bottom:6px;background:hsla(0,0%,100%,.2)}.jessibuca-container .jessibuca-volume-panel-handle:after,.jessibuca-container .jessibuca-volume-panel-handle:before{content:"";position:absolute;display:block;left:50%;width:3px;margin-left:-1px;height:60px}.jessibuca-container.jessibuca-fullscreen-web .jessibuca-controls{width:100vh}.jessibuca-container.jessibuca-fullscreen-web .jessibuca-play-big:after{transform:translate(-50%,-50%) rotate(270deg)}.jessibuca-container.jessibuca-fullscreen-web .jessibuca-loading{flex-direction:row}.jessibuca-container.jessibuca-fullscreen-web .jessibuca-loading-text{transform:rotate(270deg)}');class it{constructor(e){var t;this.player=e,((e,t)=>{e._opt.hasControl&&e._opt.controlAutoHide?e.$container.classList.add("jessibuca-controls-show-auto-hide"):e.$container.classList.add("jessibuca-controls-show");const i=e._opt,o=i.operateBtns;e.$container.insertAdjacentHTML("beforeend",`\n ${i.background?`<div class="jessibuca-poster" style="background-image: url(${i.background})"></div>`:""}\n <div class="jessibuca-loading">\n ${$e.loading}\n ${i.loadingText?`<div class="jessibuca-loading-text">${i.loadingText}</div>`:""}\n </div>\n ${i.hasControl&&o.play?'<div class="jessibuca-play-big"></div>':""}\n ${i.hasControl?`\n <div class="jessibuca-recording">\n <div class="jessibuca-recording-red-point"></div>\n <div class="jessibuca-recording-time">00:00:01</div>\n <div class="jessibuca-icon-recordStop jessibuca-recording-stop">${$e.recordStop}</div>\n </div>\n `:""}\n ${i.hasControl?`\n <div class="jessibuca-controls">\n <div class="jessibuca-controls-bottom">\n <div class="jessibuca-controls-left">\n ${i.showBandwidth?'<div class="jessibuca-controls-item jessibuca-speed"></div>':""}\n </div>\n <div class="jessibuca-controls-right">\n ${o.audio?`\n <div class="jessibuca-controls-item jessibuca-volume">\n ${$e.audio}\n ${$e.mute}\n <div class="jessibuca-volume-panel-wrap">\n <div class="jessibuca-volume-panel">\n <div class="jessibuca-volume-panel-handle"></div>\n </div>\n <div class="jessibuca-volume-panel-text"></div>\n </div>\n </div>\n `:""}\n ${o.play?`<div class="jessibuca-controls-item jessibuca-play">${$e.play}</div><div class="jessibuca-controls-item jessibuca-pause">${$e.pause}</div>`:""}\n ${o.screenshot?`<div class="jessibuca-controls-item jessibuca-screenshot">${$e.screenshot}</div>`:""}\n ${o.record?` <div class="jessibuca-controls-item jessibuca-record">${$e.record}</div><div class="jessibuca-controls-item jessibuca-record-stop">${$e.recordStop}</div>`:""}\n ${o.fullscreen?`<div class="jessibuca-controls-item jessibuca-fullscreen">${$e.fullscreen}</div><div class="jessibuca-controls-item jessibuca-fullscreen-exit">${$e.fullscreenExit}</div>`:""}\n </div>\n </div>\n </div>\n `:""}\n\n `),Object.defineProperty(t,"$poster",{value:e.$container.querySelector(".jessibuca-poster")}),Object.defineProperty(t,"$loading",{value:e.$container.querySelector(".jessibuca-loading")}),Object.defineProperty(t,"$play",{value:e.$container.querySelector(".jessibuca-play")}),Object.defineProperty(t,"$playBig",{value:e.$container.querySelector(".jessibuca-play-big")}),Object.defineProperty(t,"$recording",{value:e.$container.querySelector(".jessibuca-recording")}),Object.defineProperty(t,"$recordingTime",{value:e.$container.querySelector(".jessibuca-recording-time")}),Object.defineProperty(t,"$recordingStop",{value:e.$container.querySelector(".jessibuca-recording-stop")}),Object.defineProperty(t,"$pause",{value:e.$container.querySelector(".jessibuca-pause")}),Object.defineProperty(t,"$controls",{value:e.$container.querySelector(".jessibuca-controls")}),Object.defineProperty(t,"$fullscreen",{value:e.$container.querySelector(".jessibuca-fullscreen")}),Object.defineProperty(t,"$fullscreen",{value:e.$container.querySelector(".jessibuca-fullscreen")}),Object.defineProperty(t,"$volume",{value:e.$container.querySelector(".jessibuca-volume")}),Object.defineProperty(t,"$volumePanelWrap",{value:e.$container.querySelector(".jessibuca-volume-panel-wrap")}),Object.defineProperty(t,"$volumePanelText",{value:e.$container.querySelector(".jessibuca-volume-panel-text")}),Object.defineProperty(t,"$volumePanel",{value:e.$container.querySelector(".jessibuca-volume-panel")}),Object.defineProperty(t,"$volumeHandle",{value:e.$container.querySelector(".jessibuca-volume-panel-handle")}),Object.defineProperty(t,"$volumeOn",{value:e.$container.querySelector(".jessibuca-icon-audio")}),Object.defineProperty(t,"$volumeOff",{value:e.$container.querySelector(".jessibuca-icon-mute")}),Object.defineProperty(t,"$fullscreen",{value:e.$container.querySelector(".jessibuca-fullscreen")}),Object.defineProperty(t,"$fullscreenExit",{value:e.$container.querySelector(".jessibuca-fullscreen-exit")}),Object.defineProperty(t,"$record",{value:e.$container.querySelector(".jessibuca-record")}),Object.defineProperty(t,"$recordStop",{value:e.$container.querySelector(".jessibuca-record-stop")}),Object.defineProperty(t,"$screenshot",{value:e.$container.querySelector(".jessibuca-screenshot")}),Object.defineProperty(t,"$speed",{value:e.$container.querySelector(".jessibuca-speed")})})(e,this),t=this,Object.defineProperty(t,"controlsRect",{get:()=>t.$controls.getBoundingClientRect()}),et(e,this),((e,t)=>{const{events:{proxy:i},debug:o}=e;function r(e){const{bottom:i,height:o}=t.$volumePanel.getBoundingClientRect(),{height:r}=t.$volumeHandle.getBoundingClientRect();return pe(i-e.y-r/2,0,o-r/2)/(o-r)}if(i(window,["click","contextmenu"],(i=>{i.composedPath().indexOf(e.$container)>-1?t.isFocus=!0:t.isFocus=!1})),i(window,"orientationchange",(()=>{setTimeout((()=>{e.resize()}),300)})),i(t.$controls,"click",(e=>{e.stopPropagation()})),i(t.$pause,"click",(t=>{e.pause()})),i(t.$play,"click",(t=>{e.play(),e.resumeAudioAfterPause()})),i(t.$playBig,"click",(t=>{e.play(),e.resumeAudioAfterPause()})),i(t.$volume,"mouseover",(()=>{t.$volumePanelWrap.classList.add("jessibuca-volume-panel-wrap-show")})),i(t.$volume,"mouseout",(()=>{t.$volumePanelWrap.classList.remove("jessibuca-volume-panel-wrap-show")})),i(t.$volumeOn,"click",(i=>{i.stopPropagation(),me(t.$volumeOn,"display","none"),me(t.$volumeOff,"display","block");const o=e.volume;e.volume=0,e._lastVolume=o})),i(t.$volumeOff,"click",(i=>{i.stopPropagation(),me(t.$volumeOn,"display","block"),me(t.$volumeOff,"display","none"),e.volume=e.lastVolume||.5})),i(t.$screenshot,"click",(t=>{t.stopPropagation(),e.video.screenshot()})),i(t.$volumePanel,"click",(t=>{t.stopPropagation(),e.volume=r(t)})),i(t.$volumeHandle,"mousedown",(()=>{t.isVolumeDroging=!0})),i(t.$volumeHandle,"mousemove",(i=>{t.isVolumeDroging&&(e.volume=r(i))})),i(document,"mouseup",(()=>{t.isVolumeDroging&&(t.isVolumeDroging=!1)})),i(t.$record,"click",(t=>{t.stopPropagation(),e.recording=!0})),i(t.$recordStop,"click",(t=>{t.stopPropagation(),e.recording=!1})),i(t.$recordingStop,"click",(t=>{t.stopPropagation(),e.recording=!1})),i(t.$fullscreen,"click",(t=>{t.stopPropagation(),e.fullscreen=!0})),i(t.$fullscreenExit,"click",(t=>{t.stopPropagation(),e.fullscreen=!1})),e._opt.hasControl&&e._opt.controlAutoHide){i(e.$container,"mouseover",(()=>{e.fullscreen||(me(t.$controls,"display","block"),r())})),i(e.$container,"mousemove",(()=>{e.$container&&t.$controls&&(e.fullscreen,"none"===t.$controls.style.display&&(me(t.$controls,"display","block"),r()))})),i(e.$container,"mouseout",(()=>{s(),me(t.$controls,"display","none")}));let o=null;const r=()=>{s(),o=setTimeout((()=>{me(t.$controls,"display","none")}),5e3)},s=()=>{o&&(clearTimeout(o),o=null)}}})(e,this),e._opt.hotKey&&((e,t)=>{const{events:{proxy:i}}=e,o={};function r(e,t){o[e]?o[e].push(t):o[e]=[t]}r(te,(()=>{e.fullscreen&&(e.fullscreen=!1)})),r(ie,(()=>{e.volume+=.05})),r(oe,(()=>{e.volume-=.05})),i(window,"keydown",(e=>{if(t.isFocus){const t=document.activeElement.tagName.toUpperCase(),i=document.activeElement.getAttribute("contenteditable");if("INPUT"!==t&&"TEXTAREA"!==t&&""!==i&&"true"!==i){const t=o[e.keyCode];t&&(e.preventDefault(),t.forEach((e=>e())))}}}))})(e,this),this.player.debug.log("Control","init")}destroy(){this.$poster&&this.player.$container.removeChild(this.$poster),this.$loading&&this.player.$container.removeChild(this.$loading),this.$controls&&this.player.$container.removeChild(this.$controls),this.$recording&&this.player.$container.removeChild(this.$recording),this.$playBig&&this.player.$container.removeChild(this.$playBig),this.player.debug.log("control","destroy")}autoSize(){const e=this.player;e.$container.style.padding="0 0";const t=e.width,i=e.height,o=t/i,r=e.video.$videoElement.width/e.video.$videoElement.height;if(o>r){const o=(t-i*r)/2;e.$container.style.padding=`0 ${o}px`}else{const o=(i-t/r)/2;e.$container.style.padding=`${o}px 0`}}}tt(".jessibuca-container{position:relative;display:block;width:100%;height:100%;overflow:hidden}.jessibuca-container.jessibuca-fullscreen-web{position:fixed;z-index:9999;left:0;top:0;right:0;bottom:0;width:100vw!important;height:100vh!important;background:#000}");class ot{static init(){ot.types={avc1:[],avcC:[],hvc1:[],hvcC:[],btrt:[],dinf:[],dref:[],esds:[],ftyp:[],hdlr:[],mdat:[],mdhd:[],mdia:[],mfhd:[],minf:[],moof:[],moov:[],mp4a:[],mvex:[],mvhd:[],sdtp:[],stbl:[],stco:[],stsc:[],stsd:[],stsz:[],stts:[],tfdt:[],tfhd:[],traf:[],trak:[],trun:[],trex:[],tkhd:[],vmhd:[],smhd:[]};for(let e in ot.types)ot.types.hasOwnProperty(e)&&(ot.types[e]=[e.charCodeAt(0),e.charCodeAt(1),e.charCodeAt(2),e.charCodeAt(3)]);let e=ot.constants={};e.FTYP=new Uint8Array([105,115,111,109,0,0,0,1,105,115,111,109,97,118,99,49]),e.STSD_PREFIX=new Uint8Array([0,0,0,0,0,0,0,1]),e.STTS=new Uint8Array([0,0,0,0,0,0,0,0]),e.STSC=e.STCO=e.STTS,e.STSZ=new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]),e.HDLR_VIDEO=new Uint8Array([0,0,0,0,0,0,0,0,118,105,100,101,0,0,0,0,0,0,0,0,0,0,0,0,86,105,100,101,111,72,97,110,100,108,101,114,0]),e.HDLR_AUDIO=new Uint8Array([0,0,0,0,0,0,0,0,115,111,117,110,0,0,0,0,0,0,0,0,0,0,0,0,83,111,117,110,100,72,97,110,100,108,101,114,0]),e.DREF=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,12,117,114,108,32,0,0,0,1]),e.SMHD=new Uint8Array([0,0,0,0,0,0,0,0]),e.VMHD=new Uint8Array([0,0,0,1,0,0,0,0,0,0,0,0])}static box(e){let t=8,i=null,o=Array.prototype.slice.call(arguments,1),r=o.length;for(let e=0;e<r;e++)t+=o[e].byteLength;i=new Uint8Array(t),i[0]=t>>>24&255,i[1]=t>>>16&255,i[2]=t>>>8&255,i[3]=255&t,i.set(e,4);let s=8;for(let e=0;e<r;e++)i.set(o[e],s),s+=o[e].byteLength;return i}static generateInitSegment(e){let t=ot.box(ot.types.ftyp,ot.constants.FTYP),i=ot.moov(e),o=new Uint8Array(t.byteLength+i.byteLength);return o.set(t,0),o.set(i,t.byteLength),o}static moov(e){let t=ot.mvhd(e.timescale,e.duration),i=ot.trak(e),o=ot.mvex(e);return ot.box(ot.types.moov,t,i,o)}static mvhd(e,t){return ot.box(ot.types.mvhd,new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,e>>>24&255,e>>>16&255,e>>>8&255,255&e,t>>>24&255,t>>>16&255,t>>>8&255,255&t,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255]))}static trak(e){return ot.box(ot.types.trak,ot.tkhd(e),ot.mdia(e))}static tkhd(e){let t=e.id,i=e.duration,o=e.presentWidth,r=e.presentHeight;return ot.box(ot.types.tkhd,new Uint8Array([0,0,0,7,0,0,0,0,0,0,0,0,t>>>24&255,t>>>16&255,t>>>8&255,255&t,0,0,0,0,i>>>24&255,i>>>16&255,i>>>8&255,255&i,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,o>>>8&255,255&o,0,0,r>>>8&255,255&r,0,0]))}static mdia(e){return ot.box(ot.types.mdia,ot.mdhd(e),ot.hdlr(e),ot.minf(e))}static mdhd(e){let t=e.timescale,i=e.duration;return ot.box(ot.types.mdhd,new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,t>>>24&255,t>>>16&255,t>>>8&255,255&t,i>>>24&255,i>>>16&255,i>>>8&255,255&i,85,196,0,0]))}static hdlr(e){let t=null;return t="audio"===e.type?ot.constants.HDLR_AUDIO:ot.constants.HDLR_VIDEO,ot.box(ot.types.hdlr,t)}static minf(e){let t=null;return t="audio"===e.type?ot.box(ot.types.smhd,ot.constants.SMHD):ot.box(ot.types.vmhd,ot.constants.VMHD),ot.box(ot.types.minf,t,ot.dinf(),ot.stbl(e))}static dinf(){return ot.box(ot.types.dinf,ot.box(ot.types.dref,ot.constants.DREF))}static stbl(e){return ot.box(ot.types.stbl,ot.stsd(e),ot.box(ot.types.stts,ot.constants.STTS),ot.box(ot.types.stsc,ot.constants.STSC),ot.box(ot.types.stsz,ot.constants.STSZ),ot.box(ot.types.stco,ot.constants.STCO))}static stsd(e){return"audio"===e.type?ot.box(ot.types.stsd,ot.constants.STSD_PREFIX,ot.mp4a(e)):"avc"===e.videoType?ot.box(ot.types.stsd,ot.constants.STSD_PREFIX,ot.avc1(e)):ot.box(ot.types.stsd,ot.constants.STSD_PREFIX,ot.hvc1(e))}static mp4a(e){let t=e.channelCount,i=e.audioSampleRate,o=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,t,0,16,0,0,0,0,i>>>8&255,255&i,0,0]);return ot.box(ot.types.mp4a,o,ot.esds(e))}static esds(e){let t=e.config||[],i=t.length,o=new Uint8Array([0,0,0,0,3,23+i,0,1,0,4,15+i,64,21,0,0,0,0,0,0,0,0,0,0,0,5].concat([i]).concat(t).concat([6,1,2]));return ot.box(ot.types.esds,o)}static avc1(e){let t=e.avcc;const i=e.codecWidth,o=e.codecHeight;let r=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,i>>>8&255,255&i,o>>>8&255,255&o,0,72,0,0,0,72,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,255,255]);return ot.box(ot.types.avc1,r,ot.box(ot.types.avcC,t))}static hvc1(e){let t=e.avcc;const i=e.codecWidth,o=e.codecHeight;let r=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,i>>>8&255,255&i,o>>>8&255,255&o,0,72,0,0,0,72,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,255,255]);return ot.box(ot.types.hvc1,r,ot.box(ot.types.hvcC,t))}static mvex(e){return ot.box(ot.types.mvex,ot.trex(e))}static trex(e){let t=e.id,i=new Uint8Array([0,0,0,0,t>>>24&255,t>>>16&255,t>>>8&255,255&t,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1]);return ot.box(ot.types.trex,i)}static moof(e,t){return ot.box(ot.types.moof,ot.mfhd(e.sequenceNumber),ot.traf(e,t))}static mfhd(e){let t=new Uint8Array([0,0,0,0,e>>>24&255,e>>>16&255,e>>>8&255,255&e]);return ot.box(ot.types.mfhd,t)}static traf(e,t){let i=e.id,o=ot.box(ot.types.tfhd,new Uint8Array([0,0,0,0,i>>>24&255,i>>>16&255,i>>>8&255,255&i])),r=ot.box(ot.types.tfdt,new Uint8Array([0,0,0,0,t>>>24&255,t>>>16&255,t>>>8&255,255&t])),s=ot.sdtp(e),a=ot.trun(e,s.byteLength+16+16+8+16+8+8);return ot.box(ot.types.traf,o,r,a,s)}static sdtp(e){let t=new Uint8Array(5),i=e.flags;return t[4]=i.isLeading<<6|i.dependsOn<<4|i.isDependedOn<<2|i.hasRedundancy,ot.box(ot.types.sdtp,t)}static trun(e,t){let i=new Uint8Array(28);t+=36,i.set([0,0,15,1,0,0,0,1,t>>>24&255,t>>>16&255,t>>>8&255,255&t],0);let o=e.duration,r=e.size,s=e.flags,a=e.cts;return i.set([o>>>24&255,o>>>16&255,o>>>8&255,255&o,r>>>24&255,r>>>16&255,r>>>8&255,255&r,s.isLeading<<2|s.dependsOn,s.isDependedOn<<6|s.hasRedundancy<<4|s.isNonSync,0,0,a>>>24&255,a>>>16&255,a>>>8&255,255&a],12),ot.box(ot.types.trun,i)}static mdat(e){return ot.box(ot.types.mdat,e)}}ot.init();class rt extends Be{constructor(e){super(),this.player=e,this.isAvc=!0,this.mediaSource=new window.MediaSource,this.sourceBuffer=null,this.hasInit=!1,this.isInitInfo=!1,this.cacheTrack={},this.timeInit=!1,this.sequenceNumber=0,this.mediaSourceOpen=!1,this.dropping=!1,this.firstRenderTime=null,this.mediaSourceAppendBufferError=!1,this.mediaSourceAppendBufferFull=!1,this.isDecodeFirstIIframe=!1,this.player.video.$videoElement.src=window.URL.createObjectURL(this.mediaSource);const{debug:t,events:{proxy:i}}=e;i(this.mediaSource,"sourceopen",(()=>{this.mediaSourceOpen=!0,this.player.emit(x.mseSourceOpen)})),i(this.mediaSource,"sourceclose",(()=>{this.player.emit(x.mseSourceClose)})),e.debug.log("MediaSource","init")}destroy(){this.stop(),this.mediaSource=null,this.mediaSourceOpen=!1,this.sourceBuffer=null,this.hasInit=!1,this.isInitInfo=!1,this.sequenceNumber=0,this.cacheTrack=null,this.timeInit=!1,this.mediaSourceAppendBufferError=!1,this.mediaSourceAppendBufferFull=!1,this.isDecodeFirstIIframe=!1,this.off(),this.player.debug.log("MediaSource","destroy")}get state(){return this.mediaSource&&this.mediaSource.readyState}get isStateOpen(){return this.state===_}get isStateClosed(){return this.state===$}get isStateEnded(){return this.state===K}get duration(){return this.mediaSource&&this.mediaSource.duration}set duration(e){this.mediaSource.duration=e}decodeVideo(e,t,i,o){const r=this.player;if(r)if(this.hasInit){if(i&&0===e[1]){let t=Ze(e.slice(5));const i=this.player.video.videoInfo;i&&i.width&&i.height&&t&&t.codecWidth&&t.codecHeight&&(t.codecWidth!==i.width||t.codecHeight!==i.height)&&(this.player.debug.warn("MediaSource",`width or height is update, width ${i.width}-> ${t.codecWidth}, height ${i.height}-> ${t.codecHeight}`),this.isInitInfo=!1,this.player.video.init=!1)}if(!this.isDecodeFirstIIframe&&i&&(this.isDecodeFirstIIframe=!0),this.isDecodeFirstIIframe){null===this.firstRenderTime&&(this.firstRenderTime=t);const r=t-this.firstRenderTime;this._decodeVideo(e,r,i,o)}else this.player.debug.warn("MediaSource","decodeVideo isDecodeFirstIIframe false")}else if(i&&0===e[1]){const o=15&e[0];if(r.video.updateVideoInfo({encTypeCode:o}),o===Q)return void this.emit(j.mediaSourceH265NotSupport);r._times.decodeStart||(r._times.decodeStart=he()),this._decodeConfigurationRecord(e,t,i,o),this.hasInit=!0}}_decodeConfigurationRecord(e,t,i,o){let r=e.slice(5),s={};s=Ze(r);const a={id:1,type:"video",timescale:1e3,duration:0,avcc:r,codecWidth:s.codecWidth,codecHeight:s.codecHeight,videoType:s.videoType},n=ot.generateInitSegment(a);this.isAvc=!0,this.appendBuffer(n.buffer),this.sequenceNumber=0,this.cacheTrack=null,this.timeInit=!1}_decodeVideo(e,t,i,o){const r=this.player;let s=e.slice(5),a=s.byteLength;const n=r.video.$videoElement,A=r._opt.videoBufferDelay;if(n.buffered.length>1&&(this.removeBuffer(n.buffered.start(0),n.buffered.end(0)),this.timeInit=!1),this.dropping&&t-this.cacheTrack.dts>A)this.dropping=!1,this.cacheTrack={};else if(this.cacheTrack&&t>=this.cacheTrack.dts){let e=8+this.cacheTrack.size,i=new Uint8Array(e);i[0]=e>>>24&255,i[1]=e>>>16&255,i[2]=e>>>8&255,i[3]=255&e,i.set(ot.types.mdat,4),i.set(this.cacheTrack.data,8),this.cacheTrack.duration=t-this.cacheTrack.dts;let o=ot.moof(this.cacheTrack,this.cacheTrack.dts),s=new Uint8Array(o.byteLength+i.byteLength);s.set(o,0),s.set(i,o.byteLength),this.appendBuffer(s.buffer),r.handleRender(),r.updateStats({fps:!0,ts:t,buf:r.demux&&r.demux.delay||0}),r._times.videoStart||(r._times.videoStart=he(),r.handlePlayToRenderTimes())}else r.debug.log("MediaSource","timeInit set false , cacheTrack = {}"),this.timeInit=!1,this.cacheTrack={};this.cacheTrack||(this.cacheTrack={}),this.cacheTrack.id=1,this.cacheTrack.sequenceNumber=++this.sequenceNumber,this.cacheTrack.size=a,this.cacheTrack.dts=t,this.cacheTrack.cts=o,this.cacheTrack.isKeyframe=i,this.cacheTrack.data=s,this.cacheTrack.flags={isLeading:0,dependsOn:i?2:1,isDependedOn:i?1:0,hasRedundancy:0,isNonSync:i?0:1},this.timeInit||1!==n.buffered.length||(r.debug.log("MediaSource","timeInit set true"),this.timeInit=!0,n.currentTime=n.buffered.end(0)),!this.isInitInfo&&n.videoWidth>0&&n.videoHeight>0&&(r.debug.log("MediaSource",`updateVideoInfo: ${n.videoWidth},${n.videoHeight}`),r.video.updateVideoInfo({width:n.videoWidth,height:n.videoHeight}),r.video.initCanvasViewSize(),this.isInitInfo=!0)}appendBuffer(e){const{debug:t,events:{proxy:i}}=this.player;if(null===this.sourceBuffer&&(this.sourceBuffer=this.mediaSource.addSourceBuffer(Z),i(this.sourceBuffer,"error",(e=>{this.player.emit(x.mseSourceBufferError,e)}))),this.mediaSourceAppendBufferError)t.error("MediaSource","this.mediaSourceAppendBufferError is true");else if(this.mediaSourceAppendBufferFull)t.error("MediaSource","this.mediaSourceAppendBufferFull is true");else if(!1===this.sourceBuffer.updating&&this.isStateOpen)try{this.sourceBuffer.appendBuffer(e)}catch(e){t.warn("MediaSource","this.sourceBuffer.appendBuffer()",e.code,e),22===e.code?(this.stop(),this.mediaSourceAppendBufferFull=!0,this.emit(j.mediaSourceFull)):11===e.code?(this.stop(),this.mediaSourceAppendBufferError=!0,this.emit(j.mediaSourceAppendBufferError)):(t.error("MediaSource","appendBuffer error",e),this.player.emit(x.mseSourceBufferError,e))}else this.isStateClosed?this.player.emit(j.mseSourceBufferError,"mediaSource is not attached to video or mediaSource is closed"):this.isStateEnded?this.player.emit(j.mseSourceBufferError,"mediaSource is closed"):!0===this.sourceBuffer.updating&&this.player.emit(x.mseSourceBufferBusy)}stop(){this.abortSourceBuffer(),this.removeSourceBuffer(),this.endOfStream()}dropSourceBuffer(e){const t=this.player.video.$videoElement;this.dropping=e,t.buffered.length>0&&t.buffered.end(0)-t.currentTime>1&&(this.player.debug.warn("MediaSource","dropSourceBuffer",`$video.buffered.end(0) is ${t.buffered.end(0)} - $video.currentTime ${t.currentTime}`),t.currentTime=t.buffered.end(0))}removeBuffer(e,t){if(this.isStateOpen&&!1===this.sourceBuffer.updating)try{this.sourceBuffer.remove(e,t)}catch(e){this.player.debug.warn("MediaSource","removeBuffer() error",e)}else this.player.debug.warn("MediaSource","removeBuffer() this.isStateOpen is",this.isStateOpen,"this.sourceBuffer.updating",this.sourceBuffer.updating)}endOfStream(){const e=this.player.video&&this.player.video.$videoElement;if(this.isStateOpen&&e&&e.readyState>=1)try{this.mediaSource.endOfStream()}catch(e){this.player.debug.warn("MediaSource","endOfStream() error",e)}}abortSourceBuffer(){this.isStateOpen&&this.sourceBuffer&&(this.sourceBuffer.abort(),this.sourceBuffer=null)}removeSourceBuffer(){if(!this.isStateClosed&&this.mediaSource&&this.sourceBuffer)try{this.mediaSource.removeSourceBuffer(this.sourceBuffer)}catch(e){this.player.debug.warn("MediaSource","removeSourceBuffer() error",e)}}}const st=()=>"undefined"!=typeof navigator&&parseFloat((""+(/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_",".").replace("_",""))<10&&!window.MSStream,at=()=>"wakeLock"in navigator;class nt{constructor(e){if(this.player=e,this.enabled=!1,at()){this._wakeLock=null;const e=()=>{null!==this._wakeLock&&"visible"===document.visibilityState&&this.enable()};document.addEventListener("visibilitychange",e),document.addEventListener("fullscreenchange",e)}else st()?this.noSleepTimer=null:(this.noSleepVideo=document.createElement("video"),this.noSleepVideo.setAttribute("title","No Sleep"),this.noSleepVideo.setAttribute("playsinline",""),this._addSourceToVideo(this.noSleepVideo,"webm","data:video/webm;base64,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"),this._addSourceToVideo(this.noSleepVideo,"mp4","data:video/mp4;base64,AAAAHGZ0eXBNNFYgAAACAGlzb21pc28yYXZjMQAAAAhmcmVlAAAGF21kYXTeBAAAbGliZmFhYyAxLjI4AABCAJMgBDIARwAAArEGBf//rdxF6b3m2Ui3lizYINkj7u94MjY0IC0gY29yZSAxNDIgcjIgOTU2YzhkOCAtIEguMjY0L01QRUctNCBBVkMgY29kZWMgLSBDb3B5bGVmdCAyMDAzLTIwMTQgLSBodHRwOi8vd3d3LnZpZGVvbGFuLm9yZy94MjY0Lmh0bWwgLSBvcHRpb25zOiBjYWJhYz0wIHJlZj0zIGRlYmxvY2s9MTowOjAgYW5hbHlzZT0weDE6MHgxMTEgbWU9aGV4IHN1Ym1lPTcgcHN5PTEgcHN5X3JkPTEuMDA6MC4wMCBtaXhlZF9yZWY9MSBtZV9yYW5nZT0xNiBjaHJvbWFfbWU9MSB0cmVsbGlzPTEgOHg4ZGN0PTAgY3FtPTAgZGVhZHpvbmU9MjEsMTEgZmFzdF9wc2tpcD0xIGNocm9tYV9xcF9vZmZzZXQ9LTIgdGhyZWFkcz02IGxvb2thaGVhZF90aHJlYWRzPTEgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MCB3ZWlnaHRwPTAga2V5aW50PTI1MCBrZXlpbnRfbWluPTI1IHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCB2YnZfbWF4cmF0ZT03NjggdmJ2X2J1ZnNpemU9MzAwMCBjcmZfbWF4PTAuMCBuYWxfaHJkPW5vbmUgZmlsbGVyPTAgaXBfcmF0aW89MS40MCBhcT0xOjEuMDAAgAAAAFZliIQL8mKAAKvMnJycnJycnJycnXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXiEASZACGQAjgCEASZACGQAjgAAAAAdBmjgX4GSAIQBJkAIZACOAAAAAB0GaVAX4GSAhAEmQAhkAI4AhAEmQAhkAI4AAAAAGQZpgL8DJIQBJkAIZACOAIQBJkAIZACOAAAAABkGagC/AySEASZACGQAjgAAAAAZBmqAvwMkhAEmQAhkAI4AhAEmQAhkAI4AAAAAGQZrAL8DJIQBJkAIZACOAAAAABkGa4C/AySEASZACGQAjgCEASZACGQAjgAAAAAZBmwAvwMkhAEmQAhkAI4AAAAAGQZsgL8DJIQBJkAIZACOAIQBJkAIZACOAAAAABkGbQC/AySEASZACGQAjgCEASZACGQAjgAAAAAZBm2AvwMkhAEmQAhkAI4AAAAAGQZuAL8DJIQBJkAIZACOAIQBJkAIZACOAAAAABkGboC/AySEASZACGQAjgAAAAAZBm8AvwMkhAEmQAhkAI4AhAEmQAhkAI4AAAAAGQZvgL8DJIQBJkAIZACOAAAAABkGaAC/AySEASZACGQAjgCEASZACGQAjgAAAAAZBmiAvwMkhAEmQAhkAI4AhAEmQAhkAI4AAAAAGQZpAL8DJIQBJkAIZACOAAAAABkGaYC/AySEASZACGQAjgCEASZACGQAjgAAAAAZBmoAvwMkhAEmQAhkAI4AAAAAGQZqgL8DJIQBJkAIZACOAIQBJkAIZACOAAAAABkGawC/AySEASZACGQAjgAAAAAZBmuAvwMkhAEmQAhkAI4AhAEmQAhkAI4AAAAAGQZsAL8DJIQBJkAIZACOAAAAABkGbIC/AySEASZACGQAjgCEASZACGQAjgAAAAAZBm0AvwMkhAEmQAhkAI4AhAEmQAhkAI4AAAAAGQZtgL8DJIQBJkAIZACOAAAAABkGbgCvAySEASZACGQAjgCEASZACGQAjgAAAAAZBm6AnwMkhAEmQAhkAI4AhAEmQAhkAI4AhAEmQAhkAI4AhAEmQAhkAI4AAAAhubW9vdgAAAGxtdmhkAAAAAAAAAAAAAAAAAAAD6AAABDcAAQAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAzB0cmFrAAAAXHRraGQAAAADAAAAAAAAAAAAAAABAAAAAAAAA+kAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAALAAAACQAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAAPpAAAAAAABAAAAAAKobWRpYQAAACBtZGhkAAAAAAAAAAAAAAAAAAB1MAAAdU5VxAAAAAAALWhkbHIAAAAAAAAAAHZpZGUAAAAAAAAAAAAAAABWaWRlb0hhbmRsZXIAAAACU21pbmYAAAAUdm1oZAAAAAEAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAhNzdGJsAAAAr3N0c2QAAAAAAAAAAQAAAJ9hdmMxAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAALAAkABIAAAASAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGP//AAAALWF2Y0MBQsAN/+EAFWdCwA3ZAsTsBEAAAPpAADqYA8UKkgEABWjLg8sgAAAAHHV1aWRraEDyXyRPxbo5pRvPAyPzAAAAAAAAABhzdHRzAAAAAAAAAAEAAAAeAAAD6QAAABRzdHNzAAAAAAAAAAEAAAABAAAAHHN0c2MAAAAAAAAAAQAAAAEAAAABAAAAAQAAAIxzdHN6AAAAAAAAAAAAAAAeAAADDwAAAAsAAAALAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAAiHN0Y28AAAAAAAAAHgAAAEYAAANnAAADewAAA5gAAAO0AAADxwAAA+MAAAP2AAAEEgAABCUAAARBAAAEXQAABHAAAASMAAAEnwAABLsAAATOAAAE6gAABQYAAAUZAAAFNQAABUgAAAVkAAAFdwAABZMAAAWmAAAFwgAABd4AAAXxAAAGDQAABGh0cmFrAAAAXHRraGQAAAADAAAAAAAAAAAAAAACAAAAAAAABDcAAAAAAAAAAAAAAAEBAAAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAkZWR0cwAAABxlbHN0AAAAAAAAAAEAAAQkAAADcAABAAAAAAPgbWRpYQAAACBtZGhkAAAAAAAAAAAAAAAAAAC7gAAAykBVxAAAAAAALWhkbHIAAAAAAAAAAHNvdW4AAAAAAAAAAAAAAABTb3VuZEhhbmRsZXIAAAADi21pbmYAAAAQc21oZAAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAADT3N0YmwAAABnc3RzZAAAAAAAAAABAAAAV21wNGEAAAAAAAAAAQAAAAAAAAAAAAIAEAAAAAC7gAAAAAAAM2VzZHMAAAAAA4CAgCIAAgAEgICAFEAVBbjYAAu4AAAADcoFgICAAhGQBoCAgAECAAAAIHN0dHMAAAAAAAAAAgAAADIAAAQAAAAAAQAAAkAAAAFUc3RzYwAAAAAAAAAbAAAAAQAAAAEAAAABAAAAAgAAAAIAAAABAAAAAwAAAAEAAAABAAAABAAAAAIAAAABAAAABgAAAAEAAAABAAAABwAAAAIAAAABAAAACAAAAAEAAAABAAAACQAAAAIAAAABAAAACgAAAAEAAAABAAAACwAAAAIAAAABAAAADQAAAAEAAAABAAAADgAAAAIAAAABAAAADwAAAAEAAAABAAAAEAAAAAIAAAABAAAAEQAAAAEAAAABAAAAEgAAAAIAAAABAAAAFAAAAAEAAAABAAAAFQAAAAIAAAABAAAAFgAAAAEAAAABAAAAFwAAAAIAAAABAAAAGAAAAAEAAAABAAAAGQAAAAIAAAABAAAAGgAAAAEAAAABAAAAGwAAAAIAAAABAAAAHQAAAAEAAAABAAAAHgAAAAIAAAABAAAAHwAAAAQAAAABAAAA4HN0c3oAAAAAAAAAAAAAADMAAAAaAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAAAJAAAACQAAAAkAAACMc3RjbwAAAAAAAAAfAAAALAAAA1UAAANyAAADhgAAA6IAAAO+AAAD0QAAA+0AAAQAAAAEHAAABC8AAARLAAAEZwAABHoAAASWAAAEqQAABMUAAATYAAAE9AAABRAAAAUjAAAFPwAABVIAAAVuAAAFgQAABZ0AAAWwAAAFzAAABegAAAX7AAAGFwAAAGJ1ZHRhAAAAWm1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAALWlsc3QAAAAlqXRvbwAAAB1kYXRhAAAAAQAAAABMYXZmNTUuMzMuMTAw"),this.noSleepVideo.addEventListener("loadedmetadata",(()=>{this.noSleepVideo.duration<=1?this.noSleepVideo.setAttribute("loop",""):this.noSleepVideo.addEventListener("timeupdate",(()=>{this.noSleepVideo.currentTime>.5&&(this.noSleepVideo.currentTime=Math.random())}))})))}_addSourceToVideo(e,t,i){var o=document.createElement("source");o.src=i,o.type=`video/${t}`,e.appendChild(o)}get isEnabled(){return this.enabled}enable(){const e=this.player.debug;if(at())return navigator.wakeLock.request("screen").then((t=>{this._wakeLock=t,this.enabled=!0,e.log("wakeLock","Wake Lock active."),this._wakeLock.addEventListener("release",(()=>{e.log("wakeLock","Wake Lock released.")}))})).catch((t=>{throw this.enabled=!1,e.error("wakeLock",`${t.name}, ${t.message}`),t}));if(st())return this.disable(),this.noSleepTimer=window.setInterval((()=>{document.hidden||(window.location.href=window.location.href.split("#")[0],window.setTimeout(window.stop,0))}),15e3),this.enabled=!0,Promise.resolve();return this.noSleepVideo.play().then((e=>(this.enabled=!0,e))).catch((e=>{throw this.enabled=!1,e}))}disable(){const e=this.player.debug;at()?(this._wakeLock&&this._wakeLock.release(),this._wakeLock=null):st()?this.noSleepTimer&&(e.warn("wakeLock","NoSleep now disabled for older iOS devices."),window.clearInterval(this.noSleepTimer),this.noSleepTimer=null):this.noSleepVideo.pause(),this.enabled=!1}}class At extends Be{constructor(e,t){var i;super(),this.$container=e,this._opt=Object.assign({},l,t),this.debug=new Ae(this),this._opt.useWCS&&(this._opt.useWCS="VideoEncoder"in window),this._opt.useMSE&&(this._opt.useMSE=window.MediaSource&&window.MediaSource.isTypeSupported(Z)),this._opt.wcsUseVideoRender&&(this._opt.wcsUseVideoRender=window.MediaStreamTrackGenerator&&"function"==typeof window.MediaStreamTrackGenerator),this._opt.useMSE&&(this._opt.useWCS&&this.debug.log("Player","useWCS set true->false"),this._opt.forceNoOffscreen||this.debug.log("Player","forceNoOffscreen set false->true"),this._opt.useWCS=!1,this._opt.forceNoOffscreen=!0),this._opt.forceNoOffscreen||("undefined"==typeof OffscreenCanvas?(this._opt.forceNoOffscreen=!0,this._opt.useOffscreen=!1):this._opt.useOffscreen=!0),this._opt.hasAudio||(this._opt.operateBtns.audio=!1),this._opt.hasControl=this._hasControl(),this._loading=!1,this._playing=!1,this._hasLoaded=!1,this._checkHeartTimeout=null,this._checkLoadingTimeout=null,this._checkStatsInterval=null,this._startBpsTime=null,this._isPlayingBeforePageHidden=!1,this._stats={buf:0,fps:0,abps:0,vbps:0,ts:0},this._times={playInitStart:"",playStart:"",streamStart:"",streamResponse:"",demuxStart:"",decodeStart:"",videoStart:"",playTimestamp:"",streamTimestamp:"",streamResponseTimestamp:"",demuxTimestamp:"",decodeTimestamp:"",videoTimestamp:"",allTimestamp:""},this._videoTimestamp=0,this._audioTimestamp=0,i=this,Object.defineProperty(i,"rect",{get:()=>{const e=i.$container.getBoundingClientRect();return e.width=Math.max(e.width,i.$container.clientWidth),e.height=Math.max(e.height,i.$container.clientHeight),e}}),["bottom","height","left","right","top","width"].forEach((e=>{Object.defineProperty(i,e,{get:()=>i.rect[e]})})),this.events=new de(this),this.video=new Fe(this),this._opt.hasAudio&&(this.audio=new Ve(this)),this.recorder=new Pe(this),this._onlyMseOrWcsVideo()?this.loaded=!0:this.decoderWorker=new Ge(this),this.stream=null,this.demux=null,this._lastVolume=null,this._opt.useWCS&&(this.webcodecsDecoder=new Ke(this),this.loaded=!0),this._opt.useMSE&&(this.mseDecoder=new rt(this),this.loaded=!0),this.control=new it(this),ye()&&(this.keepScreenOn=new nt(this)),(e=>{try{const t=t=>{Ee(t)===e.$container&&(e.emit(D.fullscreen,e.fullscreen),e.fullscreen?e._opt.useMSE&&e.resize():e.resize())};ce.on("change",t),e.events.destroys.push((()=>{ce.off("change",t)}))}catch(e){}if(e.on(x.decoderWorkerInit,(()=>{e.debug.log("player","has loaded"),e.loaded=!0})),e.on(x.play,(()=>{e.loading=!1})),e.on(x.fullscreen,(t=>{if(t)try{ce.request(e.$container).then((()=>{})).catch((t=>{ye()&&e._opt.useWebFullScreen&&(e.webFullscreen=!0)}))}catch(t){ye()&&e._opt.useWebFullScreen&&(e.webFullscreen=!0)}else try{ce.exit().then((()=>{e.webFullscreen&&(e.webFullscreen=!1)})).catch((()=>{e.webFullscreen=!1}))}catch(t){e.webFullscreen=!1}})),ye()&&e.on(x.webFullscreen,(t=>{t?e.$container.classList.add("jessibuca-fullscreen-web"):e.$container.classList.remove("jessibuca-fullscreen-web"),e.emit(D.fullscreen,e.fullscreen)})),e.on(x.resize,(()=>{e.video&&e.video.resize()})),e._opt.debug){const t=[x.timeUpdate];Object.keys(x).forEach((i=>{e.on(x[i],(o=>{t.includes(i)||e.debug.log("player events",x[i],o)}))})),Object.keys(j).forEach((t=>{e.on(j[t],(i=>{e.debug.log("player event error",j[t],i)}))}))}})(this),(e=>{const{_opt:t,debug:i,events:{proxy:o}}=e;t.supportDblclickFullscreen&&o(e.$container,"dblclick",(t=>{const i=Ee(t).nodeName.toLowerCase();"canvas"!==i&&"video"!==i||(e.fullscreen=!e.fullscreen)})),o(document,"visibilitychange",(()=>{t.hiddenAutoPause&&(i.log("visibilitychange",document.visibilityState,e._isPlayingBeforePageHidden),"visible"===document.visibilityState?e._isPlayingBeforePageHidden&&e.play():(e._isPlayingBeforePageHidden=e.playing,e.playing&&e.pause()))})),o(window,"fullscreenchange",(()=>{null!==e.keepScreenOn&&"visible"===document.visibilityState&&e.enableWakeLock()}))})(this),this._opt.useWCS&&this.debug.log("Player","use WCS"),this._opt.useMSE&&this.debug.log("Player","use MSE"),this._opt.useOffscreen&&this.debug.log("Player","use offscreen"),this.debug.log("Player options",this._opt)}destroy(){this._loading=!1,this._playing=!1,this._hasLoaded=!1,this._lastVolume=null,this._times={playInitStart:"",playStart:"",streamStart:"",streamResponse:"",demuxStart:"",decodeStart:"",videoStart:"",playTimestamp:"",streamTimestamp:"",streamResponseTimestamp:"",demuxTimestamp:"",decodeTimestamp:"",videoTimestamp:"",allTimestamp:""},this.decoderWorker&&(this.decoderWorker.destroy(),this.decoderWorker=null),this.video&&(this.video.destroy(),this.video=null),this.audio&&(this.audio.destroy(),this.audio=null),this.stream&&(this.stream.destroy(),this.stream=null),this.recorder&&(this.recorder.destroy(),this.recorder=null),this.control&&(this.control.destroy(),this.control=null),this.webcodecsDecoder&&(this.webcodecsDecoder.destroy(),this.webcodecsDecoder=null),this.mseDecoder&&(this.mseDecoder.destroy(),this.mseDecoder=null),this.demux&&(this.demux.destroy(),this.demux=null),this.events&&(this.events.destroy(),this.events=null),this.clearCheckHeartTimeout(),this.clearCheckLoadingTimeout(),this.clearStatsInterval(),this.releaseWakeLock(),this.keepScreenOn=null,this.resetStats(),this._audioTimestamp=0,this._videoTimestamp=0,this.emit("destroy"),this.off(),this.debug.log("play","destroy end")}set fullscreen(e){ye()&&this._opt.useWebFullScreen?(this.emit(x.webFullscreen,e),setTimeout((()=>{this.updateOption({rotate:e?270:0}),this.resize()}),10)):this.emit(x.fullscreen,e)}get fullscreen(){return ce.isFullscreen||this.webFullscreen}set webFullscreen(e){this.emit(x.webFullscreen,e)}get webFullscreen(){return this.$container.classList.contains("jessibuca-fullscreen-web")}set loaded(e){this._hasLoaded=e}get loaded(){return this._hasLoaded}set playing(e){e&&(this.loading=!1),this.playing!==e&&(this._playing=e,this.emit(x.playing,e),this.emit(x.volumechange,this.volume),e?this.emit(x.play):this.emit(x.pause))}get playing(){return this._playing}get volume(){return this.audio&&this.audio.volume||0}set volume(e){e!==this.volume&&(this.audio&&this.audio.setVolume(e),this._lastVolume=e)}get lastVolume(){return this._lastVolume}set loading(e){this.loading!==e&&(this._loading=e,this.emit(x.loading,this._loading))}get loading(){return this._loading}set recording(e){e?this.playing&&this.recorder&&this.recorder.startRecord():this.recorder&&this.recorder.stopRecordAndSave()}get recording(){return!!this.recorder&&this.recorder.recording}set audioTimestamp(e){null!==e&&(this._audioTimestamp=e)}get audioTimestamp(){return this._audioTimestamp}set videoTimestamp(e){null!==e&&(this._videoTimestamp=e,this._opt.useWCS||this._opt.useMSE||this.audioTimestamp&&this.videoTimestamp&&this.audio&&this.audio.emit(x.videoSyncAudio,{audioTimestamp:this.audioTimestamp,videoTimestamp:this.videoTimestamp,diff:this.audioTimestamp-this.videoTimestamp}))}get videoTimestamp(){return this._videoTimestamp}get isDebug(){return!0===this._opt.debug}updateOption(e){this._opt=Object.assign({},this._opt,e)}init(){return new Promise(((e,t)=>{this.stream||(this.stream=new Qe(this)),this.audio||this._opt.hasAudio&&(this.audio=new Ve(this)),this.demux||(this.demux=new Ye(this)),this._opt.useWCS&&(this.webcodecsDecoder||(this.webcodecsDecoder=new Ke(this))),this._opt.useMSE&&(this.mseDecoder||(this.mseDecoder=new rt(this))),this.decoderWorker||this._onlyMseOrWcsVideo()?e():(this.decoderWorker=new Ge(this),this.once(x.decoderWorkerInit,(()=>{e()})))}))}play(e,t){return new Promise(((i,o)=>{if(!e&&!this._opt.url)return o();this.loading=!0,this.playing=!1,this._times.playInitStart=he(),e||(e=this._opt.url),this._opt.url=e,this.clearCheckHeartTimeout(),this.init().then((()=>{this._times.playStart=he(),this._opt.isNotMute&&this.mute(!1),this.webcodecsDecoder&&this.webcodecsDecoder.once(j.webcodecsH265NotSupport,(()=>{this.emit(j.webcodecsH265NotSupport),this._opt.autoWasm||this.emit(x.error,j.webcodecsH265NotSupport)})),this.mseDecoder&&(this.mseDecoder.once(j.mediaSourceH265NotSupport,(()=>{this.emit(j.mediaSourceH265NotSupport),this._opt.autoWasm||this.emit(x.error,j.mediaSourceH265NotSupport)})),this.mseDecoder.once(j.mediaSourceFull,(()=>{this.emit(j.mediaSourceFull)})),this.mseDecoder.once(j.mediaSourceAppendBufferError,(()=>{this.emit(j.mediaSourceAppendBufferError)})),this.mseDecoder.once(j.mediaSourceBufferListLarge,(()=>{this.emit(j.mediaSourceBufferListLarge)})),this.mseDecoder.once(j.mediaSourceAppendBufferEndTimeout,(()=>{this.emit(j.mediaSourceAppendBufferEndTimeout)}))),this.enableWakeLock(),this.stream.fetchStream(e,t),this.checkLoadingTimeout(),this.stream.once(j.fetchError,(e=>{o(e)})),this.stream.once(j.websocketError,(e=>{o(e)})),this.stream.once(x.streamEnd,(()=>{o()})),this.stream.once(j.hlsError,(e=>{o(e)})),this.stream.once(x.streamSuccess,(()=>{i(),this._times.streamResponse=he(),this.video.play(),this.checkStatsInterval()}))})).catch((e=>{o(e)}))}))}close(){return new Promise(((e,t)=>{this._close().then((()=>{this.video&&this.video.clearView(),e()}))}))}resumeAudioAfterPause(){this.lastVolume&&(this.volume=this.lastVolume)}_close(){return new Promise(((e,t)=>{this.stream&&(this.stream.destroy(),this.stream=null),this.demux&&(this.demux.destroy(),this.demux=null),this.decoderWorker&&(this.decoderWorker.destroy(),this.decoderWorker=null),this.webcodecsDecoder&&(this.webcodecsDecoder.destroy(),this.webcodecsDecoder=null),this.mseDecoder&&(this.mseDecoder.destroy(),this.mseDecoder=null),this.audio&&(this.audio.destroy(),this.audio=null),this.clearCheckHeartTimeout(),this.clearCheckLoadingTimeout(),this.clearStatsInterval(),this.playing=!1,this.loading=!1,this.recording=!1,this.video&&(this.video.resetInit(),this.video.pause(!0)),this.releaseWakeLock(),this.resetStats(),this._audioTimestamp=0,this._videoTimestamp=0,this._times={playInitStart:"",playStart:"",streamStart:"",streamResponse:"",demuxStart:"",decodeStart:"",videoStart:"",playTimestamp:"",streamTimestamp:"",streamResponseTimestamp:"",demuxTimestamp:"",decodeTimestamp:"",videoTimestamp:"",allTimestamp:""},setTimeout((()=>{e()}),0)}))}pause(){return arguments.length>0&&void 0!==arguments[0]&&arguments[0]?this.close():this._close()}mute(e){this.audio&&this.audio.mute(e)}resize(){this.video.resize()}startRecord(e,t){this.recording||(this.recorder.setFileName(e,t),this.recording=!0)}stopRecordAndSave(){this.recording&&(this.recording=!1)}_hasControl(){let e=!1,t=!1;return Object.keys(this._opt.operateBtns).forEach((e=>{this._opt.operateBtns[e]&&(t=!0)})),(this._opt.showBandwidth||this._opt.text||t)&&(e=!0),e}_onlyMseOrWcsVideo(){return!1===this._opt.hasAudio&&(this._opt.useMSE||this._opt.useWCS&&!this._opt.useOffscreen)}checkHeart(){this.clearCheckHeartTimeout(),this.checkHeartTimeout()}checkHeartTimeout(){this._checkHeartTimeout=setTimeout((()=>{if(this.playing){if(0!==this._stats.fps)return;this.pause().then((()=>{this.emit(x.timeout,x.delayTimeout),this.emit(x.delayTimeout)}))}}),1e3*this._opt.heartTimeout)}checkStatsInterval(){this._checkStatsInterval=setInterval((()=>{this.updateStats()}),1e3)}clearCheckHeartTimeout(){this._checkHeartTimeout&&(clearTimeout(this._checkHeartTimeout),this._checkHeartTimeout=null)}checkLoadingTimeout(){this._checkLoadingTimeout=setTimeout((()=>{this.playing||this.pause().then((()=>{this.emit(x.timeout,x.loadingTimeout),this.emit(x.loadingTimeout)}))}),1e3*this._opt.loadingTimeout)}clearCheckLoadingTimeout(){this._checkLoadingTimeout&&(clearTimeout(this._checkLoadingTimeout),this._checkLoadingTimeout=null)}clearStatsInterval(){this._checkStatsInterval&&(clearInterval(this._checkStatsInterval),this._checkStatsInterval=null)}handleRender(){this.loading&&(this.emit(x.start),this.loading=!1,this.clearCheckLoadingTimeout()),this.playing||(this.playing=!0),this.checkHeart()}updateStats(e){e=e||{},this._startBpsTime||(this._startBpsTime=he()),Se(e.ts)&&(this._stats.ts=e.ts),Se(e.buf)&&(this._stats.buf=e.buf),e.fps&&(this._stats.fps+=1),e.abps&&(this._stats.abps+=e.abps),e.vbps&&(this._stats.vbps+=e.vbps);const t=he();t-this._startBpsTime<1e3||(this.emit(x.stats,this._stats),this.emit(x.performance,function(e){let t=0;return e>=24?t=2:e>=15&&(t=1),t}(this._stats.fps)),this._stats.fps=0,this._stats.abps=0,this._stats.vbps=0,this._startBpsTime=t)}resetStats(){this._startBpsTime=null,this._stats={buf:0,fps:0,abps:0,vbps:0,ts:0}}enableWakeLock(){this._opt.keepScreenOn&&this.keepScreenOn&&this.keepScreenOn.enable()}releaseWakeLock(){this._opt.keepScreenOn&&this.keepScreenOn&&this.keepScreenOn.disable()}handlePlayToRenderTimes(){const e=this._times;e.playTimestamp=e.playStart-e.playInitStart,e.streamTimestamp=e.streamStart-e.playStart,e.streamResponseTimestamp=e.streamResponse-e.streamStart,e.demuxTimestamp=e.demuxStart-e.streamResponse,e.decodeTimestamp=e.decodeStart-e.demuxStart,e.videoTimestamp=e.videoStart-e.decodeStart,e.allTimestamp=e.videoStart-e.playInitStart,this.emit(x.playToRenderTimes,e)}getOption(){return this._opt}}class dt extends Be{constructor(e){super();let t=e,i=e.container;if("string"==typeof e.container&&(i=document.querySelector(e.container)),!i)throw new Error("Jessibuca need container option");if("CANVAS"===i.nodeName||"VIDEO"===i.nodeName)throw new Error(`Jessibuca container type can not be ${i.nodeName} type`);if(t.videoBuffer>=t.heartTimeout)throw new Error(`Jessibuca videoBuffer ${t.videoBuffer}s must be less than heartTimeout ${t.heartTimeout}s`);i.classList.add("jessibuca-container"),delete t.container,t.forceNoOffscreen=!0,ye()&&(t.controlAutoHide=!1),Se(t.videoBuffer)&&(t.videoBuffer=1e3*Number(t.videoBuffer)),Se(t.timeout)&&(we(t.loadingTimeout)&&(t.loadingTimeout=t.timeout),we(t.heartTimeout)&&(t.heartTimeout=t.timeout)),this._opt=t,this.$container=i,this._loadingTimeoutReplayTimes=0,this._heartTimeoutReplayTimes=0,this.events=new de(this),this._initPlayer(i,t)}destroy(){this.events&&(this.events.destroy(),this.events=null),this.player&&(this.player.destroy(),this.player=null),this.$container=null,this._opt=null,this._loadingTimeoutReplayTimes=0,this._heartTimeoutReplayTimes=0,this.off()}_initPlayer(e,t){this.player=new At(e,t),this.player.debug.log("jessibuca","_initPlayer",this.player.getOption()),this._bindEvents()}_resetPlayer(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.player.destroy(),this.player=null,this._opt=Object.assign(this._opt,e),this._opt.url="",this._initPlayer(this.$container,this._opt)}_bindEvents(){Object.keys(D).forEach((e=>{this.player.on(D[e],(t=>{this.emit(e,t)}))}))}setDebug(e){this.player.updateOption({debug:!!e})}mute(){this.player.mute(!0)}cancelMute(){this.player.mute(!1)}setVolume(e){this.player.volume=e}audioResume(){this.player.audio&&this.player.audio.audioEnabled(!0)}setTimeout(e){e=Number(e),this.player.updateOption({timeout:e,loadingTimeout:e,heartTimeout:e})}setScaleMode(e){let t={isFullResize:!1,isResize:!1};switch(e=Number(e)){case P:t.isFullResize=!1,t.isResize=!1;break;case G:t.isFullResize=!1,t.isResize=!0;break;case N:t.isFullResize=!0,t.isResize=!0}this.player.updateOption(t),this.resize()}pause(){return this.player.pause()}close(){return this._opt.url="",this._opt.playOptions={},this.player.close()}clearView(){this.player.video.clearView()}play(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return new Promise(((i,o)=>{if(!e&&!this._opt.url)return this.emit(x.error,j.playError),void o("play url is empty");e?this._opt.url?e===this._opt.url?this.player.playing?i():(this.clearView(),this.player.play(this._opt.url,this._opt.playOptions).then((()=>{i(),this.player.resumeAudioAfterPause()})).catch((e=>{this.player.debug.warn("jessibuca","pause -> play and play error",e),this.player.pause().then((()=>{o(e)}))}))):this.player.pause().then((()=>{this.clearView(),this._play(e,t).then((()=>{i()})).catch((e=>{this.player.debug.warn("jessibuca","this._play error",e),o(e)}))})).catch((e=>{this.player.debug.warn("jessibuca","this._opt.url is null and pause error",e),o(e)})):this._play(e,t).then((()=>{i()})).catch((e=>{this.player.debug.warn("jessibuca","this._play error",e),o(e)})):this.player.play(this._opt.url,this._opt.playOptions).then((()=>{i(),this.player.resumeAudioAfterPause()})).catch((e=>{this.player.debug.warn("jessibuca","url is null and play error",e),this.player.pause().then((()=>{o(e)}))}))}))}_play(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return new Promise(((i,o)=>{this._opt.url=e,this._opt.playOptions=t;const r=0===e.indexOf("http"),d=r?a:s,c=r||-1!==e.indexOf(".flv")||this._opt.isFlv?n:A;this.player.updateOption({protocol:d,demuxType:c}),this.player.once(j.webglAlignmentError,(()=>{this.pause().then((()=>{this.player.debug.log("Jessibuca","webglAlignmentError"),this._resetPlayer({openWebglAlignment:!0}),this.play(e).then((()=>{this.player.debug.log("Jessibuca","webglAlignmentError and play success")})).catch((()=>{this.player.debug.log("Jessibuca","webglAlignmentError and play error")}))}))})),this.player.once(j.mediaSourceH265NotSupport,(()=>{this.pause().then((()=>{this.player._opt.autoWasm&&(this.player.debug.log("Jessibuca","auto wasm [mse-> wasm] reset player and play"),this._resetPlayer({useMSE:!1}),this.play(e,t).then((()=>{this.player.debug.log("Jessibuca","auto wasm [mse-> wasm] reset player and play success")})).catch((()=>{this.player.debug.log("Jessibuca","auto wasm [mse-> wasm] reset player and play error")})))}))})),this.player.once(j.webcodecsH265NotSupport,(()=>{this.pause().then((()=>{this.player._opt.autoWasm&&(this.player.debug.log("Jessibuca","auto wasm [wcs-> wasm] reset player and play"),this._resetPlayer({useWCS:!1}),this.play(e,t).then((()=>{this.player.debug.log("Jessibuca","auto wasm [wcs-> wasm] reset player and play success")})).catch((()=>{this.player.debug.log("Jessibuca","auto wasm [wcs-> wasm] reset player and play error")})))}))})),this.player.once(j.mediaSourceFull,(()=>{this.pause().then((()=>{this.player.debug.log("Jessibuca","media source full"),this._resetPlayer(),this.play(e).then((()=>{this.player.debug.log("Jessibuca","media source full and reset player and play success")})).catch((()=>{this.player.debug.warn("Jessibuca","media source full and reset player and play error")}))}))})),this.player.once(j.mediaSourceAppendBufferError,(()=>{this.pause().then((()=>{this.player.debug.log("Jessibuca","media source append buffer error"),this._resetPlayer(),this.play(e).then((()=>{this.player.debug.log("Jessibuca","media source append buffer error and reset player and play success")})).catch((()=>{this.player.debug.warn("Jessibuca","media source append buffer error and reset player and play error")}))}))})),this.player.once(j.mediaSourceBufferListLarge,(()=>{this.pause().then((()=>{this.player.debug.log("Jessibuca","media source buffer list large"),this._resetPlayer(),this.play(e).then((()=>{this.player.debug.log("Jessibuca","media source buffer list large and reset player and play success")})).catch((()=>{this.player.debug.warn("Jessibuca","media source buffer list large and reset player and play error")}))}))})),this.player.once(j.mediaSourceAppendBufferEndTimeout,(()=>{this.pause().then((()=>{this.player.debug.log("Jessibuca","media source append buffer end timeout"),this._resetPlayer(),this.play(e).then((()=>{this.player.debug.log("Jessibuca","media source append buffer end timeout and reset player and play success")})).catch((()=>{this.player.debug.warn("Jessibuca","media source append buffer end timeout and reset player and play error")}))}))})),this.player.once(j.mseSourceBufferError,(()=>{this.pause().then((()=>{this.player.debug.log("Jessibuca","mseSourceBufferError close success")}))})),this.player.once(j.webcodecsH265NotSupport,(()=>{this.pause().then((()=>{this.player._opt.autoWasm&&(this.player.debug.log("Jessibuca","auto wasm [wcs-> wasm] reset player and play"),this._resetPlayer({useWCS:!1}),this.play(e).then((()=>{this.player.debug.log("Jessibuca","auto wasm [wcs-> wasm] reset player and play success")})).catch((()=>{this.player.debug.warn("Jessibuca","auto wasm [wcs-> wasm] reset player and play error")})))}))})),this.player.once(j.webcodecsWidthOrHeightChange,(()=>{this.pause().then((()=>{this.player.debug.log("Jessibuca","webcodecs Width Or Height Change reset player and play"),this._resetPlayer({useWCS:!0}),this.play(e).then((()=>{this.player.debug.log("Jessibuca","webcodecs Width Or Height Change reset player and play success")})).catch((()=>{this.player.debug.warn("Jessibuca","webcodecs Width Or Height Change reset player and play error")}))}))})),this.player.once(j.webcodecsDecodeError,(()=>{this.pause().then((()=>{this.player._opt.autoWasm&&(this.player.debug.log("Jessibuca","webcodecs decode error reset player and play"),this._resetPlayer({useWCS:!1}),this.play(e).then((()=>{this.player.debug.log("Jessibuca","webcodecs decode error reset player and play success")})).catch((()=>{this.player.debug.warn("Jessibuca","webcodecs decode error reset player and play error")})))}))})),this.player.once(j.wasmDecodeError,(()=>{this.player._opt.wasmDecodeErrorReplay&&this.pause().then((()=>{this.player.debug.log("Jessibuca","wasm decode error and reset player and play"),this._resetPlayer({useWCS:!1}),this.play(e,t).then((()=>{this.player.debug.log("Jessibuca","wasm decode error and reset player and play success")})).catch((()=>{this.player.debug.warn("Jessibuca","wasm decode error and reset player and play error")}))}))})),this.player.on(x.delayTimeout,(()=>{this.player._opt.heartTimeoutReplay&&(this._heartTimeoutReplayTimes<this.player._opt.heartTimeoutReplayTimes||-1===this.player._opt.heartTimeoutReplayTimes)&&(this.player.debug.log("Jessibuca",`delay timeout replay time is ${this._heartTimeoutReplayTimes}`),this._heartTimeoutReplayTimes+=1,this.play(e,t).then((()=>{this._heartTimeoutReplayTimes=0})).catch((()=>{})))})),this.player.on(x.loadingTimeout,(()=>{this.player._opt.loadingTimeoutReplay&&(this._loadingTimeoutReplayTimes<this.player._opt.loadingTimeoutReplayTimes||-1===this.player._opt.loadingTimeoutReplayTimes)&&(this.player.debug.log("Jessibuca",`loading timeout replay time is ${this._loadingTimeoutReplayTimes}`),this._loadingTimeoutReplayTimes+=1,this.play(e,t).then((()=>{this._loadingTimeoutReplayTimes=0})).catch((()=>{})))})),this.hasLoaded()?this.player.play(e,t).then((()=>{i()})).catch((e=>{this.player.debug.warn("Jessibuca","hasLoaded and play error",e),this.player.pause().then((()=>{o(e)}))})):this.player.once(x.decoderWorkerInit,(()=>{this.player.play(e,t).then((()=>{i()})).catch((e=>{this.player.debug.warn("Jessibuca","decoderWorkerInit and play error",e),this.player.pause().then((()=>{o(e)}))}))}))}))}resize(){this.player.resize()}setBufferTime(e){e=Number(e),this.player.updateOption({videoBuffer:1e3*e}),this.player.decoderWorker&&this.player.decoderWorker.updateWorkConfig({key:"videoBuffer",value:1e3*e})}setRotate(e){e=parseInt(e,10);this._opt.rotate!==e&&-1!==[0,90,180,270].indexOf(e)&&(this.player.updateOption({rotate:e}),this.resize())}hasLoaded(){return this.player.loaded}setKeepScreenOn(){this.player.updateOption({keepScreenOn:!0})}setFullscreen(e){const t=!!e;this.player.fullscreen!==t&&(this.player.fullscreen=t)}screenshot(e,t,i,o){return this.player.video?this.player.video.screenshot(e,t,i,o):""}startRecord(e,t){return new Promise(((i,o)=>{this.player.playing?(this.player.startRecord(e,t),i()):o()}))}stopRecordAndSave(){this.player.recording&&this.player.stopRecordAndSave()}isPlaying(){return!!this.player&&this.player.playing}isMute(){return!this.player.audio||this.player.audio.isMute}isRecording(){return this.player.recorder.recording}}return r(dt,"ERROR",j),r(dt,"TIMEOUT",{loadingTimeout:x.loadingTimeout,delayTimeout:x.delayTimeout}),window.Jessibuca=dt,dt}));