如何实现数组内视频URL的依次播放?求更优实现方案
问题描述
我有一组视频URL,需要将数组中的视频逐个依次播放,直至全部完成。目前采用的基于sleep的实现方案虽能运行,但存在明显不足,请问有什么更优的实现方式?
当前代码如下:
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <video id="video" src="" controls/>
CSS
video { width: 100%; height: 40vh; }
JavaScript
const myArr = ["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 sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); (async() => { for (let i = 0; i < myArr.length; i++) { $('#video').attr('src', myArr[i]) // 等待元数据加载 await sleep(600) const duration = $('#video')[0].duration console.log(duration) $('#video')[0].play() // 等待视频播放完成(原代码存在单位错误,duration是秒,sleep需传入毫秒) await sleep(duration * 1000); } console.log("done"); })();
优化方案
你当前的sleep方案存在两个关键缺陷:
- 固定等待600ms获取元数据,网络环境不稳定时,要么提前执行导致无法获取
duration,要么浪费不必要的等待时间 - 依赖视频时长做延时,一旦出现用户手动暂停、视频卡顿等情况,播放流程会完全混乱
更可靠的实现是利用视频的原生事件监听,完全根据视频的实际状态推进播放流程,具体思路如下:
- 用
loadedmetadata事件替代固定延时,确保元数据加载完成后再操作 - 用
ended事件替代sleep,当前视频播放结束后自动切换下一个
优化后的完整代码
HTML(无需修改)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <video id="video" src="" controls/>
CSS(无需修改)
video { width: 100%; height: 40vh; }
JavaScript
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 videoElement = $('#video')[0]; // 封装事件监听为Promise,方便用await等待事件触发 function waitForEvent(element, eventName) { return new Promise(resolve => { element.addEventListener(eventName, resolve, { once: true }); }); } async function playVideosSequentially(urls) { for (const url of urls) { // 设置当前视频源 videoElement.src = url; // 等待元数据加载完成(确保能获取到视频时长等信息) await waitForEvent(videoElement, 'loadedmetadata'); console.log('当前视频时长:', videoElement.duration); // 开始播放视频 await videoElement.play(); // 等待当前视频播放结束 await waitForEvent(videoElement, 'ended'); } console.log('所有视频播放完成'); } // 启动顺序播放 playVideosSequentially(videoUrls);
优化点说明
waitForEvent函数:将事件监听封装成Promise,用await替代回调,代码更简洁易读loadedmetadata事件:确保视频元数据完全加载后再执行后续操作,不会出现duration为NaN的异常ended事件:仅在视频自然播放结束时触发,能正确处理用户暂停、卡顿等情况,播放流程更稳定- 彻底规避了原代码中时长单位错误的问题
内容的提问来源于stack exchange,提问作者seriously
相关产品推荐
相关产品推荐

