连接视频流flv格式和live格式(使用easycvr和萤石云EZUIKitPlayer)
项目需求:要求登录不同城市的账号适配不同的视频流
(1)进入页面判断哪个城市登录并监听
进入页面逻辑,通过videoBol判断视频流是否为flv
created () {
if(this.username() == '**'){
this.videoBol = true
}
},
监听逻辑 created()的执行比watch快
watch: {
fivedata(value) {
if(this.videoBol){
this.toCvr();//easycvr
}else {
this.getToken() //EZUIKitPlayer
}
},
},
页面标签
<div v-if="!videoBol" :id="'video-container' + index" class="h_100 w_100" />
<video v-else :id="'cvr-container' + index" class="video-js" preload="auto" muted autoplay type="rtmp/flv" @click="changevideoIndex(index)"></video>
(2)easycvr逻辑处理
获取数据,视频流需要实时更新,使用setInterval,2分钟刷新一次
toCvr() {
this.videoType = 1
this.getEasycvrVideoList()
this.flvRefresh = setInterval(() => {
console.log("定时刷新flv")
this.getEasycvrVideoList()
}, 120000);
},
// easycvr视频流数据获取
getEasycvrVideoList() {
getAction('socket/new/videoListPlus', {
videoSize: this.videoSize //获取视频数量
}).then(res => {
if (res.code == 0) {
console.log(res.data)
this.easycvrVideoData = res.data //赋值
this.loadVideoDataPlus(); //处理视频数据
}
});
},
对后端数据进行处理
parkId: ****
parkName: "*****"
videoPaths:["https://**********.flv"]
loadVideoDataPlus(){
for (let i = 0; i < this.videoSize; i++) {
if (this.easycvrVideoData[i]) {
this.setPlayerPlus(i, this.easycvrVideoData[i].videoPaths[0]);
if (this.isTest()) { //这一步是方便某些城市地址进行脱敏处理
let str = this.easycvrVideoData[i].parkName;
str = str.substring(0, 1) + '***' + str.substring(str.length - 1, str.length);
this.cvrTitleData.push(str);
} else {
this.cvrTitleData.push(this.easycvrVideoData[i].parkName);
}
console.log(this.cvrTitleData)
} else {
this.cvrTitleData.push('');
}
}
}
渲染
setPlayerPlus(index, path) {
if (index > this.videoSize - 1) {
return
}
this.players.push({ player: null })
console.log('player', this.players)
// http://ip/flv/live/*****.flv
this.$nextTick(() => { //使用定时器是因为,在mounted声明周期里调用,可能会出现DOM没加载出来的原因
var videoElement = document.getElementById('cvr-container' + index); // 获取到html中的video标签
if (flvjs.isSupported()) { //flvjs内置方法,判断游览器是否支持flv格式
let player = this.players[index].player
//因为我这个是复用组件,进来先判断 player是否存在,如果存在,销毁掉它,不然会占用TCP名额
if (player !== null) {
player.pause();
player.unload();
player.detachMediaElement();
player.destroy();
player = null;
}
player = flvjs.createPlayer( //创建直播流,加载到DOM中去
{
type: "flv",
url: path, //你的url地址
isLive: true, //数据源是否为直播流
hasAudio: false, //数据源是否包含有音频
hasVideo: true, //数据源是否包含有视频
enableStashBuffer: true, //是否启用缓存区
},
{
enableWorker: false, //不启用分离线程
enableStashBuffer: false, //关闭IO隐藏缓冲区
autoCleanupSourceBuffer: true, //自动清除缓存
lazyLoad: false,
}
);
this.players[index].player = player
console.log('playertsy', this.players)
player.attachMediaElement(videoElement); //放到dom中去
player.load();//准备完成
//!!!!!!这里需要注意,有的时候load加载完成不一定可以播放,要是播放不成功,用settimeout 给下面的this.player.play() 延时几百毫秒再播放
player.play();//播放
player.on(flvjs.Events.ERROR, (errorType, errorDetail, errorInfo) => {
console.log("errorType:", errorType);
console.log("errorDetail:", errorDetail);
console.log("errorInfo:", errorInfo);
// this.statusMsg="正在重连。。。"
//视频出错后销毁重新创建
if (player) {
this.reloadVideo(player);
}
// 根据需求是否打开
setTimeout(() => {
_this.startPlay(_this.dataList.list[i], i);
console.log('重建', _this.videoElement, item, i);
console.log(_this.dataList.list);
}, 1 * 60 * 1000);
});
}
});
},
(3)萤石云EZUIKitPlayer
萤石云监控有些特别,先调接口拿取accessToken
getAction('****/***').then(res => {
if (res.code == 0) {
this.accessToken = res.data.accessToken;
this.getVideoPah(this.accessToken);
}
});
getVideoPah(accessToken) {
getAction('**/***', { token: accessToken, videoSize: this.videoSize }).then(res => {
if (res.code == 0) {
this.result = res.data;
console.log('result',this.result);
this.loadVideoData();
}
});
},
//数据格式
{
"parkId": 10125,
"parkName": "**医院(监控1)",
"videoPaths": [
"ezopen://**/**/1.live"
]
}
loadVideoData() {
for (let i = 0; i < this.videoSize; i++) {
const wrap = document.getElementById('video-container' + i);
if (document.getElementById('myPlayer' + i)) {
wrap.removeChild(document.getElementById('myPlayer' + i));
}
if (this.result.parkVideos[i]) {
this.setPlayer(i, this.result.parkVideos[i].videoPaths[0]);
if (this.isTest()) {
let str = this.result.parkVideos[i].parkName;
str = str.substring(0, 1) + '***' + str.substring(str.length - 1, str.length);
this.titleData.push(str);
} else {
this.titleData.push(this.result.parkVideos[i].parkName);
}
} else {
this.titleData.push('');
}
}
},
setPlayer(index, path) {
if (index > this.videoSize - 1) {
return
}
const wrap = document.getElementById('video-container' + index);
let video = document.createElement('div')
video.id = "myPlayer" + index
video.style.width = '100%';
video.style.height = "100%";
video.style.overflow = 'hidden';
wrap.appendChild(video);
let player = new EZUIKit.EZUIKitPlayer({
autoplay: true,
id: "myPlayer" + index,
accessToken: this.accessToken,
url: path,
template: "simple", // simple - 极简版;standard-标准版;security - 安防版(预览回放);voice-语音版;
audio: 0, // 是否默认开启声音 0 - 关闭 1 - 开启
splitBasis: 1,
handleSuccess: e => {
this.playCount++;
if (this.playCount == this.result.parkVideos.length && this.hasError) {
let result = this.result.parkVideos.filter(item => {
return this.errorData.indexOf(item.videoPaths[0]) == -1;
})
this.result.parkVideos = result;
this.loadVideoData();
}
},
handleError: e => {
this.playCount++;
this.errorData.push(path);
this.hasError = true;
if (this.playCount == this.result.parkVideos.length) {
let result = this.result.parkVideos.filter(item => {
return this.errorData.indexOf(item.videoPaths[0]) == -1;
})
this.result.parkVideos = result;
this.loadVideoData();
}
}
});
},