报404是因src请求失败,非标签错误;常见原因包括路径错误、file://协议拦截、服务端未配text/vtt MIME类型、大小写不匹配或VTT文件首行不合规(须顶格全大写WEBVTT)。

加了 <track></track> 却报 404,不是标签写错了,而是浏览器在请求字幕文件时失败了——它把 src 当成普通 HTTP 请求发出去,而这个请求返回了 404 状态码。
为什么 <track src="zh.vtt"></track> 会触发 404 错误
浏览器解析到 <track></track> 后,会立即发起对 src 的 GET 请求,和图片、脚本加载逻辑一致。一旦服务器返回 404(文件不存在)、403(权限拒绝)或 CORS 拦截,字幕轨道就加载失败,video.textTracks 里对应项的 readyState 会是 0(notLoaded),后续设 mode = "showing" 也无效。
- 路径写错:比如
src="subtitles/zh.vtt",但实际文件在assets/subs/zh.vtt - 本地双击 HTML 打开:
file://协议下所有<track></track>的src请求都会被浏览器静默拦截(同<audio></audio>和<video></video>的媒体资源限制) - 服务端没配 MIME 类型:VTT 文件必须返回
Content-Type: text/vtt,返回text/plain或空值,Chrome/Firefox 直接拒收 - 拼写或大小写错误:Linux 服务器区分大小写,
ZH.VTT≠zh.vtt
如何快速定位是哪个环节出问题
打开浏览器 DevTools → Network 面板 → 刷新页面 → 筛选 media 或直接搜 .vtt。找到对应请求后看三点:
- 状态码是不是
404、403或0(CORS 或 file:// 协议) - Preview / Response 标签页是否为空,或显示 “Failed to load response data”
- Response Headers 里有没有
Content-Type: text/vtt
如果请求根本没出现在 Network 面板里,大概率是 file:// 协议导致的加载跳过 —— Safari 甚至可能完全不创建 <track></track> 节点。
立即学习“前端免费学习笔记(深入)”;
真正能跑通的部署和路径写法
必须用 HTTP 服务启动页面,且路径要经得起静态部署验证:
- VS Code 安装 Live Server 插件,右键 HTML → “Open with Live Server”
- 终端运行:
python3 -m http.server 8000,然后访问http://localhost:8000/index.html -
src推荐用根相对路径:如src="/subs/en.vtt"(假设项目结构为subs/en.vtt在站点根目录下) - 避免
../向上跳:嵌套层级深时容易算错基准目录;也不要用绝对 URL(除非你确定跨域已配好 CORS)
Netlify、Vercel 等平台部署时,确认 en.vtt 文件确实被上传到了输出目录(比如 _site/subs/en.vtt),而不是被构建工具忽略。
JS 主动启用字幕前必须检查加载状态
就算路径和 MIME 都对,loadedmetadata 触发时 textTracks 也可能还没就绪。不能一上来就 find(...).mode = "showing":
- 先等
video.addEventListener('loadeddata', ...)或更稳妥地监听textTracks.onaddtrack(但兼容性差) - 遍历时检查
track.readyState === 2(loaded),跳过0或1的轨道 - 对加载失败的轨道,可降级提示:
console.warn('Subtitles failed to load:', track.src)
最常被忽略的一点:VTT 文件本身必须以 WEBVTT 开头(全大写、顶格、无 BOM、无空格),否则即使 HTTP 响应成功,浏览器也会当作无效内容丢弃 —— 此时 Network 显示 200,但字幕就是不出现。



















