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

当前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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 20:15:09