是 HTML 中唯一合法声明外挂字幕的方式,仅限 或 内部使用,必须指定 kind="subtitles"、合法 srclang 和 UTF-8 编码的 VTT 文件。

HTML 中不能用原生标签“配置”外挂 SMI/SRT/VTT 字幕文件——只有 <track></track> 标签能声明外部字幕,且仅对 <video></video> 有效,不适用于纯文本或音频加载场景。
为什么 <track></track> 是唯一合法方式
浏览器规范只允许在 <video></video> 或 <audio></audio> 元素内部用 <track></track> 引入外挂字幕。它不是“配置”,而是语义化声明:告诉浏览器“这里有一条字幕轨道”。其他任何写法(比如在 里放 <link rel="subtitles">、用 JS 动态 append <div> 模拟)都不被标准支持,也不会触发原生字幕 UI(如右键“字幕”菜单、快捷键切换)。
<ul>
<li>
<code><track></track> 必须是 <video></video> 的子元素,位置必须在 <source></source> 之后、<video></video> 结束前
kind="subtitles",否则不会显示在字幕开关列表中srclang 属性必须为合法 BCP 47 语言码(如 "zh"、"en-US"),空值或错值会导致轨道被忽略
<track></track> 的实际写法与常见错误
正确示例:
<video controls> <source src="movie.mp4" type="video/mp4"> <track kind="subtitles" label="中文" srclang="zh" src="movie.zh.vtt" default> <track kind="subtitles" label="English" srclang="en" src="movie.en.vtt"> </video>
容易踩的坑:
立即学习“前端免费学习笔记(深入)”;
- 路径错误:
src必须是相对或绝对 URL,不能是本地文件路径(file:///协议下多数浏览器会因安全策略拒绝加载) - 跨域问题:如果
src指向不同源的 VTT 文件,需服务端返回Access-Control-Allow-Origin: *,否则控制台报CORS error - 编码错误:VTT 文件必须是 UTF-8 无 BOM,含中文却用 GBK 编码会导致乱码或加载失败
- 误用
default:一个<video></video>中只能有一个default,多设等于没设
SMI 和 SRT 文件怎么处理才真正可用
SMI 和 SRT 都不是 HTML 标准支持的字幕格式。若你手头只有这类文件,必须先转换为 WebVTT(.vtt):
- SMI → VTT:SMI 是类 HTML 格式,
<sync start="12345"></sync>对应 VTT 的00:00:12.345,但 CSS 样式、多语言块需手动剥离或重写;推荐用开源工具smi2vtt(Node.js CLI)或在线转换器 - SRT → VTT:结构接近,只需改时间戳格式(逗号→点)、加
WEBVTT头行;可用ffmpeg -i input.srt output.vtt一键转(要求 ffmpeg ≥ 4.4) - 别信“浏览器插件自动加载 SRT”:那只是 JS 模拟渲染,不走原生
<track></track>流程,无法响应系统级字幕设置、无障碍 API 或画中画字幕
想让字幕和视频同名自动加载?浏览器不干这事
Windows Media Player 或 RockPlayer 支持“同名 SMI/SRT 自动加载”,是因为它们自己实现了文件发现逻辑。HTML 标准没有“自动查找同名字幕”机制——<track></track> 的 src 必须显式写出。想模拟自动加载,只能靠 JS:
- 读取
<video></video>的src,用正则提取文件名(不含扩展),拼出xxx.zh.vtt - 动态创建
<track></track>并 append 到<video></video>,再调用video.textTracks[0].mode = "showing" - 注意:此操作必须在
video的loadedmetadata事件后执行,否则textTracks可能为空
真正麻烦的从来不是写几行 HTML,而是确保 VTT 文件可访问、编码正确、时间轴无负值、服务器配好 CORS——这些细节一漏,字幕就静默消失,连错误提示都没有。



















