点击左侧判断当前数组播放的个数有没有超出,如果有就替换第一个点是做替换的时候会报错
解决方案:
依赖下flv.js/src/core/mse-controller.js
找到appendMediaSegment(),_needCleanupSourceBuffer ()这两个方法,在方法中加入以下代码
if (!this._mediaSource || this._mediaSource.readyState !== 'open') { return; }
在页面flv createPlayer方法中加入 fixAudioTimestampGap: false//false才会音视频同步
之后我点击的时候还是会报,我会在创建前移除要替换的那个数据,再创建就不会报了
<!--
* @Author: 周云芳
* @Date: 2022-04-27 10:52:30
* @LastEditTime: 2022-05-02 18:00:29
* @LastEditors: Please set LastEditors
* @Description: 实时监控
* @FilePath: \web-pc\src\components\realTimeMonito\index.vue
-->
<template>
<div class="video-container">
<div :class="['video-box',dataList.parentClass]" v-if="dataList.list&&dataList.list.length>0">
<template v-for="(item,i) in dataList.list">
<video v-show="item.url" :key="i" :class="[item.className,videoActive == i ? 'active' : ' ']" autoplay :ref="'video'+i" :id="'video'+i" @click="handleVideo(i,item.refs,item.method)"></video>
<div :key="i+ new Date()" v-if="!item.url" class="imags-box">
<el-image class="imgs" :src="require('@/assets/img/shexiangji.png')" fit="fill"></el-image>
</div>
</template>
</div>
</div>
</template>
<script>
import flvjs from 'flv.js'
export default {
name: 'RealTimeVideo',
props: {
dataList: {
type: Object,
default: () => {
return {
className: {
type: [String, Array],
default: ''
},
parentClass: {
type: String,
default: ''
},
refs: {
type: String,
default: ''
},
method: {
type: [String, Function],
default: null
},
url: {
type: String,
default: ''
},
types: {
type: Object,
default: () => {
return {
url: null,
type: 'flv'
}
}
}
}
}
}
},
components: {},
data () {
return {
videoActive: '', // 用于点击当前视频样式
player: null,
videoElement: '',
flvPlayerList: []//用来存储实例
}
},
computed: {
newDataList () {
return JSON.parse(JSON.stringify(this.dataList))
}
},
beforeMount () { },
mounted () {
document.addEventListener("click", this.handeCurVideo)
},
methods: {
// 视频浏览
startPlay (item, i) {
let _this = this
if (flvjs.isSupported()) {
_this.videoElement = document.getElementById("video" + i)
let urlExt = item.url.replace(/.+\./, "");
// let urlExtension = item.url.substring(item.url.lastIndexOf('.') + 1);
_this.player = flvjs.createPlayer({
type: urlExt, // => 媒体类型 flv 或 mp4,m3u8
isLive: true, // => 是否为直播流
hasAudio: false, // => 是否开启声音
url: item.url, // => 视频流地址
stashInitialSize: 128 // 减少首桢显示等待时长
}, {
enableWorker: false, //不启用分离线程
enableStashBuffer: false, //关闭IO隐藏缓冲区
reuseRedirectedURL: true, //重用301/302重定向url,用于随后的请求,如查找、重新连接等。
autoCleanupSourceBuffer: true, //自动清除缓存
fixAudioTimestampGap: false//false才会音视频同步
})
_this.player.attachMediaElement(_this.videoElement) // => 绑DOM
_this.player.load()
_this.player.play()
// 视频错误
_this.player.on(flvjs.Events.ERROR, (errorType, errorDetail, errorInfo) => {
console.log("errorType:", errorType);
console.log("errorDetail:", errorDetail);
console.log("errorInfo:", errorInfo);
// this.statusMsg="正在重连。。。"
//视频出错后销毁重新创建
if (_this.player) {
this.reloadVideo(_this.player);
}
// 根据需求是否打开
// setTimeout(() => {
// _this.startPlay(_this.dataList.list[i], i);
// console.log('重建', _this.videoElement, item, i);
// console.log(_this.dataList.list);
// }, 1 * 60 * 1000);
});
this.flvPlayerList.push(_this.player);
} else {
console.log("flvjs不支持")
}
},
handeCurVideo (e) {
// console.log('选中了视频', e)
// this.$store.commit('videoMonitorSystem/SET_VIDEO_FULL', null)
// if (e.target.id.indexOf(hasVideoId) == -1) {
// // 点击视频之外的区域清空commit,禁用icon,取消边框色
// this.$store.commit('videoMonitorSystem/SET_VIDEO_FULL', null)
// this.videoActive = ''
// }
},
// 选中视频,加入border色及commit选中视频的ID用于父组件进行全屏
handleVideo (i, domid, method) {
// console.log(' 选中视频,加入border色及commit选中视频的ID用于父组件进行全屏', i, domid);
if (method) { // 如果传了方法进入就返回出去方法及参数
let params = {
index: i, domid
}
this.$emit(method, params)
} else {
this.videoActive = i
console.log('handleVideo', domid)
this.$store.commit('videoMonitorSystem/SET_VIDEO_FULL', domid)
}
},
//销毁断流方法
destoryVideo (flvPlayer) {
console.log('销毁断流方法', flvPlayer);
flvPlayer.pause();
flvPlayer.unload();
flvPlayer.detachMediaElement();
flvPlayer.destroy();
flvPlayer = null;
},
reloadVideo (flvPlayer) {
this.destoryVideo(flvPlayer);
// this.startPlay();
}
},
watch: {
newDataList: {
immediate: true,
deep: true,
handler (cuVal, oldVal) {
if (cuVal.list) {
this.$nextTick(() => { // 获取不同数据下标并更新到DOM
console.log('this.flvPlayerList', this.flvPlayerList);
if (this.flvPlayerList.length > 3) {//这个大于多少根据需求设计,这里才是不报错的重点
this.destoryVideo(this.flvPlayerList[0]);
this.flvPlayerList.shift();
}
if (oldVal && oldVal.list) {
for (let idx = 0; idx < cuVal.list.length; idx++) {
const cur = cuVal.list[idx]
for (let i = 0; i < oldVal.list.length; i++) {
const old = oldVal.list[i]
if (cur.refs == old.refs && cur.url !== old.url) { // 如果ID相同,url不相同就给当前的地址更改并播放
// console.log(cur, cur.url, idx)
this.startPlay(cur, idx)
}
}
}
}
})
}
}
}
},
beforeDestroy () {
window.removeEventListener('click', this.handeCurVideo)
}
}
</script>
<style lang='scss' scoped>
@import './style/index.scss';
.video-box {
}
</style>