<!--
@name: fullScreenMpegtsVideo
@description: 通用视频组件
@author: zc
@time: 2023/11/30
@引入:

  <full-screen-mpegts-video ref="fullScreenMpegtsVideo" :videoProps="videoProps"></full-screen-mpegts-video>

  import fullScreenMpegtsVideo from '@/components/fullScreenMpegtsVideo/fullScreenMpegtsVideo.vue'

  components: {
    fullScreenMpegtsVideo,
  },

  videoProps:{
    id:50,        //(ID:非必传-默认随机生成)
    width:600,    //(宽度:非必传-默认600)
    height:338,   //(高度:非必传-默认338)
    type:'flv',   //(视频类型:非必传-默认'flv')
    isLive:true,  //(是否直播流:非必传-默认true)
    url:""        //(视频地址:必传)
  }

  this.$refs.fullScreenMpegtsVideo.openVideo()

-->

<template>
  <div class="fullScreenMpegtsVideo-max-box" v-if="fullScreenMpegtsVideoType">
    <div class="fullScreenMpegtsVideo">
      <div class="fullScreenMpegtsVideo-min">
        <p class="reconnectText"
           :style="'height:'+videoData.height+'px;width:'+videoData.width+'px;line-height:'+videoData.height+'px;'"
           v-if="reconnectType">连接已断开,请联系管理员或等待重连</p>
        <video
          :id="videoData.id" :ref="videoData.id"
          :width="videoData.width" :height="videoData.height"
          autoplay controls  muted >
        </video>
      </div>
      <p class="el-icon-full-screen full-screen-button" @click="fullScreen"></p>
    </div>
    <p class="out-position-p el-icon-circle-close" @click="offVideo"></p>
  </div>

</template>
<script>
  import mpegts from 'mpegts.js'
  export default {
    name: 'fullScreenMpegtsVideo',
    props: {
      videoProps:{},
    },
    data () {
      return {
        fullScreenMpegtsVideoType:false,
        videoData:{},
        flvPlayer:null,//连接数据
        decodedFrames:null,//断流帧
        decodedFramesNum:null,//断流计数器
        reconnectType:false,//重连状态
        videoImg:null,
      }
    },
    created(){

    },
    mounted(){

    },
    methods:{
      //开启视频窗口
      openVideo(){
        let self = this;
        this.$set(this,'videoData',{
          id:this.videoProps.id?this.videoProps.id:this.generateRandomString(),
          width:1065,
          height:603,
          type:this.videoProps.type?this.videoProps.type:'flv',
          isLive:this.videoProps.isLive?this.videoProps.isLive:true,
          url:this.videoProps.url,
        });
        this.$set(this,'fullScreenMpegtsVideoType',true);
        setTimeout(function(){
          self.initMpegts();
        },200);
      },
      offVideo(){
        this.videoOff();
        this.$set(this,'fullScreenMpegtsVideoType',false);
      },
      //窗口全屏
      fullScreen(){
        this.$refs[this.videoData.id].webkitRequestFullScreen();
      },
      //截取封面
      videoCover(){
        let video = document.getElementById(this.videoData.id);
        let canvas = document.createElement("canvas");
        let width = video.width; //canvas的尺寸和图片一样
        let height = video.height;
        canvas.width = width;
        canvas.height = height;
        canvas.getContext("2d").drawImage(video, 0, 0, width, height); //绘制canvas
        let videoImg = canvas.toDataURL('image/jpeg'); //转换为base64
      },
      //连接视频
      initMpegts() {
        if (mpegts.getFeatureList().mseLivePlayback) {
          //视频DOM
          let videoElement = document.getElementById(this.videoData.id);
          //设置
          let config = {
            liveBufferLatencyChasing: true,//自动追针
            autoCleanupMaxBackwardDuration:3*60,//清除缓存  默认保留3*60
          };
          this.flvPlayer = mpegts.createPlayer({
            type: this.videoData.type,
            isLive: this.videoData.isLive,
            url: this.videoData.url,
          },config);
          this.flvPlayer.attachMediaElement(videoElement);
          this.flvPlayer.load();
          this.flvPlayer.play();
          let playPromise = this.flvPlayer.play();
          if (playPromise !== undefined) {
            playPromise.then((_) => {
              //播放
              this.$set(this,'reconnectType',false);
            }).
            catch ((error) => {
              //暂停
              this.$set(this,'reconnectType',true);
              this.reconnectVideo();
            });
          }
          //断流检测
          this.flvPlayer.on(mpegts.Events.STATISTICS_INFO, (e) => {
            // 解码帧
            if(this.decodedFrames !== e.decodedFrames){
              //连接正常
              this.$set(this,'decodedFrames',e.decodedFrames);
              this.$set(this,'decodedFramesNum',0);
            }else{
              //连接异常
              this.decodedFramesNum++
              if(this.decodedFramesNum>30){
                this.$set(this,'reconnectType',true);
                this.reconnectVideo();
              }
            }
          });
          this.flvPlayer.on(mpegts.Events.ERROR, e=> {
            // 发生异常
            this.$set(this,'reconnectType',true);
            this.reconnectVideo();
          });
          this.flvPlayer.on(mpegts.Events.LOADING_COMPLETE, (e) => {
            // 视频流已结束
            this.$set(this,'reconnectType',true);
            this.reconnectVideo();
          });
        }
      },
      //重新连接
      reconnectVideo(){
        let self = this;
        this.flvPlayer.pause();
        this.flvPlayer.unload();
        this.flvPlayer.detachMediaElement();
        this.flvPlayer.destroy();
        this.flvPlayer = null;
        setTimeout(function(){
          self.initMpegts();
        },2000);
      },
      //断开视频流
      videoOff(){
        this.flvPlayer.pause();
        this.flvPlayer.unload();
        this.flvPlayer.detachMediaElement();
        this.flvPlayer.destroy();
        this.flvPlayer = null;
      },
      //生成随机ID
      generateRandomString() {
        let chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        let randomString = "";
        for (let i = 0; i < 8; i++) {
          let randomIndex = Math.floor(Math.random() * chars.length);
          randomString += chars.charAt(randomIndex);
        }
        return randomString;
      }
    },
    beforeDestroy() {
      let self = this;
      self.videoOff();
    },
  }
</script>
<style scoped lang="scss">
  .fullScreenMpegtsVideo-max-box{
    position: fixed;
    top:0;
    left:0;
    width:100%;
    height:100%;
    background-color: rgba(0,0,0,0.8);
    z-index:10000;
  }
  .out-position-p{
    position: absolute;
    top:20px;
    right:20px;
    font-size:30px;
    color:#fff;
    width:30px;
    height:30px;
    line-height:30px;
    cursor: pointer;
  }
  .fullScreenMpegtsVideo{
    position: absolute;
    top:50%;
    left:50%;
    margin-top:-301px;
    margin-left:-532px;
    *{
      margin:0;
      padding:0;
    }
    .fullScreenMpegtsVideo-min{
      position: relative;
      .reconnectText{
        position: absolute;
        color:#fff;
        z-index:2;
        text-align: center;
        top:0;
        left:0;
      }
      .full-screen-button{
        color:#fff;
        position:absolute;
        font-size:20px;
        height:30px;
        width:30px;
        line-height:30px;
        text-align: center;
        top:0;
        right:0;
        z-index: 1;
        cursor: pointer;
      }
      .full-screen-button:hover{
        color:#00b7ee;
      }
    }
  }
</style>
