CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-video-js

An HTML5 video player that supports HLS and DASH with a common API and skin.

Pending
Overview
Eval results
Files

tracks.mddocs/

Track Management

Video.js provides comprehensive track management for video, audio, and text tracks with full accessibility support and standardized APIs following HTML5 specifications.

Capabilities

Text Tracks

Manage subtitles, captions, descriptions, chapters, and metadata tracks.

/**
 * Text track for subtitles, captions, descriptions, chapters, and metadata
 */
class TextTrack {
  /**
   * Text track kind
   */
  readonly kind: TextTrackKind;
  
  /**
   * Text track label
   */
  readonly label: string;
  
  /**
   * Text track language code
   */
  readonly language: string;
  
  /**
   * Text track display mode
   */
  mode: TextTrackMode;
  
  /**
   * List of track cues
   */
  readonly cues: TextTrackCueList;
  
  /**
   * Active cues at current playback time
   */
  readonly activeCues: TextTrackCueList;
  
  /**
   * Add cue to track
   * @param cue - Cue to add
   */
  addCue(cue: VTTCue): void;
  
  /**
   * Remove cue from track
   * @param cue - Cue to remove
   */
  removeCue(cue: VTTCue): void;
}

/**
 * List of text tracks
 */  
class TextTrackList {
  /**
   * Number of tracks
   */
  readonly length: number;
  
  /**
   * Get track by index
   * @param index - Track index
   * @returns Text track
   */
  [index: number]: TextTrack;
  
  /**
   * Get track by ID
   * @param id - Track ID
   * @returns Text track or null
   */
  getTrackById(id: string): TextTrack | null;
}

Usage Examples:

// Access text tracks
const textTracks = player.textTracks();
console.log('Number of text tracks:', textTracks.length);

// Find subtitle track
for (let i = 0; i < textTracks.length; i++) {
  const track = textTracks[i];
  if (track.kind === 'subtitles' && track.language === 'en') {
    track.mode = 'showing'; // Show English subtitles
    break;
  }
}

// Add programmatic text track
const track = player.addTextTrack('subtitles', 'English', 'en');
track.addCue(new VTTCue(0, 5, 'Hello World'));
track.addCue(new VTTCue(5, 10, 'This is a subtitle'));
track.mode = 'showing';

// Listen for cue changes
track.addEventListener('cuechange', () => {
  const activeCues = track.activeCues;
  if (activeCues.length > 0) {
    console.log('Active cue:', activeCues[0].text);
  }
});

Audio Tracks

Manage multiple audio tracks for language selection and audio descriptions.

/**
 * Audio track representation
 */
class AudioTrack {
  /**
   * Unique track identifier
   */
  readonly id: string;
  
  /**
   * Track kind (main, alternative, commentary, etc.)
   */
  readonly kind: string;
  
  /**
   * Human-readable track label
   */
  readonly label: string;
  
  /**
   * Track language code
   */
  readonly language: string;
  
  /**
   * Whether track is enabled (only one can be enabled at a time)
   */
  enabled: boolean;
}

/**
 * List of audio tracks
 */
class AudioTrackList {
  /**
   * Number of tracks
   */
  readonly length: number;
  
  /**
   * Get track by index
   * @param index - Track index
   * @returns Audio track
   */
  [index: number]: AudioTrack;
  
  /**
   * Get track by ID
   * @param id - Track ID
   * @returns Audio track or null
   */
  getTrackById(id: string): AudioTrack | null;
}

Usage Examples:

// Access audio tracks
const audioTracks = player.audioTracks();
console.log('Available audio tracks:', audioTracks.length);

// Switch to Spanish audio
for (let i = 0; i < audioTracks.length; i++) {
  const track = audioTracks[i];
  if (track.language === 'es') {
    track.enabled = true; // Enable Spanish audio
  } else {
    track.enabled = false; // Disable other audio tracks
  }
}

// Listen for audio track changes
audioTracks.addEventListener('change', () => {
  const enabledTrack = Array.from(audioTracks).find(track => track.enabled);
  console.log('Audio track changed to:', enabledTrack?.label);
});

Video Tracks

Manage multiple video tracks for different camera angles or video qualities.

/**
 * Video track representation
 */
class VideoTrack {
  /**
   * Unique track identifier
   */
  readonly id: string;
  
  /**
   * Track kind (main, alternative, sign, etc.)
   */
  readonly kind: string;
  
  /**
   * Human-readable track label
   */
  readonly label: string;
  
  /**
   * Track language code
   */
  readonly language: string;
  
  /**
   * Whether track is selected (only one can be selected at a time)
   */
  selected: boolean;
}

/**
 * List of video tracks
 */
class VideoTrackList {
  /**
   * Number of tracks
   */
  readonly length: number;
  
  /**
   * Get track by index
   * @param index - Track index
   * @returns Video track
   */
  [index: number]: VideoTrack;
  
  /**
   * Get track by ID
   * @param id - Track ID
   * @returns Video track or null
   */
  getTrackById(id: string): VideoTrack | null;
  
  /**
   * Get currently selected track
   * @returns Selected video track or null
   */
  getSelectedTrack(): VideoTrack | null;
}

Usage Examples:

// Access video tracks
const videoTracks = player.videoTracks();

// Switch to alternate camera angle
for (let i = 0; i < videoTracks.length; i++) {
  const track = videoTracks[i];
  if (track.kind === 'alternative' && track.label.includes('Angle 2')) {
    track.selected = true; // Select alternate angle
  } else {
    track.selected = false; // Deselect other tracks
  }
}

// Get currently selected track
const selectedTrack = videoTracks.getSelectedTrack();
console.log('Current video track:', selectedTrack?.label);

Player Track Methods

Player-level methods for managing tracks.

/**
 * Get text tracks list
 * @returns Text tracks list
 */
textTracks(): TextTrackList;

/**
 * Get audio tracks list  
 * @returns Audio tracks list
 */
audioTracks(): AudioTrackList;

/**
 * Get video tracks list
 * @returns Video tracks list
 */
videoTracks(): VideoTrackList;

/**
 * Add text track programmatically
 * @param kind - Track kind
 * @param label - Track label
 * @param language - Language code
 * @returns Created text track
 */
addTextTrack(kind: TextTrackKind, label?: string, language?: string): TextTrack;

/**
 * Add remote text track from URL
 * @param options - Track options including src URL
 * @param manualCleanup - Whether to handle cleanup manually
 * @returns HTML track element
 */
addRemoteTextTrack(options: RemoteTextTrackOptions, manualCleanup?: boolean): HTMLTrackElement;

/**
 * Remove remote text track
 * @param track - Track or track element to remove
 */
removeRemoteTextTrack(track: TextTrack | HTMLTrackElement): void;

Text Track Cues

Manage individual cues within text tracks.

/**
 * VTT cue representing timed text
 */
class VTTCue {
  /**
   * Create VTT cue
   * @param startTime - Start time in seconds
   * @param endTime - End time in seconds
   * @param text - Cue text content
   */
  constructor(startTime: number, endTime: number, text: string);
  
  /**
   * Cue start time in seconds
   */
  startTime: number;
  
  /**
   * Cue end time in seconds
   */
  endTime: number;
  
  /**
   * Cue text content
   */
  text: string;
  
  /**
   * Cue identifier
   */
  id: string;
  
  /**
   * Cue positioning and styling
   */
  position: number;
  line: number;
  size: number;
  align: string;
  vertical: string;
}

/**
 * List of cues
 */
class TextTrackCueList {
  /**
   * Number of cues
   */
  readonly length: number;
  
  /**
   * Get cue by index
   * @param index - Cue index
   * @returns VTT cue
   */
  [index: number]: VTTCue;
  
  /**
   * Get cue by ID
   * @param id - Cue ID
   * @returns VTT cue or null
   */
  getCueById(id: string): VTTCue | null;
}

Usage Examples:

// Create cues with styling
const cue1 = new VTTCue(0, 3, 'Welcome to our video');
cue1.line = 1;
cue1.position = 50;
cue1.align = 'center';

const cue2 = new VTTCue(3, 6, '<c.highlight>Important information</c>');
cue2.line = -1; // Bottom line

// Add to track
const track = player.addTextTrack('captions', 'English Captions', 'en');
track.addCue(cue1);
track.addCue(cue2);
track.mode = 'showing';

Remote Text Tracks

Load text tracks from external files.

// Add remote text track
const trackElement = player.addRemoteTextTrack({
  kind: 'subtitles',
  src: 'path/to/subtitles.vtt',
  srclang: 'en',
  label: 'English Subtitles',
  default: true
});

// Access the track
const track = trackElement.track;
track.addEventListener('load', () => {
  console.log('Track loaded with', track.cues.length, 'cues');
});

// Remove when done
player.removeRemoteTextTrack(trackElement);

Track Events

Text tracks support various events for monitoring state changes.

// Track list events
textTracks.addEventListener('addtrack', (event) => {
  console.log('Track added:', event.track);
});

textTracks.addEventListener('removetrack', (event) => {
  console.log('Track removed:', event.track);
});

textTracks.addEventListener('change', () => {
  console.log('Track modes changed');
});

// Individual track events
track.addEventListener('cuechange', () => {
  const activeCues = track.activeCues;
  for (let i = 0; i < activeCues.length; i++) {
    console.log('Active cue:', activeCues[i].text);
  }
});

track.addEventListener('load', () => {
  console.log('Track cues loaded');
});

track.addEventListener('error', (event) => {
  console.error('Track error:', event);
});

Accessibility Features

Video.js provides built-in accessibility support for text tracks.

// Configure accessibility options
const player = videojs('my-video', {
  tracks: [
    {
      kind: 'captions',
      src: 'captions.vtt',
      srclang: 'en',
      label: 'English Captions',
      default: true
    },
    {
      kind: 'descriptions', 
      src: 'descriptions.vtt',
      srclang: 'en',
      label: 'Audio Descriptions'
    }
  ]
});

// Enable keyboard navigation for tracks
player.ready(() => {
  // Tracks menu is automatically accessible via keyboard
  const trackMenuButton = player.getChild('ControlBar').getChild('SubtitlesButton');
  if (trackMenuButton) {
    trackMenuButton.focus(); // Can be focused with keyboard
  }
});

Types

type TextTrackKind = 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata';
type TextTrackMode = 'disabled' | 'hidden' | 'showing';

interface RemoteTextTrackOptions {
  kind: TextTrackKind;
  src: string;
  srclang?: string;
  label?: string;
  default?: boolean;
}

interface TextTrackOptions {
  kind: TextTrackKind;
  src?: string;
  srclang?: string;
  label?: string;
  default?: boolean;
  [key: string]: any;
}

interface TextTrack {
  kind: TextTrackKind;
  label: string;
  language: string;
  mode: TextTrackMode;
  cues: TextTrackCueList;
  activeCues: TextTrackCueList;
  addCue(cue: VTTCue): void;
  removeCue(cue: VTTCue): void;
}

interface AudioTrack {
  id: string;
  kind: string;
  label: string;
  language: string;
  enabled: boolean;
}

interface VideoTrack {
  id: string;
  kind: string;
  label: string;
  language: string;
  selected: boolean;
}

interface VTTCue {
  startTime: number;
  endTime: number;
  text: string;
  id: string;
  position: number;
  line: number;
  size: number;
  align: string;
  vertical: string;
}

Install with Tessl CLI

npx tessl i tessl/npm-video-js

docs

components.md

events.md

index.md

player.md

plugins.md

tech.md

tracks.md

utilities.md

tile.json