Commit 2d8054be18bf6ad6591703c6ab957777d137ecfe
Committed by
GitHub
Merge pull request #32 from lawrencehj/master
优化录像列表获取算法等
Showing
8 changed files
with
80 additions
and
85 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java
| 1 | /* | 1 | /* |
| 2 | -* Conditions Of Use | ||
| 3 | -* | ||
| 4 | -* This software was developed by employees of the National Institute of | ||
| 5 | -* Standards and Technology (NIST), an agency of the Federal Government. | ||
| 6 | -* Pursuant to title 15 Untied States Code Section 105, works of NIST | ||
| 7 | -* employees are not subject to copyright protection in the United States | ||
| 8 | -* and are considered to be in the public domain. As a result, a formal | ||
| 9 | -* license is not needed to use the software. | ||
| 10 | -* | ||
| 11 | -* This software is provided by NIST as a service and is expressly | ||
| 12 | -* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED | ||
| 13 | -* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF | ||
| 14 | -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT | ||
| 15 | -* AND DATA ACCURACY. NIST does not warrant or make any representations | ||
| 16 | -* regarding the use of the software or the results thereof, including but | ||
| 17 | -* not limited to the correctness, accuracy, reliability or usefulness of | ||
| 18 | -* the software. | ||
| 19 | -* | ||
| 20 | -* Permission to use this software is contingent upon your acceptance | ||
| 21 | -* of the terms of this agreement | ||
| 22 | -* | ||
| 23 | -* . | ||
| 24 | -* | ||
| 25 | -*/ | 2 | + * Conditions Of Use |
| 3 | + * | ||
| 4 | + * This software was developed by employees of the National Institute of | ||
| 5 | + * Standards and Technology (NIST), an agency of the Federal Government. | ||
| 6 | + * Pursuant to title 15 Untied States Code Section 105, works of NIST | ||
| 7 | + * employees are not subject to copyright protection in the United States | ||
| 8 | + * and are considered to be in the public domain. As a result, a formal | ||
| 9 | + * license is not needed to use the software. | ||
| 10 | + * | ||
| 11 | + * This software is provided by NIST as a service and is expressly | ||
| 12 | + * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED | ||
| 13 | + * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF | ||
| 14 | + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT | ||
| 15 | + * AND DATA ACCURACY. NIST does not warrant or make any representations | ||
| 16 | + * regarding the use of the software or the results thereof, including but | ||
| 17 | + * not limited to the correctness, accuracy, reliability or usefulness of | ||
| 18 | + * the software. | ||
| 19 | + * | ||
| 20 | + * Permission to use this software is contingent upon your acceptance | ||
| 21 | + * of the terms of this agreement | ||
| 22 | + * | ||
| 23 | + * . | ||
| 24 | + * | ||
| 25 | + */ | ||
| 26 | package com.genersoft.iot.vmp.gb28181.auth; | 26 | package com.genersoft.iot.vmp.gb28181.auth; |
| 27 | 27 | ||
| 28 | import java.security.MessageDigest; | 28 | import java.security.MessageDigest; |
| @@ -42,18 +42,18 @@ import gov.nist.core.InternalErrorHandler; | @@ -42,18 +42,18 @@ import gov.nist.core.InternalErrorHandler; | ||
| 42 | 42 | ||
| 43 | /** | 43 | /** |
| 44 | * Implements the HTTP digest authentication method server side functionality. | 44 | * Implements the HTTP digest authentication method server side functionality. |
| 45 | - * | 45 | + * |
| 46 | * @author M. Ranganathan | 46 | * @author M. Ranganathan |
| 47 | * @author Marc Bednarek | 47 | * @author Marc Bednarek |
| 48 | */ | 48 | */ |
| 49 | 49 | ||
| 50 | public class DigestServerAuthenticationHelper { | 50 | public class DigestServerAuthenticationHelper { |
| 51 | - | 51 | + |
| 52 | private MessageDigest messageDigest; | 52 | private MessageDigest messageDigest; |
| 53 | - | 53 | + |
| 54 | public static final String DEFAULT_ALGORITHM = "MD5"; | 54 | public static final String DEFAULT_ALGORITHM = "MD5"; |
| 55 | public static final String DEFAULT_SCHEME = "Digest"; | 55 | public static final String DEFAULT_SCHEME = "Digest"; |
| 56 | - | 56 | + |
| 57 | 57 | ||
| 58 | 58 | ||
| 59 | 59 | ||
| @@ -63,11 +63,11 @@ public class DigestServerAuthenticationHelper { | @@ -63,11 +63,11 @@ public class DigestServerAuthenticationHelper { | ||
| 63 | 63 | ||
| 64 | /** | 64 | /** |
| 65 | * Default constructor. | 65 | * Default constructor. |
| 66 | - * @throws NoSuchAlgorithmException | 66 | + * @throws NoSuchAlgorithmException |
| 67 | */ | 67 | */ |
| 68 | - public DigestServerAuthenticationHelper() | ||
| 69 | - throws NoSuchAlgorithmException { | ||
| 70 | - messageDigest = MessageDigest.getInstance(DEFAULT_ALGORITHM); | 68 | + public DigestServerAuthenticationHelper() |
| 69 | + throws NoSuchAlgorithmException { | ||
| 70 | + messageDigest = MessageDigest.getInstance(DEFAULT_ALGORITHM); | ||
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | public static String toHexString(byte b[]) { | 73 | public static String toHexString(byte b[]) { |
| @@ -79,7 +79,7 @@ public class DigestServerAuthenticationHelper { | @@ -79,7 +79,7 @@ public class DigestServerAuthenticationHelper { | ||
| 79 | } | 79 | } |
| 80 | return new String(c); | 80 | return new String(c); |
| 81 | } | 81 | } |
| 82 | - | 82 | + |
| 83 | /** | 83 | /** |
| 84 | * Generate the challenge string. | 84 | * Generate the challenge string. |
| 85 | * | 85 | * |
| @@ -121,34 +121,34 @@ public class DigestServerAuthenticationHelper { | @@ -121,34 +121,34 @@ public class DigestServerAuthenticationHelper { | ||
| 121 | * | 121 | * |
| 122 | * @param request - the request to authenticate. | 122 | * @param request - the request to authenticate. |
| 123 | * @param hashedPassword -- the MD5 hashed string of username:realm:plaintext password. | 123 | * @param hashedPassword -- the MD5 hashed string of username:realm:plaintext password. |
| 124 | - * | 124 | + * |
| 125 | * @return true if authentication succeded and false otherwise. | 125 | * @return true if authentication succeded and false otherwise. |
| 126 | */ | 126 | */ |
| 127 | public boolean doAuthenticateHashedPassword(Request request, String hashedPassword) { | 127 | public boolean doAuthenticateHashedPassword(Request request, String hashedPassword) { |
| 128 | - AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); | 128 | + AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); |
| 129 | if ( authHeader == null ) return false; | 129 | if ( authHeader == null ) return false; |
| 130 | String realm = authHeader.getRealm(); | 130 | String realm = authHeader.getRealm(); |
| 131 | String username = authHeader.getUsername(); | 131 | String username = authHeader.getUsername(); |
| 132 | - | 132 | + |
| 133 | if ( username == null || realm == null ) { | 133 | if ( username == null || realm == null ) { |
| 134 | return false; | 134 | return false; |
| 135 | } | 135 | } |
| 136 | - | 136 | + |
| 137 | String nonce = authHeader.getNonce(); | 137 | String nonce = authHeader.getNonce(); |
| 138 | URI uri = authHeader.getURI(); | 138 | URI uri = authHeader.getURI(); |
| 139 | if (uri == null) { | 139 | if (uri == null) { |
| 140 | return false; | 140 | return false; |
| 141 | } | 141 | } |
| 142 | - | ||
| 143 | 142 | ||
| 144 | - | 143 | + |
| 144 | + | ||
| 145 | String A2 = request.getMethod().toUpperCase() + ":" + uri.toString(); | 145 | String A2 = request.getMethod().toUpperCase() + ":" + uri.toString(); |
| 146 | String HA1 = hashedPassword; | 146 | String HA1 = hashedPassword; |
| 147 | 147 | ||
| 148 | - | 148 | + |
| 149 | byte[] mdbytes = messageDigest.digest(A2.getBytes()); | 149 | byte[] mdbytes = messageDigest.digest(A2.getBytes()); |
| 150 | String HA2 = toHexString(mdbytes); | 150 | String HA2 = toHexString(mdbytes); |
| 151 | - | 151 | + |
| 152 | String cnonce = authHeader.getCNonce(); | 152 | String cnonce = authHeader.getCNonce(); |
| 153 | String KD = HA1 + ":" + nonce; | 153 | String KD = HA1 + ":" + nonce; |
| 154 | if (cnonce != null) { | 154 | if (cnonce != null) { |
| @@ -158,7 +158,7 @@ public class DigestServerAuthenticationHelper { | @@ -158,7 +158,7 @@ public class DigestServerAuthenticationHelper { | ||
| 158 | mdbytes = messageDigest.digest(KD.getBytes()); | 158 | mdbytes = messageDigest.digest(KD.getBytes()); |
| 159 | String mdString = toHexString(mdbytes); | 159 | String mdString = toHexString(mdbytes); |
| 160 | String response = authHeader.getResponse(); | 160 | String response = authHeader.getResponse(); |
| 161 | - | 161 | + |
| 162 | 162 | ||
| 163 | return mdString.equals(response); | 163 | return mdString.equals(response); |
| 164 | } | 164 | } |
| @@ -168,11 +168,11 @@ public class DigestServerAuthenticationHelper { | @@ -168,11 +168,11 @@ public class DigestServerAuthenticationHelper { | ||
| 168 | * | 168 | * |
| 169 | * @param request - the request to authenticate. | 169 | * @param request - the request to authenticate. |
| 170 | * @param pass -- the plain text password. | 170 | * @param pass -- the plain text password. |
| 171 | - * | 171 | + * |
| 172 | * @return true if authentication succeded and false otherwise. | 172 | * @return true if authentication succeded and false otherwise. |
| 173 | */ | 173 | */ |
| 174 | public boolean doAuthenticatePlainTextPassword(Request request, String pass) { | 174 | public boolean doAuthenticatePlainTextPassword(Request request, String pass) { |
| 175 | - AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); | 175 | + AuthorizationHeader authHeader = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); |
| 176 | if ( authHeader == null ) return false; | 176 | if ( authHeader == null ) return false; |
| 177 | String realm = authHeader.getRealm().trim(); | 177 | String realm = authHeader.getRealm().trim(); |
| 178 | String username = authHeader.getUsername().trim(); | 178 | String username = authHeader.getUsername().trim(); |
| @@ -184,7 +184,7 @@ public class DigestServerAuthenticationHelper { | @@ -184,7 +184,7 @@ public class DigestServerAuthenticationHelper { | ||
| 184 | String nonce = authHeader.getNonce(); | 184 | String nonce = authHeader.getNonce(); |
| 185 | URI uri = authHeader.getURI(); | 185 | URI uri = authHeader.getURI(); |
| 186 | if (uri == null) { | 186 | if (uri == null) { |
| 187 | - return false; | 187 | + return false; |
| 188 | } | 188 | } |
| 189 | // qop 保护质量 包含auth(默认的)和auth-int(增加了报文完整性检测)两种策略 | 189 | // qop 保护质量 包含auth(默认的)和auth-int(增加了报文完整性检测)两种策略 |
| 190 | String qop = authHeader.getQop(); | 190 | String qop = authHeader.getQop(); |
| @@ -233,6 +233,6 @@ public class DigestServerAuthenticationHelper { | @@ -233,6 +233,6 @@ public class DigestServerAuthenticationHelper { | ||
| 233 | String response = authHeader.getResponse(); | 233 | String response = authHeader.getResponse(); |
| 234 | System.out.println("response: " + response); | 234 | System.out.println("response: " + response); |
| 235 | return mdString.equals(response); | 235 | return mdString.equals(response); |
| 236 | - | 236 | + |
| 237 | } | 237 | } |
| 238 | } | 238 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| @@ -409,7 +409,12 @@ public class SIPCommander implements ISIPCommander { | @@ -409,7 +409,12 @@ public class SIPCommander implements ISIPCommander { | ||
| 409 | try { | 409 | try { |
| 410 | MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); | 410 | MediaServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); |
| 411 | String ssrc = streamSession.createPlayBackSsrc(); | 411 | String ssrc = streamSession.createPlayBackSsrc(); |
| 412 | - String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); | 412 | + String streamId = null; |
| 413 | + if (rtpEnable) { | ||
| 414 | + streamId = String.format("gb_playback_%s_%s", device.getDeviceId(), channelId); | ||
| 415 | + }else { | ||
| 416 | + streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); | ||
| 417 | + } | ||
| 413 | // 添加订阅 | 418 | // 添加订阅 |
| 414 | JSONObject subscribeKey = new JSONObject(); | 419 | JSONObject subscribeKey = new JSONObject(); |
| 415 | subscribeKey.put("app", "rtp"); | 420 | subscribeKey.put("app", "rtp"); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
| @@ -342,6 +342,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | @@ -342,6 +342,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 342 | try { | 342 | try { |
| 343 | // 回复200 OK | 343 | // 回复200 OK |
| 344 | responseAck(evt); | 344 | responseAck(evt); |
| 345 | + String seqNo = String.valueOf(System.currentTimeMillis()); | ||
| 345 | RecordInfo recordInfo = new RecordInfo(); | 346 | RecordInfo recordInfo = new RecordInfo(); |
| 346 | Element rootElement = getRootElement(evt); | 347 | Element rootElement = getRootElement(evt); |
| 347 | Element deviceIdElement = rootElement.element("DeviceID"); | 348 | Element deviceIdElement = rootElement.element("DeviceID"); |
| @@ -396,32 +397,22 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | @@ -396,32 +397,22 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 396 | if (recordInfo.getSumNum() > 0 && recordList.size() > 0 && recordList.size() < recordInfo.getSumNum()) { | 397 | if (recordInfo.getSumNum() > 0 && recordList.size() > 0 && recordList.size() < recordInfo.getSumNum()) { |
| 397 | // 为防止连续请求该设备的录像数据,返回数据错乱,特增加sn进行区分 | 398 | // 为防止连续请求该设备的录像数据,返回数据错乱,特增加sn进行区分 |
| 398 | String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn; | 399 | String cacheKey = CACHE_RECORDINFO_KEY + deviceId + sn; |
| 399 | - // TODO 暂时直接操作redis存储,后续封装专用缓存接口,改为本地内存缓存 | ||
| 400 | - if (redis.hasKey(cacheKey)) { | ||
| 401 | - List<RecordItem> previousList = (List<RecordItem>) redis.get(cacheKey); | ||
| 402 | - if (previousList != null && previousList.size() > 0) { | ||
| 403 | - recordList.addAll(previousList); | ||
| 404 | - } | ||
| 405 | - // 本分支表示录像列表被拆包,且加上之前的数据还是不够,保存缓存返回,等待下个包再处理 | ||
| 406 | - if (recordList.size() < recordInfo.getSumNum()) { | ||
| 407 | - logger.info("已获取" + recordList.size() + "项录像数据,共" + recordInfo.getSumNum() + "项"); | ||
| 408 | - redis.set(cacheKey, recordList, 90); | ||
| 409 | - return; | ||
| 410 | - } else { | ||
| 411 | - // 本分支表示录像被拆包,但加上之前的数据够足够,返回响应 | ||
| 412 | - // 因设备心跳有监听redis过期机制,为提高性能,此处手动删除 | ||
| 413 | - logger.info("录像数据已全部获取"); | ||
| 414 | - redis.del(cacheKey); | ||
| 415 | - } | ||
| 416 | - } else { | ||
| 417 | - // 本分支有两种可能:1、录像列表被拆包,且是第一个包,直接保存缓存返回,等待下个包再处理 | ||
| 418 | - // 2、之前有包,但超时清空了,那么这次sn批次的响应数据已经不完整,等待过期时间后redis自动清空数据 | ||
| 419 | - logger.info("已获取" + recordList.size() + "项录像数据,共" + recordInfo.getSumNum() + "项"); | ||
| 420 | - logger.info("等待后续的包..."); | ||
| 421 | 400 | ||
| 422 | - redis.set(cacheKey, recordList, 90); | 401 | + redis.set(cacheKey + "_" + seqNo, recordList, 90); |
| 402 | + List<Object> cacheKeys = redis.scan(cacheKey + "_*"); | ||
| 403 | + List<RecordItem> totalRecordList = new ArrayList<RecordItem>(); | ||
| 404 | + for (int i = 0; i < cacheKeys.size(); i++) { | ||
| 405 | + totalRecordList.addAll((List<RecordItem>) redis.get(cacheKeys.get(i).toString())); | ||
| 406 | + } | ||
| 407 | + if (totalRecordList.size() < recordInfo.getSumNum()) { | ||
| 408 | + logger.info("已获取" + totalRecordList.size() + "项录像数据,共" + recordInfo.getSumNum() + "项"); | ||
| 423 | return; | 409 | return; |
| 424 | } | 410 | } |
| 411 | + logger.info("录像数据已全部获取,共" + recordInfo.getSumNum() + "项"); | ||
| 412 | + recordInfo.setRecordList(totalRecordList); | ||
| 413 | + for (int i = 0; i < cacheKeys.size(); i++) { | ||
| 414 | + redis.del(cacheKeys.get(i).toString()); | ||
| 415 | + } | ||
| 425 | } | 416 | } |
| 426 | // 自然顺序排序, 元素进行升序排列 | 417 | // 自然顺序排序, 元素进行升序排列 |
| 427 | recordInfo.getRecordList().sort(Comparator.naturalOrder()); | 418 | recordInfo.getRecordList().sort(Comparator.naturalOrder()); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java
| @@ -144,10 +144,10 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | @@ -144,10 +144,10 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 144 | storager.updateDevice(device); | 144 | storager.updateDevice(device); |
| 145 | publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER); | 145 | publisher.onlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_ONLINE_REGISTER); |
| 146 | 146 | ||
| 147 | - // 只有第一次注册才更新通道 | ||
| 148 | - if (!exists) { | 147 | + // 重新注册更新设备和通道,以免设备替换或更新后信息无法更新 |
| 148 | + //if (!exists) { | ||
| 149 | handler.onRegister(device); | 149 | handler.onRegister(device); |
| 150 | - } | 150 | + //} |
| 151 | } else if (registerFlag == 2) { | 151 | } else if (registerFlag == 2) { |
| 152 | logger.info("注销成功! deviceId:" + device.getDeviceId()); | 152 | logger.info("注销成功! deviceId:" + device.getDeviceId()); |
| 153 | publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER); | 153 | publisher.outlineEventPublish(device.getDeviceId(), VideoManagerConstants.EVENT_OUTLINE_UNREGISTER); |
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
| @@ -43,7 +43,6 @@ public interface DeviceMapper { | @@ -43,7 +43,6 @@ public interface DeviceMapper { | ||
| 43 | ")") | 43 | ")") |
| 44 | int add(Device device); | 44 | int add(Device device); |
| 45 | 45 | ||
| 46 | - | ||
| 47 | @Update(value = {" <script>" + | 46 | @Update(value = {" <script>" + |
| 48 | "UPDATE device " + | 47 | "UPDATE device " + |
| 49 | "SET deviceId='${deviceId}'" + | 48 | "SET deviceId='${deviceId}'" + |
src/main/resources/application-dev.yml
| @@ -13,12 +13,12 @@ spring: | @@ -13,12 +13,12 @@ spring: | ||
| 13 | timeout: 10000 | 13 | timeout: 10000 |
| 14 | # [不可用] jdbc数据库配置, 暂不支持 | 14 | # [不可用] jdbc数据库配置, 暂不支持 |
| 15 | datasource: | 15 | datasource: |
| 16 | - # name: eiot | ||
| 17 | - # url: jdbc:mysql://127.0.0.1:3306/eiot?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true | ||
| 18 | - # username: | ||
| 19 | - # password: | ||
| 20 | - # type: com.alibaba.druid.pool.DruidDataSource | ||
| 21 | - # driver-class-name: com.mysql.jdbc.Driver | 16 | + #name: eiot |
| 17 | + #url: jdbc:mysql://127.0.0.1:3306/eiot?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true | ||
| 18 | + #username: | ||
| 19 | + #password: | ||
| 20 | + #type: com.alibaba.druid.pool.DruidDataSource | ||
| 21 | + #driver-class-name: com.mysql.jdbc.Driver | ||
| 22 | name: eiot | 22 | name: eiot |
| 23 | url: jdbc:sqlite::resource:wvp.sqlite | 23 | url: jdbc:sqlite::resource:wvp.sqlite |
| 24 | username: | 24 | username: |
src/main/resources/application.yml
web_src/src/components/gb28181/devicePlayer.vue
| 1 | <template> | 1 | <template> |
| 2 | <div id="devicePlayer" v-loading="isLoging"> | 2 | <div id="devicePlayer" v-loading="isLoging"> |
| 3 | - | 3 | + |
| 4 | <el-dialog title="视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" :destroy-on-close="true" @close="close()"> | 4 | <el-dialog title="视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" :destroy-on-close="true" @close="close()"> |
| 5 | <!-- <LivePlayer v-if="showVideoDialog" ref="videoPlayer" :videoUrl="videoUrl" :error="videoError" :message="videoError" :hasaudio="hasaudio" fluent autoplay live></LivePlayer> --> | 5 | <!-- <LivePlayer v-if="showVideoDialog" ref="videoPlayer" :videoUrl="videoUrl" :error="videoError" :message="videoError" :hasaudio="hasaudio" fluent autoplay live></LivePlayer> --> |
| 6 | <player ref="videoPlayer" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" :hasaudio="hasaudio" fluent autoplay live></player> | 6 | <player ref="videoPlayer" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" :hasaudio="hasaudio" fluent autoplay live></player> |
| @@ -125,7 +125,7 @@ | @@ -125,7 +125,7 @@ | ||
| 125 | <p>采样率: {{item.sample_rate}}</p> | 125 | <p>采样率: {{item.sample_rate}}</p> |
| 126 | </div> | 126 | </div> |
| 127 | </div> | 127 | </div> |
| 128 | - | 128 | + |
| 129 | </div> | 129 | </div> |
| 130 | 130 | ||
| 131 | </el-tab-pane> | 131 | </el-tab-pane> |
| @@ -237,7 +237,7 @@ export default { | @@ -237,7 +237,7 @@ export default { | ||
| 237 | console.log(val) | 237 | console.log(val) |
| 238 | }, | 238 | }, |
| 239 | play: function (streamInfo, hasAudio) { | 239 | play: function (streamInfo, hasAudio) { |
| 240 | - | 240 | + |
| 241 | this.hasaudio = hasAudio; | 241 | this.hasaudio = hasAudio; |
| 242 | this.isLoging = false; | 242 | this.isLoging = false; |
| 243 | this.videoUrl = streamInfo.ws_flv; | 243 | this.videoUrl = streamInfo.ws_flv; |
| @@ -319,7 +319,7 @@ export default { | @@ -319,7 +319,7 @@ export default { | ||
| 319 | } | 319 | } |
| 320 | this.convertKey = '' | 320 | this.convertKey = '' |
| 321 | }, | 321 | }, |
| 322 | - | 322 | + |
| 323 | copySharedInfo: function (data) { | 323 | copySharedInfo: function (data) { |
| 324 | console.log('复制内容:' + data); | 324 | console.log('复制内容:' + data); |
| 325 | this.coverPlaying = false; | 325 | this.coverPlaying = false; |