| 4 min read

最近一直在做 MSE 相关的事情,机缘巧合下碰到了关于 ReadyState 和它有可能触发的事情的研究,于是写下这篇文章作为记录。

Video 元素维持内部几个非常重要的状态,这些都是只读的:

  • paused 属性,你可以直接从 video elment 上读取,当你暂停视频的时候,Video 元素会讲这个属性值改为 true, 这里还有一些别的情况,我会在后面一篇文章分析
  • readyState 属性,当然你也可以从 Video 元素上读取,不同 readyState 意味着 video 的不同状态。

官方罗列了这些状态值:

// video element ready state Enum
const unsigned short HAVE_NOTHING = 0;
const unsigned short HAVE_METADATA = 1;
const unsigned short HAVE_CURRENT_DATA = 2;
const unsigned short HAVE_FUTURE_DATA = 3;
const unsigned short HAVE_ENOUGH_DATA = 4;

我们这里只考虑正常网络情况,比如断网的情况我们先忽略,这种情况比较特殊。

HAVE_NOTHING

表示当前并没有可以播放的资源,还有一种是当前位置没有可用的数据。

HAVE_METADATA

顾名思义,我们知道视频的 metadata 里面包含了什么信息,如果我们加载的视频,已经可以解码出改信息,那么我们就可以对视频的一些信息进行读取,比如视频的时长,宽高等。

HAVE_CURRENT_DATA

表示当前位置的数据已经完成解码,但是不代表接下来有足够帧进行播放。比如平时,我们可能是起点0,如果是我们 seek 过后,就是表示 seek 过后当前位置的帧是否完成解码。

HAVE_FUTURE_DATA

根据前文的信息,它相对来说会更加安全点,不仅表示当前位置帧的信息已经解码完成,还表示接下来的片段也具备了足够的buffer,不至于向前播放的时候理解切回 HAVE_METADATA 的状态。那么我们可以采用这个状态来评估视频该片段是相对安全的。

HAVE_ENOUGH_DATA

这是目前最为复杂的一个状态,它表示两种情形:

  • 当前浏览器会评估下载的速率和播放速率的一个关系,从而确保下载的足够的buffer 不会阻碍到用户的播放
  • 浏览器进入一种状态,也是有足够的buffer,等待更多的时间并不会获取 buffer (比如 buffer 已经填满)

我们可以通过一个实验来验证下,

https://codepen.io/Jack_Pu/pen/PoXaPvx

Demo 组要是会记录当前的状态和一个历史记录, 您可以自己测试,

我们先看下默认的状态

我们给它加载一个视频

可以看到它从 HAVE_NOTHING -> HAVE_METADATA -> HAVE_ENOUGH_DATA 非常迅速。

接下来我们看下在低网速的情况下,是怎样的效果:

我们可以看到它是从 HAVE_NOTHING -> HAVE_METADATA -> HAVE_FUTURE_DATA 。唯一的区别便是后面一个状态,很明显浏览器认为当前网速是无法完成未来的播放的,也就是可能出现卡顿的情况。

接下来我们看看 seek 的操作。

可以看到从 HAVE_METADATA -> HAVE_ENOUGH_DATA 一个状态的切换。

简单一张图总结如上。

这里留下一个疑问,如果我现在没有视频源的时候,将视频 seek 20s, 然后再 load 资源,会触发哪些状态?

这些状态其实可以辅助你的一些日志和逻辑,至于选择什么样的时机播放,我会在下一篇文章分享。

强烈推荐阅读官方的文档:

https://html.spec.whatwg.org/multipage/media.html#media-element-event-task-source

You Can Speak "Hi" to Me in Those Ways