npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@molecule/app-video

v1.0.2

Published

Video player interface and utilities for molecule.dev

Readme

@molecule/app-video

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.