<template>
|
<div class="videoBox" @mouseenter="handleEnter" @mouseleave="handleLeave">
|
<div class="video" ref="videoRef" style="width: 100%; height: 100%"></div>
|
<div class="playerBtn">
|
<el-icon class="icon" v-if="showPlay" @click="handlePlayer"><VideoPlay /></el-icon>
|
<el-icon class="icon" v-if="showPause" @click="hanlePause"><VideoPause /></el-icon>
|
<el-icon class="icon is-loading" v-if="showLoading"><Loading /></el-icon>
|
</div>
|
</div>
|
</template>
|
|
<script setup lang="ts">
|
import {onMounted, onUnmounted, ref} from 'vue';
|
import { getVideoMedia, stopVideoMedia, renewVideoMedia } from '@/api/screen/video';
|
import { debounce } from '@/utils/tool';
|
|
const props = defineProps({
|
item: {
|
type: Object,
|
default: {}
|
},
|
autoPlay: {
|
type: Boolean,
|
default: false
|
}
|
});
|
|
const videoRef = ref(null);
|
const videojsb = ref();
|
const showPlay = ref(true);
|
const showPause = ref(false);
|
const showLoading = ref(false);
|
let timer = null;
|
|
//通知设备上传媒体流,做节流,防止过度点击
|
const handlePlayer = debounce(function() {
|
showPlay.value = false;
|
showLoading.value = true;
|
// 获取播放地址
|
getVideoMedia(props.item.deviceId, props.item.channelId).then(res => {
|
videojsb.value.play(res.data.url);
|
}).catch(() => {
|
showPlay.value = true;
|
}).finally(() => {
|
showLoading.value = false;
|
})
|
// 挂定时任务,2分钟获取一次直播流数据,防止客户关闭页面,如果2分钟未获取,后端断开链接
|
if(timer) clearInterval(timer)
|
timer = setInterval(() => {
|
// 调用续时点播
|
renewVideoMedia(props.item.deviceId, props.item.channelId)
|
}, 120000)
|
}, 2000, true)
|
|
const hanlePause = () => {
|
showPause.value = false;
|
showPlay.value = true;
|
clearInterval(timer)
|
stopVideoMedia(props.item.deviceId, props.item.channelId).then(() => {
|
console.log('关闭成功')
|
})
|
}
|
|
const handleEnter = () => {
|
if(!showPlay.value && !showLoading.value) {
|
showPause.value = true;
|
}
|
}
|
|
const handleLeave = () => {
|
showPause.value = false;
|
}
|
|
// 实例化dom节点
|
const initDom = async () => {
|
videojsb.value = new window.Jessibuca(
|
Object.assign({
|
container: videoRef.value,
|
isResize: true,
|
isFullResize: true,
|
text: '',
|
videoBuffer: 2,
|
loadingText: '加载中...',
|
useMSE: true,
|
useWCS: true,
|
autoWasm: true,
|
// debug: true,
|
supportDblclickFullscreen: false,
|
operateBtns: {
|
fullscreen: true,
|
play: false,
|
audio: true,
|
recorder: false,
|
},
|
controlAutoHide: true,
|
forceNoOffscreen: true,
|
isNotMute: false,
|
heartTimeoutReplay:false,
|
})
|
);
|
}
|
|
// 初始化
|
const init = async () => {
|
await initDom()
|
// 自动播放
|
if(props.autoPlay && props.item.deviceId && props.item.channelId) {
|
handlePlayer()
|
}
|
};
|
|
onMounted(() => {
|
init();
|
});
|
|
onUnmounted(() => {
|
if(videojsb.value) {
|
videojsb.value.destroy();
|
}
|
if(timer) clearInterval(timer)
|
})
|
|
|
// 外抛方法
|
defineExpose({
|
handlePlayer
|
})
|
</script>
|
|
<style scoped lang="scss">
|
.videoBox {
|
width: 100%;
|
height: 100%;
|
position: relative;
|
.video {
|
width: 100%;
|
height: 100%;
|
background-color: #000;
|
}
|
.playerBtn {
|
width: 4rem;
|
height: 4rem;
|
position: absolute;
|
left: 50%;
|
top: 50%;
|
transform: translate(-50%, -50%);
|
z-index: 100;
|
.icon {
|
color: #fff;
|
font-size: 3rem;
|
}
|
}
|
:deep(.jessibuca-controls) {
|
background-color: transparent;
|
}
|
}
|
</style>
|