系列文章目录
vue前端对接监控视频 FLV格式
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
西瓜视频
前言
接触智慧园区,智慧工地,水泵站等项目之后,发现都有实时监控的对接,并且是可以多屏进行,就研究了相关的技术栈,找到了这个强大的播放器对前端还是很友好的,话不多说上干货!!!
提示:代码片段里有博主对的接口,读代码的时候注意
一、准备工作
1. 使用npm 、cnpm、yarn 下载如下插件
2. npm install xgplayer
3. npm install xgplayer-flv
4. npm install xgplayer-flv.js
下好以后在 package.json 检查一下
二、引入到index的文件当中
1.引入库、介绍
代码如下(示例):
import Player from"xgplayer";// 这是他的一个方法import FlvPlayer from"xgplayer-flv";// 这个是搭配上面哪个使用的import'xgplayer/dist/index.min.css'// 这个是播放器的样式 ,可以在当前页面使用,也可以放全局let a =newPlayer({id:this.playList[0].id,// 对应<div :id='this.playList[0].id'></div> isLive:true,// 是否是直播,plugins:[FlvPlayer],// 视频播放的方式url:'你的视屏地址',// 地址autoplay:true,// lang:"zh-cn",// 是否自动播放,autoplayMuted:true,//是否自动静音自动播放screenShot:true,//是否使用截图插件rotate:false,//是否使用旋转插件download:false,//是否使下载按钮pip:false,//是否使用画中画插件mini:false,//是否启用mini小窗插件playbackRate:[0.5,0.75,1,1.5,2],//倍速插件显示列表});
2.开始绘制页面
提示 :这里用到了Element-ui的tree组件,还有博主自己写一些样式就直接拿过来的 取自己用的即可
代码如下(示例):
<template><divclass="list"><divclass="lsieqqwe"><divclass="boseList bgImg"><span@click="getall"style="color: #fff;margin-left: 12px;font-size: 16px">设备分组</span></div><divstyle="padding: 5px"><el-inputv-model="deptName"placeholder="请输入部门名称"clearablesize="small"prefix-icon="el-icon-search"style="margin-bottom: 5px"/></div><divclass="treeDataLsit"><el-treeclass="filter-tree":data="treeData"ref="tree":props="defaultProps"node-key="id"default-expand-all:expand-on-click-node="false"highlight-current@node-click="handleNodeClick":filter-node-method="filterNode"><spanslot-scope="{ node, data }"class="customize-tree-p"><divclass="haha"v-if="node.level == 3"><img:src="
data.isOnline == 1
? '/img/isOnlinetrue.png'
: '/img/isOnlinefalse.png'
"alt=""/><span>{{ data.channelName }} </span></div><spanv-else>{{ data.channelName }} </span></span></el-tree></div><divstyle="
width: 100%;
height: 42%;
display: flex;
flex-direction: column;
position: relative;
"><divclass="control toplst"v-if="zheDielist"@click="zheDielist = false"><div></div><div>云台控制</div><div><imgsrc="@/assets/carmear/xiala.png"alt=""/></div></div><divv-if="zheDielist"style="height: 90%;flex: 1;margin-top: 65px"><divclass="control_list"><img@mousedown="cameraBtn(1)"@mouseup="mouseup(1)"class="ShArrows"src="@/assets/jianTou/shang.png"alt=""/><img@mousedown="cameraBtn(2)"@mouseup="mouseup(2)"class="XArrows"src="@/assets/jianTou/xia.png"alt=""/><img@mousedown="cameraBtn(3)"@mouseup="mouseup(3)"class="ZArrows"src="@/assets/jianTou/zuo.png"alt=""/><img@mousedown="cameraBtn(4)"@mouseup="mouseup(4)"class="YArrows"src="@/assets/jianTou/you.png"alt=""/><img@mousedown="cameraBtn(7)"@mouseup="mouseup(7)"class="YSArrows"src="@/assets/jianTou/Yshang.png"alt=""/><img@mousedown="cameraBtn(8)"@mouseup="mouseup(8)"class="YXArrows"src="@/assets/jianTou/Yxia.png"alt=""/><img@mousedown="cameraBtn(6)"@mouseup="mouseup(6)"class="ZXArrows"src="@/assets/jianTou/Zxia.png"alt=""/><img@mousedown="cameraBtn(5)"@mouseup="mouseup(5)"class="ZSArrows"src="@/assets/jianTou/Zshang.png"alt=""/></div><divclass="footerLsitStyle_why"><divstyle="padding: 5px"@mousedown="BigCamera(1)"@mouseup="BigCameraMouseup(1)"><imgsrc="@/assets/jianTou/magnify.png"alt=""/></div><divstyle="padding: 5px;border-left: 2px solid #1f4075"@mousedown="BigCamera(2)"@mouseup="BigCameraMouseup(2)"><imgsrc="@/assets/jianTou/reduce.png"alt=""/></div></div></div><divclass="control footer"v-else@click="zheDielist = true"><div></div><div>云台控制</div><div><imgsrc="@/assets/carmear/xiala.png"alt=""/></div></div></div></div><divstyle="width: 100%;padding: 10px"><divclass="carStyle"><divclass="shexinag"><divstyle="margin-left: 40px;display: flex"><divstyle="padding: 6px;font-size: 17px":class="1 == 1 ? 'tableLIstStyle ' : 'table_hui'">
实时监控
</div><divstyle="padding: 5px;font-size: 17px":class="1 == 2 ? 'tableLIstStyle' : 'table_hui'">
录像回放
</div></div></div></div><ul:class="1 != 1 ? 'FenPingCenter_box' : 'FenPingCenter_list_box'"><li:class="
item == FenPingCenType ? 'FenPingCenter_Ui' : 'FenPingCenter_li'
"v-for="(item, index) in IconFontNumber":key="item":style="{ width: 100 / IconFontTypenumber + '%' }"><divclass="FenPingLise"v-if="item == mouType"><button@click="playerBtnItem(index)">关 闭</button></div><divclass="divVide":id="'FenPingCenter_li' + index"@mouseenter="mouseenteBtn(item)"@click="
FenPingCenClick({ type: item, Nme: 'FenPingCenter_li' + index })
"></div></li></ul><divclass="footer_box"><divclass="iconFlist_box"><spanstyle="color: #fff">分屏 : </span><i@mousedown="FenPing(item)"v-for="item in IconFont":key="item.className":class="
item.number == IconFontNumber
? ` iconFlist ${item.className}`
: ` iconStyle ${item.className}`
"></i></div><div><ulclass="operationUl"><liv-for="(item, index) in operationArray":key="index"@click="FooterBtn(item)"><div><img:src="item.image"alt=""/></div><div>{{ item.name }}</div></li></ul></div></div></div></div></template>
定义的变量
data(){return{FenPingCenType:null,// mouType:null,destroyType:null,// 判断是否销毁zheDielist:false,// 左侧云台控制显示uuidv4:'',// uuid 视频放大时使用treeData:[// 左侧 tree 的数据{id:1,channelName:"全部",children:[],},],// 图标IconFontNumber:1,IconFontTypenumber:1,IconFont:[{className:'iconfont icontiFenPingOne',number:1,},{className:'iconfont icontiFenPingSi',number:4,},{className:'iconfont icontiFenPingLiu',number:6,},],operationArray:[// 分屏数据// {// name: '抓拍',// image: require('../../../assets/carmear/zhuapai.png')// },// {// name: '放大',// image: require('../../../assets/carmear/BigList.png')// },// {// name: '录像',// image: require('../../../assets/carmear/luxiang.png')// },// {// name: '音频',// image: require('../../../assets/carmear/yinpin.png')// },// {// name: '对讲',// image: require('../../../assets/carmear/duijiang.png')// },// {// name: '全屏',// image: require('../../../assets/carmear/qaunping.png')// },],// tree 重置 数据的属性名defaultProps:{children:'children',label:'channelName'},// 部门名称deptName:undefined,// 用于筛选tree 数据selectArry:'',playList:[],// 所有视频的 实例cameraName:null,// 判断是否选中视频checkchannelId:null// 调取视频接口 接收 其他页面传过来的数据};},
css样式
<style lang="scss" scoped>
.list{width: 100%;padding: 20px;height: 90vh;display: flex;overflow-y: auto;background-color: #040c1e;.lsieqqwe{width: 20%;border: 1px solid #13355a;.boseList{padding: 5px;padding-left: 20px;font-size: 17px;}.bgImg{background-size: 100%, 100%;background-image:url("../../../assets/carmear/reight.png");}}.control{display: flex;justify-content: space-between;align-items: center;text-align: center;border-top: 2px solid #409eff;height: 10%;padding: 5px;color: #fff;background:linear-gradient(180deg, #246ab1 0%, #183a74 100%);img{width: 30px;}}.control_list{width: 100%;height: 210px;background-image:url("../../../assets/carmear/yuanpan.png");background-size: 100% 100%;background-repeat: no-repeat;position: relative;.ShArrows{position: absolute;top: 0;left: 0;margin-top: 9%;margin-left: 42%;}.XArrows{position: absolute;top: 0;left: 0;margin-top: 58%;margin-left: 42%;}.ZArrows{position: absolute;top: 0;left: 0;margin-top: 28%;margin-left: 17%;}.YArrows{position: absolute;top: 0;right: 0;margin-top: 28%;margin-right: 18%;}.YSArrows{position: absolute;top: 0;right: 0;margin-top: 15%;margin-right: 28%;}.YXArrows{position: absolute;top: 0;right: 0;margin-top: 50%;margin-right: 28%;}.ZXArrows{position: absolute;top: 0;left: 0;margin-top: 50%;margin-left: 28%;}.ZSArrows{position: absolute;top: 0;left: 0;margin-top: 16%;margin-left: 28%;}}.footerLsitStyle_why{padding: 5px;display: flex;justify-content: space-between;div{text-align: center;flex: 1;background-color: #183a74;img{width: 2rem;}}}.carStyle{width: 100%;height: 50px;.shexinag{width: 100%;height: 100%;display: flex;background-size: 100%, 100%;background-repeat: no-repeat;background-image:url("../../../assets/carmear/left.png");}.tableLIstStyle{color: #54c0ff;border-top: 3px solid #54c0ff;}.table_hui{border-top: 3px solid #54c0ff00;}}.footer_box{display: flex;padding: 10px;align-items: center;border: 1px solid #1d4a92;justify-content: space-between;.operationUl{display: flex;li{margin-right: 10px;text-align: center;}img{width: 30px;}}}.iconFlist_box{display: flex;font-size: 20px;.iconFlist{color: #239de7;font-size: 25px;margin-right: 15px;}.iconStyle{color: #6e809c;font-size: 25px;margin-right: 15px;}}}.footer{bottom: 0;right: 0;position: absolute;width: 100%;height: 45px;}.toplst{top: 0;left: 0;position: absolute;width: 100%;height: 45px;}.FenPingCenter_box{width: 100%;height: 80%;display: flex;flex-wrap: wrap;background-color: #ce9292;.FenPingCenter_li{border: 1px solid #25a9f6;background-color: #0c3781;position: relative;overflow: hidden;}.FenPingCenter_Ui{border: 2px solid #d18109;background-color: #0c3781;position: relative;overflow: hidden;}.FenPingLise{position: absolute;z-index: 99999;}}::v-deep.FenPingCenter_list_box:first-child{width: 66% !important;border: 10px solid red !important;}.FenPingCenter_list_box{height: 80%;display: flex;flex-wrap: wrap;background-color: #ce9292;.FenPingCenter_li{border: 1px solid #25a9f6;background-color: #0c3781;position: relative;overflow: hidden;}.FenPingCenter_Ui{border: 2px solid #d18109;background-color: #0c3781;position: relative;overflow: hidden;}.FenPingLise{position: absolute;z-index: 99999;}}// .leftbox{.treeDataLsit{height: 48%;
// height: 78%;border: 1px solid #1e5494;overflow-y: auto;::v-deep .el-tree{color:rgba(255, 255, 255, 0.7);.el-tree-node__content:hover{background-color: #0c3781 !important;}&.el-tree--highlight-current
.el-tree-node.is-current
> .el-tree-node__content{background-color: #0c3781 !important;}}}.el-tree--highlight-current{background-color: #040c1e !important;}.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content{background-color: #0c3781 !important;}.el-tree-node__content{background-color: red !important;}::v-deep .el-input--small .el-input__inner{background-color: #040c1e !important;border: none;}</style>
<style lang="scss">
.divVide{width: 100% !important;position: relative !important;height: 100%;
// border: 1px solid red;}::v-deep video{height: 50% !important;}.player-content{width: 100%;height: 10%;position: absolute;display: block;}// .iconqingxiLOGO{
// display: none !important;
// }#FenPingCenter_li0,
#FenPingCenter_li1,
#FenPingCenter_li2,
#FenPingCenter_li3,
#FenPingCenter_li4,
#FenPingCenter_li5,
#FenPingCenter_li6,
#FenPingCenter_li7,
#FenPingCenter_li8{height: 100% !important;}// .xgplayer-fullscreen,
.xgplayer-cssfullscreen,
.xgplayer-volume,
.icon-text{display: none !important;}
</style>
三核心代码的书写
- video 划入事件
// video 划入事件mouseenteBtn(value){this.mouType = value;
console.log(11111)},
- video 划出事件
// video 划入事件mouseout(){setTimeout(()=>{this.mouType =null},1000)},
提示:视频出来后 显示 全屏或者 抓拍的 按钮 这个块不需要 如果是就一个平并且需要写自己的全屏抓拍样式的话可以用道 这个播放器本身带这些功能 只是样式不好看
FooterBtn(FooterObj){
console.log(FooterObj.name)if(FooterObj.name =='全屏'){// this.playList[this.FenPingCenType -1].ShiLi.getFullscreen()}elseif(FooterObj.name =='抓拍'){let aasd =""// 这格式掉后端的接口xxxx({id:this.defaultPropsBtnBjc.deviceCode }).then(res=>{
aasd = res.msg
window.open(aasd).download()})}},
- 分屏按钮 分别为 单屏 、四平、六平
// 分屏按钮FenPing(value){/*
1.当你点击下方的三个图标的时候,分别获取 4 ,3 ,1三个值
对应下面的三个判断
2. 将对应的盒子添加上是shili:'' ,id(对应的上每一个盒子),当前视频的状态
*/this.IconFontNumber = value.number
console.log(value.number)if(value.number ==4){this.IconFontTypenumber =2for(let index =1; index <4; index++){this.playList.push({ShiLi:null,id:`${'FenPingCenter_li'+ index}`,type:0,flg:false})}}else{this.IconFontTypenumber =3for(let index =1; index <6; index++){this.playList.push({ShiLi:null,id:`${'FenPingCenter_li'+ index}`,type:0,flg:false})}}if(value.number ==1){this.IconFontTypenumber =1this.playList =this.playList.splice(0,1)this.$forceUpdate()}},
- 每个分屏 的 实例销毁 按钮
playerBtnItem(index){
console.log(index);// 这个index是下标/**
1.实例销毁调用.ShiLi.destroy();这个方法
2.初始化当前的数据的状态
*/this.mouType =null;this.destroyType =true;// // 视频的销毁this.playList[index].ShiLi.destroy();this.playList[index].ShiLi =null;this.playList[index].flg =true;this.playList[index].type =0;},
- 联合tree node-click事件
handleNodeClick(value){this.defaultPropsBtnBjc = value
console.log(value)let a =[]/**
* 判断是否是tree的最里层的数据
*/if(!value.children){this.playList.forEach(item=>{if(item.type ==1){
a.push(item.type)}})// 接口xxxxx({channelId: value.channelCode ||this.checkchannelId }).then(res=>{let b = a.length
/**
* 判断是否是 选中 容器
* 如果选择容器
* 判断他是否为null 查找到他的下标
* 拿容器ID 生成 播放器实例
* 并且插入到 实例的数据组中
* 将播放状态 改为 1
* */if(this.cameraName &&!this.destroyType){let player =newPlayer({id:this.cameraName,isLive:true,plugins:[FlvPlayer],url: res.data.url,autoplay:true,lang:"zh-cn",autoplayMuted:true,"screenShot":true});this.playList[this.FenPingCenType -1].ShiLi = player
this.playList[this.FenPingCenType -1].type =1}else{/**
* 判断是否是 是否是 销毁实例后
* 判断他是否为null 查找到他的下标
* 拿容器ID 生成 播放器实例
* 并且插入到 实例的数据组中
* 将播放状态 改为1
* */if(this.destroyType){let iB =this.playList.findIndex(item=>{return item.ShiLi ==null})
console.log(iB,'ppppppp',this.FenPingCenType)if(this.FenPingCenType){this.playList[this.FenPingCenType -1].ShiLi =newPlayer({id:this.cameraName,isLive:true,plugins:[FlvPlayer],url: res.data.url,autoplay:true,lang:"zh-cn",autoplayMuted:true,"screenShot":true});this.playList[this.FenPingCenType -1].type =1this.destroyType =!this.playList.every(item=> item.type ==1)// this.classLList()}else{this.playList[iB].ShiLi =newPlayer({id:this.playList[iB].id,isLive:true,plugins:[FlvPlayer],url: res.data.url,autoplay:true,lang:"zh-cn",autoplayMuted:true,"screenShot":true});this.playList[iB].type =1this.destroyType =!this.playList.every(item=> item.type ==1)}}else{for(let i =0; i <this.playList.length; i++){if(this.IconFontTypenumber ==1){this.playList.forEach(item=>{if(item.ShiLi !=null){
item.ShiLi.destroy();
item.ShiLi =null;
item.type =0;let a =newPlayer({id:this.playList[0].id,isLive:true,plugins:[FlvPlayer],url: res.data.url,autoplay:true,lang:"zh-cn",autoplayMuted:true,"screenShot":true,});
item.ShiLi = a
}return item
})}
console.log(9999)if(this.playList[i].ShiLi ==null){this.playList[b].ShiLi =newPlayer({id:this.playList[b].id,isLive:true,plugins:[FlvPlayer],url: res.data.url,autoplay:true,lang:"zh-cn",autoplayMuted:true,"screenShot":true,playsinline:true,height: window.innerHeight,width: window.innerWidth
});this.playList[b].type =1break;}}}}})}},
- 下面的代码是防止报错加的
// 云台控制必须是球机-上下左右转动cameraBtn(value){},// 停止事件xx`qmouseup(value){},// 放大开始事件BigCamera(value){},// 放大结束事件BigCameraMouseup(value){}
到此也就结束,使用代码片段的时候需要将图片替换一下不然会出现路径的问题
本文转载自: https://blog.csdn.net/id_EquinoxFlower/article/details/132076520
版权归原作者 LZQ <=小氣鬼=> 所有, 如有侵权,请联系我们删除。
版权归原作者 LZQ <=小氣鬼=> 所有, 如有侵权,请联系我们删除。