精准掌握视频播放状态需串联加载、就绪、播放三阶段事件:loadstart→loadedmetadata→canplaythrough→timeupdate,并配合seeking/seeked、ended兜底及缓冲轮询,避免依赖单一事件导致边界异常。

要精准掌握视频播放状态,关键不是只盯住 timeupdate,而是把加载、就绪、播放三个阶段的事件串起来用。单独监听某个事件容易漏掉边界情况,比如视频刚点开还没拿到时长就去算进度,或者缓冲中断时进度条卡死。
核心播放进度监听:timeupdate 是主力,但得配好前提
timeupdate 在播放过程中高频触发,是更新当前时间、计算进度百分比、驱动进度条的核心事件。但它有个硬前提:必须等 loadedmetadata 触发后才能安全读取 video.duration,否则 duration 是 NaN 或 0,所有百分比计算都会出错。
- 在
loadedmetadata后初始化进度条最大值(max)和总时长显示 - 在
timeupdate中只做两件事:更新currentTime显示、按公式(currentTime / duration) * 100设置进度条值 - 避免在
timeupdate里反复调用耗时操作(如 DOM 查询、格式化时间),建议提前缓存元素引用和格式化函数
加载与就绪事件链:从 loadstart 到 canplaythrough
视频加载不是一蹴而就,而是一连串依赖关系明确的状态跃迁:
-
loadstart:浏览器开始请求视频文件,此时可显示“加载中”提示 -
loadedmetadata:宽高、时长等元数据已知,UI 可显示总时长、启用进度条拖动 -
loadeddata:首帧图像已解码,画面首次可渲染,适合隐藏加载遮罩 -
canplay:已有足够数据播放一帧,但可能很快卡顿 -
canplaythrough:浏览器预估能一路播完不卡顿,是启动自动播放或移除“缓冲中”提示的安全时机
缓冲进度监控:别信 bufferedupdate,用轮询 + timeupdate 组合
浏览器没有标准的 bufferedupdate 事件,video.buffered 对象只能主动读取。单纯靠 timeupdate 会漏掉暂停/拖动后的后台缓冲。
- 在
canplay或loadedmetadata后启动一个setInterval(推荐 300ms 间隔),持续检查video.buffered - 读取前务必判断
video.readyState >= HTMLMediaElement.HAVE_FUTURE_DATA,否则buffered.length可能为 0 - 计算缓冲百分比时必须处理三种边界:
currentTime超出所有缓冲区间 → 返回 0;duration为Infinity(如直播)→ 改算“已缓冲时长 = buffered.end(i) - currentTime”;buffered.length === 0→ 直接返回 0
常见陷阱与健壮写法
真实环境里,用户拖动、网络波动、直播流、低性能设备都会让视频行为变得复杂:
- 不要假设
duration永远是有限数字,对直播流需单独判断isFinite(video.duration) - 拖动进度条后,
timeupdate可能延迟触发或不触发,应同时监听seeking和seeked事件来响应拖动动作 -
ended事件只在自然播完时触发,用户手动拖到末尾不会触发,需结合currentTime >= duration - 0.1做兜底判断 - 移动端 Safari 对
autoplay和play()调用限制严格,首次播放必须由用户手势触发,否则会静默失败
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











