新版
1、npm install tcplayer.js
建议使用版本 "tcplayer.js": "^4.8.0", 5.0的版本需要什么licensource
<tcplayer v-if="i.videoStream" :enableFlag="true" :src="i.videoStream"></tcplayer>
以下是组件代码
<template>
<div class="component-player">
<div ref="video-outer" v-show="enableFlag" class="player-outer"></div>
<el-image v-show="!enableFlag" src="/images/no-single.gif" fit="cover" />
<div class="no-single" v-show="!enableFlag">
<p>
<strong>无法连接</strong>
<span>connection failure</span>
</p>
</div>
</div>
</template>
<script setup lang="ts">
import TCPlayer from 'tcplayer.js';
import 'tcplayer.js/dist/tcplayer.min.css';
import { reactive, watch, nextTick, getCurrentInstance, onBeforeUnmount } from "vue";
const { proxy } = getCurrentInstance();
const props = defineProps({
enableFlag: Boolean,
src:String,
});
const state = reactive({
player: null,
});
watch(() => props.enableFlag, (n, o) => {
if(n){
nextTick(()=>initPlayer())
}
else{
nextTick(()=>state.player && state.player.pause())
}
}, { immediate: true })
onBeforeUnmount(() => {
if(state.player) state.player.dispose();
})
function initPlayer(){
if(state.player) state.player.dispose();
let domId = `video${Math.floor(Math.random()*(99999-10000+1))+parseInt(10000)}`
let dom = document.createElement('video')
dom.setAttribute('class', 'video')
dom.setAttribute('id', domId)
dom.setAttribute('class', 'video')
dom.setAttribute('id', domId)
proxy.$refs['video-outer'].appendChild(dom)
state.player = TCPlayer(domId, {
sources: [{ src: props.src }], //此处不用添加视频流类型,会自动识别视频流格式的
// m3u8: props.src,
autoplay: true, // 是否自动播放
controls: true,
live: false,
muted: true,
controlBar: {
playbackRateMenuButton: true, //是否显示播放速率选择按钮。
volumePanel: false,
durationDisplay: false,
currentTimeDisplay: false,
timeDivider: false,
//volumePanel: false,
progressControl: false,
},
listener: function (msg) {
console.log('error',msg)
// 播放失败,重新连接
// if (msg.type == "error") {
// setTimeout(() => {
// state.player.load(); // 重连
// }, 400);
// }
}
});
state.player.on('canplay', event=> {
proxy.$emit('loadDone',false)
})
}
</script>
<style lang="less" scoped>
.component-player{height: calc(100%); position: relative; overflow: hidden;
.el-image{width: 100%;height: 100%;
img{width: 100%;height: 100%;}
}
.no-single{width: 100%;height: 100%; position: absolute; top: 0; left: 0; display: flex; align-items: center; justify-content: center; color: white; text-shadow: 0px 0px 5px #000; text-align: center;
strong{ font-size: 18px; font-weight: 600;}
span{display: block; font-size: 12px;}
}
.player-outer{position: relative; width: 100%; height: 100%; overflow: hidden;
:deep(.video){ width:100% !important; height: 100% !important; }
}
}
</style>
(旧版 不建议采用)
也可以全局引入 在index.html,全局引入文件我是放在public下面的。
<link href="./js/release/tcplayer.min.css" rel="stylesheet"/>
<script src="./js/release/tcplayer.v4.7.0.min.js"></script>
js依赖文件是在官网下载的tcplayer官网地址
代码实例, urlAddress是父组件传来的视频流地址,也有可用的网上找的视频流地址为注释的source。
样式的话需要在main.js引用下图的tcplayer.min.css
<template>
<div class="player">
<div ref="videoOuter" class="video-player-page">
</div>
</div>
</template>
<script>
import TcPlayer from '../../assets/js/release/tcplayer.v4.7.0.min.js'
export default {
props: ['urlAddress'],
data() {
return {
player: null,
}
},
created() {},
mounted() {
this.initPlayer();
},
destroyed() {
// 页面销毁,同时也销毁 TcPlayer
this.player.dispose();
},
methods: {
initPlayer() {
let that=this;
if(this.player){
this.player.dispose();
}
this.domId = `video${Math.floor(Math.random()*(99999-10000+1))+parseInt(10000)}`
let dom = document.createElement('video')
dom.setAttribute('class', 'video')
dom.setAttribute('id', this.domId)
this.$refs.videoOuter.appendChild(dom)
this.player = TcPlayer(this.domId, {
sources: [{ src: this.urlAddress, type: 'video/flv' }],
// sources: [{ src: 'https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv', type: 'video/flv' }],
autoplay: true, // 是否自动播放
controls: true,
muted: true,
controlBar: {
playbackRateMenuButton: false, //是否显示播放速率选择按钮。
volumePanel: false,
durationDisplay: false,
currentTimeDisplay: false,
timeDivider: false,
volumePanel: false,
progressControl: false,
},
listener: function (msg) {
// 播放失败,重新连接
// if (msg.type == "error") {
// setTimeout(() => {
// this.player.load(); // 重连
// }, 400);
// }
}
});
// this.player.on('canplay', function(event) {
// // 从回调参数 event 中获取事件状态码及相关数据
// // console.log(event)
// that.$emit('loadDone',false)
// // const emit=defineEmits(['loadDone'])
// // emit('loadDone',false)
// });
}
}
}
</script>
<style lang="less" scoped>
.vjs-tech{
width:100% !important; height: 100% !important;
}
.video-player-page{position: relative; width: 100%; height: 100%; overflow: hidden;
/deep/.video{
width:100% !important; height: 100% !important;
}
}
.player{height: calc((100vh - 350px)/3); position: relative;
img{width: 100%;height: 100%;}
span{ position:absolute; top:50%; left: 50%;transform:translate(-50%,-50%); color: white;}
.noneBox{
display: flex;
align-items:center;
background: #07348a;
color: #fff;
line-height: 1em;
text-align: center;
position: absolute;
top: 0;
z-index: 2;
width: 100%;
height: 100%;
}
.called{
z-index: 3;
}
}
</style>