# Video players that hide captions in a settings menu

Source: https://easeweb.dev/learn/caption-controls
Topics: Images and media > Video players put caption and audio description buttons beside volume (EN 301 549 7.3; Section 508 503.4.1, 503.4.2)
The fix: Put a captions button and an audio description button in the player's control bar, beside volume, so each takes one press, as play and volume do. A settings menu can still hold the caption language and style.
Test with: keyboard, screen reader, zoom
References: https://www.access-board.gov/ict/#503-applications https://www.etsi.org/deliver/etsi_en/301500_301599/301549/03.02.01_60/en_301549v030201p.pdf https://bitvtest.de/pruefschritt/bitv-20-web/bitv-20-web-7-3-bedienelemente-fuer-untertitel-und-audiodeskription https://www.w3.org/WAI/media/av/player/ https://developer.mozilla.org/en-US/docs/Web/API/TextTrack/mode https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-pressed

This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.

## What happens

The coffee roaster's brewing video now has checked captions and a described version. Then the shop swapped the browser's own player for a branded one from its video plugin, to match the site. Its control bar has Play, a volume slider, Settings and Full screen. To turn on captions, you open Settings, then Subtitles, then choose English: three presses. Audio description is under Settings, then Audio, then "English, described". Play and volume take one press each. Nothing in the bar says captions exist.

## Why it fails

No WCAG criterion says where a captions button goes. WCAG asks for the captions (1.2.2) and the description (1.2.5), and for controls that work from the keyboard; this player has all of those. The requirement is in the procurement standards:

- Section 508, 503.4.1: where a player has volume controls, the controls to choose captions must be at the same menu level as volume or program selection.
- Section 508, 503.4.2: where a player has program selection, the controls for audio description must be at the same menu level as volume or program selection.
- EN 301 549, 7.3: where a web page primarily displays video with sound, the controls to turn on subtitles and audio description must be at the same level of interaction, the number of steps to complete the task, as the primary media controls such as play and volume. Table A.1 of EN 301 549 lists it among the requirements for web pages under the EU's web accessibility directive.

Volume takes one press here, and captions and audio description take three each, so the player fails 503.4.1 and 7.3. It has no program selection, so 503.4.2 doesn't apply to it. Section 508 can excuse a web application that meets WCAG 2.0 Level AA from 503, but the Trusted Tester process US federal agencies use for web content still tests a media player's caption and audio description controls (tests 17.D to 17.G). German BITV testers, who apply the EN clause, check it on every player a site builds with its own controls, and not on the browser's own player, which the site can't arrange.

## Who is affected

The menu is the same for everyone, but only the people who need captions or description have to go through it, and they have to do it again on every video.

## What automation and AI miss

No WCAG rule covers this, so axe and other WCAG scanners don't look. EaseWeb's audit lists every video for review; for a player with its own controls, it names a captions or subtitles button it finds near the video, or says it found a volume or mute control there but no captions button, and asks a person to confirm both captions and audio description take one press, as volume does. It can't open the player's menus, see inside a player in a frame, such as a YouTube embed, or tell an unnamed icon button is the captions one. A code assistant asked to "tidy up the player bar" may move captions into a settings menu, because that is where many popular players keep the caption language and style.

## Before: captions and description inside Settings

```html
<div class="player">
  <video src="brew-guide.webm" poster="brew-guide.jpg">
    <track kind="captions" srclang="en" label="English"
      src="brew-guide.en.vtt">
  </video>
  <div class="player-bar">
    <button type="button" aria-label="Play">…</button>
    <input type="range" aria-label="Volume"
      min="0" max="1" step="0.1" value="1">
    <button type="button" aria-label="Settings"
      aria-expanded="false" aria-controls="player-settings">…</button>
    <button type="button" aria-label="Full screen">…</button>
  </div>
  <div id="player-settings" class="player-menu" hidden>
    <!-- Opens a second menu: Off, English -->
    <button type="button">Subtitles</button>
    <!-- Opens a second menu: English; English, described -->
    <button type="button">Audio</button>
  </div>
</div>
```

Every control works from the keyboard and has a name, so the player passes WCAG's checks on its controls. But captions and audio description each take three presses where volume takes one, and the bar gives no sign that either exists.

## After: captions and audio description buttons beside volume

```html
<div class="player">
  <video src="brew-guide.webm" poster="brew-guide.jpg">
    <track kind="captions" srclang="en" label="English"
      src="brew-guide.en.vtt">
  </video>
  <div class="player-bar">
    <button type="button" aria-label="Play">…</button>
    <input type="range" aria-label="Volume"
      min="0" max="1" step="0.1" value="1">
    <button type="button" class="captions"
      aria-pressed="false">CC<span class="visually-hidden"> captions</span></button>
    <button type="button" class="described"
      aria-pressed="false">AD<span class="visually-hidden"> audio description</span></button>
    <button type="button" aria-label="Settings"
      aria-expanded="false" aria-controls="player-settings">…</button>
    <button type="button" aria-label="Full screen">…</button>
  </div>
  …
</div>
```

```js
const player = document.querySelector('.player');
const video = player.querySelector('video');
const captions = player.querySelector('.captions');
const described = player.querySelector('.described');
const SOURCES = { false: 'brew-guide.webm', true: 'brew-guide.ad.webm' };

captions.addEventListener('click', () => {
  const on = captions.getAttribute('aria-pressed') !== 'true';
  video.textTracks[0].mode = on ? 'showing' : 'hidden';
  captions.setAttribute('aria-pressed', on);
});

// Swap to the described version, or back, at the same place in the video.
described.addEventListener('click', () => {
  const on = described.getAttribute('aria-pressed') !== 'true';
  const { currentTime, paused } = video;
  video.src = SOURCES[on];
  video.addEventListener('loadedmetadata', () => {
    video.currentTime = currentTime;
    if (!paused) video.play();
  }, { once: true });
  described.setAttribute('aria-pressed', on);
});
```

Captions and audio description are now one press each, like play and volume, and the letters CC and AD in the bar show they are there. Each is a native button whose name starts with its visible letters, so speech input users can say "click CC", and `aria-pressed` tells screen reader users whether it is on. The described version swaps in at the same place, as in [videos without audio description of what they show](/learn/audio-description); a player that switches between two audio tracks of one file can switch tracks instead. The Settings menu stays for the caption language and the caption style.

## Implementation decisions

Keep both buttons in the bar at every width. When a narrow player runs out of room, move speed, quality and picture-in-picture into the overflow menu, not captions and description. Test at phone width and in full screen: some players rebuild their bar for full screen and leave buttons out there.

Show only what the video has. A video with captions but no described version gets the captions button only; an audio description button that does nothing misleads. With several caption languages, the CC button turns on the viewer's last choice, or the page's language, and the Settings menu offers the others. The same menu is the place for caption size, colours and background, which [captions stuck in one style, or lost when video is converted](/learn/caption-quality) covers.

Remember the choice. A viewer who turned captions on wants them on the next video too, and EN 301 549 notes it is best practice to let people choose whether captions and description start on by default. Keep the setting in the browser, so the next video starts the way the viewer left the last one.

A keyboard shortcut, such as C for captions, is a welcome extra, but not a substitute for the button: nobody sees it, touch users can't press it, and a single letter is one of the [single-key shortcuts that can't be turned off](/learn/character-key-shortcuts) unless people can turn it off or change it.

Where the controls aren't yours, check them anyway:

- The browser's own controls (`<video controls>`): the browser arranges them, and Chromium keeps its captions button in the controls' overflow menu at any width, and moves play, volume and full screen there too when the player is too narrow for them. Give the video enough width, and put the audio description button next to the player, as the audio description guide does.
- An embedded player, such as YouTube or Vimeo: its captions button is the platform's. If audio description is a separate video there, put a link to it directly under the player.

## Verify the fix

1. From the player, count the presses to turn on captions, to turn on audio description and to change the volume. Each takes one.
2. Using only the keyboard, Tab through the control bar, and turn captions and audio description on and off with Enter and Space. The described version keeps its place in the video.
3. At phone width, at 200% zoom and in full screen, check the captions and audio description buttons are still in the bar.
4. With a screen reader, find both buttons in the bar, and check each is read with its name and whether it is pressed, such as "CC captions, toggle button, not pressed".

Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after updating the player or its plugin.

## Limits

This is a starting pattern, not a guarantee for every application. The buttons only help when there is something behind them: captions that are right, covered in [videos without captions, or with unchecked automatic ones](/learn/video-captions), and a description that says what is shown. The player's other controls need names, state and keyboard support too. EN 301 549 and the Trusted Tester tests for Section 508 ask this of players the site builds; test the complete journey with the people who will watch it, in the players and platforms the video really plays in.

---

Get this guide in your coding agent: MCP https://easeweb.dev/mcp (setup at https://easeweb.dev/services/developers)
