@gumlet/player.js
v3.0.3
Published
Player.js =========
Readme
Player.js
A JavaScript library for interacting with iframes that support Player.js spec.
const player = new playerjs.Player('iframe');
player.on('ready', async () => {
player.on('play', () => {
console.log('play');
});
const duration = await player.getDuration();
console.log(duration);
if (player.supports('method', 'mute')) {
await player.mute();
}
await player.play();
});Install
Player.js is hosted on JSDelivr's CDN:
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@gumlet/[email protected]/dist/main.global.js"></script>Install via npm:
npm install @gumlet/player.jsTypeScript Support
Player.js v3.0.0+ includes full TypeScript support with type definitions included. The library is written in TypeScript and provides comprehensive type safety:
import playerjs from '@gumlet/player.js';
const player = new playerjs.Player('iframe');
player.on('ready', async () => {
try {
const duration = await player.getDuration();
console.log(`Duration: ${duration} seconds`);
if (player.supports('method', 'mute')) {
await player.mute();
}
await player.play();
} catch (error) {
console.error('Player error:', error);
}
});Promise-Based API
All player methods return promises, making it easier to work with async/await patterns:
// Get multiple values concurrently
const [duration, currentTime, volume] = await Promise.all([
player.getDuration(),
player.getCurrentTime(),
player.getVolume()
]);
// Chain operations
await player.setCurrentTime(10);
await player.setVolume(75);
await player.play();Ready
Because of the dance that we need to do between both iframes, you should always wait till the ready event fires before interacting with the player object. However, the player will internally queue messages until ready is called:
const player = new playerjs.Player('iframe');
player.on('ready', async () => {
await player.setCurrentTime(20);
});Timing
The timing between when the iframe is added and when the ready event is fired is important. Sadly we cannot fire the ready event till the iframe is loaded, but there is no concrete way of telling when postmessage is available to us.
The best way is to do one of the following:
Create the iframe via JavaScript
const iframe = document.createElement('iframe');
iframe.src = 'https://example.com/iframe';
document.body.appendChild(iframe);
const player = new playerjs.Player(iframe);In this case, Player.js will listen to the onload event of the iframe and only try to communicate when ready.
Wait for the document to be ready
<iframe src="//example.com/iframe"></iframe>
<script>
$(document).on('ready', () => {
$('iframes').each(async () => {
const player = new playerjs.Player(this);
player.on('ready', async () => {
await player.play();
});
});
});
</script>At this point we can reasonably assume that the iframe's been loaded and the ready. Player.js will take care of listening for ready events that were fired before the player is set up.
Methods
All methods return promises for modern async/await patterns:
play(): Promise<void>
Play the media:
await player.play();pause(): Promise<void>
Pause the media:
await player.pause();getPaused(): Promise<boolean>
Determine if the media is paused:
const isPaused = await player.getPaused();
console.log('paused:', isPaused);mute(): Promise<void>
Mute the media:
await player.mute();unmute(): Promise<void>
Unmute the media:
await player.unmute();getMuted(): Promise<boolean>
Determine if the media is muted:
const isMuted = await player.getMuted();
console.log('muted:', isMuted);setVolume(volume: number): Promise<void>
Set the volume. Value needs to be between 0-100:
await player.setVolume(50);getVolume(): Promise<number>
Get the volume. Value will be between 0-100:
const volume = await player.getVolume();
console.log('volume:', volume);getDuration(): Promise<number>
Get the duration of the media in seconds:
const duration = await player.getDuration();
console.log('duration:', duration);setCurrentTime(time: number): Promise<void>
Perform a seek to a particular time in seconds:
await player.setCurrentTime(50);getCurrentTime(): Promise<number>
Get the current time in seconds of the video:
const currentTime = await player.getCurrentTime();
console.log('currentTime:', currentTime);setPlaybackRate(rate: number): Promise<void>
Set the playback rate which are available in the player. Doesn't return an error if the passed playback rate is not available:
await player.setPlaybackRate(0.5);getPlaybackRate(): Promise<number>
Get the current playback rate of the player:
const rate = await player.getPlaybackRate();
console.log('playbackRate:', rate);setLoop(loop: boolean): Promise<void>
Set whether the media should loop:
await player.setLoop(true);getLoop(): Promise<boolean>
Get whether the media is set to loop:
const isLooping = await player.getLoop();
console.log('looping:', isLooping);off(event: string, callback?: Function): void
Remove an event listener. If the listener is specified it should remove only that listener, otherwise remove all listeners:
player.off('play');
player.off('play', playCallback);on(event: string, callback: Function): void
Add an event listener:
player.on('play', () => console.log('play'));supports(type: 'method' | 'event', name: string | string[]): boolean
Determines if the player supports a given event or method:
player.supports('method', 'getDuration');
player.supports('event', 'ended');
player.supports('method', ['play', 'pause']);Events
Player.js provides comprehensive event handling to monitor playback state and user interactions. All events can be listened to using the on() method.
Core Events
ready
Fired when the media is ready to receive commands. Always wait for this event before calling player methods.
player.on('ready', async () => {
console.log('Player is ready!');
// Safe to call player methods now
await player.play();
});Note: As outlined in the PlayerJs Spec, you may run into inconsistencies if you have multiple players on the page with the same src. To avoid this, append a UUID or timestamp to the iframe's src.
play
Fired when playback starts.
player.on('play', () => {
console.log('Video started playing');
});pause
Fired when playback is paused.
player.on('pause', () => {
console.log('Video paused');
});ended
Fired when playback reaches the end of the media.
player.on('ended', async () => {
console.log('Video finished');
// Reset to beginning if needed
await player.setCurrentTime(0);
});Progress Events
timeupdate
Fired regularly during playback with current time information.
player.on('timeupdate', (data) => {
const { seconds, duration } = data;
const progress = (seconds / duration) * 100;
console.log(`Progress: ${progress.toFixed(1)}%`);
console.log(`Current time: ${formatTime(seconds)} / ${formatTime(duration)}`);
});
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs.toString().padStart(2, '0')}`;
}progress
Fired when the media is buffering/loading additional content.
player.on('progress', (data) => {
const { percent } = data;
console.log(`Buffered: ${(percent * 100).toFixed(1)}%`);
});seeked
Fired when the user seeks to a different time position.
player.on('seeked', (data) => {
const { seconds, duration } = data;
console.log(`Seeked to ${seconds}s of ${duration}s`);
});Audio/Video Control Events
volumeChange
Fired when the volume level changes, including mute/unmute actions.
player.on('volumeChange', async () => {
const volume = await player.getVolume();
const isMuted = await player.getMuted();
console.log(`Volume: ${volume}%, Muted: ${isMuted}`);
});playbackRateChange
Fired when playback speed is changed.
player.on('playbackRateChange', async () => {
const rate = await player.getPlaybackRate();
console.log(`Playback rate: ${rate}x`);
});Display Events
fullscreenChange
Fired when fullscreen mode is toggled.
player.on('fullscreenChange', (data) => {
const { isFullScreen } = data;
console.log(`Fullscreen: ${isFullScreen}`);
});pipChange
Fired when Picture-in-Picture mode is toggled.
player.on('pipChange', (data) => {
const { isPIP } = data;
console.log(`Picture-in-Picture: ${isPIP}`);
});Quality Events
qualityChange
Fired when video quality/resolution is changed.
player.on('qualityChange', (data) => {
const { quality } = data;
console.log(`Quality changed to: ${quality}`);
});audioChange
Fired when the audio track is changed.
player.on('audioChange', (data) => {
console.log('Audio track changed:', data);
});Error Handling
error
Fired when an error occurs during playback.
player.on('error', (error) => {
console.error('Playback error:', error);
// Handle error appropriately for your application
});Complete Example
Here's a comprehensive example showing how to listen to multiple events:
const player = new playerjs.Player('video-iframe');
player.on('ready', async () => {
console.log('Player is ready!');
// Get initial player state
const duration = await player.getDuration();
const volume = await player.getVolume();
const isPaused = await player.getPaused();
console.log(`Duration: ${duration}s, Volume: ${volume}%, Paused: ${isPaused}`);
});
// Listen to playback events
player.on('play', () => console.log('Started playing'));
player.on('pause', () => console.log('Paused'));
player.on('ended', () => console.log('Playback finished'));
// Listen to progress events
player.on('timeupdate', (data) => {
const { seconds, duration } = data;
console.log(`${seconds.toFixed(1)}s / ${duration.toFixed(1)}s`);
});
// Listen to user interaction events
player.on('volumeChange', async () => {
const volume = await player.getVolume();
const muted = await player.getMuted();
console.log(`Volume: ${volume}%, Muted: ${muted}`);
});
player.on('seeked', (data) => {
console.log(`Seeked to: ${data.seconds}s`);
});
// Listen to display events
player.on('fullscreenChange', (data) => {
console.log(`Fullscreen: ${data.isFullScreen}`);
});
player.on('pipChange', (data) => {
console.log(`Picture-in-Picture: ${data.isPIP}`);
});
// Handle errors
player.on('error', (error) => {
console.error('Player error:', error);
});Related Documentation
- Receiver Implementation Guide - For implementing the Player.js spec in your video player
- Legacy Callback API - Documentation for backward-compatible callback-based methods
