HTML5 Video VideoPlaybackQuality 实现丢帧统计

在 Web 开发中,我们依赖于 Video 元素进行视频播放,相对 Android 或者 Windows 客户端程序,我们更加依赖浏览器测对 Video 元素提供了什么样的能力。

而如果我们需要对丢帧率进行统计,现在有了 VideoPlaybackQuality 来完成改功能。

目前主流浏览器都得到了支持

VideoPlaybackQuality 对象表示了一系列描述视频播放质量的指标。

可以通过

HTMLVideoElement.getVideoPlaybackQuality()

创建一个实例来获取。

里面包含下面的属性;

  • .creationTime 一个用毫秒表示从开始页面浏览到对象创建的 DOMHighResTimeStamp 对象
  • .totalVideoFrames 表示相 HTMLVideoElement 自从创建起的已创建和丢弃帧数数量总和的值
  • .droppedVideoFrames 表示相关联的 HTMLVideoElement 自从创建起的已丢弃帧数数量值
  • .corruptedVideoFrames 一个表示相关联的 HTMLVideoElement 自从创建起的损坏帧数数量的值。一个损坏帧可能属于创建帧或丢弃帧

这样我们通过简单的

droppedVideoFrames / totalVideoFrames

来实现一个丢帧比例的计算,从而实现一个质量的保证。而 hls.js-fps-controller.ts 也是采用相关 API 来实现播控质量的控制。

checkFPSInterval() {
    const video = this.media;
    if (video) {
      if (this.isVideoPlaybackQualityAvailable) {
        const videoPlaybackQuality = video.getVideoPlaybackQuality();
        this.checkFPS(
          video,
          videoPlaybackQuality.totalVideoFrames,
          videoPlaybackQuality.droppedVideoFrames,
        );
      } else {
        // HTMLVideoElement doesn't include the webkit types
        this.checkFPS(
          video,
          (video as any).webkitDecodedFrameCount as number,
          (video as any).webkitDroppedFrameCount as number,
        );
      }
    }
  }
  
  checkFPS() {
   // ...
   const currentPeriod = currentTime - this.lastTime;
        const currentDropped = droppedFrames - this.lastDroppedFrames;
        const currentDecoded = decodedFrames - this.lastDecodedFrames;
        const droppedFPS = (1000 * currentDropped) / currentPeriod;
        const hls = this.hls;
        hls.trigger(Events.FPS_DROP, {
          currentDropped: currentDropped,
          currentDecoded: currentDecoded,
          totalDroppedFrames: droppedFrames,
        });
        // ...
  }

时机上这里在实践过程中有很多需要考虑的地方,

  • 网速过低的情况主动丢帧的情况, 会出现快速的大范围丢帧
  • 丢帧波动,比如我们可能出现一些用户的操作,导致解码能力资源不足的丢帧

所以我们建议是这个指标还是需要通过一些去噪声的手段来规避一些大范围波动的情况。