功能:ant Design vue使用腾讯播放器实现监控视频直播、点播,多个视频同时播放
第一步安装npm包
npm install tcplayer@0.0.24 --save
第二步封装子组件
<template >
<div :id="`video_container_${index}`" class="video_container"></div>
</template>
<script>
import { TcPlayer } from 'tcplayer'
export default {
name: 'Cviewplayer',
props: {
//默认监控图片
Defaultimage: { type: String, default: '' },
//视频的url
videoUrl: { type: String, default: '' },
//视频的坐标,用于判断div的id赋值到对应的容器
index: { type: Number, default: 0 },
//是否播放
isPlay: { type: Boolean, default: false },
},
data() {
return {
player: [],
poster: '' /* 视频封面 */,
}
},
created() {
this.$nextTick(() => {
this.initPlayer()
})
},
watch: {
isPlay() {
this.$nextTick(() => {
if (this.isPlay) {
this.play()
this.$emit('PlayClose', false)
}
})
},
},
methods: {
initPlayer() {
if (this.player.length) {
this.player.forEach((item) => {
item.destroy()
})
this.player = []
}
var options = {
//视频地址
m3u8: this.videoUrl,
flv: this.videoUrl,
//是否自动播放
autoplay: false,
preload: true,
//暂停时视频封面
poster: { style: 'cover', src: this.Defaultimage },
coverpic: this.Defaultimage,
// live: live,
width: '100%',
height: '100%',
x5_player: true,
x5_type: 'h5-page',
x5_fullscreen: true,
wording: {
1: '网络错误,请检查网络配置或者播放连接是否正确',
1002: '即将开始,请稍等',
2032: '请求视频失败,请检查网络',
2048: '请求m3u8文件失败,多是网络错误或者跨域问题',
},
flash: false, //是否优先使用 flash 播放视频
pausePosterEnabled: true /* 暂停时显示封面 默认为true */,
listener: (msg) => {
if (msg.type == 'load') {
//加载完事件
// this.player.play()
}
if (msg.type == 'ended') {
//播放完成事件
// this.player[this.index].close()
}
// 播放失败,重新连接
if (msg.type == 'error') {
setTimeout(() => {
if (this.player[this.index]?.options.src == undefined) return false
this.player[this.index]?.load() // 重连
}, 4000)
}
},
}
// 初始化
this.player.push(new TcPlayer('video_container_' + this.index, options))
},
// 播放或暂停
play() {
if (this.player.length) {
this.player.forEach((item) => {
//如果没有地址则跳过
if (item.options.src == undefined) return false
item?.play()
})
} else {
this.$message.warning('暂无视频播放源,请检查设置')
}
},
},
}
</script>
<style lang="less" scoped>
.video_container {
width: 100%;
height: 100%;
}
// 修改视频提示语位置
/deep/ .vcp-error-tips {
padding-top: 66px;
}
</style>
第三步父组件调用
<template>
<div class="b-wrapper">
<!-- 按钮组 -->
<div class="buttonList">
<a-button type="primary" @click="VideoPlay">播放</a-button>
<a-button @click="proportionSumbit(1)">1:1</a-button>
<a-button @click="proportionSumbit(2)">2:2</a-button>
<a-button @click="proportionSumbit(3)">3:3</a-button>
<a-button @click="proportionSumbit(4)">4:4</a-button>
</div>
<!-- 视频组 -->
<div class="VideoGirus" :style="`grid-template-columns:${autoNumber} `">
<div v-for="(item, index) in Proportion" :key="index">
<div class="colvideo">
<div
class="titlevideo"
:style="`color:${com.config.textColor};font-weight: ${
com.config.textWeight == true ? '600' : 'normal'
};font-size: ${com.config.textSize};`"
v-show="com.config.isShow"
>
{{ item.title }}
</div>
<cviewplayer
class="cviewplayer"
:key="freshDom"
:videoUrl="item.videoUrl"
:index="item.index"
:isPlay="isPlay"
@PlayClose="PlayClose"
></cviewplayer>
</div>
</div>
</div>
</div>
</template>
<script>
//这个是引用子组件
import cviewplayer from './cview-player'
export default {
name: 'BVideoMonitor',
components: { cviewplayer },
data() {
return {
//赋值时间戳达到刷新的效果
freshDom: '',
//数据的数组
Proportion: [],
//判断比例
autoNumber: 'auto auto auto auto',
//是否播放
isPlay: false,
//存储数据的变量
com:{
//配置
config:{
//标题颜色
textColor:'',
//字体大小
textSize:'',
//默认展示比例: 1(1:1) 2(2:2) 3(3:3) 4(4:4)
defaultProportion: 2,
//是否显示标题栏
isShow:true,
//字体大小
textSize: 'small', //medium / small / mini
//字体加粗
textWeight: false,
//用于播放首个视频用
showVideo: {},
//是否数据新增,修改,删除
isDataUpdate: false
},
//数据
apiData:{
data:[
{
//视频唯一id
id:'0',
//视频状态 根据业务自定义是否需要此字段
status:0,
//视频标题名称
title:'视频地址标题名称',
//视频地址
videoUrl:'https://new.qqaku.com/20220508/s44ly5RX/1100kb/hls/index.m3u8'
}
]
}
},
}
},
created() {
this.fun_into()
},
watch: {
//监听是否更改了视频数据源
'com.config.isDataUpdate': {
handler: function () {
if (this.com.config.isDataUpdate) {
this.proportionSumbit(this.com.config.defaultProportion)
this.com.config.isDataUpdate = false
}
},
},
},
methods: {
//接收子级传来的是否播放状态
PlayClose() {
this.isPlay = false
},
//初始化
fun_into() {
this.proportionSumbit(this.com.config.defaultProportion)
},
//播放事件
VideoPlay() {
this.isPlay = true
},
//视频比例
proportionSumbit(val) {
//grid赋值比例的
this.proportion(val)
this.Proportion = []
this.freshDom = +new Date()
for (var i = 0; i < val * val; i++) {
this.Proportion.push({
id: this.com.apiData.data[i]?.id,
status: this.com.apiData.data[i]?.status,
title: this.com.apiData.data[i]?.title,
videoUrl: this.com.apiData.data[i]?.videoUrl,
index: i,
})
}
},
//grid赋值比例的
proportion(val) {
switch (val) {
case 1:
this.autoNumber = 'auto'
break
case 2:
this.autoNumber = 'auto auto'
break
case 3:
this.autoNumber = 'auto auto auto'
break
case 4:
this.autoNumber = 'auto auto auto auto'
break
default:
this.autoNumber = 'auto auto auto auto'
break
}
},
},
}
</script>
<style lang="less" scoped>
.b-wrapper {
height: 100%;
width: 100%;
> .buttonList {
width: 100%;
margin-top: -10px;
padding-bottom: 10px;
display: flex;
justify-content: flex-start;
flex-direction: row;
> button:first-child {
margin: 0;
width: 80px;
height: 35px;
}
> button {
margin-left: 10px;
width: 80px;
height: 35px;
}
}
> .VideoGirus {
width: 100%;
height: 97%;
// border: 1px dashed #000;
display: grid;
grid-column-gap: 5px;
> div {
width: 100%;
height: 100%;
display: inline-table;
> .colvideo {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
position: relative;
> .titlevideo {
// position: initial;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
position: absolute;
z-index: 1;
height: 35px;
width: 100%;
background-color: #000;
opacity: 0.7;
font-size: 16px;
padding: 4px 0 0 15px;
}
> .cviewplayer {
position: absolute;
width: 100%;
height: 98%;
}
}
}
}
}
</style>
踩坑点
1.该功能中需要同时播放多个视频,因此需要给div赋值唯一的id :id=“video_container_${index}
”
2.因为是自适应布局所有需要给父组件最外层div赋值固定的高宽度
3.刷新视频数据源同时需要给子组件加key进行强制刷新 :key=“freshDom” this.freshDom = +new Date()
4.官网地址:播放器API文档
5.如果无法播放flv的视频,则可能是无法请求到http://cloudcache.tencent-cloud.com/open/qcloud/video/vcplayer/libs/flv.min.1.5.js文件的接口,这种一般是测试电脑局域网防火墙的问题