|
|
@@ -1,29 +1,28 @@
|
|
|
<template>
|
|
|
<div
|
|
|
class="o-video"
|
|
|
- :class="{ offline: !online }"
|
|
|
- @mouseenter.stop="mouseOver"
|
|
|
- @mouseleave.stop="mouseLeave"
|
|
|
+ :class="{ offline: !online, mask: showMask }"
|
|
|
>
|
|
|
- <video
|
|
|
- v-if="online"
|
|
|
- ref="player"
|
|
|
- class="o-video__player o-simple-video"
|
|
|
- muted
|
|
|
- :poster="poster"
|
|
|
- />
|
|
|
- <slot />
|
|
|
- <div
|
|
|
- v-show="maskShow"
|
|
|
- class="o-video__mask"
|
|
|
- >
|
|
|
- <div
|
|
|
- class="l-flex--row center o-video__btn u-pointer"
|
|
|
- @click="onClick"
|
|
|
- >
|
|
|
- <i :class="iconClass" />
|
|
|
+ <template v-if="online">
|
|
|
+ <video
|
|
|
+ ref="video"
|
|
|
+ class="o-video__player o-simple-video"
|
|
|
+ :poster="poster"
|
|
|
+ autoplay
|
|
|
+ muted
|
|
|
+ @pause="onPause"
|
|
|
+ @play="onPlay"
|
|
|
+ />
|
|
|
+ <div class="o-video__mask">
|
|
|
+ <div
|
|
|
+ class="l-flex--row center o-video__btn u-pointer"
|
|
|
+ @click="onClick"
|
|
|
+ >
|
|
|
+ <i :class="iconClass" />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
+ </template>
|
|
|
+ <slot />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
@@ -40,10 +39,6 @@ export default {
|
|
|
type: Object,
|
|
|
required: true
|
|
|
},
|
|
|
- simple: {
|
|
|
- type: [Boolean, String],
|
|
|
- default: false
|
|
|
- },
|
|
|
autoplay: {
|
|
|
type: [Boolean, String],
|
|
|
default: false
|
|
|
@@ -53,12 +48,14 @@ export default {
|
|
|
return {
|
|
|
poster: videoPoster,
|
|
|
loading: false,
|
|
|
- maskShow: false,
|
|
|
refreshShow: false,
|
|
|
- paused: !this.autoplay
|
|
|
+ paused: false
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
+ showMask () {
|
|
|
+ return this.loading || this.refreshShow || this.paused
|
|
|
+ },
|
|
|
iconClass () {
|
|
|
if (this.loading) {
|
|
|
return 'el-icon-loading'
|
|
|
@@ -79,20 +76,21 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
beforeDestroy () {
|
|
|
- if (this.$player) {
|
|
|
- this.destroyPlay()
|
|
|
- }
|
|
|
+ this.destroyPlayer()
|
|
|
this.$timer = null
|
|
|
},
|
|
|
methods: {
|
|
|
- mouseOver () {
|
|
|
- if (!this.online) {
|
|
|
- return
|
|
|
- }
|
|
|
- this.maskShow = true
|
|
|
+ onPause () {
|
|
|
+ this.paused = true
|
|
|
},
|
|
|
- mouseLeave () {
|
|
|
- this.maskShow = false
|
|
|
+ onPlay () {
|
|
|
+ this.paused = false
|
|
|
+ if (this.loading) {
|
|
|
+ this.loading = false
|
|
|
+ if (!this.autoplay) {
|
|
|
+ this.$player.pause()
|
|
|
+ }
|
|
|
+ }
|
|
|
},
|
|
|
onClick () {
|
|
|
if (this.loading) {
|
|
|
@@ -100,7 +98,7 @@ export default {
|
|
|
}
|
|
|
if (this.refreshShow) {
|
|
|
if (this.$player) {
|
|
|
- this.destroyPlay()
|
|
|
+ this.destroyPlayer()
|
|
|
}
|
|
|
this.getAuthCode()
|
|
|
} else {
|
|
|
@@ -124,94 +122,72 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
() => {
|
|
|
- this.refreshShow = true
|
|
|
+ this.destroyPlayer()
|
|
|
}
|
|
|
- ).finally(() => {
|
|
|
- this.loading = false
|
|
|
- })
|
|
|
+ )
|
|
|
},
|
|
|
createPlayer ({ timestamp, token, expire }) {
|
|
|
if (flvjs.isSupported()) {
|
|
|
- // 创建一个flvjs实例
|
|
|
- this.$player = flvjs.createPlayer({
|
|
|
+ const player = flvjs.createPlayer({
|
|
|
type: 'flv',
|
|
|
isLive: true,
|
|
|
hasAudio: false,
|
|
|
url: `${GATEWAY}/live/${this.device.id}.flv?authorization=${token}×tamp=${timestamp}&expire=${expire}`
|
|
|
})
|
|
|
- this.$player.on('error', () => {
|
|
|
- this.refreshShow = true
|
|
|
- this.destroyPlay()
|
|
|
+ player.on(flvjs.Events.ERROR, e => {
|
|
|
+ console.log('flvjs', this.device.name, flvjs.Events.ERROR, e)
|
|
|
+ this.destroyPlayer()
|
|
|
this.$message({
|
|
|
type: 'warning',
|
|
|
- message: '设备视频流出错'
|
|
|
+ message: `${this.device.name} 视频流出错`
|
|
|
})
|
|
|
})
|
|
|
- let decodedFrames = 0
|
|
|
- this.$player.on('statistics_info', res => {
|
|
|
- decodedFrames = res.decodedFrames
|
|
|
+ player.on(flvjs.Events.METADATA_ARRIVED, () => {
|
|
|
+ console.log('flvjs', this.device.name, flvjs.Events.METADATA_ARRIVED)
|
|
|
+ clearTimeout(this.$timer)
|
|
|
})
|
|
|
- this.$timer = setTimeout(() => {
|
|
|
- if (decodedFrames === 0) {
|
|
|
- this.destroyPlay()
|
|
|
- this.$message({
|
|
|
- type: 'warning',
|
|
|
- message: `${this.device.name}设备没有视频流`
|
|
|
- })
|
|
|
- this.refreshShow = true
|
|
|
- }
|
|
|
- }, 10000)
|
|
|
- // 将实例挂载到video元素上面
|
|
|
- this.$player.attachMediaElement(this.$refs.player)
|
|
|
|
|
|
try {
|
|
|
- // 开始运行加载 只要流地址正常 就可以在h5页面中播放出画面了
|
|
|
- this.$player.load()
|
|
|
- this.$player.play()
|
|
|
- if (this.paused) {
|
|
|
- this.$player.pause()
|
|
|
- }
|
|
|
this.refreshShow = false
|
|
|
+ this.$player = player
|
|
|
+ this.$timer = setTimeout(() => {
|
|
|
+ if (this.loading) {
|
|
|
+ this.destroyPlayer()
|
|
|
+ this.$message({
|
|
|
+ type: 'warning',
|
|
|
+ message: `暂未获取到 ${this.device.name} 的视频流`
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }, 10000)
|
|
|
+ player.attachMediaElement(this.$refs.video)
|
|
|
+ player.load()
|
|
|
} catch (error) {
|
|
|
- console.log('连接websocker异常', error)
|
|
|
+ console.log('连接异常', error)
|
|
|
+ this.destroyPlayer()
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
- destroyPlay () {
|
|
|
+ destroyPlayer () {
|
|
|
clearTimeout(this.$timer)
|
|
|
- this.$player.pause()
|
|
|
- this.$player.unload()
|
|
|
- this.$player.detachMediaElement()
|
|
|
- this.$player.destroy()
|
|
|
- this.$player = null
|
|
|
+ this.loading = false
|
|
|
+ this.refreshShow = true
|
|
|
+ const player = this.$player
|
|
|
+ if (player) {
|
|
|
+ player.pause()
|
|
|
+ player.unload()
|
|
|
+ player.detachMediaElement()
|
|
|
+ player.destroy()
|
|
|
+ this.$player = null
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-.o-video {
|
|
|
- &__mask {
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- background-color: rgba(0, 0, 0, 0.3);
|
|
|
- z-index: 2;
|
|
|
- }
|
|
|
-
|
|
|
- &__btn {
|
|
|
- position: absolute;
|
|
|
- left: 50%;
|
|
|
- top: 50%;
|
|
|
- width: 64px;
|
|
|
- height: 64px;
|
|
|
- color: #fff;
|
|
|
- font-size: 48px;
|
|
|
- border-radius: 50%;
|
|
|
- background-color: rgba(#000, 0.5);
|
|
|
- transform: translate(-50%, -50%);
|
|
|
+.o-video:hover {
|
|
|
+ .o-video__mask {
|
|
|
+ display: inline-block;
|
|
|
}
|
|
|
}
|
|
|
</style>
|