CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-happy-dom

Happy DOM is a JavaScript implementation of a web browser without its graphical user interface including DOM, HTML, CSS, events, and fetch APIs

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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);

docs

browser-apis.md

browser-window.md

css-styling.md

custom-elements.md

dom-core.md

event-system.md

fetch-http.md

form-file.md

html-elements.md

index.md

media-av.md

tile.json