最近一直在做 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