cuechange 事件只能绑定在 TextTrack 对象且 mode 为 "showing" 或 "hidden" 时生效;常见失效原因包括 track.mode 未设置、VTT 文件加载失败、textTracks 未就绪或监听过早;正确步骤是等待 loadeddata 后获取 track、设 mode="showing" 再绑定 oncuechange。

cuechange 事件本身不能直接绑定在 <track> 元素上触发——它只在 TextTrack 对象上有效,且必须满足 mode 为 "showing" 或 "hidden"(不能是 "disabled"),否则监听无效。
track.oncuechange 不生效的常见原因
-
<track>标签没加default属性,或 JS 中没手动设track.mode = "showing" - WebVTT 文件路径 404 或 MIME 类型不是
text/vtt(服务器需配置) - 字幕轨道未被浏览器识别:检查
video.textTracks.length是否 ≥ 1,且track.kind === "subtitles"或"metadata" -
oncuechange绑定太早,textTracks还没加载完成(需等loadeddata或canplay后再取 track)
正确获取并监听 cuechange 的步骤
- 确保 HTML 中
<track>已声明,例如:<track kind="subtitles" src="captions.vtt" srclang="zh" label="中文" default> - 等待视频元数据加载完成:
video.addEventListener("loadeddata", () => { ... }) - 取出第一个有效轨道:
const track = video.textTracks[0] - 设置显示模式:
track.mode = "showing"(这是触发cuechange的硬性前提) - 绑定监听:
track.oncuechange = () => { console.log(track.activeCues); } - 注意:
activeCues是实时数组,可能为空(比如 cue 刚结束)、含多个项(重叠时间点),不要直接假设activeCues[0]总存在
activeCues 中的时间判断要小心
-
cue.startTime和cue.endTime是秒级浮点数(如8.5),不是字符串或 HH:MM:SS 格式 - 不要用
===精确比对时间值(浮点误差 + 渲染延迟),建议用区间判断:if (currentTime >= cue.startTime && currentTime < cue.endTime) - 若想只在 cue 刚激活时执行一次逻辑(比如弹题),需自行记录已处理的 cue ID 或用 Map 缓存状态,因为
cuechange在激活/失活时都会触发
真正容易被忽略的是:cuechange 不代表“到了某个时间点”,它只反映字幕 cue 的显隐状态切换。如果你只是想在视频播到 12.3 秒时弹窗,用 timeupdate + 时间数组更稳;只有当你已有 VTT 文件、且业务逻辑与字幕内容强耦合(比如每条字幕对应一个知识点卡片),才值得走 cuechange 这条路。



















