From 170ee55bd1f0858fdbad3147a72c0f185d49a9a6 Mon Sep 17 00:00:00 2001 From: zhangzengfei <zhangzengfei@smartai.com> Date: 星期四, 10 三月 2022 11:02:01 +0800 Subject: [PATCH] cameraPlayer 添加h265b播放功能 --- src/components/wasmPlayer/index.vue | 435 +++++++++++++++++++++++++++++------------------------- 1 files changed, 233 insertions(+), 202 deletions(-) diff --git a/src/components/wasmPlayer/index.vue b/src/components/wasmPlayer/index.vue index 447a4a5..9c0e2c7 100644 --- a/src/components/wasmPlayer/index.vue +++ b/src/components/wasmPlayer/index.vue @@ -1,58 +1,31 @@ <template> <div class="video-player"> - <canvas - v-show="showArea" - id="area-canvas" - ref="areaCanvas" - width="960" - height="540" - ></canvas> + <canvas v-show="showArea" id="area-canvas" ref="areaCanvas" width="960" height="540"></canvas> <div class="container" id="videoPlayer"> <div class="canvasDiv"> - <div class="loadEffect" id="loading" style="display:none;"> - <span></span> - <span></span> - <span></span> - <span></span> - <span></span> - <span></span> - <span></span> - <span></span> - </div> - <canvas - ref="playCanvas" - id="paly-canvas" - width="960" - height="540" - ></canvas> + <div + v-loading="videoLoading" + element-loading-background="rgba(0, 0, 0, 0.8)" + style="position: unset !important" + ></div> + <canvas ref="playCanvas" id="paly-canvas" width="960" height="540"></canvas> </div> + <transition name="fade"> + <div class="popuptext" id="myPopup" v-if="fullScreenNotice">璧勬簮涓嬭浇涓�,璇风◢鍚�...</div> + </transition> + <!-- 鎺у埗鏉� --> - <section - class="jsmodern-video-panel" - :style="{ display: isStream ? 'none' : 'block' }" - > + <section class="jsmodern-video-panel" :style="{ display: isStream ? 'none' : 'block' }"> <!-- 鎾斁/鏆傚仠 --> - <b - :class=" - playerStatus == 0 ? 'jsmodern-video-play' : 'jsmodern-video-pause' - " - @click="playVideo" - ></b> + <b :class="playerStatus == 0 ? 'jsmodern-video-play' : 'jsmodern-video-pause'" @click="playVideo"></b> <!-- 鏃堕棿 --> - <span class="jsmodern-video-start" ref="timeLabel" - >00:00:00/00:00:00</span - > + <span class="jsmodern-video-start" ref="timeLabel">00:00:00/00:00:00</span> <!-- 杩涘害鏉� --> <div> - <input - class="jsmodern-video-linebox" - ref="timeTrack" - type="range" - value="0" - /> + <input class="jsmodern-video-linebox" ref="timeTrack" type="range" value="0" /> </div> <!-- 澹伴煶 --> @@ -63,18 +36,15 @@ </div> --> <!-- 鍏ㄥ睆 --> - <b - class="jsmodern-video-fullin" - @click="fullScreen" - :disable="false" - ></b> + <b class="jsmodern-video-fullin" @click="fullScreen" :disable="false"></b> + + <!-- 涓嬭浇 --> + <i class="el-icon-download jsmodern-video-download" @click="downLoad"></i> </section> <!-- 澶ф挱鏀炬寜閽� --> <div v-show="!isStream"> - <span class="video-btn" v-show="playerStatus == 0" @click="playVideo" - ><img src="./wasm/img/bo1.png" - /></span> + <span class="video-btn" v-show="playerStatus == 0" @click="playVideo"><img src="./wasm/img/bo1.png"/></span> <!-- 涓婁竴涓� --> <span class="video-prve" v-show="showPrev"> @@ -85,6 +55,13 @@ <span class="video-next" v-show="showNext"> <i class="el-icon-arrow-right" @click="playNext"></i> </span> + + <!-- 鎾斁澶辫触 --> + <span class="video-error" v-show="playerStatus == -1"> + <i class="el-icon-warning-outline" style="font-size:40px"></i> + <br /> + 瑙嗛鍔犺浇澶辫触 鏃犳晥鐨勮棰戝湴鍧� + </span> </div> </div> </div> @@ -94,72 +71,74 @@ /* 2021.09.22 娣诲姞澶氫釜褰曞儚鍦板潃鐨勫鐞�, 涓庡綍鍍忔ā鍧楃害瀹�, 鐢� || 鍒嗗壊澶氫釜瑙嗛鍦板潃, 鍓嶇澶勭悊鎾斁. */ -import { Player } from './wasm/player' -import VideoRuleData from '@/Pool/VideoRuleData' -import { getAllPolygon } from '@/api/polygon' +import { Player } from "./wasm/player" +import { getAllPolygon } from "@/api/polygon" export default { - name: 'CameraPlayer', + name: "CameraPlayer", props: { videoUrl: { type: String, // default: "ws://192.168.1.182:10101/ws" - default: `${location.protocol === 'https' ? 'wss' : 'ws'}://${ - location.host - }/ws`, + default: `${location.protocol === "https" ? "wss" : "ws"}://${location.host}/ws` }, cameraName: { type: String, - default: '', + default: "" }, cameraID: { type: String, - default: 'C4668FD0-3CAE-C31F-C21E-28B7001243C4', + default: "C4668FD0-3CAE-C31F-C21E-28B7001243C4" }, rtspUrl: { type: String, - default: - 'rtsp://admin:a1234567@192.168.1.201:554/h264/ch1/main/av_stream', + default: "rtsp://admin:a1234567@192.168.1.201:554/h264/ch1/main/av_stream" }, isRunning: { type: Boolean, - default: false, + default: false }, isGb: { type: Boolean, - default: false, + default: false }, showArea: { type: Boolean, - default: false, + default: false }, isStream: { type: Boolean, - default: true, + default: true }, + autoPlay: { + type: Boolean, + default: false + }, + preload: { + type: Boolean, + default: true + } }, computed: { poster() { - return '/images/player/player_poster.gif?t=' + Math.random() + return "/images/player/player_poster.gif?t=" + Math.random() }, showPrev() { return this.playerIndex - 1 >= 0 }, showNext() { return this.playerIndex + 1 < this.videoUrls.length - }, + } }, data() { return { player: null, playerId: 0, - Camera: new VideoRuleData(), - showCanvas: true, canvasData: { line: [], rect: [], // {id:'uuid', name: '鐭╁舰1', location: [{ x: 20, y: 30 }, { x: 20, y: 60 }, { x: 100, y: 60 }, { x: 100, y: 30 }] } arrow: [], - polygon: [], + polygon: [] }, //showProportion: 3.2, //showProportionY: 3.58, @@ -175,6 +154,11 @@ playerStatus: 0, videoUrls: [], playerIndex: 0, + isEmptyUrl: false, + videoLoading: false, + loadUrl: "", + isFullScreen: false, + fullScreenNotice: false } }, watch: { @@ -188,107 +172,65 @@ this.playVideo() }) } - }, + } }, mounted() { this.player = new Player() - - // 褰曞儚URL澶勭悊, 鍙兘瀛樺湪澶氫釜褰曞儚鍦板潃 - if (!this.isStream) { - this.videoUrls = this.videoUrl.split('||') - } + this.player.preload = this.preload + this.player.statusCallback = this.setPlayerStatus if (this.isStream) { this.playVideo() this.$nextTick(() => { this.canvas = this.$refs.areaCanvas - this.ctx = this.canvas.getContext('2d') + this.ctx = this.canvas.getContext("2d") this.ctx.lineWidth = 1 this.initArea() }) + } else { + // 褰曞儚URL澶勭悊, 鍙兘瀛樺湪澶氫釜褰曞儚鍦板潃 + if (this.videoUrl === "") { + this.playerStatus = -1 + return + } + + this.videoUrls = this.videoUrl.split("||") + + if (this.autoPlay || this.preload) { + this.playVideo() + } } }, beforeDestroy() { this.player.stop() }, methods: { - checkConnect(id) { - if (id !== this.playerId) { - return - } - - if (this.wfs.websocketLoader && this.wfs.websocketLoader.client) { - if (this.wfs.websocketLoader.client.disconnected) { - this.playVideo() - console.log('瀹炴椂瑙嗛宸叉柇寮�锛屾鍦ㄩ噸杩�') - return - } - } - - let _this = this - setTimeout(() => { - _this.checkConnect(id) - }, 10000) - }, - getUuid() { - var s = [] - var hexDigits = '0123456789abcdefghijkopqrst' - for (var i = 0; i < 36; i++) { - s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1) - } - s[14] = '4' //聽bits聽12-15聽of聽the聽time_hi_and_version聽field聽to聽0010 - s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) //聽bits聽6-7聽of聽the聽clock_seq_hi_and_reserved聽to聽01 - s[8] = s[13] = s[18] = s[23] = '-' - var uuid = s.join('') - return uuid - }, // 鍥炴樉cavas鏁版嵁 // 鐐瑰嚮閫変腑鍙樿壊 灏嗗綋鍓嶉〉闈㈡墍鏈夎矾寰勯噸缁樺垽鏂綋鍓嶉紶鏍囩殑鍧愭爣鍦ㄥ摢涓浘褰㈠唴 濡傛灉涓嶄紶鍧愭爣鍙傛暟灏辨槸鍥炴樉鐨勬柟娉� clickSelect(e) { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height) let _this = this // 闆嗗悎涓亶鍘嗛渶瑕佸皢this杞瓨涓�涓嬩娇鐢� _this.canvasData.line.forEach(function(v, i) { - _this.ctx.strokeStyle = 'yellow' + _this.ctx.strokeStyle = "yellow" _this.ctx.beginPath() - _this.ctx.moveTo( - v.location[0].x / _this.showProportion, - v.location[0].y / _this.showProportion - ) - _this.ctx.lineTo( - v.location[1].x / _this.showProportion, - v.location[1].y / _this.showProportion - ) + _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion) + _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion) _this.ctx.stroke() - _this.canvas.style.cursor = 'default' + _this.canvas.style.cursor = "default" }) _this.canvasData.rect.forEach(function(v, i) { - _this.ctx.strokeStyle = 'yellow' + _this.ctx.strokeStyle = "yellow" _this.ctx.beginPath() - _this.ctx.moveTo( - v.location[0].x / _this.showProportion, - v.location[0].y / _this.showProportion - ) - _this.ctx.lineTo( - v.location[1].x / _this.showProportion, - v.location[1].y / _this.showProportion - ) - _this.ctx.lineTo( - v.location[2].x / _this.showProportion, - v.location[2].y / _this.showProportion - ) - _this.ctx.lineTo( - v.location[3].x / _this.showProportion, - v.location[3].y / _this.showProportion - ) - _this.ctx.lineTo( - v.location[0].x / _this.showProportion, - v.location[0].y / _this.showProportion - ) + _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion) + _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion) + _this.ctx.lineTo(v.location[2].x / _this.showProportion, v.location[2].y / _this.showProportion) + _this.ctx.lineTo(v.location[3].x / _this.showProportion, v.location[3].y / _this.showProportion) + _this.ctx.lineTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion) _this.ctx.stroke() - _this.canvas.style.cursor = 'default' + _this.canvas.style.cursor = "default" }) _this.canvasData.arrow.forEach(function(v, i) { - _this.ctx.strokeStyle = 'yellow' + _this.ctx.strokeStyle = "yellow" _this.drawArrow( _this.ctx, v.location[0].x / _this.showProportion, @@ -297,44 +239,28 @@ v.location[1].y / _this.showProportion, 20, 30, - 'yellow' + "yellow" ) - _this.canvas.style.cursor = 'default' + _this.canvas.style.cursor = "default" }) _this.canvasData.polygon.forEach(function(v, i) { if (v.location.length === 0) { return } - _this.ctx.strokeStyle = 'yellow' + _this.ctx.strokeStyle = "yellow" _this.ctx.beginPath() - _this.ctx.moveTo( - v.location[0].x / _this.showProportion, - v.location[0].y / _this.showProportionY - ) + _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportionY) for (let i = 1; i < v.location.length; i++) { - _this.ctx.lineTo( - v.location[i].x / _this.showProportion, - v.location[i].y / _this.showProportionY - ) + _this.ctx.lineTo(v.location[i].x / _this.showProportion, v.location[i].y / _this.showProportionY) } _this.ctx.closePath() _this.ctx.stroke() - _this.canvas.style.cursor = 'default' + _this.canvas.style.cursor = "default" }) }, // 绠ご缁樺埗鍑芥暟 - drawArrow( - ctx, - fromX, - fromY, - toX, - toY, - theta = 30, - headlen = 10, - width = 1, - color = 'yellow' - ) { + drawArrow(ctx, fromX, fromY, toX, toY, theta = 30, headlen = 10, width = 1, color = "yellow") { // ctx锛欳anvas缁樺浘鐜 // fromX, fromY锛氳捣鐐瑰潗鏍囷紙涔熷彲浠ユ崲鎴恜1锛屽彧涓嶈繃瀹冩槸涓�涓暟缁勶級 // toX, toY锛氱粓鐐瑰潗鏍� (涔熷彲浠ユ崲鎴恜2锛屽彧涓嶈繃瀹冩槸涓�涓暟缁�) @@ -378,32 +304,25 @@ // 鍥炴樉鍥惧舰澶囨敞 showRemarks(x, y, remarks) { this.ctx.moveTo(x, y - 10) // 鍥犱负鏀惧ぇ涔嬪悗鏄痽-20锛屾墍浠ョ缉灏忕増鐨勪负y-10 - this.ctx.fillStyle = 'green' // 璁剧疆濉厖棰滆壊涓虹豢鑹� + this.ctx.fillStyle = "green" // 璁剧疆濉厖棰滆壊涓虹豢鑹� this.ctx.font = '10px "寰蒋闆呴粦"' // 璁剧疆瀛椾綋 - this.ctx.textBaseline = 'bottom' // 璁剧疆瀛椾綋搴曠嚎瀵归綈缁樺埗鍩虹嚎 - this.ctx.textAlign = 'left' // 璁剧疆瀛椾綋瀵归綈鐨勬柟寮� + this.ctx.textBaseline = "bottom" // 璁剧疆瀛椾綋搴曠嚎瀵归綈缁樺埗鍩虹嚎 + this.ctx.textAlign = "left" // 璁剧疆瀛椾綋瀵归綈鐨勬柟寮� this.ctx.fillText(remarks, x, y - 10) // 濉厖鏂囧瓧 }, - getCanvasData(data) { - let polyon = { ...data } - polyon.camera_id = this.Camera.cameraId - savePolygon(polyon).then((rsp) => { - this.Camera.getPolygon() - this.Camera.getCameraTask() - }) - }, + setWidthHeight() { this.canvasWidth = this.$refs.videoPlayer.offsetWidth this.canvasHeight = this.$refs.videoPlayer.offsetHeight console.log(this.canvasWidth, this.canvasHeight) }, async initArea() { - if (!this.showCanvas) { + if (!this.showArea) { return } const res = await getAllPolygon({ - cameraId: this.TreeDataPool.selectedNode.id, + cameraId: this.TreeDataPool.selectedNode.id }) this.canvasData.line = res.data.line this.canvasData.rect = res.data.rect @@ -412,15 +331,15 @@ this.clickSelect(this.canvasData) }, initAlgoDataWebScoket() { - if (typeof WebSocket === 'undefined') { - console.log('error,鎮ㄧ殑娴忚鍣ㄤ笉鏀寔socket') + if (typeof WebSocket === "undefined") { + console.log("error,鎮ㄧ殑娴忚鍣ㄤ笉鏀寔socket") } else { this.algoDataSocket = new WebSocket() this.algoDataSocket.onopen = () => { - console.log('socket杩炴帴鎴愬姛') + console.log("socket杩炴帴鎴愬姛") } this.algoDataSocket.onerror = () => { - console.log('杩炴帴閿欒') + console.log("杩炴帴閿欒") } this.algoDataSocket.onmessage = (msg) => { console.log(msg) @@ -428,14 +347,14 @@ } }, playVideo() { - if (this.isStream && this.rtspUrl == '') { + if (this.isStream && this.rtspUrl == "") { return } - let payload = '' - let url = '' + let payload = "" + let url = "" if (this.isStream) { - if (this.cameraID == '') { + if (this.cameraID == "") { this.cameraID = this.getUuid() } @@ -443,18 +362,15 @@ cameraID: this.cameraID, rtspUrl: this.rtspUrl, isRunning: this.isRunning, - isGb28181: this.isGb, + isGb28181: this.isGb }) url = this.videoUrl } else { - url = '/httpImage/' + this.videoUrls[this.playerIndex] + url = "/httpImage/" + this.videoUrls[this.playerIndex] } - if (url == '') { - return - } - + this.videoLoading = true if (this.player.hPlayer == 0) { this.player.play( url, @@ -462,19 +378,27 @@ this.isStream, this.$refs.timeTrack, this.$refs.timeLabel, - payload + payload, + () => { + this.videoLoading = false + } ) } else if (this.player.PlayOrPause == 0) { this.player.resume() + this.videoLoading = false } else { this.player.pause() + this.videoLoading = false } this.playerStatus = this.player.PlayOrPause - let randomId = this.getUuid() - this.checkConnect(randomId) - }, + this.loadUrl = url + }, + setPlayerStatus(stat) { + this.videoLoading = false + this.playerStatus = stat + }, stopVideo() { if (this.player.hPlayer == 0) return @@ -482,7 +406,61 @@ }, fullScreen() { - this.player.fullscreen() + if (!this.isFullScreen) { + this.player.fullscreen() + } else { + this.player.exitfullscreen() + } + this.isFullScreen = !this.isFullScreen + }, + + async downLoad() { + if (!this.loadUrl) { + this.$notify.info({ + title: "娑堟伅", + message: "涓嬭浇澶辫触锛屾棤鏁堢殑瑙嗛鍦板潃" + }) + return + } + + if (this.isFullScreen) { + /* const screen = this.player.webglPlayer.canvas.parentNode + var p = document.createElement("p"); + var txt = document.createTextNode("璧勬簮涓嬭浇涓�,璇风◢鍚�..."); + p.appendChild(txt); + p.classList.add("downloadNotice"); + screen.appendChild(p); */ + this.fullScreenNotice = true + setTimeout(() => { + this.fullScreenNotice = false + }, 2000) + } else { + this.$notify.info({ + title: "娑堟伅", + message: `璧勬簮涓嬭浇涓�,璇风◢鍚�...` + }) + } + + let url = "http://" + window.location.host + this.loadUrl + + // let url = "http://localhost:8080/httpImage/192.168.20.189:6700/283,2f49bf283ad7?collection=2021-09-28-DSVAD010120190703-video" + let name = url.substring(url.lastIndexOf("/") + 1) + let responsePromise = await fetch(url) + let blob = await responsePromise.blob() + let objectURL = window.URL.createObjectURL(blob) + let a = document.createElement("a") + a.href = objectURL + a.download = name + a.click() + a.remove() + /* let url = 'http:/'+this.loadUrl.substring(10) + let link = document.createElement("a"); //鍒涘缓a鏍囩 + let name = url.substring(url.lastIndexOf("/") + 1) + link.style.display = "none"; //浣垮叾闅愯棌 + link.href = url; //璧嬩簣鏂囦欢涓嬭浇鍦板潃 + link.setAttribute("download", name); //璁剧疆涓嬭浇灞炴�� 浠ュ強鏂囦欢鍚� + document.body.appendChild(link); //a鏍囩鎻掕嚦椤甸潰涓� + link.click(); //寮哄埗瑙﹀彂a鏍囩浜嬩欢 */ }, playPrev() { @@ -495,9 +473,8 @@ this.playerIndex++ this.player.stop() this.playVideo() - console.log(this.playerIndex, this.videoUrls.length) - }, - }, + } + } } </script> @@ -529,7 +506,7 @@ position: absolute; bottom: 0; left: 0; - z-index: 2147483648; + z-index: 100; width: 100%; height: 40px; line-height: 40px; @@ -554,9 +531,9 @@ background: rgba(255, 255, 255, 0.25); border-radius: 3px; width: 460px; - width: -webkit-calc(100% - 220px); - width: -moz-calc(100% - 220px); - width: calc(100% - 220px); + width: -webkit-calc(100% - 260px); + width: -moz-calc(100% - 260px); + width: calc(100% - 260px); float: left; margin: 19px 0 0 65px; position: relative; @@ -700,6 +677,14 @@ opacity: 0.5; cursor: default; } + + .el-icon-download { + font-size: 24px; + width: 18px; + height: 18px; + margin-top: 7px; + margin-left: -12px; + } } .video-player:hover { @@ -737,4 +722,50 @@ .video-next { right: 0px; } + +.video-error { + position: absolute; + top: 35%; + left: 30%; + font-size: 14px; + color: #fff; +} + +.downloadNotice { + position: absolute; + height: 200px; + width: 200px; + background-color: pink; +} + +.popuptext { + /* display:none; */ + height: 50px; + line-height: 50px; + font-size: 20px; + background-color: #555; + opacity: 0.8; + color: #fff; + text-align: center; + border-radius: 25px; + position: relative; + top: 30px; + z-index: 1; +} + +.fade-enter { + opacity: 0; +} +.fade-enter-active { + transition: opacity 0.5s; +} +.fade-leave-to { + opacity: 0; +} +.fade-leave-active { + transition: opacity 3s; +} +.canvasDiv .el-loading-mask { + z-index: 1000 !important; +} </style> -- Gitblit v1.8.0