squirrelscan
GitHub

Video captions: the track element and why it is required

A video with no captions excludes anyone who cannot hear it. squirrel checks every HTML video element for a caption or subtitle track.

What a caption track is

A <track> element inside a <video> points at a timed text file, usually WebVTT, that the browser renders as captions. kind="captions" additionally carries relevant non-speech audio, such as sound effects and speaker identification, for a viewer who cannot hear the track. kind="subtitles" carries dialogue, either translated or in the same language as the audio.

WCAG success criterion 1.2.2 requires captions for prerecorded audio in synchronised media at Level A, the lowest conformance level. They also help anyone watching without sound, which is most people on a phone in public, and the text is indexable in a way audio is not.

What squirrel checks

The rule runs on every crawled page over every <video> element that is not decorative, looking for a child track[kind="captions"] or track[kind="subtitles"]. It emits a single check named video-accessible:

  • Info when the page has no <video> element. Message: No HTML5 video elements found.
  • Pass when every video that needs captions has a caption or subtitle track, or when every video is decorative (No videos need captions (N decorative skipped)). Message: All 3 video(s) have caption tracks.
  • Info when some do. Message: 2/3 video(s) have caption tracks.
  • Warn when none do. Message: No videos have caption tracks, with Add <track> elements for accessibility as the value. Severity warning, weight 4.

Decorative videos

A video is skipped when it is aria-hidden="true", or when it is muted, has no controls, and has autoplay or loop. That is the markup of a background or hero loop, which has no audio to caption. The counts in the messages above exclude skipped videos, and the check’s details record videosChecked (videos that needed captions) and decorativeSkipped. A video with controls, that is not muted, or that is muted with neither autoplay nor loop, is still checked. a11y/video-captions uses the same check, so the two rules agree.

Only HTML <video> elements are checked. A YouTube or Vimeo embed carries its own captions inside the iframe, which this rule cannot see, so a page whose video is entirely embedded reports No HTML5 video elements found.

How to fix it

<video controls poster="/thumb.jpg">
  <source src="/talk.mp4" type="video/mp4" />
  <track kind="captions" src="/talk.en.vtt" srclang="en" label="English" default />
</video>

Ship a WebVTT file alongside the video and reference it with <track>. Auto-generated captions are a starting point, not a deliverable: they get names, jargon and punctuation wrong, which is exactly the content someone relying on them needs.

Publish a transcript on the page as well. It is readable, searchable and useful to people who would rather not watch.

Rule IDvideo/video-accessible
CategoryVideo
ScopePer-page
Severitywarning
Weight4/10

Enable / disable

Disable this rule

[rules]
disable = ["video/video-accessible"]

Disable all Video rules

[rules]
disable = ["video/*"]

Enable only this rule

[rules]
enable = ["video/video-accessible"]

enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.

Video findings ship in every audit next to the SEO, performance and agent experience rules. See Fix SEO issues with AI for how an agent works through a report.

References

Check your site

Run squirrel audit https://example.com and open the Video section of the report. Each page is reported with how many of its videos carry a caption track. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.

Type to search…

↑↓ navigate↵ openesc close