or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

browser-apis.mdbrowser-window.mdcss-styling.mdcustom-elements.mddom-core.mdevent-system.mdfetch-http.mdform-file.mdhtml-elements.mdindex.mdmedia-av.md
tile.json

media-av.mddocs/

Media & A/V

Media stream handling, text tracks, and audio/video element support for multimedia applications. Provides comprehensive media functionality for web applications.

Capabilities

Media Streams

MediaStream Class

Represents a stream of media content.

/**
 * Represents a stream of media content
 */
class MediaStream extends EventTarget {
  constructor(stream?: MediaStream | MediaStreamTrack[]);
  
  /** Stream ID */
  readonly id: string;
  
  /** Stream active flag */
  readonly active: boolean;
  
  /** Get all tracks */
  getTracks(): MediaStreamTrack[];
  
  /** Get audio tracks */
  getAudioTracks(): MediaStreamTrack[];
  
  /** Get video tracks */
  getVideoTracks(): MediaStreamTrack[];
  
  /** Get track by ID */
  getTrackById(id: string): MediaStreamTrack | null;
  
  /** Add track */
  addTrack(track: MediaStreamTrack): void;
  
  /** Remove track */
  removeTrack(track: MediaStreamTrack): void;
  
  /** Clone stream */
  clone(): MediaStream;
  
  // Event handlers
  onaddtrack: ((event: MediaStreamTrackEvent) => void) | null;
  onremovetrack: ((event: MediaStreamTrackEvent) => void) | null;
}

MediaStreamTrack Class

Represents a single media track.

/**
 * Represents a single media track
 */
class MediaStreamTrack extends EventTarget {
  /** Track ID */
  readonly id: string;
  
  /** Track kind */
  readonly kind: MediaStreamTrackKind;
  
  /** Track label */
  readonly label: string;
  
  /** Enabled state */
  enabled: boolean;
  
  /** Muted state */
  readonly muted: boolean;
  
  /** Ready state */
  readonly readyState: MediaStreamTrackState;
  
  /** Get capabilities */
  getCapabilities(): MediaTrackCapabilities;
  
  /** Get constraints */
  getConstraints(): MediaTrackConstraints;
  
  /** Get settings */
  getSettings(): MediaTrackSettings;
  
  /** Apply constraints */
  applyConstraints(constraints?: MediaTrackConstraints): Promise<void>;
  
  /** Clone track */
  clone(): MediaStreamTrack;
  
  /** Stop track */
  stop(): void;
  
  // Event handlers
  onmute: ((event: Event) => void) | null;
  onunmute: ((event: Event) => void) | null;
  onended: ((event: Event) => void) | null;
}

type MediaStreamTrackKind = 'audio' | 'video';
type MediaStreamTrackState = 'live' | 'ended';

Text Tracks

TextTrack Class

Represents a text track for media elements.

/**
 * Represents a text track for media elements
 */
class TextTrack extends EventTarget {
  /** Track kind */
  readonly kind: TextTrackKind;
  
  /** Track label */
  readonly label: string;
  
  /** Track language */
  readonly language: string;
  
  /** Track ID */
  readonly id: string;
  
  /** Track mode */
  mode: TextTrackMode;
  
  /** Track cues */
  readonly cues: TextTrackCueList | null;
  
  /** Active cues */
  readonly activeCues: TextTrackCueList | null;
  
  /** Add cue */
  addCue(cue: TextTrackCue): void;
  
  /** Remove cue */
  removeCue(cue: TextTrackCue): void;
  
  // Event handlers
  oncuechange: ((event: Event) => void) | null;
}

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

TextTrackCue Class

Base class for text track cues.

/**
 * Base class for text track cues
 */
class TextTrackCue extends EventTarget {
  constructor(startTime: number, endTime: number, text: string);
  
  /** Cue start time */
  startTime: number;
  
  /** Cue end time */
  endTime: number;
  
  /** Pause on exit flag */
  pauseOnExit: boolean;
  
  /** Cue ID */
  id: string;
  
  /** Owner track */
  readonly track: TextTrack | null;
  
  // Event handlers
  onenter: ((event: Event) => void) | null;
  onexit: ((event: Event) => void) | null;
}

VTTCue Class

WebVTT cue implementation.

/**
 * WebVTT cue implementation
 */
class VTTCue extends TextTrackCue {
  constructor(startTime: number, endTime: number, text: string);
  
  /** Cue text */
  text: string;
  
  /** Cue region */
  region: VTTRegion | null;
  
  /** Vertical writing direction */
  vertical: DirectionSetting;
  
  /** Snap to lines flag */
  snapToLines: boolean;
  
  /** Line position */
  line: LineAndPositionSetting;
  
  /** Line alignment */
  lineAlign: LineAlignSetting;
  
  /** Position */
  position: LineAndPositionSetting;
  
  /** Position alignment */
  positionAlign: PositionAlignSetting;
  
  /** Size */
  size: number;
  
  /** Text alignment */
  align: AlignSetting;
  
  /** Get cue as HTML */
  getCueAsHTML(): DocumentFragment;
}

type DirectionSetting = '' | 'rl' | 'lr';
type LineAndPositionSetting = number | 'auto';
type LineAlignSetting = 'start' | 'center' | 'end';
type PositionAlignSetting = 'line-left' | 'center' | 'line-right' | 'auto';
type AlignSetting = 'start' | 'center' | 'end' | 'left' | 'right';

TextTrackList Class

Collection of text tracks.

/**
 * Collection of text tracks
 */
class TextTrackList extends EventTarget {
  /** Number of tracks */
  readonly length: number;
  
  /** Get track by index */
  item(index: number): TextTrack | null;
  
  /** Get track by ID */
  getTrackById(id: string): TextTrack | null;
  
  /** Array-like access */
  [index: number]: TextTrack;
  
  // Event handlers
  onchange: ((event: Event) => void) | null;
  onaddtrack: ((event: TrackEvent) => void) | null;
  onremovetrack: ((event: TrackEvent) => void) | null;
}

TextTrackCueList Class

Collection of text track cues.

/**
 * Collection of text track cues
 */
class TextTrackCueList {
  /** Number of cues */
  readonly length: number;
  
  /** Get cue by index */
  item(index: number): TextTrackCue | null;
  
  /** Get cue by ID */
  getCueById(id: string): TextTrackCue | null;
  
  /** Array-like access */
  [index: number]: TextTrackCue;
}

Remote Playback

RemotePlayback Class

Remote playback control for media elements.

/**
 * Remote playback control for media elements
 */
class RemotePlayback extends EventTarget {
  /** Remote playback state */
  readonly state: RemotePlaybackState;
  
  /** Watch availability */
  watchAvailability(callback: RemotePlaybackAvailabilityCallback): Promise<number>;
  
  /** Cancel watch availability */
  cancelWatchAvailability(id?: number): Promise<void>;
  
  /** Prompt for remote playback */
  prompt(): Promise<void>;
  
  // Event handlers
  onconnecting: ((event: Event) => void) | null;
  onconnect: ((event: Event) => void) | null;
  ondisconnect: ((event: Event) => void) | null;
}

type RemotePlaybackState = 'connecting' | 'connected' | 'disconnected';
type RemotePlaybackAvailabilityCallback = (available: boolean) => void;

Usage Examples

Media Stream Handling

import { MediaStream, MediaStreamTrack } from "happy-dom";

// Create media stream from tracks
const audioTrack = new MediaStreamTrack();
const videoTrack = new MediaStreamTrack();
const stream = new MediaStream([audioTrack, videoTrack]);

console.log('Stream ID:', stream.id);
console.log('Stream active:', stream.active);
console.log('Audio tracks:', stream.getAudioTracks().length);
console.log('Video tracks:', stream.getVideoTracks().length);

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

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

// Clone stream
const clonedStream = stream.clone();
console.log('Cloned stream ID:', clonedStream.id);

// Stop tracks when done
stream.getTracks().forEach(track => {
  track.stop();
});

Text Track Management

import { Window } from "happy-dom";

const window = new Window();
const document = window.document;

// Create video element
const video = document.createElement('video');
video.src = 'movie.mp4';

// Add text track
const track = video.addTextTrack('subtitles', 'English', 'en');
track.mode = 'showing';

// Add cues
track.addCue(new VTTCue(0, 5, 'Hello, welcome to our video!'));
track.addCue(new VTTCue(5, 10, 'This is the second subtitle.'));
track.addCue(new VTTCue(10, 15, 'And this is the third one.'));

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

// Access all tracks
video.textTracks.addEventListener('change', () => {
  console.log('Text tracks changed');
});

// Get track by ID
const foundTrack = video.textTracks.getTrackById('track-1');
if (foundTrack) {
  foundTrack.mode = 'showing';
}

Media Element with Tracks

import { Window, VTTCue } from "happy-dom";

const window = new Window();
const document = window.document;

// Create video element with comprehensive setup
const video = document.createElement('video');
video.src = 'presentation.mp4';
video.controls = true;

// Add multiple text tracks
const subtitlesEn = video.addTextTrack('subtitles', 'English Subtitles', 'en');
const subtitlesEs = video.addTextTrack('subtitles', 'Spanish Subtitles', 'es');
const chapters = video.addTextTrack('chapters', 'Chapters', 'en');

// Add subtitle cues
subtitlesEn.addCue(new VTTCue(0, 10, 'Introduction to the topic'));
subtitlesEn.addCue(new VTTCue(10, 20, 'Main content begins here'));

subtitlesEs.addCue(new VTTCue(0, 10, 'Introducción al tema'));
subtitlesEs.addCue(new VTTCue(10, 20, 'El contenido principal comienza aquí'));

// Add chapter cues
chapters.addCue(new VTTCue(0, 10, 'Introduction'));
chapters.addCue(new VTTCue(10, 60, 'Chapter 1: Basics'));
chapters.addCue(new VTTCue(60, 120, 'Chapter 2: Advanced Topics'));

// Set default track
subtitlesEn.mode = 'showing';
chapters.mode = 'hidden';

// Handle media events
video.addEventListener('loadedmetadata', () => {
  console.log('Video duration:', video.duration);
  console.log('Text tracks count:', video.textTracks.length);
});

video.addEventListener('timeupdate', () => {
  // Check active cues
  for (let i = 0; i < video.textTracks.length; i++) {
    const track = video.textTracks[i];
    if (track.activeCues && track.activeCues.length > 0) {
      const cue = track.activeCues[0];
      if (track.kind === 'chapters') {
        console.log('Current chapter:', cue.text);
      }
    }
  }
});

document.body.appendChild(video);