能否在JavaScript的video.addEventListener中添加循环实现视频分段重复播放?
问题描述
我要开发一个基于JavaScript的视频应用,实现每个视频片段重复播放3次后再切换到下一个片段的功能。现有多个视频,每个视频包含多个片段,视频链接与片段时间存储在嵌套数组中:
var sentences= [ ['journey27.mp4', [ [1, 2], [5, 7] ] ], ['journey28.mp4', [ [10, 12], [13, 17], [25, 36] ] ], ['journey29.mp4', [ [13, 15], [15, 19], [21, 30] ] ] ];
点击一次“Play”按钮后,应用需按以下逻辑执行:播放journey27.mp4的1-2秒片段3次,接着播放该视频的5-7秒片段3次,再切换到journey28.mp4,依次播放其10-12秒、13-17秒、25-36秒片段各3次,之后切换到journey29.mp4的对应片段,以此类推。
现有playVideo函数可正常工作,需在video.addEventListener的timeupdate事件回调中添加逻辑(如下代码片段所示),请问能否在此处添加循环来完成需求?
video.addEventListener("timeupdate", function(){ if(video.currentTime >= maxTime){ // 需在此处添加代码 playVideo(myUrl, startTime, endTime); } }, false);
解决方案
不能直接在timeupdate回调里加循环实现需求,因为JavaScript是单线程的,同步循环会彻底阻塞浏览器的事件循环——浏览器根本没时间去更新视频播放状态,循环会一直占着线程直到结束,视频播放直接卡死。
正确的做法是用状态变量追踪播放进度,靠事件驱动一步步推进,具体实现如下:
- 先定义几个状态变量,用来记录当前播到哪个视频、哪个片段,以及当前片段已经重复了几次:
// 播放状态追踪变量 let currentVideoIdx = 0; let currentClipIdx = 0; let repeatCount = 0; const REPEAT_TIMES = 3; // 每个片段要重复的次数
- 在Play按钮的点击事件里初始化状态,启动第一个片段的播放:
document.getElementById('playBtn').addEventListener('click', function() { // 重置所有状态 currentVideoIdx = 0; currentClipIdx = 0; repeatCount = 0; // 取出第一个视频的第一个片段 const [videoUrl, clips] = sentences[currentVideoIdx]; const [startTime, endTime] = clips[currentClipIdx]; playVideo(videoUrl, startTime, endTime); });
- 修改
timeupdate的回调逻辑,根据状态变量判断下一步操作:
video.addEventListener("timeupdate", function(){ const [videoUrl, clips] = sentences[currentVideoIdx]; const [startTime, endTime] = clips[currentClipIdx]; if(video.currentTime >= endTime){ repeatCount++; if(repeatCount < REPEAT_TIMES){ // 重复播放当前片段 playVideo(videoUrl, startTime, endTime); } else { // 当前片段重复够次数,切换到下一个 repeatCount = 0; currentClipIdx++; if(currentClipIdx < clips.length){ // 同一个视频的下一个片段 const [nextStart, nextEnd] = clips[currentClipIdx]; playVideo(videoUrl, nextStart, nextEnd); } else { // 当前视频的片段都播完了,切换到下一个视频 currentClipIdx = 0; currentVideoIdx++; if(currentVideoIdx < sentences.length){ const [nextVideoUrl, nextClips] = sentences[currentVideoIdx]; const [nextStart, nextEnd] = nextClips[currentClipIdx]; playVideo(nextVideoUrl, nextStart, nextEnd); } else { // 所有视频都播完了,停止播放 video.pause(); } } } } }, false);
这种方式完全靠事件驱动,每次片段播放结束时,根据当前状态决定重复当前片段、切换下一个片段或是切换下一个视频,不会阻塞线程,视频播放能正常进行。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

