当前texttrack无激活cue时跳转至上一个字幕cue的实现问题咨询
WebVTT 字幕跳转前一个有效Cue 实现方案
首先明确:原生TextTrackCueList没有内置直接获取「当前时间前最近有效cue」的属性或方法,你不想每次触发跳转都全量遍历cue的话,可以用下面两种更高效的方案:
方案1:预构建时间索引+二分查找(支持任意进度场景)
仅在字幕加载完成时做一次全量遍历提取时间索引,后续每次跳转用二分查找定位,时间复杂度为O(log n),哪怕有数千条字幕也无性能压力。
const video = document.querySelector('video'); const textTrack = video.textTracks[0]; let cueStartTimes = []; // 字幕加载完成后初始化索引,仅执行一次 textTrack.addEventListener('load', () => { // TextTrack.cues本身已按时间升序排列,直接提取起始时间即可 cueStartTimes = Array.from(textTrack.cues).map(cue => cue.startTime); }); // 跳转上一个字幕触发逻辑 function jumpToPrevCue() { const currentTime = video.currentTime; let left = 0, right = cueStartTimes.length - 1; let targetIdx = -1; // 二分查找找到小于当前时间的最大时间对应的索引 while (left <= right) { const mid = Math.floor((left + right) / 2); if (cueStartTimes[mid] < currentTime) { targetIdx = mid; left = mid + 1; } else { right = mid - 1; } } if (targetIdx >= 0) { video.currentTime = textTrack.cues[targetIdx].startTime; } }
方案2:事件监听缓存最近激活Cue(顺序播放场景性能最优)
通过监听cue的enter事件实时缓存最后一个激活的字幕,跳转时直接读取缓存即可,时间复杂度为O(1)。
const video = document.querySelector('video'); const textTrack = video.textTracks[0]; let lastActiveCue = null; textTrack.addEventListener('load', () => { Array.from(textTrack.cues).forEach(cue => { // 每个cue激活时更新缓存 cue.addEventListener('enter', () => { lastActiveCue = cue; }); }); }); function jumpToPrevCue() { if (lastActiveCue) { video.currentTime = lastActiveCue.startTime; // 若需要支持连续点击跳转到更前一个字幕,可额外维护一个历史队列存储最近N个激活的cue即可 } }
补充说明:如果字幕是动态增量加载的,新增cue时同步更新时间索引数组或绑定enter事件即可,不需要全量重新处理。
内容的提问来源于stack exchange,提问作者Rodrigo Yanez
相关产品推荐
相关产品推荐

