精准计算HTML5视频已加载进度需先找到覆盖currentTime的buffered区间终点,再除以duration;须检查loadedmetadata、readyState≥HAVE_FUTURE_DATA且buffered.length>0,再遍历TimeRanges匹配当前播放位置。

精准计算 HTML5 视频的已加载进度,关键不是看“从头缓了多少”,而是看“当前播到哪儿,后面还能撑多久”。直接用 buffered.end(0) 除以 duration 容易出错,尤其在用户拖动、网络波动或分段缓冲时。
理解 buffered 是时间区间,不是百分比
video.buffered 返回的是 TimeRanges 对象,里面可能有多个不连续的时间段(比如 [0–45] 和 [120–180])。它不表示“已下载多少字节”,而是浏览器已解码、可随时播放的时间范围。每个区间用 start(i) 和 end(i) 表示起止秒数。
-
buffered.length是区间个数,不是缓冲量 -
buffered.start(0)不一定等于 0(跳播后可能从 120 开始) - 不能假设只有一个区间,也不能默认第一个区间覆盖当前播放点
找准当前播放位置对应的缓冲终点
要反映真实可用进度,必须找到覆盖 video.currentTime 的那个区间,再取它的 end 值:
- 遍历所有区间:
for (let i = 0; i < video.buffered.length; i++) - 检查是否满足:
video.buffered.start(i) <= currentTime && currentTime <= video.buffered.end(i) - 一旦命中,
bufferedEnd = video.buffered.end(i)就是当前能连续播放的最远时间点 - 没找到匹配区间(如刚拖动完),就返回 0
确保计算前提可靠
三项检查缺一不可,否则结果无效:
立即学习“前端免费学习笔记(深入)”;
- 监听
loadedmetadata事件后再开始计算,避免duration为NaN或Infinity - 读取
buffered前确认video.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA - 若
buffered.length === 0,直接返回 0,不要调用end(0)(会触发IndexSizeError)
实时更新并防抖显示
没有标准的 bufferedupdate 事件,推荐以下方式获取最新数据:
- 用
setInterval每 300ms 主动轮询一次video.buffered,比依赖timeupdate更稳定(暂停、拖动后仍有效) - 百分比公式:
Math.min(100, (bufferedEnd / video.duration) * 100) - UI 层建议用滑动窗口平均最近 3–5 次值,避免数值跳变造成视觉抖动



















