Commit c226deacff2135751247d2e31d7e12c8b6db5314

Authored by 648540858
1 parent dea44dcd

修复语音对讲发送页

src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -45,6 +45,8 @@ import gov.nist.javax.sip.message.SIPResponse; @@ -45,6 +45,8 @@ import gov.nist.javax.sip.message.SIPResponse;
45 import org.slf4j.Logger; 45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory; 46 import org.slf4j.LoggerFactory;
47 import org.springframework.beans.factory.annotation.Autowired; 47 import org.springframework.beans.factory.annotation.Autowired;
  48 +import org.springframework.beans.factory.annotation.Qualifier;
  49 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
48 import org.springframework.stereotype.Service; 50 import org.springframework.stereotype.Service;
49 import org.springframework.util.ObjectUtils; 51 import org.springframework.util.ObjectUtils;
50 52
@@ -993,7 +995,7 @@ public class PlayServiceImpl implements IPlayService { @@ -993,7 +995,7 @@ public class PlayServiceImpl implements IPlayService {
993 logger.warn("开启语音广播的时候未找到通道: {}", channelId); 995 logger.warn("开启语音广播的时候未找到通道: {}", channelId);
994 return null; 996 return null;
995 } 997 }
996 - MediaServerItem mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(); 998 + MediaServerItem mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null);
997 String app = "broadcast"; 999 String app = "broadcast";
998 // TODO 从sip user agent中判断是什么品牌设备,大华默认使用talk模式,其他使用broadcast模式 1000 // TODO 从sip user agent中判断是什么品牌设备,大华默认使用talk模式,其他使用broadcast模式
999 // String app = "talk"; 1001 // String app = "talk";
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -271,7 +271,7 @@ public class PlayController { @@ -271,7 +271,7 @@ public class PlayController {
271 271
272 @GetMapping("/1111") 272 @GetMapping("/1111")
273 public void broadcastApi1() { 273 public void broadcastApi1() {
274 - MediaServerItem defaultMediaServer = mediaServerService.getMediaServerForMinimumLoad(); 274 + MediaServerItem defaultMediaServer = mediaServerService.getMediaServerForMinimumLoad(null);
275 Device device = storager.queryVideoDevice("34020000001320090001"); 275 Device device = storager.queryVideoDevice("34020000001320090001");
276 playService.talk(defaultMediaServer, device, "34020000001370000001", null, null, null); 276 playService.talk(defaultMediaServer, device, "34020000001370000001", null, null, null);
277 277
web_src/src/components/dialog/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" @close="close()"> 4 <el-dialog title="视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" @close="close()">
5 <div style="width: 100%; height: 100%"> 5 <div style="width: 100%; height: 100%">
6 - <el-tabs type="card" :stretch="true" v-model="activePlayer" @tab-click="changePlayer" v-if="Object.keys(this.player).length > 1"> 6 + <el-tabs type="card" :stretch="true" v-model="activePlayer" @tab-click="changePlayer"
  7 + v-if="Object.keys(this.player).length > 1">
7 <el-tab-pane label="Jessibuca" name="jessibuca"> 8 <el-tab-pane label="Jessibuca" name="jessibuca">
8 - <jessibucaPlayer v-if="activePlayer === 'jessibuca'" ref="jessibuca" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></jessibucaPlayer> 9 + <jessibucaPlayer v-if="activePlayer === 'jessibuca'" ref="jessibuca" :visible.sync="showVideoDialog"
  10 + :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px"
  11 + :hasAudio="hasAudio" fluent autoplay live></jessibucaPlayer>
9 </el-tab-pane> 12 </el-tab-pane>
10 <el-tab-pane label="WebRTC" name="webRTC"> 13 <el-tab-pane label="WebRTC" name="webRTC">
11 - <rtc-player v-if="activePlayer === 'webRTC'" ref="webRTC" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></rtc-player> 14 + <rtc-player v-if="activePlayer === 'webRTC'" ref="webRTC" :visible.sync="showVideoDialog"
  15 + :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px"
  16 + :hasAudio="hasAudio" fluent autoplay live></rtc-player>
12 </el-tab-pane> 17 </el-tab-pane>
13 <el-tab-pane label="h265web">h265web敬请期待</el-tab-pane> 18 <el-tab-pane label="h265web">h265web敬请期待</el-tab-pane>
14 <el-tab-pane label="wsPlayer">wsPlayer 敬请期待</el-tab-pane> 19 <el-tab-pane label="wsPlayer">wsPlayer 敬请期待</el-tab-pane>
15 </el-tabs> 20 </el-tabs>
16 - <jessibucaPlayer v-if="Object.keys(this.player).length == 1 && this.player.jessibuca" ref="jessibuca" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></jessibucaPlayer>  
17 - <rtc-player v-if="Object.keys(this.player).length == 1 && this.player.webRTC" ref="jessibuca" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></rtc-player> 21 + <jessibucaPlayer v-if="Object.keys(this.player).length == 1 && this.player.jessibuca" ref="jessibuca"
  22 + :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError"
  23 + height="100px" :hasAudio="hasAudio" fluent autoplay live></jessibucaPlayer>
  24 + <rtc-player v-if="Object.keys(this.player).length == 1 && this.player.webRTC" ref="jessibuca"
  25 + :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError"
  26 + height="100px" :hasAudio="hasAudio" fluent autoplay live></rtc-player>
18 27
19 </div> 28 </div>
20 - <div id="shared" style="text-align: right; margin-top: 1rem;">  
21 - <el-tabs v-model="tabActiveName" @tab-click="tabHandleClick" >  
22 - <el-tab-pane label="实时视频" name="media">  
23 - <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">  
24 - <span style="width: 5rem; line-height: 2.5rem; text-align: right;">播放地址:</span>  
25 - <el-input v-model="getPlayerShared.sharedUrl" :disabled="true" >  
26 - <template slot="append">  
27 - <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedUrl" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>  
28 - </template>  
29 - </el-input>  
30 - </div>  
31 - <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">  
32 - <span style="width: 5rem; line-height: 2.5rem; text-align: right;">iframe:</span>  
33 - <el-input v-model="getPlayerShared.sharedIframe" :disabled="true" >  
34 - <template slot="append">  
35 - <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedIframe" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>  
36 - </template>  
37 - </el-input>  
38 - </div>  
39 - <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">  
40 - <span style="width: 5rem; line-height: 2.5rem; text-align: right;">资源地址:</span>  
41 - <el-input v-model="getPlayerShared.sharedRtmp" :disabled="true" >  
42 - <el-button slot="append" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedRtmp" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>  
43 - <el-dropdown slot="prepend" v-if="streamInfo" trigger="click" @command="copyUrl">  
44 - <el-button >  
45 - 更多地址<i class="el-icon-arrow-down el-icon--right"></i>  
46 - </el-button>  
47 - <el-dropdown-menu slot="dropdown" >  
48 - <el-dropdown-item v-if="streamInfo.flv" :command="streamInfo.flv">  
49 - <el-tag >FLV:</el-tag>  
50 - <span>{{ streamInfo.flv }}</span>  
51 - </el-dropdown-item>  
52 - <el-dropdown-item v-if="streamInfo.https_flv" :command="streamInfo.https_flv">  
53 - <el-tag >FLV(https):</el-tag>  
54 - <span>{{ streamInfo.https_flv }}</span>  
55 - </el-dropdown-item>  
56 - <el-dropdown-item v-if="streamInfo.ws_flv" :command="streamInfo.ws_flv">  
57 - <el-tag >FLV(ws):</el-tag>  
58 - <span >{{ streamInfo.ws_flv }}</span>  
59 - </el-dropdown-item>  
60 - <el-dropdown-item v-if="streamInfo.wss_flv" :command="streamInfo.wss_flv">  
61 - <el-tag >FLV(wss):</el-tag>  
62 - <span>{{ streamInfo.wss_flv }}</span>  
63 - </el-dropdown-item>  
64 - <el-dropdown-item v-if="streamInfo.fmp4" :command="streamInfo.fmp4">  
65 - <el-tag >FMP4:</el-tag>  
66 - <span>{{ streamInfo.fmp4 }}</span>  
67 - </el-dropdown-item>  
68 - <el-dropdown-item v-if="streamInfo.https_fmp4" :command="streamInfo.https_fmp4">  
69 - <el-tag >FMP4(https):</el-tag>  
70 - <span>{{ streamInfo.https_fmp4 }}</span>  
71 - </el-dropdown-item>  
72 - <el-dropdown-item v-if="streamInfo.ws_fmp4" :command="streamInfo.ws_fmp4">  
73 - <el-tag >FMP4(ws):</el-tag>  
74 - <span>{{ streamInfo.ws_fmp4 }}</span>  
75 - </el-dropdown-item>  
76 - <el-dropdown-item v-if="streamInfo.wss_fmp4" :command="streamInfo.wss_fmp4">  
77 - <el-tag >FMP4(wss):</el-tag>  
78 - <span>{{ streamInfo.wss_fmp4 }}</span>  
79 - </el-dropdown-item>  
80 - <el-dropdown-item v-if="streamInfo.hls" :command="streamInfo.hls">  
81 - <el-tag>HLS:</el-tag>  
82 - <span>{{ streamInfo.hls }}</span>  
83 - </el-dropdown-item>  
84 - <el-dropdown-item v-if="streamInfo.https_hls" :command="streamInfo.https_hls">  
85 - <el-tag >HLS(https):</el-tag>  
86 - <span>{{ streamInfo.https_hls }}</span>  
87 - </el-dropdown-item>  
88 - <el-dropdown-item v-if="streamInfo.ws_hls" :command="streamInfo.ws_hls">  
89 - <el-tag >HLS(ws):</el-tag>  
90 - <span>{{ streamInfo.ws_hls }}</span>  
91 - </el-dropdown-item>  
92 - <el-dropdown-item v-if="streamInfo.wss_hls" :command="streamInfo.wss_hls">  
93 - <el-tag >HLS(wss):</el-tag>  
94 - <span>{{ streamInfo.wss_hls }}</span>  
95 - </el-dropdown-item>  
96 - <el-dropdown-item v-if="streamInfo.ts" :command="streamInfo.ts">  
97 - <el-tag>TS:</el-tag>  
98 - <span>{{ streamInfo.ts }}</span>  
99 - </el-dropdown-item>  
100 - <el-dropdown-item v-if="streamInfo.https_ts" :command="streamInfo.https_ts">  
101 - <el-tag>TS(https):</el-tag>  
102 - <span>{{ streamInfo.https_ts }}</span>  
103 - </el-dropdown-item>  
104 - <el-dropdown-item v-if="streamInfo.ws_ts" :command="streamInfo.ws_ts">  
105 - <el-tag>TS(ws):</el-tag>  
106 - <span>{{ streamInfo.ws_ts }}</span>  
107 - </el-dropdown-item>  
108 - <el-dropdown-item v-if="streamInfo.wss_ts" :command="streamInfo.wss_ts">  
109 - <el-tag>TS(wss):</el-tag>  
110 - <span>{{ streamInfo.wss_ts }}</span>  
111 - </el-dropdown-item>  
112 - <el-dropdown-item v-if="streamInfo.rtc" :command="streamInfo.rtc">  
113 - <el-tag >RTC:</el-tag>  
114 - <span>{{ streamInfo.rtc }}</span>  
115 - </el-dropdown-item>  
116 - <el-dropdown-item v-if="streamInfo.rtcs" :command="streamInfo.rtcs">  
117 - <el-tag >RTCS:</el-tag>  
118 - <span>{{ streamInfo.rtcs }}</span>  
119 - </el-dropdown-item>  
120 - <el-dropdown-item v-if="streamInfo.rtmp" :command="streamInfo.rtmp">  
121 - <el-tag >RTMP:</el-tag>  
122 - <span>{{ streamInfo.rtmp }}</span>  
123 - </el-dropdown-item>  
124 - <el-dropdown-item v-if="streamInfo.rtmps" :command="streamInfo.rtmps">  
125 - <el-tag >RTMPS:</el-tag>  
126 - <span>{{ streamInfo.rtmps }}</span>  
127 - </el-dropdown-item>  
128 - <el-dropdown-item v-if="streamInfo.rtsp" :command="streamInfo.rtsp">  
129 - <el-tag >RTSP:</el-tag>  
130 - <span>{{ streamInfo.rtsp }}</span>  
131 - </el-dropdown-item>  
132 - <el-dropdown-item v-if="streamInfo.rtsps" :command="streamInfo.rtsps">  
133 - <el-tag >RTSPS:</el-tag>  
134 - <span>{{ streamInfo.rtsps }}</span>  
135 - </el-dropdown-item>  
136 - </el-dropdown-menu>  
137 - </el-dropdown>  
138 - </el-input>  
139 -  
140 - </div>  
141 - </el-tab-pane>  
142 - <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->  
143 - <!--遥控界面-->  
144 - <el-tab-pane label="云台控制" name="control" v-if="showPtz">  
145 - <div style="display: flex; justify-content: left;">  
146 - <div class="control-wrapper">  
147 - <div class="control-btn control-top" @mousedown="ptzCamera('up')" @mouseup="ptzCamera('stop')">  
148 - <i class="el-icon-caret-top"></i>  
149 - <div class="control-inner-btn control-inner"></div>  
150 - </div>  
151 - <div class="control-btn control-left" @mousedown="ptzCamera('left')" @mouseup="ptzCamera('stop')">  
152 - <i class="el-icon-caret-left"></i>  
153 - <div class="control-inner-btn control-inner"></div>  
154 - </div>  
155 - <div class="control-btn control-bottom" @mousedown="ptzCamera('down')" @mouseup="ptzCamera('stop')">  
156 - <i class="el-icon-caret-bottom"></i>  
157 - <div class="control-inner-btn control-inner"></div>  
158 - </div>  
159 - <div class="control-btn control-right" @mousedown="ptzCamera('right')" @mouseup="ptzCamera('stop')">  
160 - <i class="el-icon-caret-right"></i>  
161 - <div class="control-inner-btn control-inner"></div>  
162 - </div>  
163 - <div class="control-round">  
164 - <div class="control-round-inner"><i class="fa fa-pause-circle"></i></div>  
165 - </div>  
166 - <div style="position: absolute; left: 7.25rem; top: 1.25rem" @mousedown="ptzCamera('zoomin')" @mouseup="ptzCamera('stop')"><i class="el-icon-zoom-in control-zoom-btn" style="font-size: 1.875rem;"></i></div>  
167 - <div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;" @mousedown="ptzCamera('zoomout')" @mouseup="ptzCamera('stop')"><i class="el-icon-zoom-out control-zoom-btn"></i></div>  
168 - <div class="contro-speed" style="position: absolute; left: 4px; top: 7rem; width: 9rem;">  
169 - <el-slider v-model="controSpeed" :max="255"></el-slider>  
170 - </div>  
171 - </div>  
172 -  
173 - <div class="control-panel">  
174 - <el-button-group>  
175 - <el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center" size="medium">预置位编号</el-tag>  
176 - <el-input-number style="position: absolute; left: 5rem; top: 0rem; width: 6rem" size="mini" v-model="presetPos" controls-position="right" :precision="0" :step="1" :min="1" :max="255"></el-input-number>  
177 - <el-button style="position: absolute; left: 11rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="presetPosition(129, presetPos)">设置</el-button>  
178 - <el-button style="position: absolute; left: 27rem; top: 0rem; width: 5rem" size="mini" type="primary" icon="el-icon-place" @click="presetPosition(130, presetPos)">调用</el-button>  
179 - <el-button style="position: absolute; left: 16rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="presetPosition(131, presetPos)">删除</el-button>  
180 - <el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">巡航速度</el-tag>  
181 - <el-input-number style="position: absolute; left: 5rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number>  
182 - <el-button style="position: absolute; left: 11rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(134, cruisingGroup, cruisingSpeed)">设置</el-button>  
183 - <el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">停留时间</el-tag>  
184 - <el-input-number style="position: absolute; left: 21rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingTime" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number>  
185 - <el-button style="position: absolute; left: 27rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-timer" @click="setSpeedOrTime(135, cruisingGroup, cruisingTime)">设置</el-button>  
186 - <el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center" size="medium">巡航组编号</el-tag>  
187 - <el-input-number style="position: absolute; left: 5rem; top: 4.5rem; width: 6rem" size="mini" v-model="cruisingGroup" controls-position="right" :precision="0" :min="0" :max="255"></el-input-number>  
188 - <el-button style="position: absolute; left: 11rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="setCommand(132, cruisingGroup, presetPos)">添加点</el-button>  
189 - <el-button style="position: absolute; left: 16rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="setCommand(133, cruisingGroup, presetPos)">删除点</el-button>  
190 - <el-button style="position: absolute; left: 21rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete" @click="setCommand(133, cruisingGroup, 0)">删除组</el-button>  
191 - <el-button style="position: absolute; left: 27rem; top: 5rem; width: 5rem" size="mini" type="primary" icon="el-icon-video-camera-solid" @click="setCommand(136, cruisingGroup, 0)">巡航</el-button>  
192 - <el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center" size="medium">扫描速度</el-tag>  
193 - <el-input-number style="position: absolute; left: 5rem; top: 7rem; width: 6rem" size="mini" v-model="scanSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number>  
194 - <el-button style="position: absolute; left: 11rem; top: 7rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(138, scanGroup, scanSpeed)">设置</el-button>  
195 - <el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center" size="medium">扫描组编号</el-tag>  
196 - <el-input-number style="position: absolute; left: 5rem; top: 9rem; width: 6rem" size="mini" v-model="scanGroup" controls-position="right" :precision="0" :step="1" :min="0" :max="255"></el-input-number>  
197 - <el-button style="position: absolute; left: 11rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-left" @click="setCommand(137, scanGroup, 1)">左边界</el-button>  
198 - <el-button style="position: absolute; left: 16rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-right" @click="setCommand(137, scanGroup, 2)">右边界</el-button>  
199 - <el-button style="position: absolute; left: 27rem; top: 7rem; width: 5rem" size="mini" type="primary" icon="el-icon-video-camera-solid" @click="setCommand(137, scanGroup, 0)">扫描</el-button>  
200 - <el-button style="position: absolute; left: 27rem; top: 9rem; width: 5rem" size="mini" type="danger" icon="el-icon-switch-button" @click="ptzCamera('stop')">停止</el-button>  
201 - </el-button-group>  
202 - </div>  
203 - </div>  
204 - </el-tab-pane>  
205 - <el-tab-pane label="编码信息" name="codec" v-loading="tracksLoading">  
206 - <p>  
207 - 无法播放或者没有声音?&nbsp&nbsp&nbsp试一试&nbsp  
208 - <el-button size="mini" type="primary" v-if="!coverPlaying" @click="coverPlay">转码播放</el-button>  
209 - <el-button size="mini" type="danger" v-if="coverPlaying" @click="convertStopClick">停止转码</el-button>  
210 - </p>  
211 - <div class="trank" >  
212 - <p v-if="tracksNotLoaded" style="text-align: center;padding-top: 3rem;">暂无数据</p>  
213 - <div v-for="(item, index) in tracks" style="width: 50%; float: left" loading>  
214 - <span >流 {{index}}</span>  
215 - <div class="trankInfo" v-if="item.codec_type == 0">  
216 - <p>格式: {{item.codec_id_name}}</p>  
217 - <p>类型: 视频</p>  
218 - <p>分辨率: {{item.width}} x {{item.height}}</p>  
219 - <p>帧率: {{item.fps}}</p>  
220 - </div>  
221 - <div class="trankInfo" v-if="item.codec_type == 1">  
222 - <p>格式: {{item.codec_id_name}}</p>  
223 - <p>类型: 音频</p>  
224 - <p>采样位数: {{item.sample_bit}}</p>  
225 - <p>采样率: {{item.sample_rate}}</p>  
226 - </div>  
227 - </div>  
228 -  
229 - </div>  
230 -  
231 - </el-tab-pane>  
232 - <el-tab-pane label="语音对讲" name="broadcast" >  
233 - <div class="trank" style="text-align: center;">  
234 - <el-button @click="broadcastStatusClick()" :type="getBroadcastStatus()" :disabled="broadcastStatus === -2" circle icon="el-icon-microphone" style="font-size: 32px; padding: 24px;margin-top: 24px;"/>  
235 - <p>  
236 - <span v-if="broadcastStatus === -2">正在释放资源</span>  
237 - <span v-if="broadcastStatus === -1">点击开始对讲</span>  
238 - <span v-if="broadcastStatus === 0">等待接通中...</span>  
239 - <span v-if="broadcastStatus === 1">请说话</span>  
240 - </p>  
241 - 29 + <div id="shared" style="text-align: right; margin-top: 1rem;">
  30 + <el-tabs v-model="tabActiveName" @tab-click="tabHandleClick">
  31 + <el-tab-pane label="实时视频" name="media">
  32 + <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
  33 + <span style="width: 5rem; line-height: 2.5rem; text-align: right;">播放地址:</span>
  34 + <el-input v-model="getPlayerShared.sharedUrl" :disabled="true">
  35 + <template slot="append">
  36 + <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedUrl"
  37 + @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
  38 + </template>
  39 + </el-input>
  40 + </div>
  41 + <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
  42 + <span style="width: 5rem; line-height: 2.5rem; text-align: right;">iframe:</span>
  43 + <el-input v-model="getPlayerShared.sharedIframe" :disabled="true">
  44 + <template slot="append">
  45 + <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedIframe"
  46 + @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
  47 + </template>
  48 + </el-input>
  49 + </div>
  50 + <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
  51 + <span style="width: 5rem; line-height: 2.5rem; text-align: right;">资源地址:</span>
  52 + <el-input v-model="getPlayerShared.sharedRtmp" :disabled="true">
  53 + <el-button slot="append" icon="el-icon-document-copy" title="点击拷贝"
  54 + v-clipboard="getPlayerShared.sharedRtmp"
  55 + @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
  56 + <el-dropdown slot="prepend" v-if="streamInfo" trigger="click" @command="copyUrl">
  57 + <el-button>
  58 + 更多地址<i class="el-icon-arrow-down el-icon--right"></i>
  59 + </el-button>
  60 + <el-dropdown-menu slot="dropdown">
  61 + <el-dropdown-item v-if="streamInfo.flv" :command="streamInfo.flv">
  62 + <el-tag>FLV:</el-tag>
  63 + <span>{{ streamInfo.flv }}</span>
  64 + </el-dropdown-item>
  65 + <el-dropdown-item v-if="streamInfo.https_flv" :command="streamInfo.https_flv">
  66 + <el-tag>FLV(https):</el-tag>
  67 + <span>{{ streamInfo.https_flv }}</span>
  68 + </el-dropdown-item>
  69 + <el-dropdown-item v-if="streamInfo.ws_flv" :command="streamInfo.ws_flv">
  70 + <el-tag>FLV(ws):</el-tag>
  71 + <span>{{ streamInfo.ws_flv }}</span>
  72 + </el-dropdown-item>
  73 + <el-dropdown-item v-if="streamInfo.wss_flv" :command="streamInfo.wss_flv">
  74 + <el-tag>FLV(wss):</el-tag>
  75 + <span>{{ streamInfo.wss_flv }}</span>
  76 + </el-dropdown-item>
  77 + <el-dropdown-item v-if="streamInfo.fmp4" :command="streamInfo.fmp4">
  78 + <el-tag>FMP4:</el-tag>
  79 + <span>{{ streamInfo.fmp4 }}</span>
  80 + </el-dropdown-item>
  81 + <el-dropdown-item v-if="streamInfo.https_fmp4" :command="streamInfo.https_fmp4">
  82 + <el-tag>FMP4(https):</el-tag>
  83 + <span>{{ streamInfo.https_fmp4 }}</span>
  84 + </el-dropdown-item>
  85 + <el-dropdown-item v-if="streamInfo.ws_fmp4" :command="streamInfo.ws_fmp4">
  86 + <el-tag>FMP4(ws):</el-tag>
  87 + <span>{{ streamInfo.ws_fmp4 }}</span>
  88 + </el-dropdown-item>
  89 + <el-dropdown-item v-if="streamInfo.wss_fmp4" :command="streamInfo.wss_fmp4">
  90 + <el-tag>FMP4(wss):</el-tag>
  91 + <span>{{ streamInfo.wss_fmp4 }}</span>
  92 + </el-dropdown-item>
  93 + <el-dropdown-item v-if="streamInfo.hls" :command="streamInfo.hls">
  94 + <el-tag>HLS:</el-tag>
  95 + <span>{{ streamInfo.hls }}</span>
  96 + </el-dropdown-item>
  97 + <el-dropdown-item v-if="streamInfo.https_hls" :command="streamInfo.https_hls">
  98 + <el-tag>HLS(https):</el-tag>
  99 + <span>{{ streamInfo.https_hls }}</span>
  100 + </el-dropdown-item>
  101 + <el-dropdown-item v-if="streamInfo.ws_hls" :command="streamInfo.ws_hls">
  102 + <el-tag>HLS(ws):</el-tag>
  103 + <span>{{ streamInfo.ws_hls }}</span>
  104 + </el-dropdown-item>
  105 + <el-dropdown-item v-if="streamInfo.wss_hls" :command="streamInfo.wss_hls">
  106 + <el-tag>HLS(wss):</el-tag>
  107 + <span>{{ streamInfo.wss_hls }}</span>
  108 + </el-dropdown-item>
  109 + <el-dropdown-item v-if="streamInfo.ts" :command="streamInfo.ts">
  110 + <el-tag>TS:</el-tag>
  111 + <span>{{ streamInfo.ts }}</span>
  112 + </el-dropdown-item>
  113 + <el-dropdown-item v-if="streamInfo.https_ts" :command="streamInfo.https_ts">
  114 + <el-tag>TS(https):</el-tag>
  115 + <span>{{ streamInfo.https_ts }}</span>
  116 + </el-dropdown-item>
  117 + <el-dropdown-item v-if="streamInfo.ws_ts" :command="streamInfo.ws_ts">
  118 + <el-tag>TS(ws):</el-tag>
  119 + <span>{{ streamInfo.ws_ts }}</span>
  120 + </el-dropdown-item>
  121 + <el-dropdown-item v-if="streamInfo.wss_ts" :command="streamInfo.wss_ts">
  122 + <el-tag>TS(wss):</el-tag>
  123 + <span>{{ streamInfo.wss_ts }}</span>
  124 + </el-dropdown-item>
  125 + <el-dropdown-item v-if="streamInfo.rtc" :command="streamInfo.rtc">
  126 + <el-tag>RTC:</el-tag>
  127 + <span>{{ streamInfo.rtc }}</span>
  128 + </el-dropdown-item>
  129 + <el-dropdown-item v-if="streamInfo.rtcs" :command="streamInfo.rtcs">
  130 + <el-tag>RTCS:</el-tag>
  131 + <span>{{ streamInfo.rtcs }}</span>
  132 + </el-dropdown-item>
  133 + <el-dropdown-item v-if="streamInfo.rtmp" :command="streamInfo.rtmp">
  134 + <el-tag>RTMP:</el-tag>
  135 + <span>{{ streamInfo.rtmp }}</span>
  136 + </el-dropdown-item>
  137 + <el-dropdown-item v-if="streamInfo.rtmps" :command="streamInfo.rtmps">
  138 + <el-tag>RTMPS:</el-tag>
  139 + <span>{{ streamInfo.rtmps }}</span>
  140 + </el-dropdown-item>
  141 + <el-dropdown-item v-if="streamInfo.rtsp" :command="streamInfo.rtsp">
  142 + <el-tag>RTSP:</el-tag>
  143 + <span>{{ streamInfo.rtsp }}</span>
  144 + </el-dropdown-item>
  145 + <el-dropdown-item v-if="streamInfo.rtsps" :command="streamInfo.rtsps">
  146 + <el-tag>RTSPS:</el-tag>
  147 + <span>{{ streamInfo.rtsps }}</span>
  148 + </el-dropdown-item>
  149 + </el-dropdown-menu>
  150 + </el-dropdown>
  151 + </el-input>
  152 +
  153 + </div>
  154 + </el-tab-pane>
  155 + <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->
  156 + <!--遥控界面-->
  157 + <el-tab-pane label="云台控制" name="control" v-if="showPtz">
  158 + <div style="display: flex; justify-content: left;">
  159 + <div class="control-wrapper">
  160 + <div class="control-btn control-top" @mousedown="ptzCamera('up')" @mouseup="ptzCamera('stop')">
  161 + <i class="el-icon-caret-top"></i>
  162 + <div class="control-inner-btn control-inner"></div>
  163 + </div>
  164 + <div class="control-btn control-left" @mousedown="ptzCamera('left')" @mouseup="ptzCamera('stop')">
  165 + <i class="el-icon-caret-left"></i>
  166 + <div class="control-inner-btn control-inner"></div>
  167 + </div>
  168 + <div class="control-btn control-bottom" @mousedown="ptzCamera('down')" @mouseup="ptzCamera('stop')">
  169 + <i class="el-icon-caret-bottom"></i>
  170 + <div class="control-inner-btn control-inner"></div>
  171 + </div>
  172 + <div class="control-btn control-right" @mousedown="ptzCamera('right')" @mouseup="ptzCamera('stop')">
  173 + <i class="el-icon-caret-right"></i>
  174 + <div class="control-inner-btn control-inner"></div>
  175 + </div>
  176 + <div class="control-round">
  177 + <div class="control-round-inner"><i class="fa fa-pause-circle"></i></div>
  178 + </div>
  179 + <div style="position: absolute; left: 7.25rem; top: 1.25rem" @mousedown="ptzCamera('zoomin')"
  180 + @mouseup="ptzCamera('stop')"><i class="el-icon-zoom-in control-zoom-btn"
  181 + style="font-size: 1.875rem;"></i></div>
  182 + <div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;"
  183 + @mousedown="ptzCamera('zoomout')" @mouseup="ptzCamera('stop')"><i
  184 + class="el-icon-zoom-out control-zoom-btn"></i></div>
  185 + <div class="contro-speed" style="position: absolute; left: 4px; top: 7rem; width: 9rem;">
  186 + <el-slider v-model="controSpeed" :max="255"></el-slider>
242 </div> 187 </div>
243 - </el-tab-pane> 188 + </div>
  189 +
  190 + <div class="control-panel">
  191 + <el-button-group>
  192 + <el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center"
  193 + size="medium">预置位编号
  194 + </el-tag>
  195 + <el-input-number style="position: absolute; left: 5rem; top: 0rem; width: 6rem" size="mini"
  196 + v-model="presetPos" controls-position="right" :precision="0" :step="1" :min="1"
  197 + :max="255"></el-input-number>
  198 + <el-button style="position: absolute; left: 11rem; top: 0rem; width: 5rem" size="mini"
  199 + icon="el-icon-add-location" @click="presetPosition(129, presetPos)">设置
  200 + </el-button>
  201 + <el-button style="position: absolute; left: 27rem; top: 0rem; width: 5rem" size="mini" type="primary"
  202 + icon="el-icon-place" @click="presetPosition(130, presetPos)">调用
  203 + </el-button>
  204 + <el-button style="position: absolute; left: 16rem; top: 0rem; width: 5rem" size="mini"
  205 + icon="el-icon-delete-location" @click="presetPosition(131, presetPos)">删除
  206 + </el-button>
  207 + <el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center"
  208 + size="medium">巡航速度
  209 + </el-tag>
  210 + <el-input-number style="position: absolute; left: 5rem; top: 2.5rem; width: 6rem" size="mini"
  211 + v-model="cruisingSpeed" controls-position="right" :precision="0" :min="1"
  212 + :max="4095"></el-input-number>
  213 + <el-button style="position: absolute; left: 11rem; top: 2.5rem; width: 5rem" size="mini"
  214 + icon="el-icon-loading" @click="setSpeedOrTime(134, cruisingGroup, cruisingSpeed)">设置
  215 + </el-button>
  216 + <el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center"
  217 + size="medium">停留时间
  218 + </el-tag>
  219 + <el-input-number style="position: absolute; left: 21rem; top: 2.5rem; width: 6rem" size="mini"
  220 + v-model="cruisingTime" controls-position="right" :precision="0" :min="1"
  221 + :max="4095"></el-input-number>
  222 + <el-button style="position: absolute; left: 27rem; top: 2.5rem; width: 5rem" size="mini"
  223 + icon="el-icon-timer" @click="setSpeedOrTime(135, cruisingGroup, cruisingTime)">设置
  224 + </el-button>
  225 + <el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center"
  226 + size="medium">巡航组编号
  227 + </el-tag>
  228 + <el-input-number style="position: absolute; left: 5rem; top: 4.5rem; width: 6rem" size="mini"
  229 + v-model="cruisingGroup" controls-position="right" :precision="0" :min="0"
  230 + :max="255"></el-input-number>
  231 + <el-button style="position: absolute; left: 11rem; top: 4.5rem; width: 5rem" size="mini"
  232 + icon="el-icon-add-location" @click="setCommand(132, cruisingGroup, presetPos)">添加点
  233 + </el-button>
  234 + <el-button style="position: absolute; left: 16rem; top: 4.5rem; width: 5rem" size="mini"
  235 + icon="el-icon-delete-location" @click="setCommand(133, cruisingGroup, presetPos)">删除点
  236 + </el-button>
  237 + <el-button style="position: absolute; left: 21rem; top: 4.5rem; width: 5rem" size="mini"
  238 + icon="el-icon-delete" @click="setCommand(133, cruisingGroup, 0)">删除组
  239 + </el-button>
  240 + <el-button style="position: absolute; left: 27rem; top: 5rem; width: 5rem" size="mini" type="primary"
  241 + icon="el-icon-video-camera-solid" @click="setCommand(136, cruisingGroup, 0)">巡航
  242 + </el-button>
  243 + <el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center"
  244 + size="medium">扫描速度
  245 + </el-tag>
  246 + <el-input-number style="position: absolute; left: 5rem; top: 7rem; width: 6rem" size="mini"
  247 + v-model="scanSpeed" controls-position="right" :precision="0" :min="1"
  248 + :max="4095"></el-input-number>
  249 + <el-button style="position: absolute; left: 11rem; top: 7rem; width: 5rem" size="mini"
  250 + icon="el-icon-loading" @click="setSpeedOrTime(138, scanGroup, scanSpeed)">设置
  251 + </el-button>
  252 + <el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center"
  253 + size="medium">扫描组编号
  254 + </el-tag>
  255 + <el-input-number style="position: absolute; left: 5rem; top: 9rem; width: 6rem" size="mini"
  256 + v-model="scanGroup" controls-position="right" :precision="0" :step="1" :min="0"
  257 + :max="255"></el-input-number>
  258 + <el-button style="position: absolute; left: 11rem; top: 9rem; width: 5rem" size="mini"
  259 + icon="el-icon-d-arrow-left" @click="setCommand(137, scanGroup, 1)">左边界
  260 + </el-button>
  261 + <el-button style="position: absolute; left: 16rem; top: 9rem; width: 5rem" size="mini"
  262 + icon="el-icon-d-arrow-right" @click="setCommand(137, scanGroup, 2)">右边界
  263 + </el-button>
  264 + <el-button style="position: absolute; left: 27rem; top: 7rem; width: 5rem" size="mini" type="primary"
  265 + icon="el-icon-video-camera-solid" @click="setCommand(137, scanGroup, 0)">扫描
  266 + </el-button>
  267 + <el-button style="position: absolute; left: 27rem; top: 9rem; width: 5rem" size="mini" type="danger"
  268 + icon="el-icon-switch-button" @click="ptzCamera('stop')">停止
  269 + </el-button>
  270 + </el-button-group>
  271 + </div>
  272 + </div>
  273 + </el-tab-pane>
  274 + <el-tab-pane label="编码信息" name="codec" v-loading="tracksLoading">
  275 + <p>
  276 + 无法播放或者没有声音?&nbsp&nbsp&nbsp试一试&nbsp
  277 + <el-button size="mini" type="primary" v-if="!coverPlaying" @click="coverPlay">转码播放</el-button>
  278 + <el-button size="mini" type="danger" v-if="coverPlaying" @click="convertStopClick">停止转码</el-button>
  279 + </p>
  280 + <div class="trank">
  281 + <p v-if="tracksNotLoaded" style="text-align: center;padding-top: 3rem;">暂无数据</p>
  282 + <div v-for="(item, index) in tracks" style="width: 50%; float: left" loading>
  283 + <span>流 {{ index }}</span>
  284 + <div class="trankInfo" v-if="item.codec_type == 0">
  285 + <p>格式: {{ item.codec_id_name }}</p>
  286 + <p>类型: 视频</p>
  287 + <p>分辨率: {{ item.width }} x {{ item.height }}</p>
  288 + <p>帧率: {{ item.fps }}</p>
  289 + </div>
  290 + <div class="trankInfo" v-if="item.codec_type == 1">
  291 + <p>格式: {{ item.codec_id_name }}</p>
  292 + <p>类型: 音频</p>
  293 + <p>采样位数: {{ item.sample_bit }}</p>
  294 + <p>采样率: {{ item.sample_rate }}</p>
  295 + </div>
  296 + </div>
  297 +
  298 + </div>
  299 +
  300 + </el-tab-pane>
  301 + <el-tab-pane label="语音对讲" name="broadcast">
  302 + <div class="trank" style="text-align: center;">
  303 + <el-button @click="broadcastStatusClick()" :type="getBroadcastStatus()" :disabled="broadcastStatus === -2"
  304 + circle icon="el-icon-microphone" style="font-size: 32px; padding: 24px;margin-top: 24px;"/>
  305 + <p>
  306 + <span v-if="broadcastStatus === -2">正在释放资源</span>
  307 + <span v-if="broadcastStatus === -1">点击开始对讲</span>
  308 + <span v-if="broadcastStatus === 0">等待接通中...</span>
  309 + <span v-if="broadcastStatus === 1">请说话</span>
  310 + </p>
  311 +
  312 + </div>
  313 + </el-tab-pane>
244 314
245 - </el-tabs>  
246 - </div> 315 + </el-tabs>
  316 + </div>
247 </el-dialog> 317 </el-dialog>
248 -</div> 318 + </div>
249 </template> 319 </template>
250 320
251 <script> 321 <script>
@@ -253,561 +323,620 @@ import rtcPlayer from &#39;../dialog/rtcPlayer.vue&#39; @@ -253,561 +323,620 @@ import rtcPlayer from &#39;../dialog/rtcPlayer.vue&#39;
253 import LivePlayer from '@liveqing/liveplayer' 323 import LivePlayer from '@liveqing/liveplayer'
254 import crypto from 'crypto' 324 import crypto from 'crypto'
255 import jessibucaPlayer from '../common/jessibuca.vue' 325 import jessibucaPlayer from '../common/jessibuca.vue'
  326 +
256 export default { 327 export default {
257 - name: 'devicePlayer',  
258 - props: {},  
259 - components: {  
260 - LivePlayer, jessibucaPlayer, rtcPlayer, 328 + name: 'devicePlayer',
  329 + props: {},
  330 + components: {
  331 + LivePlayer, jessibucaPlayer, rtcPlayer,
  332 + },
  333 + computed: {
  334 + getPlayerShared: function () {
  335 + return {
  336 + sharedUrl: window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl),
  337 + sharedIframe: '<iframe src="' + window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl) + '"></iframe>',
  338 + sharedRtmp: this.videoUrl
  339 + };
  340 + }
  341 + },
  342 + created() {
  343 + console.log("created")
  344 + console.log(this.player)
  345 + this.broadcastStatus = -1;
  346 + if (Object.keys(this.player).length === 1) {
  347 + this.activePlayer = Object.keys(this.player)[0]
  348 + }
  349 + },
  350 + data() {
  351 + return {
  352 + video: 'http://lndxyj.iqilu.com/public/upload/2019/10/14/8c001ea0c09cdc59a57829dabc8010fa.mp4',
  353 + videoUrl: '',
  354 + activePlayer: "jessibuca",
  355 + // 如何你只是用一种播放器,直接注释掉不用的部分即可
  356 + player: {
  357 + jessibuca: ["ws_flv", "wss_flv"],
  358 + webRTC: ["rtc", "rtcs"],
  359 + },
  360 + showVideoDialog: false,
  361 + streamId: '',
  362 + app: '',
  363 + mediaServerId: '',
  364 + convertKey: '',
  365 + deviceId: '',
  366 + channelId: '',
  367 + tabActiveName: 'media',
  368 + hasAudio: false,
  369 + loadingRecords: false,
  370 + recordsLoading: false,
  371 + isLoging: false,
  372 + controSpeed: 30,
  373 + timeVal: 0,
  374 + timeMin: 0,
  375 + timeMax: 1440,
  376 + presetPos: 1,
  377 + cruisingSpeed: 100,
  378 + cruisingTime: 5,
  379 + cruisingGroup: 0,
  380 + scanSpeed: 100,
  381 + scanGroup: 0,
  382 + tracks: [],
  383 + coverPlaying: false,
  384 + tracksLoading: false,
  385 + showPtz: true,
  386 + showRrecord: true,
  387 + tracksNotLoaded: false,
  388 + sliderTime: 0,
  389 + seekTime: 0,
  390 + recordStartTime: 0,
  391 + showTimeText: "00:00:00",
  392 + streamInfo: null,
  393 + broadcastRtc: null,
  394 + broadcastStatus: -1, // -2 正在释放资源 -1 默认状态 0 等待接通 1 接通成功
  395 + };
  396 + },
  397 + methods: {
  398 + tabHandleClick: function (tab, event) {
  399 + console.log(tab)
  400 + var that = this;
  401 + that.tracks = [];
  402 + that.tracksLoading = true;
  403 + that.tracksNotLoaded = false;
  404 + if (tab.name === "codec") {
  405 + this.$axios({
  406 + method: 'get',
  407 + url: '/zlm/' + this.mediaServerId + '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtsp&app=' + this.app + '&stream=' + this.streamId
  408 + }).then(function (res) {
  409 + that.tracksLoading = false;
  410 + if (res.data.code == 0 && res.data.tracks) {
  411 + that.tracks = res.data.tracks;
  412 + } else {
  413 + that.tracksNotLoaded = true;
  414 + that.$message({
  415 + showClose: true,
  416 + message: '获取编码信息失败,',
  417 + type: 'warning'
  418 + });
  419 + }
  420 + }).catch(function (e) {
  421 + });
  422 + }
261 }, 423 },
262 - computed: {  
263 - getPlayerShared: function () {  
264 - return {  
265 - sharedUrl: window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl),  
266 - sharedIframe: '<iframe src="' + window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl) + '"></iframe>',  
267 - sharedRtmp: this.videoUrl  
268 - };  
269 - } 424 + changePlayer: function (tab) {
  425 + console.log(this.player[tab.name][0])
  426 + this.activePlayer = tab.name;
  427 + this.videoUrl = this.getUrlByStreamInfo()
  428 + console.log(this.videoUrl)
270 }, 429 },
271 - created() {  
272 - console.log("created")  
273 - console.log(this.player)  
274 - this.broadcastStatus = -1;  
275 - if (Object.keys(this.player).length === 1) {  
276 - this.activePlayer = Object.keys(this.player)[0] 430 + openDialog: function (tab, deviceId, channelId, param) {
  431 + if (this.showVideoDialog) {
  432 + return;
  433 + }
  434 + this.tabActiveName = tab;
  435 + this.channelId = channelId;
  436 + this.deviceId = deviceId;
  437 + this.streamId = "";
  438 + this.mediaServerId = "";
  439 + this.app = "";
  440 + this.videoUrl = ""
  441 + if (!!this.$refs[this.activePlayer]) {
  442 + this.$refs[this.activePlayer].pause();
  443 + }
  444 + switch (tab) {
  445 + case "media":
  446 + this.play(param.streamInfo, param.hasAudio)
  447 + break;
  448 + case "streamPlay":
  449 + this.tabActiveName = "media";
  450 + this.showRrecord = false;
  451 + this.showPtz = false;
  452 + this.play(param.streamInfo, param.hasAudio)
  453 + break;
  454 + case "control":
  455 + break;
277 } 456 }
278 }, 457 },
279 - data() {  
280 - return {  
281 - video: 'http://lndxyj.iqilu.com/public/upload/2019/10/14/8c001ea0c09cdc59a57829dabc8010fa.mp4',  
282 - videoUrl: '',  
283 - activePlayer: "jessibuca",  
284 - // 如何你只是用一种播放器,直接注释掉不用的部分即可  
285 - player: {  
286 - jessibuca : ["ws_flv", "wss_flv"],  
287 - webRTC: ["rtc", "rtcs"],  
288 - },  
289 - showVideoDialog: false,  
290 - streamId: '',  
291 - app : '',  
292 - mediaServerId : '',  
293 - convertKey: '',  
294 - deviceId: '',  
295 - channelId: '',  
296 - tabActiveName: 'media',  
297 - hasAudio: false,  
298 - loadingRecords: false,  
299 - recordsLoading: false,  
300 - isLoging: false,  
301 - controSpeed: 30,  
302 - timeVal: 0,  
303 - timeMin: 0,  
304 - timeMax: 1440,  
305 - presetPos: 1,  
306 - cruisingSpeed: 100,  
307 - cruisingTime: 5,  
308 - cruisingGroup: 0,  
309 - scanSpeed: 100,  
310 - scanGroup: 0,  
311 - tracks: [],  
312 - coverPlaying:false,  
313 - tracksLoading: false,  
314 - showPtz: true,  
315 - showRrecord: true,  
316 - tracksNotLoaded: false,  
317 - sliderTime: 0,  
318 - seekTime: 0,  
319 - recordStartTime: 0,  
320 - showTimeText: "00:00:00",  
321 - streamInfo: null,  
322 - broadcastRtc: null,  
323 - broadcastStatus: -1, // -2 正在释放资源 -1 默认状态 0 等待接通 1 接通成功  
324 - }; 458 + play: function (streamInfo, hasAudio) {
  459 + this.streamInfo = streamInfo;
  460 + this.hasAudio = hasAudio;
  461 + this.isLoging = false;
  462 + // this.videoUrl = streamInfo.rtc;
  463 + this.videoUrl = this.getUrlByStreamInfo();
  464 + this.streamId = streamInfo.stream;
  465 + this.app = streamInfo.app;
  466 + this.mediaServerId = streamInfo.mediaServerId;
  467 + this.playFromStreamInfo(false, streamInfo)
325 }, 468 },
326 - methods: {  
327 - tabHandleClick: function(tab, event) {  
328 - console.log(tab)  
329 - var that = this;  
330 - that.tracks = [];  
331 - that.tracksLoading = true;  
332 - that.tracksNotLoaded = false;  
333 - if (tab.name === "codec") {  
334 - this.$axios({  
335 - method: 'get',  
336 - url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtsp&app='+ this.app +'&stream='+ this.streamId  
337 - }).then(function (res) {  
338 - that.tracksLoading = false;  
339 - if (res.data.code == 0 && res.data.tracks) {  
340 - that.tracks = res.data.tracks;  
341 - }else{  
342 - that.tracksNotLoaded = true;  
343 - that.$message({  
344 - showClose: true,  
345 - message: '获取编码信息失败,',  
346 - type: 'warning'  
347 - });  
348 - }  
349 - }).catch(function (e) {});  
350 - }  
351 - },  
352 - changePlayer: function (tab) {  
353 - console.log(this.player[tab.name][0])  
354 - this.activePlayer = tab.name;  
355 - this.videoUrl = this.getUrlByStreamInfo()  
356 - console.log(this.videoUrl)  
357 - },  
358 - openDialog: function (tab, deviceId, channelId, param) {  
359 - if (this.showVideoDialog) {  
360 - return;  
361 - }  
362 - this.tabActiveName = tab;  
363 - this.channelId = channelId;  
364 - this.deviceId = deviceId;  
365 - this.streamId = "";  
366 - this.mediaServerId = "";  
367 - this.app = "";  
368 - this.videoUrl = ""  
369 - if (!!this.$refs[this.activePlayer]) {  
370 - this.$refs[this.activePlayer].pause();  
371 - }  
372 - switch (tab) {  
373 - case "media":  
374 - this.play(param.streamInfo, param.hasAudio)  
375 - break;  
376 - case "streamPlay":  
377 - this.tabActiveName = "media";  
378 - this.showRrecord = false;  
379 - this.showPtz = false;  
380 - this.play(param.streamInfo, param.hasAudio)  
381 - break;  
382 - case "control":  
383 - break;  
384 - }  
385 - },  
386 - play: function (streamInfo, hasAudio) {  
387 - this.streamInfo = streamInfo;  
388 - this.hasAudio = hasAudio;  
389 - this.isLoging = false;  
390 - // this.videoUrl = streamInfo.rtc;  
391 - this.videoUrl = this.getUrlByStreamInfo();  
392 - this.streamId = streamInfo.stream;  
393 - this.app = streamInfo.app;  
394 - this.mediaServerId = streamInfo.mediaServerId;  
395 - this.playFromStreamInfo(false, streamInfo)  
396 - },  
397 - getUrlByStreamInfo(){  
398 - console.log(this.streamInfo)  
399 - if (location.protocol === "https:") {  
400 - this.videoUrl = this.streamInfo[this.player[this.activePlayer][1]]  
401 - }else {  
402 - this.videoUrl = this.streamInfo[this.player[this.activePlayer][0]]  
403 - }  
404 - return this.videoUrl; 469 + getUrlByStreamInfo() {
  470 + console.log(this.streamInfo)
  471 + if (location.protocol === "https:") {
  472 + this.videoUrl = this.streamInfo[this.player[this.activePlayer][1]]
  473 + } else {
  474 + this.videoUrl = this.streamInfo[this.player[this.activePlayer][0]]
  475 + }
  476 + return this.videoUrl;
405 477
406 - },  
407 - coverPlay: function () {  
408 - var that = this;  
409 - this.coverPlaying = true;  
410 - this.$refs[this.activePlayer].pause()  
411 - that.$axios({  
412 - method: 'post',  
413 - url: '/api/play/convert/' + that.streamId  
414 - }).then(function (res) {  
415 - if (res.data.code === 0) {  
416 - that.convertKey = res.data.key;  
417 - setTimeout(()=>{  
418 - that.isLoging = false;  
419 - that.playFromStreamInfo(false, res.data.data);  
420 - }, 2000)  
421 - } else {  
422 - that.isLoging = false;  
423 - that.coverPlaying = false;  
424 - that.$message({  
425 - showClose: true,  
426 - message: '转码失败',  
427 - type: 'error'  
428 - });  
429 - }  
430 - }).catch(function (e) {  
431 - console.log(e)  
432 - that.coverPlaying = false;  
433 - that.$message({  
434 - showClose: true,  
435 - message: '播放错误',  
436 - type: 'error'  
437 - });  
438 - });  
439 - },  
440 - convertStopClick: function() {  
441 - this.convertStop(()=>{  
442 - this.$refs[this.activePlayer].play(this.videoUrl)  
443 - });  
444 - },  
445 - convertStop: function(callback) {  
446 - var that = this;  
447 - that.$refs.videoPlayer.pause()  
448 - this.$axios({  
449 - method: 'post',  
450 - url: '/api/play/convertStop/' + this.convertKey  
451 - }).then(function (res) {  
452 - if (res.data.code == 0) {  
453 - console.log(res.data.msg)  
454 - }else {  
455 - console.error(res.data.msg)  
456 - }  
457 - if (callback )callback();  
458 - }).catch(function (e) {});  
459 - that.coverPlaying = false;  
460 - that.convertKey = "";  
461 - // if (callback )callback();  
462 - }, 478 + },
  479 + coverPlay: function () {
  480 + var that = this;
  481 + this.coverPlaying = true;
  482 + this.$refs[this.activePlayer].pause()
  483 + that.$axios({
  484 + method: 'post',
  485 + url: '/api/play/convert/' + that.streamId
  486 + }).then(function (res) {
  487 + if (res.data.code === 0) {
  488 + that.convertKey = res.data.key;
  489 + setTimeout(() => {
  490 + that.isLoging = false;
  491 + that.playFromStreamInfo(false, res.data.data);
  492 + }, 2000)
  493 + } else {
  494 + that.isLoging = false;
  495 + that.coverPlaying = false;
  496 + that.$message({
  497 + showClose: true,
  498 + message: '转码失败',
  499 + type: 'error'
  500 + });
  501 + }
  502 + }).catch(function (e) {
  503 + console.log(e)
  504 + that.coverPlaying = false;
  505 + that.$message({
  506 + showClose: true,
  507 + message: '播放错误',
  508 + type: 'error'
  509 + });
  510 + });
  511 + },
  512 + convertStopClick: function () {
  513 + this.convertStop(() => {
  514 + this.$refs[this.activePlayer].play(this.videoUrl)
  515 + });
  516 + },
  517 + convertStop: function (callback) {
  518 + var that = this;
  519 + that.$refs.videoPlayer.pause()
  520 + this.$axios({
  521 + method: 'post',
  522 + url: '/api/play/convertStop/' + this.convertKey
  523 + }).then(function (res) {
  524 + if (res.data.code == 0) {
  525 + console.log(res.data.msg)
  526 + } else {
  527 + console.error(res.data.msg)
  528 + }
  529 + if (callback) callback();
  530 + }).catch(function (e) {
  531 + });
  532 + that.coverPlaying = false;
  533 + that.convertKey = "";
  534 + // if (callback )callback();
  535 + },
463 536
464 - playFromStreamInfo: function (realHasAudio, streamInfo) {  
465 - this.showVideoDialog = true;  
466 - this.hasaudio = realHasAudio && this.hasaudio;  
467 - this.$refs[this.activePlayer].play(this.getUrlByStreamInfo(streamInfo))  
468 - },  
469 - close: function () {  
470 - console.log('关闭视频');  
471 - if (!!this.$refs[this.activePlayer]){  
472 - this.$refs[this.activePlayer].pause();  
473 - }  
474 - this.videoUrl = '';  
475 - this.coverPlaying = false;  
476 - this.showVideoDialog = false;  
477 - if (this.convertKey != '') {  
478 - this.convertStop();  
479 - }  
480 - this.convertKey = ''  
481 - this.stopBroadcast()  
482 - }, 537 + playFromStreamInfo: function (realHasAudio, streamInfo) {
  538 + this.showVideoDialog = true;
  539 + this.hasaudio = realHasAudio && this.hasaudio;
  540 + this.$refs[this.activePlayer].play(this.getUrlByStreamInfo(streamInfo))
  541 + },
  542 + close: function () {
  543 + console.log('关闭视频');
  544 + if (!!this.$refs[this.activePlayer]) {
  545 + this.$refs[this.activePlayer].pause();
  546 + }
  547 + this.videoUrl = '';
  548 + this.coverPlaying = false;
  549 + this.showVideoDialog = false;
  550 + if (this.convertKey != '') {
  551 + this.convertStop();
  552 + }
  553 + this.convertKey = ''
  554 + this.stopBroadcast()
  555 + },
483 556
484 - copySharedInfo: function (data) {  
485 - console.log('复制内容:' + data);  
486 - this.coverPlaying = false;  
487 - this.tracks = []  
488 - let _this = this;  
489 - this.$copyText(data).then(  
490 - function (e) {  
491 - _this.$message({  
492 - showClose: true,  
493 - message: '复制成功',  
494 - type: 'success'  
495 - });  
496 - },  
497 - function (e) {  
498 - _this.$message({  
499 - showClose: true,  
500 - message: '复制失败,请手动复制',  
501 - type: 'error'  
502 - });  
503 - }  
504 - );  
505 - },  
506 - ptzCamera: function (command) {  
507 - console.log('云台控制:' + command);  
508 - let that = this;  
509 - this.$axios({  
510 - method: 'post',  
511 - url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed  
512 - }).then(function (res) {});  
513 - },  
514 - //////////////////////播放器事件处理//////////////////////////  
515 - videoError: function (e) {  
516 - console.log("播放器错误:" + JSON.stringify(e));  
517 - },  
518 - presetPosition: function (cmdCode, presetPos) {  
519 - console.log('预置位控制:' + this.presetPos + ' : 0x' + cmdCode.toString(16));  
520 - let that = this;  
521 - this.$axios({  
522 - method: 'post',  
523 - url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=0&parameter2=' + presetPos + '&combindCode2=0'  
524 - }).then(function (res) {});  
525 - },  
526 - setSpeedOrTime: function (cmdCode, groupNum, parameter) {  
527 - let that = this;  
528 - let parameter2 = parameter % 256;  
529 - let combindCode2 = Math.floor(parameter / 256) * 16;  
530 - console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter2.toString(16) + ' 0x' + combindCode2.toString(16));  
531 - this.$axios({  
532 - method: 'post',  
533 - url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=' + groupNum + '&parameter2=' + parameter2 + '&combindCode2=' + combindCode2  
534 - }).then(function (res) {});  
535 - },  
536 - setCommand: function (cmdCode, groupNum, parameter) {  
537 - let that = this;  
538 - console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter.toString(16) + ' 0x0');  
539 - this.$axios({  
540 - method: 'post',  
541 - url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=' + groupNum + '&parameter2=' + parameter + '&combindCode2=0'  
542 - }).then(function (res) {}); 557 + copySharedInfo: function (data) {
  558 + console.log('复制内容:' + data);
  559 + this.coverPlaying = false;
  560 + this.tracks = []
  561 + let _this = this;
  562 + this.$copyText(data).then(
  563 + function (e) {
  564 + _this.$message({
  565 + showClose: true,
  566 + message: '复制成功',
  567 + type: 'success'
  568 + });
543 }, 569 },
544 - copyUrl: function (dropdownItem){  
545 - console.log(dropdownItem)  
546 - this.$copyText(dropdownItem).then((e)=> {  
547 - this.$message.success("成功拷贝到粘贴板");  
548 - }, (e)=> { 570 + function (e) {
  571 + _this.$message({
  572 + showClose: true,
  573 + message: '复制失败,请手动复制',
  574 + type: 'error'
  575 + });
  576 + }
  577 + );
  578 + },
  579 + ptzCamera: function (command) {
  580 + console.log('云台控制:' + command);
  581 + let that = this;
  582 + this.$axios({
  583 + method: 'post',
  584 + url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed
  585 + }).then(function (res) {
  586 + });
  587 + },
  588 + //////////////////////播放器事件处理//////////////////////////
  589 + videoError: function (e) {
  590 + console.log("播放器错误:" + JSON.stringify(e));
  591 + },
  592 + presetPosition: function (cmdCode, presetPos) {
  593 + console.log('预置位控制:' + this.presetPos + ' : 0x' + cmdCode.toString(16));
  594 + let that = this;
  595 + this.$axios({
  596 + method: 'post',
  597 + url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=0&parameter2=' + presetPos + '&combindCode2=0'
  598 + }).then(function (res) {
  599 + });
  600 + },
  601 + setSpeedOrTime: function (cmdCode, groupNum, parameter) {
  602 + let that = this;
  603 + let parameter2 = parameter % 256;
  604 + let combindCode2 = Math.floor(parameter / 256) * 16;
  605 + console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter2.toString(16) + ' 0x' + combindCode2.toString(16));
  606 + this.$axios({
  607 + method: 'post',
  608 + url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=' + groupNum + '&parameter2=' + parameter2 + '&combindCode2=' + combindCode2
  609 + }).then(function (res) {
  610 + });
  611 + },
  612 + setCommand: function (cmdCode, groupNum, parameter) {
  613 + let that = this;
  614 + console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter.toString(16) + ' 0x0');
  615 + this.$axios({
  616 + method: 'post',
  617 + url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=' + groupNum + '&parameter2=' + parameter + '&combindCode2=0'
  618 + }).then(function (res) {
  619 + });
  620 + },
  621 + copyUrl: function (dropdownItem) {
  622 + console.log(dropdownItem)
  623 + this.$copyText(dropdownItem).then((e) => {
  624 + this.$message.success("成功拷贝到粘贴板");
  625 + }, (e) => {
549 626
550 - })  
551 - }, 627 + })
  628 + },
  629 + startBroadcast(url) {
  630 + // 获取推流鉴权Key
  631 + this.$axios({
  632 + method: 'post',
  633 + url: '/api/user/userInfo',
  634 + }).then((res) => {
  635 + if (res.data.code !== 0) {
  636 + this.$message({
  637 + showClose: true,
  638 + message: "获取推流鉴权Key失败",
  639 + type: "error",
  640 + });
  641 + this.broadcastStatus = -1;
  642 + } else {
  643 + let pushKey = res.data.data.pushKey;
  644 + // 获取推流鉴权KEY
  645 + url += "&sign=" + crypto.createHash('md5').update(pushKey, "utf8").digest('hex')
  646 + console.log("开始语音对讲: " + url)
  647 + this.broadcastRtc = new ZLMRTCClient.Endpoint({
  648 + debug: true, // 是否打印日志
  649 + zlmsdpUrl: url, //流地址
  650 + simulecast: false,
  651 + useCamera: false,
  652 + audioEnable: true,
  653 + videoEnable: false,
  654 + recvOnly: false,
  655 + })
  656 +
  657 + // webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_REMOTE_STREAMS,(e)=>{//获取到了远端流,可以播放
  658 + // console.error('播放成功',e.streams)
  659 + // this.broadcastStatus = 1;
  660 + // });
  661 + //
  662 + // webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_LOCAL_STREAM,(s)=>{// 获取到了本地流
  663 + // this.broadcastStatus = 1;
  664 + // // document.getElementById('selfVideo').srcObject=s;
  665 + // // this.eventcallbacK("LOCAL STREAM", "获取到了本地流")
  666 + // });
  667 +
  668 + this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_NOT_SUPPORT, (e) => {// 获取到了本地流
  669 + console.error('不支持webrtc', e)
  670 + this.$message({
  671 + showClose: true,
  672 + message: '不支持webrtc, 无法进行语音对讲',
  673 + type: 'error'
  674 + });
  675 + this.broadcastStatus = -1;
  676 + });
552 677
  678 + this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR, (e) => {// ICE 协商出错
  679 + console.error('ICE 协商出错')
  680 + this.$message({
  681 + showClose: true,
  682 + message: 'ICE 协商出错',
  683 + type: 'error'
  684 + });
  685 + this.broadcastStatus = -1;
  686 + });
553 687
554 - this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR,(e)=>{// ICE 协商出错  
555 - console.error('ICE 协商出错')  
556 - this.$message({  
557 - showClose: true,  
558 - message: 'ICE 协商出错',  
559 - type: 'error'  
560 - });  
561 - this.broadcastStatus = -1;  
562 - });  
563 -  
564 - this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED,(e)=>{// offer anwser 交换失败  
565 - console.error('offer anwser 交换失败',e)  
566 - this.$message({  
567 - showClose: true,  
568 - message: 'offer anwser 交换失败' + e,  
569 - type: 'error'  
570 - });  
571 - this.broadcastStatus = -1;  
572 - });  
573 - this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_ON_CONNECTION_STATE_CHANGE,(e)=>{// offer anwser 交换失败  
574 - console.log('状态改变',e)  
575 - if (e === "connecting") {  
576 - this.broadcastStatus = 0;  
577 - }else if (e === "connected") {  
578 - this.broadcastStatus = 1;  
579 - }else if (e === "disconnected") {  
580 - this.broadcastStatus = -1;  
581 - }  
582 - });  
583 - this.broadcastRtc.on(ZLMRTCClient.Events.CAPTURE_STREAM_FAILED,(e)=>{// offer anwser 交换失败  
584 - console.log('捕获流失败',e)  
585 - this.$message({  
586 - showClose: true,  
587 - message: '捕获流失败' + e,  
588 - type: 'error'  
589 - });  
590 - this.broadcastStatus = -1;  
591 - }); 688 + this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED, (e) => {// offer anwser 交换失败
  689 + console.error('offer anwser 交换失败', e)
  690 + this.$message({
  691 + showClose: true,
  692 + message: 'offer anwser 交换失败' + e,
  693 + type: 'error'
  694 + });
  695 + this.broadcastStatus = -1;
  696 + });
  697 + this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_ON_CONNECTION_STATE_CHANGE, (e) => {// offer anwser 交换失败
  698 + console.log('状态改变', e)
  699 + if (e === "connecting") {
  700 + this.broadcastStatus = 0;
  701 + } else if (e === "connected") {
  702 + this.broadcastStatus = 1;
  703 + } else if (e === "disconnected") {
  704 + this.broadcastStatus = -1;
592 } 705 }
593 - }).catch((e) => { 706 + });
  707 + this.broadcastRtc.on(ZLMRTCClient.Events.CAPTURE_STREAM_FAILED, (e) => {// offer anwser 交换失败
  708 + console.log('捕获流失败', e)
594 this.$message({ 709 this.$message({
595 showClose: true, 710 showClose: true,
596 - message: e, 711 + message: '捕获流失败' + e,
597 type: 'error' 712 type: 'error'
598 }); 713 });
599 this.broadcastStatus = -1; 714 this.broadcastStatus = -1;
600 }); 715 });
  716 + }
  717 + }).catch((e) => {
  718 + this.$message({
  719 + showClose: true,
  720 + message: e,
  721 + type: 'error'
  722 + });
  723 + this.broadcastStatus = -1;
  724 + });
601 725
602 726
603 - },  
604 - stopBroadcast(){  
605 - this.broadcastRtc.close();  
606 - this.broadcastStatus = -1;  
607 - this.$axios({  
608 - method: 'get',  
609 - url: '/api/play/broadcast/stop/' + this.deviceId + '/' + this.channelId  
610 - }).then( (res)=> {  
611 - if (res.data.code == 0) {  
612 - // this.broadcastStatus = -1;  
613 - // this.broadcastRtc.close()  
614 - }else {  
615 - this.$message({  
616 - showClose: true,  
617 - message: res.data.msg,  
618 - type: "error",  
619 - });  
620 - } 727 + },
  728 + stopBroadcast() {
  729 + this.broadcastRtc.close();
  730 + this.broadcastStatus = -1;
  731 + this.$axios({
  732 + method: 'get',
  733 + url: '/api/play/broadcast/stop/' + this.deviceId + '/' + this.channelId
  734 + }).then((res) => {
  735 + if (res.data.code == 0) {
  736 + // this.broadcastStatus = -1;
  737 + // this.broadcastRtc.close()
  738 + } else {
  739 + this.$message({
  740 + showClose: true,
  741 + message: res.data.msg,
  742 + type: "error",
621 }); 743 });
622 } 744 }
  745 + });
623 } 746 }
  747 + }
624 }; 748 };
625 </script> 749 </script>
626 750
627 <style> 751 <style>
628 .control-wrapper { 752 .control-wrapper {
629 - position: relative;  
630 - width: 6.25rem;  
631 - height: 6.25rem;  
632 - max-width: 6.25rem;  
633 - max-height: 6.25rem;  
634 - border-radius: 100%;  
635 - margin-top: 1.5rem;  
636 - margin-left: 0.5rem;  
637 - float: left; 753 + position: relative;
  754 + width: 6.25rem;
  755 + height: 6.25rem;
  756 + max-width: 6.25rem;
  757 + max-height: 6.25rem;
  758 + border-radius: 100%;
  759 + margin-top: 1.5rem;
  760 + margin-left: 0.5rem;
  761 + float: left;
638 } 762 }
639 763
640 .control-panel { 764 .control-panel {
641 - position: relative;  
642 - top: 0;  
643 - left: 5rem;  
644 - height: 11rem;  
645 - max-height: 11rem; 765 + position: relative;
  766 + top: 0;
  767 + left: 5rem;
  768 + height: 11rem;
  769 + max-height: 11rem;
646 } 770 }
647 771
648 .control-btn { 772 .control-btn {
649 - display: flex;  
650 - justify-content: center;  
651 - position: absolute;  
652 - width: 44%;  
653 - height: 44%;  
654 - border-radius: 5px;  
655 - border: 1px solid #78aee4;  
656 - box-sizing: border-box;  
657 - transition: all 0.3s linear; 773 + display: flex;
  774 + justify-content: center;
  775 + position: absolute;
  776 + width: 44%;
  777 + height: 44%;
  778 + border-radius: 5px;
  779 + border: 1px solid #78aee4;
  780 + box-sizing: border-box;
  781 + transition: all 0.3s linear;
658 } 782 }
  783 +
659 .control-btn:hover { 784 .control-btn:hover {
660 - cursor:pointer 785 + cursor: pointer
661 } 786 }
662 787
663 .control-btn i { 788 .control-btn i {
664 - font-size: 20px;  
665 - color: #78aee4;  
666 - display: flex;  
667 - justify-content: center;  
668 - align-items: center; 789 + font-size: 20px;
  790 + color: #78aee4;
  791 + display: flex;
  792 + justify-content: center;
  793 + align-items: center;
669 } 794 }
  795 +
670 .control-btn i:hover { 796 .control-btn i:hover {
671 - cursor:pointer 797 + cursor: pointer
672 } 798 }
  799 +
673 .control-zoom-btn:hover { 800 .control-zoom-btn:hover {
674 - cursor:pointer 801 + cursor: pointer
675 } 802 }
676 803
677 .control-round { 804 .control-round {
678 - position: absolute;  
679 - top: 21%;  
680 - left: 21%;  
681 - width: 58%;  
682 - height: 58%;  
683 - background: #fff;  
684 - border-radius: 100%; 805 + position: absolute;
  806 + top: 21%;
  807 + left: 21%;
  808 + width: 58%;
  809 + height: 58%;
  810 + background: #fff;
  811 + border-radius: 100%;
685 } 812 }
686 813
687 .control-round-inner { 814 .control-round-inner {
688 - position: absolute;  
689 - left: 13%;  
690 - top: 13%;  
691 - display: flex;  
692 - justify-content: center;  
693 - align-items: center;  
694 - width: 70%;  
695 - height: 70%;  
696 - font-size: 40px;  
697 - color: #78aee4;  
698 - border: 1px solid #78aee4;  
699 - border-radius: 100%;  
700 - transition: all 0.3s linear; 815 + position: absolute;
  816 + left: 13%;
  817 + top: 13%;
  818 + display: flex;
  819 + justify-content: center;
  820 + align-items: center;
  821 + width: 70%;
  822 + height: 70%;
  823 + font-size: 40px;
  824 + color: #78aee4;
  825 + border: 1px solid #78aee4;
  826 + border-radius: 100%;
  827 + transition: all 0.3s linear;
701 } 828 }
702 829
703 .control-inner-btn { 830 .control-inner-btn {
704 - position: absolute;  
705 - width: 60%;  
706 - height: 60%;  
707 - background: #fafafa; 831 + position: absolute;
  832 + width: 60%;
  833 + height: 60%;
  834 + background: #fafafa;
708 } 835 }
709 836
710 .control-top { 837 .control-top {
711 - top: -8%;  
712 - left: 27%;  
713 - transform: rotate(-45deg);  
714 - border-radius: 5px 100% 5px 0; 838 + top: -8%;
  839 + left: 27%;
  840 + transform: rotate(-45deg);
  841 + border-radius: 5px 100% 5px 0;
715 } 842 }
716 843
717 .control-top i { 844 .control-top i {
718 - transform: rotate(45deg);  
719 - border-radius: 5px 100% 5px 0; 845 + transform: rotate(45deg);
  846 + border-radius: 5px 100% 5px 0;
720 } 847 }
721 848
722 .control-top .control-inner { 849 .control-top .control-inner {
723 - left: -1px;  
724 - bottom: 0;  
725 - border-top: 1px solid #78aee4;  
726 - border-right: 1px solid #78aee4;  
727 - border-radius: 0 100% 0 0; 850 + left: -1px;
  851 + bottom: 0;
  852 + border-top: 1px solid #78aee4;
  853 + border-right: 1px solid #78aee4;
  854 + border-radius: 0 100% 0 0;
728 } 855 }
729 856
730 .control-top .fa { 857 .control-top .fa {
731 - transform: rotate(45deg) translateY(-7px); 858 + transform: rotate(45deg) translateY(-7px);
732 } 859 }
733 860
734 .control-left { 861 .control-left {
735 - top: 27%;  
736 - left: -8%;  
737 - transform: rotate(45deg);  
738 - border-radius: 5px 0 5px 100%; 862 + top: 27%;
  863 + left: -8%;
  864 + transform: rotate(45deg);
  865 + border-radius: 5px 0 5px 100%;
739 } 866 }
740 867
741 .control-left i { 868 .control-left i {
742 - transform: rotate(-45deg); 869 + transform: rotate(-45deg);
743 } 870 }
744 871
745 .control-left .control-inner { 872 .control-left .control-inner {
746 - right: -1px;  
747 - top: -1px;  
748 - border-bottom: 1px solid #78aee4;  
749 - border-left: 1px solid #78aee4;  
750 - border-radius: 0 0 0 100%; 873 + right: -1px;
  874 + top: -1px;
  875 + border-bottom: 1px solid #78aee4;
  876 + border-left: 1px solid #78aee4;
  877 + border-radius: 0 0 0 100%;
751 } 878 }
752 879
753 .control-left .fa { 880 .control-left .fa {
754 - transform: rotate(-45deg) translateX(-7px); 881 + transform: rotate(-45deg) translateX(-7px);
755 } 882 }
756 883
757 .control-right { 884 .control-right {
758 - top: 27%;  
759 - right: -8%;  
760 - transform: rotate(45deg);  
761 - border-radius: 5px 100% 5px 0; 885 + top: 27%;
  886 + right: -8%;
  887 + transform: rotate(45deg);
  888 + border-radius: 5px 100% 5px 0;
762 } 889 }
763 890
764 .control-right i { 891 .control-right i {
765 - transform: rotate(-45deg); 892 + transform: rotate(-45deg);
766 } 893 }
767 894
768 .control-right .control-inner { 895 .control-right .control-inner {
769 - left: -1px;  
770 - bottom: -1px;  
771 - border-top: 1px solid #78aee4;  
772 - border-right: 1px solid #78aee4;  
773 - border-radius: 0 100% 0 0; 896 + left: -1px;
  897 + bottom: -1px;
  898 + border-top: 1px solid #78aee4;
  899 + border-right: 1px solid #78aee4;
  900 + border-radius: 0 100% 0 0;
774 } 901 }
775 902
776 .control-right .fa { 903 .control-right .fa {
777 - transform: rotate(-45deg) translateX(7px); 904 + transform: rotate(-45deg) translateX(7px);
778 } 905 }
779 906
780 .control-bottom { 907 .control-bottom {
781 - left: 27%;  
782 - bottom: -8%;  
783 - transform: rotate(45deg);  
784 - border-radius: 0 5px 100% 5px; 908 + left: 27%;
  909 + bottom: -8%;
  910 + transform: rotate(45deg);
  911 + border-radius: 0 5px 100% 5px;
785 } 912 }
786 913
787 .control-bottom i { 914 .control-bottom i {
788 - transform: rotate(-45deg); 915 + transform: rotate(-45deg);
789 } 916 }
790 917
791 .control-bottom .control-inner { 918 .control-bottom .control-inner {
792 - top: -1px;  
793 - left: -1px;  
794 - border-bottom: 1px solid #78aee4;  
795 - border-right: 1px solid #78aee4;  
796 - border-radius: 0 0 100% 0; 919 + top: -1px;
  920 + left: -1px;
  921 + border-bottom: 1px solid #78aee4;
  922 + border-right: 1px solid #78aee4;
  923 + border-radius: 0 0 100% 0;
797 } 924 }
798 925
799 .control-bottom .fa { 926 .control-bottom .fa {
800 - transform: rotate(-45deg) translateY(7px); 927 + transform: rotate(-45deg) translateY(7px);
801 } 928 }
  929 +
802 .trank { 930 .trank {
803 - width: 80%;  
804 - height: 180px;  
805 - text-align: left;  
806 - padding: 0 10%;  
807 - overflow: auto; 931 + width: 80%;
  932 + height: 180px;
  933 + text-align: left;
  934 + padding: 0 10%;
  935 + overflow: auto;
808 } 936 }
  937 +
809 .trankInfo { 938 .trankInfo {
810 - width: 80%;  
811 - padding: 0 10%; 939 + width: 80%;
  940 + padding: 0 10%;
812 } 941 }
813 </style> 942 </style>