
本文介绍一种基于原生 HTMLMediaElement ended 事件的可靠方式,实现视频 URL 数组的逐个自动播放,避免轮询、硬编码延时和元数据加载不确定性等问题。
本文介绍一种基于原生 htmlmediaelement `ended` 事件的可靠方式,实现视频 url 数组的逐个自动播放,避免轮询、硬编码延时和元数据加载不确定性等问题。
在前端开发中,实现多个视频按序自动连播是一个常见需求(如数字标牌、教学课件、广告轮播等),但直接使用 setTimeout 或 sleep() 模拟播放时长极易出错:视频实际加载延迟、缓冲中断、duration 初始为 NaN、用户手动暂停/跳转等都会导致逻辑崩溃。
✅ 推荐方案:监听 ended 事件驱动状态流转
HTML
<video id="player" controls width="100%" height="40vh"></video>
const videoUrls = [
"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4",
"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerMeltdowns.mp4",
"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4"
];
const player = document.getElementById('player');
let currentIndex = 0;
// 播放指定索引的视频
function playVideoAtIndex(index) {
if (index >= videoUrls.length) {
console.log("全部视频播放完成");
return;
}
player.src = videoUrls[index];
player.load(); // 显式调用 load() 确保重新加载元数据
player.play().catch(err => {
console.warn(`视频 ${index} 播放失败:`, err.message);
});
}
// 监听 ended 事件,自动进入下一集
player.addEventListener('ended', () => {
currentIndex++;
playVideoAtIndex(currentIndex);
});
// 启动播放(第一段)
playVideoAtIndex(0);关键优势说明:
- ✅ 事件驱动,不依赖时间猜测:ended 是浏览器真实播放结束的信号,不受网络波动、解码性能影响;
- ✅ 无需 jQuery:纯原生 JavaScript,轻量、兼容性好(IE9+),减少外部依赖;
- ✅ 自动处理加载状态:load() 方法确保每次切换时重置媒体资源,避免 duration 为 NaN;
- ✅ 错误防御性强:play() 返回 Promise,.catch() 可捕获自动播放策略拒绝(如移动端静音限制)、404 等异常;
- ✅ 可扩展性强:后续可轻松添加「循环播放」「跳过按钮」「进度回调」「播放统计」等功能。
⚠️ 注意事项:
- 浏览器自动播放策略(Autoplay Policy)要求:若页面无用户交互(如点击),首次播放可能被静音或阻止。建议在用户触发(如点击“开始播放”按钮)后初始化队列;
- 若需支持 preload="metadata" 提前加载下一段,可在 ended 回调中预设 nextPlayer.src = videoUrls[currentIndex + 1](需额外创建隐藏
- 如需暂停/恢复控制,应监听 pause、play 事件并暂停队列推进,避免事件冲突。
通过事件而非定时器驱动流程,是媒体播放类应用的工程最佳实践。它让代码更贴近浏览器真实行为,显著提升稳定性与可维护性。










