devicePlayer.vue 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. <template>
  2. <div id="devicePlayer" v-loading="isLoging">
  3. <el-dialog title="视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" @close="close()">
  4. <div style="width: 100%; height: 100%">
  5. <el-tabs type="card" :stretch="true" v-model="activePlayer" @tab-click="changePlayer" v-if="Object.keys(this.player).length > 1">
  6. <!-- <el-tab-pane label="LivePlayer" name="livePlayer">-->
  7. <!-- <LivePlayer v-if="showVideoDialog" ref="livePlayer" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" :hasaudio="hasAudio" fluent autoplay live></LivePlayer>-->
  8. <!-- </el-tab-pane>-->
  9. <el-tab-pane label="Jessibuca" name="jessibuca">
  10. <jessibucaPlayer v-if="activePlayer === 'jessibuca'" ref="jessibuca" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></jessibucaPlayer>
  11. </el-tab-pane>
  12. <el-tab-pane label="WebRTC" name="webRTC">
  13. <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. </el-tab-pane>
  15. <el-tab-pane label="h265web">h265web敬请期待</el-tab-pane>
  16. </el-tabs>
  17. <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>
  18. <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>
  19. </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. </div>
  140. </el-tab-pane>
  141. <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->
  142. <!--遥控界面-->
  143. <el-tab-pane label="云台控制" name="control" v-if="showPtz">
  144. <div style="display: flex; justify-content: left;">
  145. <div class="control-wrapper">
  146. <div class="control-btn control-top" @mousedown="ptzCamera('up')" @mouseup="ptzCamera('stop')">
  147. <i class="el-icon-caret-top"></i>
  148. <div class="control-inner-btn control-inner"></div>
  149. </div>
  150. <div class="control-btn control-left" @mousedown="ptzCamera('left')" @mouseup="ptzCamera('stop')">
  151. <i class="el-icon-caret-left"></i>
  152. <div class="control-inner-btn control-inner"></div>
  153. </div>
  154. <div class="control-btn control-bottom" @mousedown="ptzCamera('down')" @mouseup="ptzCamera('stop')">
  155. <i class="el-icon-caret-bottom"></i>
  156. <div class="control-inner-btn control-inner"></div>
  157. </div>
  158. <div class="control-btn control-right" @mousedown="ptzCamera('right')" @mouseup="ptzCamera('stop')">
  159. <i class="el-icon-caret-right"></i>
  160. <div class="control-inner-btn control-inner"></div>
  161. </div>
  162. <div class="control-round">
  163. <div class="control-round-inner"><i class="fa fa-pause-circle"></i></div>
  164. </div>
  165. <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>
  166. <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>
  167. <div class="contro-speed" style="position: absolute; left: 4px; top: 7rem; width: 9rem;">
  168. <el-slider v-model="controSpeed" :max="255"></el-slider>
  169. </div>
  170. </div>
  171. <div class="control-panel">
  172. <el-button-group>
  173. <el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center" size="medium">预置位编号</el-tag>
  174. <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>
  175. <el-button style="position: absolute; left: 11rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="presetPosition(129, presetPos)">设置</el-button>
  176. <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>
  177. <el-button style="position: absolute; left: 16rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="presetPosition(131, presetPos)">删除</el-button>
  178. <el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">巡航速度</el-tag>
  179. <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>
  180. <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>
  181. <el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">停留时间</el-tag>
  182. <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>
  183. <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>
  184. <el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center" size="medium">巡航组编号</el-tag>
  185. <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>
  186. <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>
  187. <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>
  188. <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>
  189. <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>
  190. <el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center" size="medium">扫描速度</el-tag>
  191. <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>
  192. <el-button style="position: absolute; left: 11rem; top: 7rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(138, scanGroup, scanSpeed)">设置</el-button>
  193. <el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center" size="medium">扫描组编号</el-tag>
  194. <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>
  195. <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>
  196. <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>
  197. <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>
  198. <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>
  199. </el-button-group>
  200. </div>
  201. </div>
  202. </el-tab-pane>
  203. <el-tab-pane label="编码信息" name="codec" v-loading="tracksLoading">
  204. <p>
  205. 无法播放或者没有声音?&nbsp&nbsp&nbsp试一试&nbsp
  206. <el-button size="mini" type="primary" v-if="!coverPlaying" @click="coverPlay">转码播放</el-button>
  207. <el-button size="mini" type="danger" v-if="coverPlaying" @click="convertStopClick">停止转码</el-button>
  208. </p>
  209. <div class="trank" >
  210. <p v-if="tracksNotLoaded" style="text-align: center;padding-top: 3rem;">暂无数据</p>
  211. <div v-for="(item, index) in tracks" style="width: 50%; float: left" loading>
  212. <span >流 {{index}}</span>
  213. <div class="trankInfo" v-if="item.codec_type == 0">
  214. <p>格式: {{item.codec_id_name}}</p>
  215. <p>类型: 视频</p>
  216. <p>分辨率: {{item.width}} x {{item.height}}</p>
  217. <p>帧率: {{item.fps}}</p>
  218. </div>
  219. <div class="trankInfo" v-if="item.codec_type == 1">
  220. <p>格式: {{item.codec_id_name}}</p>
  221. <p>类型: 音频</p>
  222. <p>采样位数: {{item.sample_bit}}</p>
  223. <p>采样率: {{item.sample_rate}}</p>
  224. </div>
  225. </div>
  226. </div>
  227. </el-tab-pane>
  228. </el-tabs>
  229. </div>
  230. </el-dialog>
  231. </div>
  232. </template>
  233. <script>
  234. import rtcPlayer from '../dialog/rtcPlayer.vue'
  235. import LivePlayer from '@liveqing/liveplayer'
  236. import jessibucaPlayer from '../common/jessibuca.vue'
  237. export default {
  238. name: 'devicePlayer',
  239. props: {},
  240. components: {
  241. LivePlayer, jessibucaPlayer, rtcPlayer,
  242. },
  243. computed: {
  244. getPlayerShared: function () {
  245. return {
  246. sharedUrl: window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl),
  247. sharedIframe: '<iframe src="' + window.location.origin + '/#/play/wasm/' + encodeURIComponent(this.videoUrl) + '"></iframe>',
  248. sharedRtmp: this.videoUrl
  249. };
  250. }
  251. },
  252. created() {
  253. console.log(this.player)
  254. if (Object.keys(this.player).length === 1) {
  255. this.activePlayer = Object.keys(this.player)[0]
  256. }
  257. },
  258. data() {
  259. return {
  260. video: 'http://lndxyj.iqilu.com/public/upload/2019/10/14/8c001ea0c09cdc59a57829dabc8010fa.mp4',
  261. videoUrl: '',
  262. activePlayer: "jessibuca",
  263. // 如何你只是用一种播放器,直接注释掉不用的部分即可
  264. player: {
  265. jessibuca : ["ws_flv", "wss_flv"],
  266. livePlayer : ["ws_flv", "wss_flv"],
  267. webRTC: ["rtc", "rtcs"],
  268. },
  269. showVideoDialog: false,
  270. streamId: '',
  271. app : '',
  272. mediaServerId : '',
  273. convertKey: '',
  274. deviceId: '',
  275. channelId: '',
  276. tabActiveName: 'media',
  277. hasAudio: false,
  278. loadingRecords: false,
  279. recordsLoading: false,
  280. isLoging: false,
  281. controSpeed: 30,
  282. timeVal: 0,
  283. timeMin: 0,
  284. timeMax: 1440,
  285. presetPos: 1,
  286. cruisingSpeed: 100,
  287. cruisingTime: 5,
  288. cruisingGroup: 0,
  289. scanSpeed: 100,
  290. scanGroup: 0,
  291. tracks: [],
  292. coverPlaying:false,
  293. tracksLoading: false,
  294. showPtz: true,
  295. showRrecord: true,
  296. tracksNotLoaded: false,
  297. sliderTime: 0,
  298. seekTime: 0,
  299. recordStartTime: 0,
  300. showTimeText: "00:00:00",
  301. streamInfo: null,
  302. };
  303. },
  304. methods: {
  305. tabHandleClick: function(tab, event) {
  306. console.log(tab)
  307. var that = this;
  308. that.tracks = [];
  309. that.tracksLoading = true;
  310. that.tracksNotLoaded = false;
  311. if (tab.name === "codec") {
  312. this.$axios({
  313. method: 'get',
  314. url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtsp&app='+ this.app +'&stream='+ this.streamId
  315. }).then(function (res) {
  316. that.tracksLoading = false;
  317. if (res.data.code == 0 && res.data.tracks) {
  318. that.tracks = res.data.tracks;
  319. }else{
  320. that.tracksNotLoaded = true;
  321. that.$message({
  322. showClose: true,
  323. message: '获取编码信息失败,',
  324. type: 'warning'
  325. });
  326. }
  327. }).catch(function (e) {});
  328. }
  329. },
  330. changePlayer: function (tab) {
  331. console.log(this.player[tab.name][0])
  332. this.activePlayer = tab.name;
  333. this.videoUrl = this.getUrlByStreamInfo()
  334. console.log(this.videoUrl)
  335. },
  336. openDialog: function (tab, deviceId, channelId, param) {
  337. if (this.showVideoDialog) {
  338. return;
  339. }
  340. this.tabActiveName = tab;
  341. this.channelId = channelId;
  342. this.deviceId = deviceId;
  343. this.streamId = "";
  344. this.mediaServerId = "";
  345. this.app = "";
  346. this.videoUrl = ""
  347. if (!!this.$refs[this.activePlayer]) {
  348. this.$refs[this.activePlayer].pause();
  349. }
  350. switch (tab) {
  351. case "media":
  352. this.play(param.streamInfo, param.hasAudio)
  353. break;
  354. case "streamPlay":
  355. this.tabActiveName = "media";
  356. this.showRrecord = false;
  357. this.showPtz = false;
  358. this.play(param.streamInfo, param.hasAudio)
  359. break;
  360. case "control":
  361. break;
  362. }
  363. },
  364. play: function (streamInfo, hasAudio) {
  365. this.streamInfo = streamInfo;
  366. this.hasAudio = hasAudio;
  367. this.isLoging = false;
  368. // this.videoUrl = streamInfo.rtc;
  369. this.videoUrl = this.getUrlByStreamInfo();
  370. this.streamId = streamInfo.stream;
  371. this.app = streamInfo.app;
  372. this.mediaServerId = streamInfo.mediaServerId;
  373. this.playFromStreamInfo(false, streamInfo)
  374. },
  375. getUrlByStreamInfo(){
  376. console.log(this.streamInfo)
  377. if (location.protocol === "https:") {
  378. this.videoUrl = this.streamInfo[this.player[this.activePlayer][1]]
  379. }else {
  380. this.videoUrl = this.streamInfo[this.player[this.activePlayer][0]]
  381. }
  382. return this.videoUrl;
  383. },
  384. coverPlay: function () {
  385. var that = this;
  386. this.coverPlaying = true;
  387. this.$refs[this.activePlayer].pause()
  388. that.$axios({
  389. method: 'post',
  390. url: '/api/play/convert/' + that.streamId
  391. }).then(function (res) {
  392. if (res.data.code === 0) {
  393. that.convertKey = res.data.key;
  394. setTimeout(()=>{
  395. that.isLoging = false;
  396. that.playFromStreamInfo(false, res.data.data);
  397. }, 2000)
  398. } else {
  399. that.isLoging = false;
  400. that.coverPlaying = false;
  401. that.$message({
  402. showClose: true,
  403. message: '转码失败',
  404. type: 'error'
  405. });
  406. }
  407. }).catch(function (e) {
  408. console.log(e)
  409. that.coverPlaying = false;
  410. that.$message({
  411. showClose: true,
  412. message: '播放错误',
  413. type: 'error'
  414. });
  415. });
  416. },
  417. convertStopClick: function() {
  418. this.convertStop(()=>{
  419. this.$refs[this.activePlayer].play(this.videoUrl)
  420. });
  421. },
  422. convertStop: function(callback) {
  423. var that = this;
  424. that.$refs.videoPlayer.pause()
  425. this.$axios({
  426. method: 'post',
  427. url: '/api/play/convertStop/' + this.convertKey
  428. }).then(function (res) {
  429. if (res.data.code == 0) {
  430. console.log(res.data.msg)
  431. }else {
  432. console.error(res.data.msg)
  433. }
  434. if (callback )callback();
  435. }).catch(function (e) {});
  436. that.coverPlaying = false;
  437. that.convertKey = "";
  438. // if (callback )callback();
  439. },
  440. playFromStreamInfo: function (realHasAudio, streamInfo) {
  441. this.showVideoDialog = true;
  442. this.hasaudio = realHasAudio && this.hasaudio;
  443. if (this.$refs[this.activePlayer]) {
  444. this.$refs[this.activePlayer].play(this.getUrlByStreamInfo(streamInfo))
  445. }else {
  446. this.$nextTick(() => {
  447. this.$refs[this.activePlayer].play(this.getUrlByStreamInfo(streamInfo))
  448. });
  449. }
  450. },
  451. close: function () {
  452. console.log('关闭视频');
  453. if (!!this.$refs[this.activePlayer]){
  454. this.$refs[this.activePlayer].pause();
  455. }
  456. this.videoUrl = '';
  457. this.coverPlaying = false;
  458. this.showVideoDialog = false;
  459. if (this.convertKey != '') {
  460. this.convertStop();
  461. }
  462. this.convertKey = ''
  463. },
  464. copySharedInfo: function (data) {
  465. console.log('复制内容:' + data);
  466. this.coverPlaying = false;
  467. this.tracks = []
  468. let _this = this;
  469. this.$copyText(data).then(
  470. function (e) {
  471. _this.$message({
  472. showClose: true,
  473. message: '复制成功',
  474. type: 'success'
  475. });
  476. },
  477. function (e) {
  478. _this.$message({
  479. showClose: true,
  480. message: '复制失败,请手动复制',
  481. type: 'error'
  482. });
  483. }
  484. );
  485. },
  486. ptzCamera: function (command) {
  487. console.log('云台控制:' + command);
  488. let that = this;
  489. this.$axios({
  490. method: 'post',
  491. url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed
  492. }).then(function (res) {});
  493. },
  494. //////////////////////播放器事件处理//////////////////////////
  495. videoError: function (e) {
  496. console.log("播放器错误:" + JSON.stringify(e));
  497. },
  498. presetPosition: function (cmdCode, presetPos) {
  499. console.log('预置位控制:' + this.presetPos + ' : 0x' + cmdCode.toString(16));
  500. let that = this;
  501. this.$axios({
  502. method: 'post',
  503. url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=0&parameter2=' + presetPos + '&combindCode2=0'
  504. }).then(function (res) {});
  505. },
  506. setSpeedOrTime: function (cmdCode, groupNum, parameter) {
  507. let that = this;
  508. let parameter2 = parameter % 256;
  509. let combindCode2 = Math.floor(parameter / 256) * 16;
  510. console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter2.toString(16) + ' 0x' + combindCode2.toString(16));
  511. this.$axios({
  512. method: 'post',
  513. url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=' + groupNum + '&parameter2=' + parameter2 + '&combindCode2=' + combindCode2
  514. }).then(function (res) {});
  515. },
  516. setCommand: function (cmdCode, groupNum, parameter) {
  517. let that = this;
  518. console.log('前端控制:0x' + cmdCode.toString(16) + ' 0x' + groupNum.toString(16) + ' 0x' + parameter.toString(16) + ' 0x0');
  519. this.$axios({
  520. method: 'post',
  521. url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=' + groupNum + '&parameter2=' + parameter + '&combindCode2=0'
  522. }).then(function (res) {});
  523. },
  524. copyUrl: function (dropdownItem){
  525. console.log(dropdownItem)
  526. this.$copyText(dropdownItem).then((e)=> {
  527. this.$message.success("成功拷贝到粘贴板");
  528. }, (e)=> {
  529. })
  530. },
  531. }
  532. };
  533. </script>
  534. <style>
  535. .control-wrapper {
  536. position: relative;
  537. width: 6.25rem;
  538. height: 6.25rem;
  539. max-width: 6.25rem;
  540. max-height: 6.25rem;
  541. border-radius: 100%;
  542. margin-top: 1.5rem;
  543. margin-left: 0.5rem;
  544. float: left;
  545. }
  546. .control-panel {
  547. position: relative;
  548. top: 0;
  549. left: 5rem;
  550. height: 11rem;
  551. max-height: 11rem;
  552. }
  553. .control-btn {
  554. display: flex;
  555. justify-content: center;
  556. position: absolute;
  557. width: 44%;
  558. height: 44%;
  559. border-radius: 5px;
  560. border: 1px solid #78aee4;
  561. box-sizing: border-box;
  562. transition: all 0.3s linear;
  563. }
  564. .control-btn:hover {
  565. cursor:pointer
  566. }
  567. .control-btn i {
  568. font-size: 20px;
  569. color: #78aee4;
  570. display: flex;
  571. justify-content: center;
  572. align-items: center;
  573. }
  574. .control-btn i:hover {
  575. cursor:pointer
  576. }
  577. .control-zoom-btn:hover {
  578. cursor:pointer
  579. }
  580. .control-round {
  581. position: absolute;
  582. top: 21%;
  583. left: 21%;
  584. width: 58%;
  585. height: 58%;
  586. background: #fff;
  587. border-radius: 100%;
  588. }
  589. .control-round-inner {
  590. position: absolute;
  591. left: 13%;
  592. top: 13%;
  593. display: flex;
  594. justify-content: center;
  595. align-items: center;
  596. width: 70%;
  597. height: 70%;
  598. font-size: 40px;
  599. color: #78aee4;
  600. border: 1px solid #78aee4;
  601. border-radius: 100%;
  602. transition: all 0.3s linear;
  603. }
  604. .control-inner-btn {
  605. position: absolute;
  606. width: 60%;
  607. height: 60%;
  608. background: #fafafa;
  609. }
  610. .control-top {
  611. top: -8%;
  612. left: 27%;
  613. transform: rotate(-45deg);
  614. border-radius: 5px 100% 5px 0;
  615. }
  616. .control-top i {
  617. transform: rotate(45deg);
  618. border-radius: 5px 100% 5px 0;
  619. }
  620. .control-top .control-inner {
  621. left: -1px;
  622. bottom: 0;
  623. border-top: 1px solid #78aee4;
  624. border-right: 1px solid #78aee4;
  625. border-radius: 0 100% 0 0;
  626. }
  627. .control-top .fa {
  628. transform: rotate(45deg) translateY(-7px);
  629. }
  630. .control-left {
  631. top: 27%;
  632. left: -8%;
  633. transform: rotate(45deg);
  634. border-radius: 5px 0 5px 100%;
  635. }
  636. .control-left i {
  637. transform: rotate(-45deg);
  638. }
  639. .control-left .control-inner {
  640. right: -1px;
  641. top: -1px;
  642. border-bottom: 1px solid #78aee4;
  643. border-left: 1px solid #78aee4;
  644. border-radius: 0 0 0 100%;
  645. }
  646. .control-left .fa {
  647. transform: rotate(-45deg) translateX(-7px);
  648. }
  649. .control-right {
  650. top: 27%;
  651. right: -8%;
  652. transform: rotate(45deg);
  653. border-radius: 5px 100% 5px 0;
  654. }
  655. .control-right i {
  656. transform: rotate(-45deg);
  657. }
  658. .control-right .control-inner {
  659. left: -1px;
  660. bottom: -1px;
  661. border-top: 1px solid #78aee4;
  662. border-right: 1px solid #78aee4;
  663. border-radius: 0 100% 0 0;
  664. }
  665. .control-right .fa {
  666. transform: rotate(-45deg) translateX(7px);
  667. }
  668. .control-bottom {
  669. left: 27%;
  670. bottom: -8%;
  671. transform: rotate(45deg);
  672. border-radius: 0 5px 100% 5px;
  673. }
  674. .control-bottom i {
  675. transform: rotate(-45deg);
  676. }
  677. .control-bottom .control-inner {
  678. top: -1px;
  679. left: -1px;
  680. border-bottom: 1px solid #78aee4;
  681. border-right: 1px solid #78aee4;
  682. border-radius: 0 0 100% 0;
  683. }
  684. .control-bottom .fa {
  685. transform: rotate(-45deg) translateY(7px);
  686. }
  687. .trank {
  688. width: 80%;
  689. height: 180px;
  690. text-align: left;
  691. padding: 0 10%;
  692. overflow: auto;
  693. }
  694. .trankInfo {
  695. width: 80%;
  696. padding: 0 10%;
  697. }
  698. </style>