@estenbyte/player
v2.0.2
Published
Control video players in iframes via postMessage API - simple, type-safe, and framework-agnostic
Maintainers
Readme
@estenbyte/player
Control video players running inside iframes using the postMessage API.
Installation
npm install @estenbyte/playerFeatures
- 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 playerAPI Reference
PlayerController
Control a player from the parent page.
Constructor
new PlayerController(iframe: HTMLIFrameElement | string)Parameters:
iframe- Either anHTMLIFrameElementor a CSS selector string (e.g.,'iframe','#player-iframe')
Playback Control
play(): Promise<void>- Start playbackpause(): Promise<void>- Pause playbacktogglePlay(): Promise<void>- Toggle play/pauseseek(time: number): Promise<void>- Seek to time (seconds)
Volume Control
setVolume(volume: number): Promise<void>- Set volume (0-1)getVolume(): Promise<number>- Get current volumemute(): Promise<void>- Mute audiounmute(): Promise<void>- Unmute audiosetMuted(muted: boolean): Promise<void>- Set muted stategetMuted(): 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 statesetPlaybackRate(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 moderequestFullscreen(): Promise<void>- Enter fullscreenexitFullscreen(): Promise<void>- Exit fullscreenshowControls(): Promise<void>- Show player controlshideControls(): Promise<void>- Hide player controlssetControlsVisible(visible: boolean): Promise<void>- Set controls visibility
Watermark
addWatermark(config: WatermarkConfig): Promise<void>- Add watermark overlay
Lifecycle
isReady(): boolean- Check if player is readywhenReady(): Promise<void>- Wait for player to be readydestroy(): void- Clean up event listeners and pending requests
Event Handling
on(event: string, callback: Function): this- Register event listeneroff(event: string, callback?: Function): this- Unregister event listeneronce(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 commandsplay,playing,pause,ended- Playback state changestimeupdate- Playback position changed (includes player state)volumechange- Volume or muted state changedseeking,seeked- Seeking state changeswaiting,canplay,canplaythrough- Buffering stateloadedmetadata,loadeddata- Loading eventsdurationchange,ratechange- Playback configuration changesfullscreenchange- Fullscreen state changederror- 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
srcURL - Bridge: Pass
allowedOriginoption 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
postMessageAPI 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:majorLicense
MIT
