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

  <mpegts-video :videoProps="item" ref="mpegtsRef" v-for="(item,index) in videoList" :key="index"></mpegts-video>

    或

  <mpegts-video :videoProps="videoProps" ref="mpegtsRef"></mpegts-video>

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

  components: {
    mpegtsVideo,
  },

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

  //父类方法-用于全屏窗口切换
  fullScreenWindowSwitch(data){
    let self = this;
    for(let i=0;i<self.$refs.mpegtsRef.length;i++){
      if(data.cameraIndexCode != self.$refs.mpegtsRef[i].videoData.cameraIndexCode){
        if(data.type){
          self.$refs.mpegtsRef[i].stopVideo();
        }else{
          self.$refs.mpegtsRef[i].playVideo();
        }
      }
    }
  },

-->

<template>
  <div class="mpegtsVideo">
    <p class="reconnectText"
       :style="'height:'+videoData.height+'px;width:'+videoData.width+'px;line-height:'+videoData.height+'px;'"
       v-if="reconnectType">连接已断开,请联系管理员或等待重连</p>
    <video
      :style="showAllType?'transform:rotate(90deg) translate(0, -'+width+'px':''"
      :class="showAllType?'showAllVideo':''"
      :id="videoData.cameraIndexCode" :ref="videoData.cameraIndexCode"
      :width="videoData.width" :height="videoData.height"
      autoplay controls  muted >
    </video>
    <img :class="showAllType?'showAllButton':'full-screen-button'" class="el-icon-full-screen" @click="fullScreen" src="data:image/png;base64,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">
    <!--<p :class="showAllType?'showAllButton':''" class="el-icon-full-screen full-screen-button" @click="fullScreen"></p>-->
  </div>
</template>
<script>
  import mpegts from 'mpegts.js'
  export default {
    name: 'mpegtsVideo',
    props: {
      videoProps:{},
    },
    data () {
      return {
        videoData:{},
        flvPlayer:null,//连接数据
        decodedFrames:null,//断流帧
        decodedFramesNum:null,//断流计数器
        reconnectType:false,//重连状态
        videoImg:null,
        errorNum:0,//异常次数
        showAllType:false,
        width:0,
      }
    },
    created(){
      const winWidth = window.innerWidth;
      this.$set(this,'width',parseInt(winWidth));
      this.$set(this,'videoData',{
        cameraIndexCode:this.videoProps.cameraIndexCode?this.videoProps.cameraIndexCode:this.generateRandomString(),
        width:this.videoProps.width?this.videoProps.width:600,
        height:this.videoProps.height?this.videoProps.height:338,
        type:this.videoProps.type?this.videoProps.type:'flv',
        isLive:this.videoProps.isLive?this.videoProps.isLive:true,
        url:this.videoProps.url,
      });
    },
    mounted(){
      this.initMpegts();
    },
    methods:{
      //暂停流-供父调用
      stopVideo(){
        if(this.flvPlayer){
          this.flvPlayer.pause();
          this.flvPlayer.unload();
          this.flvPlayer.detachMediaElement();
          this.flvPlayer.destroy();
          this.flvPlayer = null;
        }
      },
      //播放流-供父调用
      playVideo(){
        if(!this.flvPlayer){
          this.initMpegts();
        }
      },
      //窗口全屏
      fullScreen(){
        this.$set(this,'showAllType',!this.showAllType);
        this.$parent.fullScreenWindowSwitch({type:this.showAllType,cameraIndexCode:this.videoData.cameraIndexCode});
        // this.$refs[this.videoData.cameraIndexCode].webkitRequestFullScreen();
      },
      //截取封面
      videoCover(){
        let video = document.getElementById(this.videoData.cameraIndexCode);
        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.cameraIndexCode);
          //设置
          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=> {
            // 发生异常
            if(this.errorNum > 5){
              this.videoOff();
            }else{
              this.errorNum++
              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();
        },10000);
      },
      //断开视频流
      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">
  .mpegtsVideo{
    overflow: hidden;
    display: inline-block;
    *{
      margin:0;
      padding:0;
    }
    position: relative;
    .showAllVideo{
      z-index:9999999999;
      position: fixed;
      top:0;
      left:0;
      /*width:100%;*/
      /*height:100%;*/
      width: 100vh;
      height: 100vw;
      /*transform: rotate(90deg) translate(0, -46vh);*/
      transform-origin: left top;
    }
    .showAllButton{
      color:#fff;
      text-align: center;
      right:0;
      cursor: pointer;
      bottom:0;
      font-size:40px;
      height:60px;
      width:60px;
      line-height:60px;
      z-index:99999999999;
      position: fixed;
    }
    .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;
    }
    /*video::-webkit-media-controls-enclosure {*/
      /*display: none;*/
    /*}*/
    /*// 音频开关*/
    /*video::-webkit-media-controls-mute-button {*/
      /*display: none;*/
    /*}*/
    /*// 音频大小*/
    /*video::-webkit-media-controls-volume-slider {*/
      /*display: none;*/
    /*}*/
    //全屏按钮
    video::-webkit-media-controls-fullscreen-button {
      display: none;
    }
    /*//开始暂停按钮*/
    /*video::-webkit-media-controls-play-button {*/
      /*display: none;*/
    /*}*/
    // 时间显示
    video::-webkit-media-controls-current-time-display {
      display: none;
    }
    // 未知时间
    video::-webkit-media-controls-toggle-closed-captions-button {
      display: none;
    }
    //进度条
    video::-webkit-media-controls-timeline {
      display: none;
    }
    //未知进度条
    video::-webkit-media-controls-time-remaining-display {
      display: none;
    }
    /*video {*/
      /*object-fit: fill; //视频全铺*/
      /*pointer-events: none; //点击禁用*/
    /*}*/
  }
</style>
