← All @molecule/* packages · App templates

@molecule/app-video

Feature · video · App (browser) · v1.0.1 · Apache-2.0

Video playback core — provider-swappable player interface with a built-in native HTML5 provider (MP4/WebM/Ogg; HLS/DASH require a custom provider)

npm install @molecule/app-video

npm · Source on GitHub

How it works

@molecule/app-video is a ready-made video feature for the app (browser) side. It composes the core interfaces it needs, so it works with whichever providers your app has bonded.

import { createPlayer, setProvider, createNativeVideoProvider } from '@molecule/app-video'

// Wire the provider once at startup (defaults to native HTML5 if skipped)
setProvider(createNativeVideoProvider())

// Create a player imperatively against a DOM container
const player = await createPlayer({
  container: '#video-root',
  sources: [{ src: 'https://example.com/video.mp4', type: 'video/mp4', label: '1080p' }],
  poster: 'https://example.com/poster.jpg',
  autoplay: false,
  controls: true,
})

player.on('ended', () => console.log('Playback finished'))

Providers (1): @molecule/app-video-hls

Works with: @molecule/app-bond, @molecule/app-i18n

Reference

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Video player interface for molecule.dev.

A unified imperative API for video playback: createPlayer() builds a VideoPlayer (play/pause/seek/volume/quality/fullscreen/PiP/captions/ events) from whatever VideoProvider is bonded, with a built-in native HTML5 <video> provider as the default.

Quick Start

import { createPlayer, setProvider, createNativeVideoProvider } from '@molecule/app-video'

// Wire the provider once at startup (defaults to native HTML5 if skipped)
setProvider(createNativeVideoProvider())

// Create a player imperatively against a DOM container
const player = await createPlayer({
  container: '#video-root',
  sources: [{ src: 'https://example.com/video.mp4', type: 'video/mp4', label: '1080p' }],
  poster: 'https://example.com/poster.jpg',
  autoplay: false,
  controls: true,
})

player.on('ended', () => console.log('Playback finished'))

Type

feature

Installation

npm install @molecule/app-video @molecule/app-bond @molecule/app-i18n

API

Interfaces

ControlsConfig

Video player control toggles (play/pause, progress, volume, fullscreen, PiP, captions, quality, etc.).

interface ControlsConfig {
  /**
   * Enable/disable all controls.
   */
  enabled?: boolean

  /**
   * Individual control toggles.
   */
  playPause?: boolean
  progress?: boolean
  currentTime?: boolean
  duration?: boolean
  volume?: boolean
  mute?: boolean
  fullscreen?: boolean
  pip?: boolean
  settings?: boolean
  captions?: boolean
  quality?: boolean
  playbackRate?: boolean
  download?: boolean
  seekForward?: boolean
  seekBackward?: boolean

  /**
   * Seek time in seconds.
   */
  seekTime?: number

  /**
   * Available playback rates.
   */
  playbackRates?: number[]
}

PlayerConfig

Video player initialization options (sources, poster, autoplay, controls, tracks, aspect ratio, etc.).

interface PlayerConfig {
  /**
   * Container element.
   */
  container: HTMLElement | string

  /**
   * Video sources.
   */
  sources: VideoSource[]

  /**
   * Poster image URL.
   */
  poster?: string

  /**
   * Autoplay.
   */
  autoplay?: boolean

  /**
   * Loop playback.
   */
  loop?: boolean

  /**
   * Muted.
   */
  muted?: boolean

  /**
   * Initial volume (0-1).
   */
  volume?: number

  /**
   * Playback rate.
   */
  playbackRate?: number

  /**
   * Preload mode.
   */
  preload?: 'none' | 'metadata' | 'auto'

  /**
   * Text tracks (captions/subtitles).
   */
  tracks?: TextTrack[]

  /**
   * Controls configuration.
   */
  controls?: ControlsConfig | boolean

  /**
   * Inline playback (iOS).
   */
  playsinline?: boolean

  /**
   * Cross-origin mode.
   */
  crossorigin?: 'anonymous' | 'use-credentials'

  /**
   * Aspect ratio (e.g., '16:9', '4:3').
   */
  aspectRatio?: string

  /**
   * Fluid width (responsive).
   */
  fluid?: boolean

  /**
   * Fill container.
   */
  fill?: boolean

  /**
   * Custom CSS class.
   */
  className?: string

  /**
   * Language for UI.
   */
  language?: string

  /**
   * Keyboard shortcuts.
   */
  keyboard?: boolean

  /**
   * Click to play/pause.
   */
  clickToPlay?: boolean

  /**
   * Double-click to fullscreen.
   */
  doubleClickFullscreen?: boolean

  /**
   * Hide controls delay (ms).
   */
  hideControlsDelay?: number
}

PlayerState

Current video player state (playing, paused, time, duration, volume, buffered, quality).

interface PlayerState {
  /**
   * Current playback time in seconds.
   */
  currentTime: number

  /**
   * Total duration in seconds.
   */
  duration: number

  /**
   * Buffered time ranges.
   */
  buffered: { start: number; end: number }[]

  /**
   * Whether the video is playing.
   */
  playing: boolean

  /**
   * Whether the video is paused.
   */
  paused: boolean

  /**
   * Whether the video has ended.
   */
  ended: boolean

  /**
   * Whether the video is seeking.
   */
  seeking: boolean

  /**
   * Whether the video is waiting for data.
   */
  waiting: boolean

  /**
   * Whether the video is muted.
   */
  muted: boolean

  /**
   * Volume level (0-1).
   */
  volume: number

  /**
   * Playback rate.
   */
  playbackRate: number

  /**
   * Whether fullscreen is active.
   */
  fullscreen: boolean

  /**
   * Whether picture-in-picture is active.
   */
  pip: boolean

  /**
   * Current quality level.
   */
  quality?: QualityLevel

  /**
   * Error (if any).
   */
  error?: Error
}

QualityLevel

Available video quality level (resolution, bitrate, label, and active flag).

interface QualityLevel {
  /**
   * Quality ID.
   */
  id: string | number

  /**
   * Label (e.g., '1080p HD', '720p', 'Auto').
   */
  label: string

  /**
   * Height in pixels.
   */
  height?: number

  /**
   * Width in pixels.
   */
  width?: number

  /**
   * Bitrate in kbps.
   */
  bitrate?: number
}

TextTrack

Text track (captions/subtitles) configuration.

interface TextTrack {
  /**
   * Track kind.
   */
  kind: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata'

  /**
   * Track label.
   */
  label: string

  /**
   * Language code.
   */
  language: string

  /**
   * Source URL.
   */
  src: string

  /**
   * Default track.
   */
  default?: boolean
}

VideoPlayer

Video player instance.

interface VideoPlayer {
  /**
   * Plays the video.
   */
  play(): Promise<void>

  /**
   * Pauses the video.
   */
  pause(): void

  /**
   * Toggles play/pause.
   */
  togglePlay(): void

  /**
   * Stops the video.
   */
  stop(): void

  /**
   * Seeks to a time.
   */
  seek(time: number): void

  /**
   * Seeks forward.
   */
  seekForward(seconds?: number): void

  /**
   * Seeks backward.
   */
  seekBackward(seconds?: number): void

  /**
   * Gets current time.
   */
  getCurrentTime(): number

  /**
   * Gets duration.
   */
  getDuration(): number

  /**
   * Gets buffered time ranges.
   */
  getBuffered(): { start: number; end: number }[]

  /**
   * Sets volume.
   */
  setVolume(volume: number): void

  /**
   * Gets volume.
   */
  getVolume(): number

  /**
   * Mutes the video.
   */
  mute(): void

  /**
   * Unmutes the video.
   */
  unmute(): void

  /**
   * Toggles mute.
   */
  toggleMute(): void

  /**
   * Checks if muted.
   */
  isMuted(): boolean

  /**
   * Sets playback rate.
   */
  setPlaybackRate(rate: number): void

  /**
   * Gets playback rate.
   */
  getPlaybackRate(): number

  /**
   * Gets available quality levels.
   */
  getQualityLevels(): QualityLevel[]

  /**
   * Sets quality level.
   */
  setQuality(level: QualityLevel | string | number): void

  /**
   * Gets current quality.
   */
  getQuality(): QualityLevel | undefined

  /**
   * Enters fullscreen.
   */
  enterFullscreen(): Promise<void>

  /**
   * Exits fullscreen.
   */
  exitFullscreen(): Promise<void>

  /**
   * Toggles fullscreen.
   */
  toggleFullscreen(): Promise<void>

  /**
   * Checks if fullscreen.
   */
  isFullscreen(): boolean

  /**
   * Enters picture-in-picture.
   */
  enterPip(): Promise<void>

  /**
   * Exits picture-in-picture.
   */
  exitPip(): Promise<void>

  /**
   * Toggles picture-in-picture.
   */
  togglePip(): Promise<void>

  /**
   * Checks if in picture-in-picture.
   */
  isPip(): boolean

  /**
   * Loads new sources.
   */
  load(sources: VideoSource[], poster?: string): void

  /**
   * Gets current source.
   */
  getSource(): VideoSource | undefined

  /**
   * Gets player state.
   */
  getState(): PlayerState

  /**
   * Adds event listener.
   */
  on(event: PlayerEvent, handler: (data: unknown) => void): () => void

  /**
   * Removes event listener.
   */
  off(event: PlayerEvent, handler: (data: unknown) => void): void

  /**
   * Gets available text tracks.
   */
  getTextTracks(): TextTrack[]

  /**
   * Sets active text track.
   */
  setTextTrack(language: string | null): void

  /**
   * Gets active text track.
   */
  getActiveTextTrack(): TextTrack | undefined

  /**
   * Shows controls.
   */
  showControls(): void

  /**
   * Hides controls.
   */
  hideControls(): void

  /**
   * Gets the video element.
   */
  getVideoElement(): HTMLVideoElement

  /**
   * Gets the container element.
   */
  getContainer(): HTMLElement

  /**
   * Gets the underlying player instance.
   */
  getInstance(): unknown

  /**
   * Takes a screenshot.
   */
  screenshot(): string

  /**
   * Destroys the player.
   */
  destroy(): void
}

VideoProvider

Video provider interface.

interface VideoProvider {
  /**
   * Create a new video player instance with the given configuration.
   * @returns A VideoPlayer instance for controlling playback.
   */
  createPlayer(config: PlayerConfig): VideoPlayer | Promise<VideoPlayer>

  /**
   * Get the name of this video provider (e.g., 'html5', 'hls.js', 'shaka').
   * @returns The provider name string.
   */
  getName(): string

  /**
   * Check if the video provider's library has been loaded and is ready.
   * @returns Whether the provider is loaded and ready to create players.
   */
  isLoaded(): boolean

  /**
   * Get the list of video formats supported by this provider (e.g., 'mp4', 'webm', 'hls').
   * @returns Array of supported format strings.
   */
  getSupportedFormats(): string[]

  /**
   * Check if HTTP Live Streaming (HLS) playback is supported.
   * @returns Whether HLS is supported by this provider.
   */
  supportsHls(): boolean

  /**
   * Check if MPEG-DASH adaptive streaming is supported.
   * @returns Whether DASH is supported by this provider.
   */
  supportsDash(): boolean
}

VideoSource

Video source configuration.

interface VideoSource {
  /**
   * Source URL.
   */
  src: string

  /**
   * Source type (e.g., 'video/mp4', 'video/webm', 'application/x-mpegURL').
   */
  type?: string

  /**
   * Source label (for quality selection).
   */
  label?: string

  /**
   * Resolution (e.g., '1080p', '720p', '480p').
   */
  resolution?: string

  /**
   * Bitrate in kbps.
   */
  bitrate?: number
}

Types

PlayerEvent

Video player lifecycle events (play, pause, ended, seek, time update, error, etc.).

type PlayerEvent =
  | 'play'
  | 'pause'
  | 'ended'
  | 'timeupdate'
  | 'progress'
  | 'seeking'
  | 'seeked'
  | 'volumechange'
  | 'ratechange'
  | 'waiting'
  | 'canplay'
  | 'canplaythrough'
  | 'loadedmetadata'
  | 'loadeddata'
  | 'durationchange'
  | 'error'
  | 'fullscreenchange'
  | 'enterpictureinpicture'
  | 'leavepictureinpicture'
  | 'qualitychange'

Functions

createNativePlayer(config)

Create a native HTML5 video player instance. Uses the browser's <video> element with standard playback controls, source management, and event handling.

function createNativePlayer(config: PlayerConfig): VideoPlayer
  • config — Player configuration (container, source, autoplay, controls, etc.).

Returns: A VideoPlayer instance for controlling the HTML5 video element.

createNativeVideoProvider()

Create a native HTML5 video provider. Supports standard formats (MP4, WebM, Ogg) using the browser's built-in <video> element. Does not support HLS or DASH streaming.

function createNativeVideoProvider(): VideoProvider

Returns: A VideoProvider backed by native HTML5 video.

createPlayer(config)

Create a new video player instance using the current provider.

function createPlayer(config: PlayerConfig): VideoPlayer | Promise<VideoPlayer>
  • config — Player configuration (container, source, autoplay, controls, etc.).

Returns: A VideoPlayer instance for controlling playback.

formatTime(seconds)

Format a duration in seconds as a human-readable time string. Returns 'H:MM:SS' for durations over an hour, or 'M:SS' otherwise.

function formatTime(seconds: number): string
  • seconds — The duration in seconds.

Returns: A formatted time string (e.g., '1:23:45' or '3:07').

getProvider()

Get the current video provider. Falls back to a native HTML5 video provider if none has been explicitly set.

function getProvider(): VideoProvider

Returns: The active VideoProvider instance.

getVideoType(url)

Infer the MIME type of a video from its URL based on the file extension. Supports MP4, WebM, Ogg, HLS (.m3u8), and DASH (.mpd).

function getVideoType(url: string): string | undefined
  • url — The video URL.

Returns: The MIME type string, or undefined if the format is unrecognized.

hasProvider()

Check if a video provider has been registered.

function hasProvider(): boolean

Returns: Whether a VideoProvider has been bonded.

parseTime(time)

Parse a time string (H:MM:SS or M:SS or S) into total seconds.

function parseTime(time: string): number
  • time — The time string to parse.

Returns: The total duration in seconds.

setProvider(provider)

Set the video provider.

function setProvider(provider: VideoProvider): void
  • provider — VideoProvider implementation to register.

Injection Notes

Requirements

Peer dependencies:

  • @molecule/app-bond ^1.0.1
  • @molecule/app-i18n ^1.0.1

Runtime Dependencies

  • @molecule/app-bond
  • @molecule/app-i18n

Two shipped providers: the built-in native HTML5 one (default) and @molecule/app-video-hls. For HLS (.m3u8) streaming that works in EVERY browser (adaptive bitrate; the native provider only plays HLS in Safari), bond it: import { provider } from '@molecule/app-video-hls'; setProvider(provider) at startup. For other libraries (Video.js / Plyr / Vidstack) or MPEG-DASH, implement the VideoProvider interface yourself and wire it with setProvider() (registered on the app bond registry under 'video').

Native-provider limits a weak integrator must know: MP4/WebM/Ogg only (supportsHls() / supportsDash() return false — no HLS outside Safari's native support unless you bond @molecule/app-video-hls, no DASH); controls is effectively boolean — passing a ControlsConfig object just enables the browser's native controls and every granular toggle, seekTime and playbackRates are ignored; fluid, fill, aspectRatio, language, keyboard, clickToPlay, doubleClickFullscreen, hideControlsDelay and the initial playbackRate are also ignored (the <video> is styled 100%x100% of its container — size the container). setQuality accepts a source index or label string; passing a QualityLevel object is currently a no-op. Quality "levels" are just the sources array — switching swaps video.src and restores the current time.

Source-label strings route through t('video.source.label') — the companion @molecule/app-locales-video bond translates them. For ready-made React chrome see @molecule/app-video-player-react (a standalone <video> wrapper; it does NOT consume this package).

Translations

Translation strings are provided by @molecule/app-locales-video.