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>
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐