Тег track (от английского track, «дорожка») подключает к video или audio текстовую дорожку: субтитры, названия глав или реплики, привязанные ко времени. Это одиночный тег (в стандарте пустой элемент): закрывающего тега нет, всё задаётся атрибутами. Сам по себе он ничего не показывает: браузер берёт отдельный файл с репликами, а на экран выводит только субтитры и только поверх видео.
Дальше разобраны атрибуты, значения kind, формат файла WebVTT, несколько дорожек, работа из JavaScript, дорожка для звука, главы, стили реплик и причины, по которым дорожка не загружается. Сами теги описаны на страницах о теге video и о теге audio.
<video src="film.webm" controls>
<track kind="subtitles" src="ru.vtt" srclang="ru"
label="Русский" default>
</video>
В этой статье
- Тег track в HTML: что это и почему он одиночный
- Атрибуты тега track: kind, src, srclang, label и default
- Атрибут kind у тега track: subtitles, captions, chapters и другие значения
- Файл WebVTT для тега track: как записать .vtt
- Несколько дорожек и атрибут default у тега track
- Тег track в JavaScript: textTracks, mode и cuechange
- Тег track в audio: текст для звука без картинки
- Тег track kind chapters: главы видео и навигация
- Тег track в CSS: стили реплик через ::cue
- Почему тег track не работает: загрузка, CORS и MIME
Тег track в HTML: что это и почему он одиночный
Сначала о том, где записывается тег и почему у него нет закрывающей части.
Тег track допустим только внутри video или audio, после вложенных source, если они есть. Содержимого у него нет, поэтому закрывающий тег не нужен. Браузер загружает дорожку и с записанным </track>, но писать его не нужно: слэш в конце <track /> допускается и ничего не меняет.
Дорожка состоит из двух частей: тега в разметке и отдельного файла в формате WebVTT с расширением .vtt. В файле записаны реплики и время, когда каждая появляется. Тег только указывает на файл и описывает его: вид, язык, название. Способ вшить субтитры в само изображение не даёт ни выбрать язык, ни выключить текст, а дорожка track даёт и то и другое.
<video controls>
<source src="film.webm" type="video/webm">
<track kind="subtitles" src="ru.vtt" srclang="ru" default>
<track kind="subtitles" src="en.vtt" srclang="en">
</video>
Пример: тег track внутри video и состояние дорожки
Это настоящее видео с одной дорожкой. Нажмите воспроизведение: реплики выводит браузер. Кнопки переключают режим дорожки, а строки под видео показывают её состояние.
Субтитры нужны тем, кто смотрит без звука или не знает язык ролика, а для демонстраций интерфейса без озвучки они часто единственный способ объяснить происходящее. Те же дорожки хранят названия глав и служебные данные для скриптов. Справочные описания есть на MDN, в стандарте HTML Living Standard, а формат файла описан на странице WebVTT API.
Атрибуты тега track: kind, src, srclang, label и default
Атрибутов пять, и только src нужен всегда, а остальные уточняют, что это за дорожка.
Булев атрибут default включён, если записан, и выключен, если его нет: значение не нужно. Остальные принимают значение: адрес, язык, название или слово из набора.
<track kind="captions" src="ru.vtt" srclang="ru"
label="Русский" default>
| Атрибут | Что делает | Пример записи |
|---|---|---|
kind | Вид дорожки: subtitles, captions, descriptions, chapters, metadata. Если атрибута нет, берётся subtitles | <track kind="captions" src="ru.vtt"> |
src | Адрес файла .vtt, обязателен | <track src="ru.vtt"> |
srclang | Язык дорожки кодом: ru, en, de. Стандарт требует его для subtitles | <track src="ru.vtt" srclang="ru"> |
label | Название дорожки для меню плеера | <track src="ru.vtt" label="Русский"> |
default | Включает дорожку без выбора читателя. subtitles и captions считаются одним видом, и default допускается один на оба | <track src="ru.vtt" default> |
Пример: как браузер понимает атрибуты тега track
Кнопки собирают настоящие дорожки и показывают, что браузер понял. Без kind это subtitles, а неверное значение превращается в metadata. Без srclang дорожка работает, но язык пустой. Из двух default включается только первый, а default у разных видов работают оба.
Самая коварная запись: опечатка в kind. Значение subtitle без последней буквы браузер не отвергает, а превращает дорожку в metadata, и субтитры на экране не появятся. Без srclang дорожка работает, но язык у неё пустой, а стандарт для субтитров его требует, поэтому записывайте его всегда.
Атрибут kind у тега track: subtitles, captions, chapters и другие значения
Значение kind решает, что браузер сделает с репликами: покажет на экране, предложит в меню или отдаст только скрипту.
| Значение | Для чего | Пример записи |
|---|---|---|
subtitles | Перевод или текст речи для тех, кто слышит звук, но не знает язык ролика | kind="subtitles" |
captions | Полная расшифровка для тех, кто не слышит звук: речь и важные звуки | kind="captions" |
descriptions | Описание происходящего на экране для тех, кто не видит картинку1 | kind="descriptions" |
chapters | Названия глав с временем начала для навигации | kind="chapters" |
metadata | Служебные данные для скриптов, читателю не показываются | kind="metadata" |
1 Реплики такой дорожки загружаются, но на экран не выводятся. По стандарту такие реплики озвучивает синтезатор речи, а не рисует браузер.
Пример: что показывает тег track для разных значений kind
Видео остановлено на 1,5 секунде, дорожка включена в режиме showing. Реплика видна на экране только у subtitles и captions, хотя у остальных видов она тоже загружена и активна: счётчик активных реплик везде равен единице.
Разница между subtitles и captions в том, слышит читатель звук или не слышит. В русскоязычных справочниках встречается путаница: subtitles описывают как дорожку для глухих, а это назначение captions. Для видео без озвучки подходят captions, для зарубежного ролика с переводом subtitles. Главы и служебные данные разобраны в отдельных разделах ниже.
Файл WebVTT для тега track: как записать .vtt
Файл с репликами текстовый: первая строка WEBVTT, дальше блоки, разделённые пустой строкой.
Реплика (по-английски cue) состоит из необязательного идентификатора, времени начала и конца через --> и текста. В файле допустимы комментарии, настройки положения и теги внутри текста.
WEBVTT
NOTE Комментарий для автора, зритель его не увидит
1
00:00:01.000 --> 00:00:03.000
Первая реплика
2
00:00:04.000 --> 00:00:06.000 line:10% align:start
Вторая реплика с <b>выделением</b>
| Часть файла | Как записывается | Пример |
|---|---|---|
| Заголовок | Первая строка WEBVTT. Без неё браузер отвергает файл целиком | WEBVTT |
| Время | чч:мм:сс.ттт или короче, мм:сс.ттт. Перед миллисекундами точка, а не запятая | 00:01.000 --> 00:03.000 |
| Идентификатор | Строка перед временем, в скрипте доступна как cue.id | intro |
| Настройки | После времени: line, position, size, align | line:10% align:start |
| Теги в тексте | b, i, u, c.класс, v Имя | Это <b>важно</b> |
| Комментарий | Блок со словом NOTE в начале | NOTE проверить время |
Пример: редактор файла WebVTT для тега track
Текст в поле превращается в настоящий файл дорожки. Кнопка с запятой заменяет точки в записи времени, как в формате SRT: файл принимается, но ни одна реплика не показывается. Без строки WEBVTT браузер отвергает файл целиком.
Субтитры из других программ часто сохранены в формате SRT: в нём время пишут через запятую и нет строки WEBVTT. Перед подключением файл придётся привести к виду выше. Положение реплики задают настройками в файле, а не стилями: настройка line:10% поднимает реплику к верхнему краю кадра, а align:start прижимает её влево.
Несколько дорожек и атрибут default у тега track
У одного видео может быть много дорожек, по одной на язык, и браузер должен знать, какую включить сам.
Читатель выбирает дорожку в меню плеера, где она подписана значением label. Если ничего не выбирать, включится та, у которой записан default. Остальные дорожки браузер не загружает: у выключенной дорожки readyState равен 0, и обращения за её файлом нет. Файл загрузится, когда режим дорожки сменится на включённый.
| Режим | Что значит | Пример записи |
|---|---|---|
disabled | Дорожка выключена, файл не берётся | track.mode = "disabled" |
hidden | Файл загружен, реплики доступны скрипту, на экран не выводятся | track.mode = "hidden" |
showing | Файл загружен, реплики субтитров и captions выводятся на экран | track.mode = "showing" |
Пример: несколько дорожек тега track и режим disabled
Русская дорожка включена атрибутом default, английская ещё не загружена, её readyState равен нулю. После выбора English файл второй дорожки загружается, а у русской режим становится disabled.
Если записать default у двух дорожек одного вида (subtitles и captions считаются одним видом), сработает первая, а вторая останется disabled и не загрузится. У дорожек разных видов, например subtitles и chapters, можно записать по одному default: включатся обе.
Тег track в JavaScript: textTracks, mode и cuechange
Дорожка доступна из скрипта как объект TextTrack: её можно читать, включать и даже создавать без файла.
| Свойство или метод | Что делает | Пример записи |
|---|---|---|
video.textTracks | Список всех дорожек элемента | video.textTracks[0] |
mode | Режим дорожки: disabled, hidden, showing | track.mode = "hidden" |
cues | Все реплики дорожки, пока файл не загружен, там null или пусто | track.cues.length |
activeCues | Реплики, которые идут сейчас | track.activeCues[0].text |
cuechange | Событие: набор активных реплик изменился | track.addEventListener("cuechange", f) |
readyState тега | 0 — не загружается, 1 — идёт загрузка, 2 — загружена, 3 — ошибка | trackTag.readyState |
addTextTrack() | Создаёт дорожку без файла и без тега | video.addTextTrack("metadata") |
VTTCue | Реплика для такой дорожки: начало, конец, текст | new VTTCue(1, 3, "текст") |
const video = document.querySelector("video");
const track = video.textTracks[0];
track.mode = "hidden";
track.addEventListener("cuechange", () => {
const cue = track.activeCues[0];
caption.textContent = cue ? cue.text : "";
});
Пример: события cuechange у дорожки тега track
Видео идёт 8 секунд, а журнал показывает каждую смену активной реплики. Дорожка из тега track и дорожка из addTextTrack() ведут себя одинаково: режим у обеих hidden, на экран ничего не выводится.
Реплика активна с момента start до момента end, сам момент end уже не входит: в примере событие в 2,5 секунды показало ноль активных реплик. Видео в примере идёт . Режим hidden нужен, когда реплики хотят вывести самим: файл загружен, события приходят, а браузер ничего не рисует. Дорожка из addTextTrack() сразу получает режим hidden и не появляется в разметке: в video тегов track при этом нет. Текст реплики в свойстве text хранится вместе с тегами, например Вторая <b>реплика</b>, а разобранный вид даёт cue.getCueAsHTML().
Тег track в audio: текст для звука без картинки
У audio нет области показа, поэтому браузер ничего не выведет, и текст показывает сам скрипт.
Дорожка к audio загружается и работает так же, как у видео: у audio с default загружаются все реплики, а cuechange приходит в те же моменты. На экране при этом ничего не появляется: блок остаётся прежнего размера. Поэтому для звука выбирают kind="metadata": вместе с default режим hidden включается сам, а текст выводится на страницу скриптом.
<audio src="podcast.mp3" controls>
<track kind="metadata" src="podcast.vtt" default>
</audio>
Пример: тег track в audio и расшифровка, которая следует за звуком
Звук идёт в настоящем audio, а строка под ним подсвечивается по событию cuechange. Нажмите на строку, чтобы перемотать звук к ней. Размер блока audio не изменился: сама дорожка ничего не выводит.
Строка расшифровки, например Сначала разберём, где он записывается
, хранится в файле .vtt и не входит в разметку страницы, поэтому полную расшифровку для чтения лучше записать и обычным текстом, например внутри details. Подробнее о самом теге читайте на странице о теге audio.
Тег track kind chapters: главы видео и навигация
Дорожка глав содержит названия с временем начала, и из неё скрипт строит оглавление видео.
Для kind="chapters" файл загружается, но на экран ничего не выводится, как и у остальных видов, кроме subtitles и captions. Список глав строят сами из реплик: название берут из cue.text, время из cue.startTime. Идентификатор реплики, например intro, хорошо подходит для якоря.
WEBVTT
intro
00:00:00.000 --> 00:00:02.000
Вступление
main
00:00:02.000 --> 00:00:05.000
Главное
const cues = video.textTracks[0].cues;
for (const cue of cues) {
const item = document.createElement("li");
item.textContent = cue.text;
item.onclick = () => (video.currentTime = cue.startTime);
list.append(item);
}
Пример: главы из дорожки тега track kind chapters
Список построен из реплик файла с главами. Нажатие на главу перематывает видео, а текущая глава подсвечивается по ходу ролика.
Список строят после события load у тега track, иначе cues окажется пустым или null. Тот же приём работает для kind="metadata": в текст реплики записывают любые данные, например подсказку или номер слайда, а скрипт читает их в нужный момент. У metadata с default режим hidden включается сам.
Тег track в CSS: стили реплик через ::cue
Реплики рисует браузер, поэтому тег track стилизуют не напрямую, а псевдоэлементом ::cue у video.
Правило video::cue меняет все реплики, ::cue(b) — только текст внутри тега b, а ::cue(.hot) — только то, что записано как <c.hot>. Положение реплики задаётся в файле, размер шрифта растёт вместе с шириной видео.
| Правило | Что получается | Пример записи |
|---|---|---|
color | Цвет текста реплики | color: #FFD166 |
background | Цвет плашки под текстом, transparent убирает её | background: #0B6E6E |
font-size и font-family | Размер и шрифт | font-size: 24px |
opacity | Реплика бледнее | opacity: .5 |
::cue(b) | Только текст в теге b | color: #FF6B6B |
::cue(.hot) | Только <c.hot> | color: #FF6B6B |
::cue(v[voice]) | Реплики одного говорящего из <v Anna> | color: #FF6B6B |
Пример: стили тега track через ::cue
Видео остановлено на второй секунде, в реплике есть тег b и класс hot. Кнопки подключают правила ::cue к настоящей дорожке, под видео показано действующее правило.
Не все свойства ::cue принимает: стандарт ограничивает набор, поэтому отступы и рамку у реплики лучше не задавать. Если нужен полностью свой вид, дорожку включают в режиме hidden и выводят текст в отдельный блок страницы (об этом рассказано в разделе про JavaScript).
Почему тег track не работает: загрузка, CORS и MIME
Если субтитров нет, сначала проверяют, загрузился ли файл дорожки, а затем режим и вид.
| Причина | Что видно | Что сделать |
|---|---|---|
| Файла по адресу нет | readyState тега равен 3, приходит error, реплик 0 | Открыть адрес в браузере и проверить путь |
В файле нет строки WEBVTT | То же: 3 и ни одной реплики | Записать WEBVTT первой строкой |
| Время записано через запятую, как в SRT | Файл принят, но такие реплики пропали без ошибки | Заменить запятую на точку |
Файл на другом домене, у video нет crossorigin | Браузер не обращается к серверу, в консоли ошибка Unsafe attempt… | Записать на video атрибут crossorigin="anonymous" |
| Другой домен не разрешает доступ | Нет заголовка Access-Control-Allow-Origin: запрос идёт, но браузер блокирует ответ по правилам CORS | Включить заголовок на сервере с файлом |
Страница открыта как файл с диска, file:// | Браузер не загружает дорожку, readyState равен 3 | Открывать страницу через локальный сервер |
| Дорожка не включена | Режим disabled, файл не запрашивался | Записать default или track.mode = "showing" |
Два default одного вида | Работает первая, вторая остаётся disabled | Оставить один default |
Вид chapters, descriptions или metadata | Реплики загружены, но на экран не выводятся | Использовать subtitles или captions |
Неверный Content-Type у файла | браузер может принять файлы и с типами text/plain, text/html, application/octet-stream или без типа, но другие браузеры могут отказать | Отдавать text/vtt |
Состояние загрузки читают у самого тега: readyState равен 0, пока файл не нужен, 2 — когда он загружен, 3 — при ошибке.
const tag = document.querySelector("track");
tag.addEventListener("load", () => console.log("готово"));
tag.addEventListener("error", () => console.log(tag.readyState));
Консоль браузера открывается клавишей F12, а вкладка сети покажет, было ли обращение к файлу .vtt и какой ответ пришёл.
Частые ошибки с тегом track
Основные ошибки связаны с видом дорожки, форматом файла времени и ожиданием, что браузер сам всё включит.
| Ошибка | Что происходит | Как исправить |
|---|---|---|
</track> | Закрывающий тег не нужен, браузер его игнорирует | Записать только <track src="ru.vtt"> |
<div><track></div> | Вне video и audio тег дорожку не создаёт | Перенести внутрь video или audio |
kind="subtitle" | Опечатка превращает дорожку в metadata, субтитров нет | Записать subtitles |
kind="subtitles" | Нет srclang: дорожка работает, но язык пустой, а стандарт его требует | Добавить srclang="ru" |
<track src="ru.vtt"> | Нет default: дорожка выключена, пока читатель не выберет её в меню | Добавить default для основной дорожки |
Файл .vtt без строки WEBVTT | Браузер отвергает файл, реплик нет | Записать заголовок первой строкой |
00:00:01,000 | Запятая вместо точки: реплика пропадает без ошибки | Записать 00:00:01.000 |
kind="chapters" | Ждут, что главы появятся на экране, а браузер их не выводит | Построить список глав скриптом |
track.cues.length | Сразу после добавления тега cues равен null или пуст, чтение length даёт ошибку | Читать после события load |
Два default одного вида | Включается только первая дорожка | Оставить один |
Файл на чужом домене без crossorigin | Браузер блокирует загрузку, дорожка не появляется | Записать crossorigin="anonymous" и включить CORS |
Расшифровка для звука только в .vtt | Текст не входит в страницу, читатель его не увидит | Вывести реплики скриптом и продублировать текст на странице |