flv.js断开重连-画面卡顿-跳帧重连

发布时间 2023-11-03 17:06:42作者: Kiss丿残阳

1、播放页面卡住不动是进行截图并在一定时间内重新连接,

2、重连阶段显示截取卡住画面把图片显示等待视频流上来不至于video标签显示成黑屏;

<video   src=""
    autoplay
   muted
    loop
    :controls="false"
    style="background: #000"
     :poster="item.loadurl"  放显示图片
 ></video>

var item={

      videoRef: "", //video元素标签
      statusTime: 15, // 请求时长不播放状态为超时
      status: 0, //0离线, 1正常,2超时,
      intervalStatusTime: null, // 请求前10秒定时器实例
      inspectionTime: 30, // 巡检时长
      intervalInspectionTime: null, //正常巡检定时器实例
      playerRef: null,//flvjs视频数据
      loadurl:null,//图片url
   data:{},//数据信息
 };
 
//videoEle:video元素标签;streamUrl:播放url地址;item整个对象;channel:通道号
const startStream = (videoEle, streamUrl, item,channel) => {
  //--先断开已连接的
  if (item.playerRef) {
    if (item.playerRef._receivedCanPlay) {
  //播放过进行暂停释放
      item.playerRef.pause();//--
      item.playerRef.destroy();
    }
    item.playerRef.unload();//--
    item.playerRef.detachMediaElement();//--
    item.playerRef = null;
  }
  var mediaDataSource = {
    type: 'flv',
    hasAudio: channel == 1 ?false : true,//根据通道号判断是否带音频
    hasVideo: true,
    isLive: true,
    url: streamUrl,
    withCredentials: false
  };
  item.playerRef = flvjs.createPlayer(mediaDataSource, {
      enableWorker: false,
      lazyLoadMaxDuration: 3 * 60,
      seekType: 'range',
      autoCleanupSourceBuffer:true,
      fixAudioTimestampGap:false,
      stashInitialSize:128,//减少播放等待时间
      enableStashBuffer:false,
      lazyLoadRecoverDuration:1,
      lazyLoad: false,
  });
  item.playerRef.attachMediaElement(videoEle);
  item.playerRef.load();
  item.playerRef.play();

  //判断flv.js断开重连
  if (item.playerRef) {
    item.playerRef.on(flvjs.Events.ERROR,(err,errdet)=>{
      if (item.data) {
  //截取卡住video画面成图片
        getchangeJietu(videoEle,item);
  //重连
        startStream(videoEle,streamUrl,item,channel);
      }
    })

    //判断画面卡顿-跳帧
    item.playerRef.on(flvjs.Events.STATISTICS_INFO,(errs)=>{
      if (item.data) {
        if (item.playerRef.lastDecodedFrame == 0) {
          item.playerRef.lastDecodedFrame = errs.decodedFrames;
          item.playerRef.errorCount = 0;//记录画面卡住多少次
          item.playerRef.lastDFrame = 0;//用于判断是否第一次画面卡住
         return;
       }
       if (item.playerRef.lastDecodedFrame != errs.decodedFrames) {
        item.playerRef.lastDecodedFrame = errs.decodedFrames;
        item.playerRef.errorCount = 0;
        item.playerRef.lastDFrame = 0;
       } else {
        if (item.playerRef.buffered.length>0) {
          let end = item.playerRef.buffered.end(0); //获取当前时间值
          let diff = end - item.playerRef.currentTime; //获取相差差值
          item.playerRef.errorCount = 0;
          item.playerRef.lastDFrame = 0;
          // 延迟过大或帧率不正常,通过跳帧的方式更新视频
          if (diff > 10 || (end > 0 && diff < 0)) {
            item.playerRef.currentTime = item.playerRef.buffered.end(0);// 手动跳帧到最后
            videoEle.playbackRate = 1;
            return ;
          }
          if (diff <= 1) {
            // 正常帧率,正常播放
            videoEle.playbackRate = 1;
          }else if (diff <= 10) {
            // 10秒内的延时,1.1倍速播放
            videoEle.playbackRate = 1.1;
          } else if (diff <= 20) {
            // 20秒内的延时,1.2倍速播放
            videoEle.playbackRate = 1.2;
          }
        }else {
          item.playerRef.errorCount=item.playerRef.errorCount+1;
          if (item.playerRef.lastDFrame==0) {
       //首次页面卡住记录卡住最后一帧解码帧
            item.playerRef.lastDFrame=item.playerRef.lastDecodedFrame;
      //截取卡住video画面成图片
            getchangeJietu(videoEle,item);
          }
   //卡住页面5秒并且最后解码帧一致重新连接
          if (item.playerRef.errorCount>10 && item.playerRef.lastDFrame==item.playerRef.lastDecodedFrame) {
            if (item.data) {
    //重新连接
              startStream(videoEle,streamUrl,item,channel);
            }
          }
        }
       }
      }
    })
  }
};
 
// video卡住画面截图
const getchangeJietu = (videoRef,item) => {
  if (videoRef) {
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d"); //设置canvas绘制2d图,
    const width = videoRef.clientWidth; //设置canvas宽
    const height = videoRef.clientHeight; //设置canvas高
    canvas.width = width || 200;
    canvas.height = height || 200;
    ctx.drawImage(videoRef, 0, 0, width, height); //将video视频绘制到canvas中
    const images = canvas.toDataURL("image/png"); //canvas的api中的toDataURL()保存图像
    if (item.playerRef.statisticsInfo.decodedFrames>0) {
  //解码帧大于0进行图片替换否则会截取黑屏;
      item.loadurl=images;
    }
  }
};
 
// 停止视频播放
function stopStream(item) {
  if (item.playerRef) {
    if (item.playerRef._receivedCanPlay) {
  //播放过进行暂停释放
      item.playerRef.pause();//--
      item.playerRef.destroy();
    }
    item.playerRef.unload();//--
    item.playerRef.detachMediaElement();//--
    item.playerRef = null;
    item.data = null;
    item.loadurl=null;
  }
}