You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现数组内视频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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 08:20:01