Skip to main content
Version: 11.11.0

Text tracks and subtitles

This example demonstrates the text track components for subtitle selection and styling.

The settings menu contains four submenus:

  • Subtitles: the idiomatic TrackRadioGroup with trackType="subtitles" and show-off, which composes TextTrackOffRadioButton and TextTrackRadioButton for you.
  • Subtitles (custom): the same picker built manually from TextTrackOffRadioButton and TextTrackRadioButton.
  • Subtitle appearance: the pre-built TextTrackStyleMenu, which composes TextTrackStyleDisplay, TextTrackStyleRadioGroup and TextTrackStyleResetButton.
  • Font color (custom): a single style option built manually from TextTrackStyleRadioGroup and TextTrackStyleResetButton.
Code
import * as THEOplayerReactUI from '@theoplayer/react-ui';
import { useContext, useEffect, useState } from 'react';

const configuration = {
libraryLocation: '/path/to/theoplayer/',
license: 'your_theoplayer_license'
};

const source = {
sources: { src: 'https://cdn.theoplayer.com/video/elephants-dream/playlist.m3u8' },
metadata: { title: "Elephant's Dream" }
};

// A hook returning the player's subtitle text tracks.
const useSubtitleTracks = () => {
const player = useContext(THEOplayerReactUI.PlayerContext);
const [tracks, setTracks] = useState([]);
useEffect(() => {
if (!player) return;
const textTracks = player.textTracks;
const update = () => {
setTracks(textTracks.filter((t) => t.kind === 'subtitles' || t.kind === 'captions'));
};
update();
textTracks.addEventListener(['addtrack', 'removetrack'], update);
return () => textTracks.removeEventListener(['addtrack', 'removetrack'], update);
}, [player]);
return { player, tracks };
};

// A subtitle picker built from the low-level TextTrackOffRadioButton and TextTrackRadioButton.
// In practice, prefer <TrackRadioGroup trackType="subtitles" show-off />, which composes these for you.
const CustomSubtitlePicker = () => {
const { player, tracks } = useSubtitleTracks();
return (
<THEOplayerReactUI.RadioGroup>
<THEOplayerReactUI.TextTrackOffRadioButton trackList={player?.textTracks} />
{tracks.map((track) => (
<THEOplayerReactUI.TextTrackRadioButton key={track.uid} track={track} />
))}
</THEOplayerReactUI.RadioGroup>
);
};

const FONT_COLORS = [
{ label: 'Default', value: '' },
{ label: 'White', value: 'rgb(255,255,255)' },
{ label: 'Yellow', value: 'rgb(255,255,0)' },
{ label: 'Green', value: 'rgb(0,255,0)' },
{ label: 'Cyan', value: 'rgb(0,255,255)' },
{ label: 'Blue', value: 'rgb(0,0,255)' },
{ label: 'Magenta', value: 'rgb(255,0,255)' },
{ label: 'Red', value: 'rgb(255,0,0)' },
{ label: 'Black', value: 'rgb(0,0,0)' }
];

const App = () => {
return (
<THEOplayerReactUI.UIContainer
configuration={configuration}
source={source}
bottomChrome={
<THEOplayerReactUI.ControlBar>
<THEOplayerReactUI.PlayButton />
<THEOplayerReactUI.MuteButton />
<THEOplayerReactUI.VolumeRange />
<THEOplayerReactUI.TimeDisplay />
<THEOplayerReactUI.LanguageMenuButton menu="language-menu" />
<THEOplayerReactUI.MenuButton menu="settings-menu">CC</THEOplayerReactUI.MenuButton>
<THEOplayerReactUI.FullscreenButton />
</THEOplayerReactUI.ControlBar>
}
menu={
<>
<THEOplayerReactUI.LanguageMenu id="language-menu" />
<THEOplayerReactUI.MenuGroup id="settings-menu">
<THEOplayerReactUI.Menu heading="Subtitles & captions">
<THEOplayerReactUI.MenuButton menu="subtitle-menu">
<span>Select</span>
</THEOplayerReactUI.MenuButton>
<THEOplayerReactUI.MenuButton menu="subtitle-style-menu">
<THEOplayerReactUI.TextTrackStyleDisplay property="fontColor" />
</THEOplayerReactUI.MenuButton>
</THEOplayerReactUI.Menu>

{/* Idiomatic subtitle picker using TrackRadioGroup. */}
<THEOplayerReactUI.Menu id="subtitle-menu" closeOnInput hidden heading="Subtitles">
<THEOplayerReactUI.TrackRadioGroup trackType="subtitles" show-off />
</THEOplayerReactUI.Menu>

{/* Manual subtitle picker using TextTrackOffRadioButton and TextTrackRadioButton. */}
<THEOplayerReactUI.Menu id="subtitle-custom-menu" closeOnInput hidden heading="Subtitles (custom)">
<CustomSubtitlePicker />
</THEOplayerReactUI.Menu>

{/* Pre-built subtitle style menu. */}
<THEOplayerReactUI.TextTrackStyleMenu
id="subtitle-style-menu"
closeOnInput
hidden
heading="Subtitle appearance"
/>

{/* Manual font color submenu using TextTrackStyleRadioGroup and TextTrackStyleResetButton. */}
<THEOplayerReactUI.Menu id="font-color-menu" closeOnInput hidden heading="Font color (custom)">
<THEOplayerReactUI.TextTrackStyleResetButton slot="heading" />
<THEOplayerReactUI.TextTrackStyleRadioGroup property="fontColor">
{FONT_COLORS.map(({ label, value }) => (
<THEOplayerReactUI.RadioButton key={value} value={value}>
{label}
</THEOplayerReactUI.RadioButton>
))}
</THEOplayerReactUI.TextTrackStyleRadioGroup>
</THEOplayerReactUI.Menu>
</THEOplayerReactUI.MenuGroup>
</>
}
error={<THEOplayerReactUI.ErrorDisplay />}
/>
);
};

📜 View full source on GitHub