背景
前一段时间大佬实现了大华摄像头的推流,但是在多路播放直播时,还有一点小问题,我改了一下大佬的多路播放直播,简单记录一下。
前端是Vue项目,用到了flv.js来播放直播流,不过现在flv.js好像没有维护了。
遇到的问题
在开发过程中,遇到了挺多的问题。比如在没有销毁直播流的情况下,又开启了该直播流,这会导致浏览器疯狂报错。如下图所示:
又或者是离开画面后,延时会累加,导致整个画面延时太高。
局部代码
<div v-if="dataList.length > 0" :class="cellClass(i)" v-for="i in selectProportion" :key="i">
<div class="player">
<video :id="'videoElement' + (i-1)" v-if="dataList[i-1].isOn===1" autoplay muted="muted" width="100%" height="100%">
</video>
<div v-else class="videoText">
{{ dataList[i-1].alias }}
<div class="msgVideoText">该设备不存在</div>
</div>
</div>
</div>
import flvjs from "flv.js";
export default {
data() {
return {
select: 0,
//选中的播放数量
selectProportion: 1,
//直播流地址对象数组
dataList: [],
flvPlayer: null,
lastDecodedFrame: 0,
//video标签id
elementId: "",
//flvPlayer数组,方便销毁
flvPlayerArr:[],
}
},
methods: {
changeSelect(item, index) {
this.select = index
this.deviceId = item.deviceId
this.changeMultiVideo()
},
playVideo(device,id) {
let _this=this;
var deviceId = device.deviceId
_this.lastDecodedFrame = 0
_this.elementId = deviceId
let videoWin = ""
videoWin = document.getElementById( 'videoElement'+id);
if (flvjs.isSupported()) {
let flvPlayer = flvjs.createPlayer({
type: "flv",// 媒体类型
isLive: true,//是否是实时流
hasAudio: false,//是否有音频
url: window.SITE_CONFIG.rtmp + deviceId,// 视频流地址
stashInitialSize: 128 // 减少首帧显示等待时长
}, {
enableWorker: false,// 不启动分离线程
enableStashBuffer: false,// 关闭IO隐藏缓冲区
reuseRedirectedURL: true,// 重用301、302重定向url,用于随后的请求,入查找、重新连接等。
autoCleanupSourceBuffer: true, // 自动清除缓存
fixAudioTimestampGap: false,// false 音频同步
});
// 断流重连
flvPlayer.on(flvjs.Events.ERROR, (errorType, errorDetail, errorInfo) => {
console.log("errorType:", errorType);
console.log("errorDetail:", errorDetail);
console.log("errorInfo:", errorInfo);
if (flvPlayer) {
_this.destroyVideo();
}
});
// 画面卡死重连
flvPlayer.on("statistics_info", function (res) {
if (_this.lastDecodedFrame == 0) {
_this.lastDecodedFrame = res.decodedFrames;
return;
}
if (_this.lastDecodedFrame != res.decodedFrames) {
_this.lastDecodedFrame = res.decodedFrames;
} else {
_this.lastDecodedFrame = 0;
if (flvPlayer) {
_this.changeMultiVideo()
}
}
});
flvPlayer.attachMediaElement(videoWin);
flvPlayer.load();
//将启动的直播流添加到数组里,方便统一销毁
_this.flvPlayerArr.push(flvPlayer)
}
},
//销毁断流方法
destroyVideo() {
let _this=this;
for(let i=0;i<_this.flvPlayerArr.length;i++){//卸载已经加载的视频资源
if (_this.flvPlayerArr[i]!=null){
console.log("销毁视频资源")
_this.flvPlayerArr[i].pause();
_this.flvPlayerArr[i].unload();
_this.flvPlayerArr[i].detachMediaElement();
_this.flvPlayerArr[i].destroy();
_this.flvPlayerArr[i]=null;
}
}
},
//不同的播放策略
changeMultiVideo(){
this.destroyVideo()
this.$nextTick(()=>{
console.log(this.selectProportion)
//单个监控则不需要额外的video和id
if (this.selectProportion===1){
if (this.dataList[this.select].isOn===1) {
this.playVideo(this.dataList[this.select], "")
}
}else {
for (let i = 0; i < this.selectProportion; i++) {
if (this.dataList[i].isOn===1){
this.playVideo(this.dataList[i],i)
}
}
}
});
}
},
computed: {
cellClass() {
return function (index) {
switch (this.selectProportion) {
case 1:
return ['cell-player-1']
case 4:
return ['cell-player-4']
case 6:
return ['cell-player-6']
case 9:
return ['cell-player-9']
case 16:
return ['cell-player-16']
default:
break;
}
}
},
},
//切换页面关闭video
deactivated() {
this.destroyVideo()
}
}
结束
做完这个之后,发现浏览器只能播放6路http-flv流,具体如何解决暂时还没想好,看网上说是因为浏览器限制同源HTTP/1.x连接并发个数。最后,我只是个半吊子后端,对vue也不是很熟悉,如有错误还请多多谅解。