Player.js for Videos
This doc explains how you can better control your videos
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(): Promise<void>Play the media:
await player.play();pause(): Promise<void>
pause(): Promise<void>Pause the media:
await player.pause();getPaused(): Promise<boolean>
getPaused(): Promise<boolean>Determine if the media is paused:
const isPaused = await player.getPaused();
console.log('paused:', isPaused);mute(): Promise<void>
mute(): Promise<void>Mute the media:
await player.mute();unmute(): Promise<void>
unmute(): Promise<void>Unmute the media:
await player.unmute();getMuted(): Promise<boolean>
getMuted(): Promise<boolean>Determine if the media is muted:
const isMuted = await player.getMuted();
console.log('muted:', isMuted);setVolume(volume: number): Promise<void>
setVolume(volume: number): Promise<void>Set the volume. Value needs to be between 0-100:
await player.setVolume(50);getVolume(): Promise<number>
getVolume(): Promise<number>Get the volume. Value will be between 0-100:
const volume = await player.getVolume();
console.log('volume:', volume);getDuration(): Promise<number>
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>
setCurrentTime(time: number): Promise<void>Perform a seek to a particular time in seconds:
await player.setCurrentTime(50);getCurrentTime(): Promise<number>
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>
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>
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>
setLoop(loop: boolean): Promise<void>Set whether the media should loop:
await player.setLoop(true);getLoop(): Promise<boolean>
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
off(event: string, callback?: Function): voidRemove 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
on(event: string, callback: Function): voidAdd an event listener:
player.on('play', () => console.log('play'));supports(type: 'method' | 'event', name: string | string[]): boolean
supports(type: 'method' | 'event', name: string | string[]): booleanDetermines 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
readyFired 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
playFired when playback starts.
player.on('play', () => {
console.log('Video started playing');
});pause
pauseFired when playback is paused.
player.on('pause', () => {
console.log('Video paused');
});ended
endedFired 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
timeupdateFired 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
progressFired when the media is buffering/loading additional content.
player.on('progress', (data) => {
const { percent } = data;
console.log(`Buffered: ${(percent * 100).toFixed(1)}%`);
});seeked
seekedFired 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
volumeChangeFired 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
playbackRateChangeFired when playback speed is changed.
player.on('playbackRateChange', async () => {
const rate = await player.getPlaybackRate();
console.log(`Playback rate: ${rate}x`);
});Display Events
fullscreenChange
fullscreenChangeFired when fullscreen mode is toggled.
player.on('fullscreenChange', (data) => {
const { isFullScreen } = data;
console.log(`Fullscreen: ${isFullScreen}`);
});pipChange
pipChangeFired when Picture-in-Picture mode is toggled.
player.on('pipChange', (data) => {
const { isPIP } = data;
console.log(`Picture-in-Picture: ${isPIP}`);
});Quality Events
qualityChange
qualityChangeFired when video quality/resolution is changed.
player.on('qualityChange', (data) => {
const { quality } = data;
console.log(`Quality changed to: ${quality}`);
});audioChange
audioChangeFired when the audio track is changed.
player.on('audioChange', (data) => {
console.log('Audio track changed:', data);
});Error Handling
error
errorFired 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);
});Updated about 2 hours ago
