This documentation is for an outdated version of Video.js. See documentation for the current release.

Text Tracks

Text Tracks are a function of HTML5 video for providing time triggered text to the viewer. Video.js makes tracks work across all browsers. There are currently five types of tracks:

Creating the Text File

Timed text requires a text file in WebVTT format. This format defines a list of "cues" that have a start time, and end time, and text to display. Microsoft has a builder that can help you get started on the file.

When creating captions, there's also additional [caption formatting techniques] ( that would be good to use, like brackets around sound effects: [ sound effect ]. If you'd like a more in depth style guide for captioning, you can reference the Captioning Key, but keep in mind not all features are supported by WebVTT or (more likely) the Video.js WebVTT implementation.

Adding to Video.js

Once you have your WebVTT file created, you can add it to Video.js using the track tag. Put your track tag after all the source elements, and before any fallback content.

<video id="example_video_1" class="video-js"
  controls preload="auto" width="640" height="264"
 <source src="" type="video/mp4" />
 <source src="" type="video/webm" />
 <source src="" type="video/ogg" />

 <track kind="captions" src="" srclang="en" label="English" default>


You can also add tracks programatically.

Subtitles from Another Domain

Because we're pulling in the text track file via Javascript, the same-origin policy applies. If you'd like to have a player served from one domain, but the text track served from another, you'll need to enable CORS in order to do so. In addition to enabling CORS on the server serving the text tracks, you will need to add the crossorigin attribute to the video element itself. This attribute has two values anonymous and use-credentials. Most users will want to use anonymous with cross-origin tracks. It can be added to the video element like so:

<video class="video-js" crossorigin="anonymous">
  <source src="" type="video/mp4">
  <track src="" kind="captions" srclang="en" label="English">

One thing to be aware of is that in this case the video files themselves will also needs CORS headers applied to it. This is because some browsers apply the crossorigin attribute to the video source itself and not just the tracks and is considered a security concern by the spec.

Track Attributes

Additional settings for track tags.


One of the five track types listed above. Kind defaults to subtitles if no kind is included.


The label for the track that will be show to the user, for example in a menu that list the different languages available for subtitles.


The default attribute can be used to have a track default to showing. Otherwise the viewer would need to select their language from the captions or subtitles menu. NOTE: For chapters, default is required if you want the chapters menu to show.


The two-letter code (valid BCP 47 language tag) for the language of the text track, for example "en" for English. A list of language codes is available here.

Interacting with Text Tracks

Showing tracks programmatically

Some of you would want to turn captions on and off programmatically rather than just forcing the user to do so themselves. This can be easily achieved by modifying the mode of the text tracks. The mode can be one of three values disabled, hidden, and showing. When a text track's mode is disabled, the track does not show on screen as the video is playing. When the mode is set to showing, the track is visible to the viewer and updates while the video is playing. You can change of a particular track like so:

let tracks = player.textTracks();

for (let i = 0; i < tracks.length; i++) {
  let track = tracks[i];

  // find the captions track that's in english
  if (track.kind === 'captions' && track.language === 'en') {
    track.mode = 'showing';

Doing something when a cue becomes active

Above, we mentioned that mode can also be hidden, what this means is that the track will update as the video is playing but it won't be visible to the viewer. This is most useful for metadata text tracks. One usecase for metadata text tracks is to have something happen when their cues become active, to do so, you listen to the cuechange event on the track. These events fire when the mode is showing as well. Here's an example:

let tracks = player.textTracks();
let metadataTrack;

for (let i = 0; i < tracks.length; i++) {
  let track = tracks[i];

  // find the metadata track that's labeled ads
  if (track.kind === 'captions' && track.label === 'ads') {
    track.mode = 'hidden';
    // store it for usage outside of the loop
    metadataTrack = track;

metadataTrack.addEventListener('cuechange', function() {;

Emulated Text Tracks

By default, video.js will try and use native text tracks if possible and fall back to emulated text tracks if the native functionality is broken or incomplete or non-existent. The Flash tech will always use the emulated text track functionality. The video.js API and TextTrack objects were modeled after the w3c's specification. video.js uses Mozilla's vtt.js library to parse and display its emulated text tracks.

If you wanted to disable native text track functionality and force video.js to use emulated text tracks always, you can supply the nativeTextTracks option to the tech like so:

let player = videojs('myvideo', {
  html5: {
    nativeTextTracks: false

Text Track Settings

When using emulated Text Tracks, captions will have an additional item in the menu called "caption settings". This allows the viewer of the player to change some styles of how the captions are displayed on screen.

If you don't want that, you can disable it by turning off the text track settings component and hiding the menu item like so:

let player = videojs('myvideo', {
  // make the text track settings dialog not initialize
  textTrackSettings: false
/* hide the captions settings item from the captions menu */
.vjs-texttrack-settings {
  display: none;

Text Track Precedence

In general, the Descriptions tracks is of lower precedence than captions and subtitles. What this means for you?


player.textTracks() -> TextTrackList

This is the main interface into the text tracks of the player. It return a TextTrackList which lists all the tracks on the player.

player.remoteTextTracks() -> TextTrackList

This is a helper method to get a list of all the tracks that were created from track elements or that were added to the player by the addRemoteTextTrack method. All these tracks are removeable from the player, where-as not all tracks from player.textTracks() are necessarily removeable.

player.remoteTextTrackEls() -> HTMLTrackElementList

Another helper method, this is a list of all the track elements associated with the player. Both emulated or otherwise.

player.addTextTrack(String kind, [String label [, String language]]) -> TextTrack

This is based on the w3c spec API and when given a kind and an optional label and language, will create a new text track for you to use. This method is intended for purely programmatic usage of tracks and has one important limitation: tracks created using this method cannot be removed. The native addTextTrack does not have a corresponding removeTextTrack, so, we actually discourage the usage of this method.

player.addRemoteTextTrack(Object options) -> HTMLTrackElement

This function takes an options object that looks pretty similar to the track element and returns a HTMLTrackElement. This object has a track property on it which is the actual TextTrack object. This TextTrack object is equivalent to the one that can be returned from player.addTextTrack with the added bonus that it can be removed from the player. Internally, video.js will either add a <track> element for you, or emulate that depending on whether native text tracks are supported or not. The options available are:


This function takes either an HTMLTrackElement or a TextTrack object and removes it from the player.