Commit fa2ccb4ec8737df8718f1507bdd290fc7b5dd144

Authored by 648540858
1 parent 278264a2

修复协议端口配置不全导致前端播放页面无法弹出的问题

src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
... ... @@ -169,25 +169,31 @@ public class StreamInfo implements Serializable, Cloneable{
169 169  
170 170 public void setRtmp(String host, int port, int sslPort, String app, String stream, String callIdParam) {
171 171 String file = String.format("%s/%s/%s", app, stream, callIdParam);
172   - this.rtmp = new StreamURL("rtmp", host, port, file);
173   - if (sslPort != 0) {
  172 + if (port > 0) {
  173 + this.rtmp = new StreamURL("rtmp", host, port, file);
  174 + }
  175 + if (sslPort > 0) {
174 176 this.rtmps = new StreamURL("rtmps", host, sslPort, file);
175 177 }
176 178 }
177 179  
178 180 public void setRtsp(String host, int port, int sslPort, String app, String stream, String callIdParam) {
179 181 String file = String.format("%s/%s/%s", app, stream, callIdParam);
180   - this.rtsp = new StreamURL("rtsp", host, port, file);
181   - if (sslPort != 0) {
  182 + if (port > 0) {
  183 + this.rtsp = new StreamURL("rtsp", host, port, file);
  184 + }
  185 + if (sslPort > 0) {
182 186 this.rtsps = new StreamURL("rtsps", host, sslPort, file);
183 187 }
184 188 }
185 189  
186 190 public void setFlv(String host, int port, int sslPort, String app, String stream, String callIdParam) {
187 191 String file = String.format("%s/%s.live.flv%s", app, stream, callIdParam);
188   - this.flv = new StreamURL("http", host, port, file);
  192 + if (port > 0) {
  193 + this.flv = new StreamURL("http", host, port, file);
  194 + }
189 195 this.ws_flv = new StreamURL("ws", host, port, file);
190   - if (sslPort != 0) {
  196 + if (sslPort > 0) {
191 197 this.https_flv = new StreamURL("https", host, sslPort, file);
192 198 this.wss_flv = new StreamURL("wss", host, sslPort, file);
193 199 }
... ... @@ -195,9 +201,11 @@ public class StreamInfo implements Serializable, Cloneable{
195 201  
196 202 public void setFmp4(String host, int port, int sslPort, String app, String stream, String callIdParam) {
197 203 String file = String.format("%s/%s.live.mp4%s", app, stream, callIdParam);
198   - this.fmp4 = new StreamURL("http", host, port, file);
199   - this.ws_fmp4 = new StreamURL("ws", host, port, file);
200   - if (sslPort != 0) {
  204 + if (port > 0) {
  205 + this.fmp4 = new StreamURL("http", host, port, file);
  206 + this.ws_fmp4 = new StreamURL("ws", host, port, file);
  207 + }
  208 + if (sslPort > 0) {
201 209 this.https_fmp4 = new StreamURL("https", host, sslPort, file);
202 210 this.wss_fmp4 = new StreamURL("wss", host, sslPort, file);
203 211 }
... ... @@ -205,9 +213,11 @@ public class StreamInfo implements Serializable, Cloneable{
205 213  
206 214 public void setHls(String host, int port, int sslPort, String app, String stream, String callIdParam) {
207 215 String file = String.format("%s/%s/hls.m3u8%s", app, stream, callIdParam);
208   - this.hls = new StreamURL("http", host, port, file);
209   - this.ws_hls = new StreamURL("ws", host, port, file);
210   - if (sslPort != 0) {
  216 + if (port > 0) {
  217 + this.hls = new StreamURL("http", host, port, file);
  218 + this.ws_hls = new StreamURL("ws", host, port, file);
  219 + }
  220 + if (sslPort > 0) {
211 221 this.https_hls = new StreamURL("https", host, sslPort, file);
212 222 this.wss_hls = new StreamURL("wss", host, sslPort, file);
213 223 }
... ... @@ -215,9 +225,12 @@ public class StreamInfo implements Serializable, Cloneable{
215 225  
216 226 public void setTs(String host, int port, int sslPort, String app, String stream, String callIdParam) {
217 227 String file = String.format("%s/%s.live.ts%s", app, stream, callIdParam);
218   - this.ts = new StreamURL("http", host, port, file);
219   - this.ws_ts = new StreamURL("ws", host, port, file);
220   - if (sslPort != 0) {
  228 +
  229 + if (port > 0) {
  230 + this.ts = new StreamURL("http", host, port, file);
  231 + this.ws_ts = new StreamURL("ws", host, port, file);
  232 + }
  233 + if (sslPort > 0) {
221 234 this.https_ts = new StreamURL("https", host, sslPort, file);
222 235 this.wss_ts = new StreamURL("wss", host, sslPort, file);
223 236 }
... ... @@ -225,41 +238,78 @@ public class StreamInfo implements Serializable, Cloneable{
225 238  
226 239 public void setRtc(String host, int port, int sslPort, String app, String stream, String callIdParam) {
227 240 String file = String.format("index/api/webrtc?app=%s&stream=%s&type=play%s", app, stream, callIdParam);
228   - this.rtc = new StreamURL("http", host, port, file);
229   - if (sslPort != 0) {
  241 + if (port > 0) {
  242 + this.rtc = new StreamURL("http", host, port, file);
  243 + }
  244 + if (sslPort > 0) {
230 245 this.rtcs = new StreamURL("https", host, sslPort, file);
231 246 }
232 247 }
233 248  
234 249 public void channgeStreamIp(String localAddr) {
235   - this.flv.setHost(localAddr);
236   - this.ws_flv.setHost(localAddr);
237   - this.hls.setHost(localAddr);
238   - this.ws_hls.setHost(localAddr);
239   - this.ts.setHost(localAddr);
240   - this.ws_ts.setHost(localAddr);
241   - this.fmp4.setHost(localAddr);
242   - this.ws_fmp4.setHost(localAddr);
243   - this.rtc.setHost(localAddr);
  250 + if (this.flv != null) {
  251 + this.flv.setHost(localAddr);
  252 + }
  253 + if (this.ws_flv != null ){
  254 + this.ws_flv.setHost(localAddr);
  255 + }
  256 + if (this.hls != null ) {
  257 + this.hls.setHost(localAddr);
  258 + }
  259 + if (this.ws_hls != null ) {
  260 + this.ws_hls.setHost(localAddr);
  261 + }
  262 + if (this.ts != null ) {
  263 + this.ts.setHost(localAddr);
  264 + }
  265 + if (this.ws_ts != null ) {
  266 + this.ws_ts.setHost(localAddr);
  267 + }
  268 + if (this.fmp4 != null ) {
  269 + this.fmp4.setHost(localAddr);
  270 + }
  271 + if (this.ws_fmp4 != null ) {
  272 + this.ws_fmp4.setHost(localAddr);
  273 + }
  274 + if (this.rtc != null ) {
  275 + this.rtc.setHost(localAddr);
  276 + }
244 277 if (this.https_flv != null) {
245 278 this.https_flv.setHost(localAddr);
  279 + }
  280 + if (this.wss_flv != null) {
246 281 this.wss_flv.setHost(localAddr);
  282 + }
  283 + if (this.https_hls != null) {
247 284 this.https_hls.setHost(localAddr);
  285 + }
  286 + if (this.wss_hls != null) {
248 287 this.wss_hls.setHost(localAddr);
  288 + }
  289 + if (this.wss_ts != null) {
249 290 this.wss_ts.setHost(localAddr);
  291 + }
  292 + if (this.https_fmp4 != null) {
250 293 this.https_fmp4.setHost(localAddr);
  294 + }
  295 + if (this.wss_fmp4 != null) {
251 296 this.wss_fmp4.setHost(localAddr);
  297 + }
  298 + if (this.rtcs != null) {
252 299 this.rtcs.setHost(localAddr);
253 300 }
254   - this.rtsp.setHost(localAddr);
  301 + if (this.rtsp != null) {
  302 + this.rtsp.setHost(localAddr);
  303 + }
255 304 if (this.rtsps != null) {
256 305 this.rtsps.setHost(localAddr);
257 306 }
258   - this.rtmp.setHost(localAddr);
  307 + if (this.rtmp != null) {
  308 + this.rtmp.setHost(localAddr);
  309 + }
259 310 if (this.rtmps != null) {
260 311 this.rtmps.setHost(localAddr);
261 312 }
262   -
263 313 }
264 314  
265 315  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
1 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2  
3   -import gov.nist.javax.sip.message.SIPRequest;
4   -
5 3 public class SendRtpItem {
6 4  
7 5 /**
... ... @@ -108,6 +106,11 @@ public class SendRtpItem {
108 106 */
109 107 private boolean onlyAudio = false;
110 108  
  109 + /**
  110 + * 是否开启rtcp保活
  111 + */
  112 + private boolean rtcp = false;
  113 +
111 114  
112 115 /**
113 116 * 播放类型
... ... @@ -281,4 +284,12 @@ public class SendRtpItem {
281 284 public void setToTag(String toTag) {
282 285 this.toTag = toTag;
283 286 }
  287 +
  288 + public boolean isRtcp() {
  289 + return rtcp;
  290 + }
  291 +
  292 + public void setRtcp(boolean rtcp) {
  293 + this.rtcp = rtcp;
  294 + }
284 295 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
... ... @@ -120,9 +120,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
120 120 param.put("pt", sendRtpItem.getPt());
121 121 param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0");
122 122 param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0");
123   - if (!sendRtpItem.isTcp() && parentPlatform.isRtcp()) {
  123 + if (!sendRtpItem.isTcp()) {
124 124 // 开启rtcp保活
125   - param.put("udp_rtcp_timeout", "1");
  125 + param.put("udp_rtcp_timeout", sendRtpItem.isRtcp()? "1":"0");
126 126 }
127 127  
128 128 if (mediaInfo == null) {
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
... ... @@ -341,8 +341,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
341 341 return;
342 342 }
343 343 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
344   - device.getDeviceId(), channelId,
345   - mediaTransmissionTCP);
  344 + device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp());
346 345  
347 346 if (tcpActive != null) {
348 347 sendRtpItem.setTcpActive(tcpActive);
... ... @@ -537,8 +536,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
537 536 if (streamReady) {
538 537 // 自平台内容
539 538 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
540   - gbStream.getApp(), gbStream.getStream(), channelId,
541   - mediaTransmissionTCP);
  539 + gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp());
542 540  
543 541 if (sendRtpItem == null) {
544 542 logger.warn("服务器端口资源不足");
... ... @@ -577,8 +575,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
577 575 if (streamReady) {
578 576 // 自平台内容
579 577 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
580   - gbStream.getApp(), gbStream.getStream(), channelId,
581   - mediaTransmissionTCP);
  578 + gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP, platform.isRtcp());
582 579  
583 580 if (sendRtpItem == null) {
584 581 logger.warn("服务器端口资源不足");
... ... @@ -695,7 +692,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
695 692 dynamicTask.stop(callIdHeader.getCallId());
696 693 if (serverId.equals(userSetting.getServerId())) {
697 694 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId,
698   - app, stream, channelId, mediaTransmissionTCP);
  695 + app, stream, channelId, mediaTransmissionTCP, platform.isRtcp());
699 696  
700 697 if (sendRtpItem == null) {
701 698 logger.warn("上级点时创建sendRTPItem失败,可能是服务器端口资源不足");
... ... @@ -757,7 +754,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
757 754 // 发送redis消息
758 755 redisGbPlayMsgListener.sendMsg(streamPushItem.getServerId(), streamPushItem.getMediaServerId(),
759 756 streamPushItem.getApp(), streamPushItem.getStream(), addressStr, port, ssrc, requesterId,
760   - channelId, mediaTransmissionTCP, null, responseSendItemMsg -> {
  757 + channelId, mediaTransmissionTCP, platform.isRtcp(),null, responseSendItemMsg -> {
761 758 SendRtpItem sendRtpItem = responseSendItemMsg.getSendRtpItem();
762 759 if (sendRtpItem == null || responseSendItemMsg.getMediaServerItem() == null) {
763 760 logger.warn("服务器端口资源不足");
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
... ... @@ -175,7 +175,7 @@ public class ZLMRTPServerFactory {
175 175 * @param tcp 是否为tcp
176 176 * @return SendRtpItem
177 177 */
178   - public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){
  178 + public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp, boolean rtcp){
179 179  
180 180 // 默认为随机端口
181 181 int localPort = 0;
... ... @@ -195,6 +195,7 @@ public class ZLMRTPServerFactory {
195 195 sendRtpItem.setDeviceId(deviceId);
196 196 sendRtpItem.setChannelId(channelId);
197 197 sendRtpItem.setTcp(tcp);
  198 + sendRtpItem.setRtcp(rtcp);
198 199 sendRtpItem.setApp("rtp");
199 200 sendRtpItem.setLocalPort(localPort);
200 201 sendRtpItem.setServerId(userSetting.getServerId());
... ... @@ -212,7 +213,7 @@ public class ZLMRTPServerFactory {
212 213 * @param tcp 是否为tcp
213 214 * @return SendRtpItem
214 215 */
215   - public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){
  216 + public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp, boolean rtcp){
216 217 // 默认为随机端口
217 218 int localPort = 0;
218 219 if (userSetting.getGbSendStreamStrict()) {
... ... @@ -233,6 +234,7 @@ public class ZLMRTPServerFactory {
233 234 sendRtpItem.setLocalPort(localPort);
234 235 sendRtpItem.setServerId(userSetting.getServerId());
235 236 sendRtpItem.setMediaServerId(serverItem.getId());
  237 + sendRtpItem.setRtcp(rtcp);
236 238 return sendRtpItem;
237 239 }
238 240  
... ...
src/main/java/com/genersoft/iot/vmp/service/bean/RequestSendItemMsg.java
... ... @@ -63,10 +63,16 @@ public class RequestSendItemMsg {
63 63 private Boolean isTcp;
64 64  
65 65  
  66 + /**
  67 + * 是否使用TCP
  68 + */
  69 + private Boolean rtcp;
  70 +
  71 +
66 72  
67 73  
68 74 public static RequestSendItemMsg getInstance(String serverId, String mediaServerId, String app, String stream, String ip, int port,
69   - String ssrc, String platformId, String channelId, Boolean isTcp, String platformName) {
  75 + String ssrc, String platformId, String channelId, Boolean isTcp, Boolean rtcp, String platformName) {
70 76 RequestSendItemMsg requestSendItemMsg = new RequestSendItemMsg();
71 77 requestSendItemMsg.setServerId(serverId);
72 78 requestSendItemMsg.setMediaServerId(mediaServerId);
... ... @@ -79,6 +85,7 @@ public class RequestSendItemMsg {
79 85 requestSendItemMsg.setPlatformName(platformName);
80 86 requestSendItemMsg.setChannelId(channelId);
81 87 requestSendItemMsg.setTcp(isTcp);
  88 + requestSendItemMsg.setRtcp(rtcp);
82 89  
83 90 return requestSendItemMsg;
84 91 }
... ... @@ -170,4 +177,12 @@ public class RequestSendItemMsg {
170 177 public void setTcp(Boolean tcp) {
171 178 isTcp = tcp;
172 179 }
  180 +
  181 + public Boolean getRtcp() {
  182 + return rtcp;
  183 + }
  184 +
  185 + public void setRtcp(Boolean rtcp) {
  186 + this.rtcp = rtcp;
  187 + }
173 188 }
... ...
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java
... ... @@ -318,7 +318,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
318 318 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, content.getIp(),
319 319 content.getPort(), content.getSsrc(), content.getPlatformId(),
320 320 content.getApp(), content.getStream(), content.getChannelId(),
321   - content.getTcp());
  321 + content.getTcp(), content.getRtcp());
322 322  
323 323 WVPResult<ResponseSendItemMsg> result = new WVPResult<>();
324 324 result.setCode(0);
... ... @@ -348,9 +348,9 @@ public class RedisGbPlayMsgListener implements MessageListener {
348 348 * @param callback 得到信息的回调
349 349 */
350 350 public void sendMsg(String serverId, String mediaServerId, String app, String stream, String ip, int port, String ssrc,
351   - String platformId, String channelId, boolean isTcp, String platformName, PlayMsgCallback callback, PlayMsgErrorCallback errorCallback) {
  351 + String platformId, String channelId, boolean isTcp, boolean rtcp, String platformName, PlayMsgCallback callback, PlayMsgErrorCallback errorCallback) {
352 352 RequestSendItemMsg requestSendItemMsg = RequestSendItemMsg.getInstance(
353   - serverId, mediaServerId, app, stream, ip, port, ssrc, platformId, channelId, isTcp, platformName);
  353 + serverId, mediaServerId, app, stream, ip, port, ssrc, platformId, channelId, isTcp, rtcp, platformName);
354 354 requestSendItemMsg.setServerId(serverId);
355 355 String key = UUID.randomUUID().toString();
356 356 WvpRedisMsg redisMsg = WvpRedisMsg.getRequestInstance(userSetting.getServerId(), serverId, WvpRedisMsgCmd.GET_SEND_ITEM,
... ...
web_src/src/components/dialog/devicePlayer.vue
... ... @@ -53,91 +53,91 @@
53 53 更多地址<i class="el-icon-arrow-down el-icon--right"></i>
54 54 </el-button>
55 55 <el-dropdown-menu slot="dropdown" >
56   - <el-dropdown-item :command="streamInfo.flv.url">
  56 + <el-dropdown-item v-if="streamInfo.flv" :command="streamInfo.flv.url">
57 57 <el-tag >FLV:</el-tag>
58 58 <span>{{ streamInfo.flv.url }}</span>
59 59 </el-dropdown-item>
60   - <el-dropdown-item :command="streamInfo.https_flv.url">
  60 + <el-dropdown-item v-if="streamInfo.https_flv" :command="streamInfo.https_flv.url">
61 61 <el-tag >FLV(https):</el-tag>
62 62 <span>{{ streamInfo.https_flv.url }}</span>
63 63 </el-dropdown-item>
64   - <el-dropdown-item :command="streamInfo.ws_flv.url">
  64 + <el-dropdown-item v-if="streamInfo.ws_flv" :command="streamInfo.ws_flv.url">
65 65 <el-tag >FLV(ws):</el-tag>
66 66 <span >{{ streamInfo.ws_flv.url }}</span>
67 67 </el-dropdown-item>
68   - <el-dropdown-item :command="streamInfo.wss_flv.url">
  68 + <el-dropdown-item v-if="streamInfo.wss_flv" :command="streamInfo.wss_flv.url">
69 69 <el-tag >FLV(wss):</el-tag>
70 70 <span>{{ streamInfo.wss_flv.url }}</span>
71 71 </el-dropdown-item>
72   - <el-dropdown-item :command="streamInfo.fmp4.url">
  72 + <el-dropdown-item v-if="streamInfo.fmp4" :command="streamInfo.fmp4.url">
73 73 <el-tag >FMP4:</el-tag>
74 74 <span>{{ streamInfo.fmp4.url }}</span>
75 75 </el-dropdown-item>
76   - <el-dropdown-item :command="streamInfo.https_fmp4.url">
  76 + <el-dropdown-item v-if="streamInfo.https_fmp4" :command="streamInfo.https_fmp4.url">
77 77 <el-tag >FMP4(https):</el-tag>
78 78 <span>{{ streamInfo.https_fmp4.url }}</span>
79 79 </el-dropdown-item>
80   - <el-dropdown-item :command="streamInfo.ws_fmp4.url">
  80 + <el-dropdown-item v-if="streamInfo.ws_fmp4" :command="streamInfo.ws_fmp4.url">
81 81 <el-tag >FMP4(ws):</el-tag>
82 82 <span>{{ streamInfo.ws_fmp4.url }}</span>
83 83 </el-dropdown-item>
84   - <el-dropdown-item :command="streamInfo.wss_fmp4.url">
  84 + <el-dropdown-item v-if="streamInfo.wss_fmp4" :command="streamInfo.wss_fmp4.url">
85 85 <el-tag >FMP4(wss):</el-tag>
86 86 <span>{{ streamInfo.wss_fmp4.url }}</span>
87 87 </el-dropdown-item>
88   - <el-dropdown-item :command="streamInfo.hls.url">
  88 + <el-dropdown-item v-if="streamInfo.hls" :command="streamInfo.hls.url">
89 89 <el-tag>HLS:</el-tag>
90 90 <span>{{ streamInfo.hls.url }}</span>
91 91 </el-dropdown-item>
92   - <el-dropdown-item :command="streamInfo.https_hls.url">
  92 + <el-dropdown-item v-if="streamInfo.https_hls" :command="streamInfo.https_hls.url">
93 93 <el-tag >HLS(https):</el-tag>
94 94 <span>{{ streamInfo.https_hls.url }}</span>
95 95 </el-dropdown-item>
96   - <el-dropdown-item :command="streamInfo.ws_hls.url">
  96 + <el-dropdown-item v-if="streamInfo.ws_hls" :command="streamInfo.ws_hls.url">
97 97 <el-tag >HLS(ws):</el-tag>
98 98 <span>{{ streamInfo.ws_hls.url }}</span>
99 99 </el-dropdown-item>
100   - <el-dropdown-item :command="streamInfo.wss_hls.url">
  100 + <el-dropdown-item v-if="streamInfo.wss_hls" :command="streamInfo.wss_hls.url">
101 101 <el-tag >HLS(wss):</el-tag>
102 102 <span>{{ streamInfo.wss_hls.url }}</span>
103 103 </el-dropdown-item>
104   - <el-dropdown-item :command="streamInfo.ts.url">
  104 + <el-dropdown-item v-if="streamInfo.ts" :command="streamInfo.ts.url">
105 105 <el-tag>TS:</el-tag>
106 106 <span>{{ streamInfo.ts.url }}</span>
107 107 </el-dropdown-item>
108   - <el-dropdown-item :command="streamInfo.https_ts.url">
  108 + <el-dropdown-item v-if="streamInfo.https_ts" :command="streamInfo.https_ts.url">
109 109 <el-tag>TS(https):</el-tag>
110 110 <span>{{ streamInfo.https_ts.url }}</span>
111 111 </el-dropdown-item>
112   - <el-dropdown-item :command="streamInfo.ws_ts.url">
  112 + <el-dropdown-item v-if="streamInfo.ws_ts" :command="streamInfo.ws_ts.url">
113 113 <el-tag>TS(ws):</el-tag>
114 114 <span>{{ streamInfo.ws_ts.url }}</span>
115 115 </el-dropdown-item>
116   - <el-dropdown-item :command="streamInfo.wss_ts.url">
  116 + <el-dropdown-item v-if="streamInfo.wss_ts" :command="streamInfo.wss_ts.url">
117 117 <el-tag>TS(wss):</el-tag>
118 118 <span>{{ streamInfo.wss_ts.url }}</span>
119 119 </el-dropdown-item>
120   - <el-dropdown-item :command="streamInfo.rtc.url">
  120 + <el-dropdown-item v-if="streamInfo.rtc" :command="streamInfo.rtc.url">
121 121 <el-tag >RTC:</el-tag>
122 122 <span>{{ streamInfo.rtc.url }}</span>
123 123 </el-dropdown-item>
124   - <el-dropdown-item :command="streamInfo.rtcs.url">
  124 + <el-dropdown-item v-if="streamInfo.rtcs" :command="streamInfo.rtcs.url">
125 125 <el-tag >RTCS:</el-tag>
126 126 <span>{{ streamInfo.rtcs }}</span>
127 127 </el-dropdown-item>
128   - <el-dropdown-item :command="streamInfo.rtmp.url">
  128 + <el-dropdown-item v-if="streamInfo.rtmp" :command="streamInfo.rtmp.url">
129 129 <el-tag >RTMP:</el-tag>
130 130 <span>{{ streamInfo.rtmp.url }}</span>
131 131 </el-dropdown-item>
132   - <el-dropdown-item :command="streamInfo.rtmps.url">
  132 + <el-dropdown-item v-if="streamInfo.rtmps" :command="streamInfo.rtmps.url">
133 133 <el-tag >RTMPS:</el-tag>
134 134 <span>{{ streamInfo.rtmps.url }}</span>
135 135 </el-dropdown-item>
136   - <el-dropdown-item :command="streamInfo.rtsp.url">
  136 + <el-dropdown-item v-if="streamInfo.rtsp" :command="streamInfo.rtsp.url">
137 137 <el-tag >RTSP:</el-tag>
138 138 <span>{{ streamInfo.rtsp.url }}</span>
139 139 </el-dropdown-item>
140   - <el-dropdown-item :command="streamInfo.rtsps.url">
  140 + <el-dropdown-item v-if="streamInfo.rtsps" :command="streamInfo.rtsps.url">
141 141 <el-tag >RTSPS:</el-tag>
142 142 <span>{{ streamInfo.rtsps.url }}</span>
143 143 </el-dropdown-item>
... ...