vue项目中播放flv和hls类型视频流
你好!首先只适用于flv和hls不能用rtmp格式的流,rtmp使用video-player必须使用flash插件,然而新版本的浏览器已经不支持flash。所以只能使用这两种流。下面是以hls为例,flv和这个类似。
安装环境
npm install hls.js --save-dev
播放视频的组件
<template>
<div class="ali-player">
<div class="main">
<div class="video-center">
<div v-if="!sourceUrls" class="tips">请选择视频源</div>
<div v-if="waiting" class="tips">获取视频中,请稍等...</div>
<div v-if="!hls" class ="video" style="background-color: #0c0b0b">
</div>
<video v-show ="hls" id="video" controls class="video" ref="video" style="background-color: #0c0b0b"></video>
</div>
</div>
</div>
</template>
<script>
import Hls from 'hls.js'
export default {
name: '',
components: {},
props:{
sourceUrl:{
type:String,
default:''
},
height:{
type:String,
default:'550px'
}
},
data() {
return {
hls: null,
sourceUrls:this.sourceUrl,//如果不赋值,在加载组件时会报错
loadingVideo:false,
waiting:false,
reloadPlayTime:null //当视频流获取超时定时器
}
},
computed: {
},
watch: {
sourceUrl: {
handler(newVal, oldVal) {
if(this.reloadPlayTime) { //重新播放或者播放新视频时,清空定时器
console.log('清空定时器...')
this.videoPause();
clearTimeout(this.reloadPlayTime);
}
if( newVal && newVal !== oldVal ) {
console.log('执行监听')
this.waiting = true
this.sourceUrls = newVal
this.playVideo()
}
},
// 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
immediate: false
}
},
created() {},
mounted() {
this.playVideo()
},
methods: {
playVideo() {
this.$nextTick(()=>[
this.loadingVideo = false
])
if (Hls.isSupported()) {
console.log('支持hls播放')
this.hls = new Hls();
this.hls.loadSource(this.sourceUrls);
this.hls.attachMedia(this.$refs.video);
this.hls.on(Hls.Events.MANIFEST_PARSED, (event, data) => {
console.log('playing...');
this.loadingVideo = false
this.waiting = false
this.$emit('playStatus', true) // 当点位存在播放地址时,可以截图
this.$refs.video.play();
});
let timerArr = []
let delay = 5000
this.hls.on(Hls.Events.ERROR, (event, data) => {
delay += 1000
console.log(event, data);
if(data.type === "networkError") { //网络故障
console.log('网络故障了...')
this.reloadPlayTime = setTimeout( ()=> {
console.log('获取视频失败,请重新播放...')
this.sourceUrls = ''
this.loadingVideo = false
this.waiting = false
this.disabledShot = true
this.$emit('playStatus', false)
this.videoPause()
// 监听出错事件
},delay)
timerArr.push(this.reloadPlayTime)
if(timerArr.length > 1) {
//当视频播放中无法播放时,会多次执行Hls.Events.ERROR,因此需要处理一下定时器触发问题
for(let i =1;i< timerArr.length;i++) {
clearTimeout(timerArr[i]);
timerArr.splice(i,1)
}
}
console.log(timerArr)
} else if(data.type === "mediaError") { //推流失败
// console.log("播放流断了....");
}
});
} else if (this.$refs.video.canPlayType('application/vnd.apple.mpegurl')) {
/* this.$refs.video.src = 'https://video-dev.github.io/streams/x36xhzz/x36xhzz.m3u8';
this.$refs.video.addEventListener('loadedmetadata',function() {
this.$refs.video.play();
});*/
}
},
// 停止流
videoPause() {
if (this.hls) {
this.$refs.video.pause();
this.hls.destroy();
this.hls = null;
}
}
},
beforeDestroy () {
clearTimeout(this.reloadPlayTime);
this.hls = null;
}
}
</script>
在其他组件调用
<template>
<el-dialog
title="直播监控"
:visible.sync="dialogVisible"
width="60%"
height = "70%"
:before-close="handleClose">
<div class="liveCon">
<player :sourceUrl="sourceUrl" @playStatus= "changePlayStatus"></player>
</div>
</el-dialog>
</template>
<script>
import player from "./component/player.vue";
export default {
name: 'playList',
data() {
return {
sourceUrl:'http://wshls.live.migucloud.com/live/WAERPZJD_C0/playlist.m3u8',
};
},
created() {
},
components: {
player
},
methods: {
changePlayStatus(status) { //获取子组件的播放状态
console.log('子组建的状态',status)
if(status) {
this.disabledShot = false
} else {
this.disabledShot = true
this.sourceUrl = ''
this.checkedPontsName = ''
}
},
};
</script>