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

@estenbyte/player

v2.0.2

Published

Control video players in iframes via postMessage API - simple, type-safe, and framework-agnostic

Readme

@estenbyte/player

Control video players running inside iframes using the postMessage API.

Installation

npm install @estenbyte/player

Features

  • Full Player Control - Control video playback from parent window
  • Secure Communication - Origin validation for postMessage
  • Event Streaming - Real-time player events forwarded to parent
  • Type-Safe - Full TypeScript support with type definitions
  • Lightweight - Zero dependencies, minimal footprint
  • Promise-Based - Modern async/await API

Usage

Parent Page (Controller)

Control a video player running inside an iframe from the parent page:

import { PlayerController } from '@estenbyte/player/controller';

// Option 1: Pass a CSS selector (simplest)
const controller = new PlayerController('iframe');

// Option 2: Pass an HTMLIFrameElement directly
const iframe = document.querySelector('iframe');
const controller = new PlayerController(iframe);

// Wait for the player to be ready
await controller.whenReady();

// Control playback
await controller.play();
await controller.pause();
await controller.seek(30);
await controller.setVolume(0.5);
await controller.setPlaybackRate(1.5);

// Get player state
const currentTime = await controller.getCurrentTime();
const duration = await controller.getDuration();
const volume = await controller.getVolume();

// Listen to player events
controller.on('play', () => console.log('Playing'));
controller.on('pause', () => console.log('Paused'));
controller.on('timeupdate', (state) => {
  console.log('Current time:', state.currentTime);
});

Inside Iframe (Bridge)

Enable external control for a player inside an iframe:

import { PlayerBridge } from '@estenbyte/player/bridge';

// Your player instance (must implement PlayerInstance interface)
const player = {
  element: document.querySelector('.player-container'),
  play: () => videoElement.play(),
  pause: () => videoElement.pause(),
  togglePlay: () => videoElement.paused ? videoElement.play() : videoElement.pause(),
  setVolume: (vol) => videoElement.volume = vol,
  mute: () => videoElement.muted = true,
  unmute: () => videoElement.muted = false,
  setMuted: (muted) => videoElement.muted = muted,
  toggleFullscreen: () => { /* fullscreen logic */ },
  showControls: () => { /* show controls */ },
  hideControls: () => { /* hide controls */ },
  setControlsVisible: (visible) => { /* set controls visibility */ },
  addWatermark: (config) => { /* add watermark */ },
};

// Enable iframe control with optional origin restriction
const bridge = new PlayerBridge(player, {
  allowedOrigin: 'https://yoursite.com' // Optional: restrict to specific origin
});

// Parent page can now control this player

API Reference

PlayerController

Control a player from the parent page.

Constructor

new PlayerController(iframe: HTMLIFrameElement | string)

Parameters:

  • iframe - Either an HTMLIFrameElement or a CSS selector string (e.g., 'iframe', '#player-iframe')

Playback Control

  • play(): Promise<void> - Start playback
  • pause(): Promise<void> - Pause playback
  • togglePlay(): Promise<void> - Toggle play/pause
  • seek(time: number): Promise<void> - Seek to time (seconds)

Volume Control

  • setVolume(volume: number): Promise<void> - Set volume (0-1)
  • getVolume(): Promise<number> - Get current volume
  • mute(): Promise<void> - Mute audio
  • unmute(): Promise<void> - Unmute audio
  • setMuted(muted: boolean): Promise<void> - Set muted state
  • getMuted(): Promise<boolean> - Get muted state

Playback State

  • getCurrentTime(): Promise<number> - Get playback position (seconds)
  • getDuration(): Promise<number> - Get video duration (seconds)
  • getPaused(): Promise<boolean> - Get paused state
  • setPlaybackRate(rate: number): Promise<void> - Set playback speed (e.g., 0.5, 1.0, 2.0)
  • getPlaybackRate(): Promise<number> - Get current playback rate

Display Control

  • toggleFullscreen(): Promise<void> - Toggle fullscreen mode
  • requestFullscreen(): Promise<void> - Enter fullscreen
  • exitFullscreen(): Promise<void> - Exit fullscreen
  • showControls(): Promise<void> - Show player controls
  • hideControls(): Promise<void> - Hide player controls
  • setControlsVisible(visible: boolean): Promise<void> - Set controls visibility

Watermark

  • addWatermark(config: WatermarkConfig): Promise<void> - Add watermark overlay

Lifecycle

  • isReady(): boolean - Check if player is ready
  • whenReady(): Promise<void> - Wait for player to be ready
  • destroy(): void - Clean up event listeners and pending requests

Event Handling

  • on(event: string, callback: Function): this - Register event listener
  • off(event: string, callback?: Function): this - Unregister event listener
  • once(event: string, callback: Function): this - Register one-time event listener

Events

The controller forwards all native video events plus custom events:

  • ready - Player is ready to receive commands
  • play, playing, pause, ended - Playback state changes
  • timeupdate - Playback position changed (includes player state)
  • volumechange - Volume or muted state changed
  • seeking, seeked - Seeking state changes
  • waiting, canplay, canplaythrough - Buffering state
  • loadedmetadata, loadeddata - Loading events
  • durationchange, ratechange - Playback configuration changes
  • fullscreenchange - Fullscreen state changed
  • error - Playback error occurred

PlayerBridge

Enable external control for a player inside an iframe.

Constructor

new PlayerBridge(player: PlayerInstance, options?: {
  allowedOrigin?: string // Optional: restrict to specific parent origin
})

PlayerInstance Interface

Your player must implement:

interface PlayerInstance {
  element?: HTMLElement; // Container with video element
  play(): Promise<void> | void; // Start playback
  pause(): void; // Pause playback
  togglePlay(): void; // Toggle play/pause
  setVolume(volume: number): void; // Set volume (0-1)
  mute(): void; // Mute audio
  unmute(): void; // Unmute audio
  setMuted(muted: boolean): void; // Set muted state
  toggleFullscreen(): void; // Toggle fullscreen
  showControls(): void; // Show controls
  hideControls(): void; // Hide controls
  setControlsVisible(visible: boolean): void; // Set controls visibility
  addWatermark(config: any): void; // Add watermark
}

Methods

  • destroy(): void - Clean up event listeners and stop message handling

Security

Both PlayerController and PlayerBridge support origin validation:

  • Controller: Automatically determines allowed origin from iframe src URL
  • Bridge: Pass allowedOrigin option to restrict parent origin
// In iframe
const bridge = new PlayerBridge(player, {
  allowedOrigin: 'https://trusted-parent.com'
});

Examples

Basic Video Player

// Parent page
import { PlayerController } from '@estenbyte/player';

const iframe = document.createElement('iframe');
iframe.src = 'https://player.example.com/embed/video123';
document.body.appendChild(iframe);

// Simple: pass the element or a selector
const controller = new PlayerController(iframe);
await controller.whenReady();

// Play/pause with button
document.getElementById('play-btn').addEventListener('click', () => {
  controller.togglePlay();
});

// Volume slider
document.getElementById('volume').addEventListener('input', (e) => {
  controller.setVolume(e.target.value / 100);
});

// Show current time
controller.on('timeupdate', (state) => {
  document.getElementById('time').textContent =
    `${Math.floor(state.currentTime)}s / ${Math.floor(state.duration)}s`;
});

With TypeScript

import { PlayerController } from '@estenbyte/player/controller';
import type { WatermarkConfig } from '@estenbyte/player';

// Simpler: just pass the selector
const controller = new PlayerController('#player-iframe');

await controller.whenReady();

// Type-safe API calls
const volume: number = await controller.getVolume();
const isPaused: boolean = await controller.getPaused();

// Add watermark with proper typing
const watermark: WatermarkConfig = {
  text: 'Confidential',
  color: '#ffffff',
  opacity: 0.3,
  fontSize: 24
};
await controller.addWatermark(watermark);

TypeScript Support

Full TypeScript definitions are included. Import types as needed:

import type {
  PlayerInstance,
  WatermarkConfig,
  WatermarkOptions
} from '@estenbyte/player';

Browser Support

  • Modern browsers with ES6+ support
  • Requires postMessage API support
  • Fullscreen API support varies by browser

Development

# Install dependencies
npm install

# Build the library
npm run build

# The build outputs to dist/ with:
# - ESM (.mjs) and CJS (.js) formats
# - TypeScript declarations (.d.ts)

Publishing

# Publish current version
npm run publish

# Bump patch version (2.0.0 -> 2.0.1) and publish
npm run release:patch

# Bump minor version (2.0.0 -> 2.1.0) and publish
npm run release:minor

# Bump major version (2.0.0 -> 3.0.0) and publish
npm run release:major

License

MIT