@gumlet/player.js 2.0.16 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +281 -205
- package/dist/main.cjs +2 -0
- package/dist/main.cjs.map +1 -0
- package/dist/main.d.cts +203 -0
- package/dist/main.d.ts +203 -0
- package/dist/main.global.js +2 -0
- package/dist/main.global.js.map +1 -0
- package/dist/main.js +2 -0
- package/dist/main.js.map +1 -0
- package/package.json +20 -21
- package/dist/package.json +0 -1
- package/dist/player.min.js +0 -2
- package/dist/player.min.js.LICENSE.txt +0 -10
package/README.md
CHANGED
|
@@ -6,67 +6,105 @@ Player.js
|
|
|
6
6
|
)](https://www.npmjs.com/package/@gumlet/player.js)
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
A JavaScript library for interacting with iframes that support Player.js
|
|
10
|
-
spec.
|
|
9
|
+
A JavaScript library for interacting with iframes that support Player.js spec.
|
|
11
10
|
|
|
12
11
|
```js
|
|
13
12
|
const player = new playerjs.Player('iframe');
|
|
14
13
|
|
|
15
|
-
player.on('ready', () => {
|
|
14
|
+
player.on('ready', async () => {
|
|
16
15
|
player.on('play', () => {
|
|
17
16
|
console.log('play');
|
|
18
17
|
});
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
const duration = await player.getDuration();
|
|
20
|
+
console.log(duration);
|
|
21
21
|
|
|
22
22
|
if (player.supports('method', 'mute')) {
|
|
23
|
-
player.mute();
|
|
23
|
+
await player.mute();
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
player.play();
|
|
26
|
+
await player.play();
|
|
27
27
|
});
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
Install
|
|
31
31
|
-------
|
|
32
32
|
|
|
33
|
-
Player.js is hosted on JSDelivr's CDN
|
|
33
|
+
Player.js is hosted on JSDelivr's CDN:
|
|
34
34
|
|
|
35
35
|
```html
|
|
36
|
-
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@gumlet/player.js@
|
|
36
|
+
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@gumlet/player.js@3.0/dist/main.global.js"></script>
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
Install via npm:
|
|
40
40
|
|
|
41
41
|
```sh
|
|
42
42
|
npm install @gumlet/player.js
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
TypeScript Support
|
|
46
|
+
------------------
|
|
47
|
+
|
|
48
|
+
Player.js v3.0.0+ includes full TypeScript support with type definitions included. The library is written in TypeScript and provides comprehensive type safety:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import playerjs from '@gumlet/player.js';
|
|
52
|
+
|
|
53
|
+
const player = new playerjs.Player('iframe');
|
|
54
|
+
|
|
55
|
+
player.on('ready', async () => {
|
|
56
|
+
try {
|
|
57
|
+
const duration = await player.getDuration();
|
|
58
|
+
console.log(`Duration: ${duration} seconds`);
|
|
59
|
+
|
|
60
|
+
if (player.supports('method', 'mute')) {
|
|
61
|
+
await player.mute();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
await player.play();
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error('Player error:', error);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Promise-Based API
|
|
72
|
+
|
|
73
|
+
All player methods return promises, making it easier to work with async/await patterns:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// Get multiple values concurrently
|
|
77
|
+
const [duration, currentTime, volume] = await Promise.all([
|
|
78
|
+
player.getDuration(),
|
|
79
|
+
player.getCurrentTime(),
|
|
80
|
+
player.getVolume()
|
|
81
|
+
]);
|
|
82
|
+
|
|
83
|
+
// Chain operations
|
|
84
|
+
await player.setCurrentTime(10);
|
|
85
|
+
await player.setVolume(75);
|
|
86
|
+
await player.play();
|
|
87
|
+
```
|
|
88
|
+
|
|
45
89
|
Ready
|
|
46
90
|
-----
|
|
47
91
|
|
|
48
|
-
Because of the dance that we need to do between both iframes, you should
|
|
49
|
-
always wait till the `ready` events to fire before interacting with the
|
|
50
|
-
player object. However, the player will internally queue messages until
|
|
51
|
-
ready is called. :
|
|
92
|
+
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:
|
|
52
93
|
|
|
53
94
|
```js
|
|
54
95
|
const player = new playerjs.Player('iframe');
|
|
55
96
|
|
|
56
|
-
player.on(
|
|
57
|
-
|
|
58
|
-
|
|
97
|
+
player.on('ready', async () => {
|
|
98
|
+
await player.setCurrentTime(20);
|
|
99
|
+
});
|
|
59
100
|
```
|
|
60
101
|
|
|
61
102
|
Timing
|
|
62
103
|
------
|
|
63
104
|
|
|
64
|
-
The timing between when the iframe is added and when the ready event is
|
|
65
|
-
fired is important. Sadly we cannot fire the ready event till the iframe
|
|
66
|
-
is loaded, but there is no concrete way of telling when postmessage is
|
|
67
|
-
available to us.
|
|
105
|
+
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.
|
|
68
106
|
|
|
69
|
-
The best way is to do one of the following
|
|
107
|
+
The best way is to do one of the following:
|
|
70
108
|
|
|
71
109
|
### Create the iframe via JavaScript
|
|
72
110
|
|
|
@@ -78,355 +116,393 @@ document.body.appendChild(iframe);
|
|
|
78
116
|
const player = new playerjs.Player(iframe);
|
|
79
117
|
```
|
|
80
118
|
|
|
81
|
-
In this case, Player.js will listen to the onload event of the iframe
|
|
82
|
-
and only try to communicate when ready.
|
|
119
|
+
In this case, Player.js will listen to the onload event of the iframe and only try to communicate when ready.
|
|
83
120
|
|
|
84
|
-
### Wait for the document to be ready
|
|
121
|
+
### Wait for the document to be ready
|
|
85
122
|
|
|
86
123
|
```html
|
|
87
124
|
<iframe src="//example.com/iframe"></iframe>
|
|
88
125
|
|
|
89
126
|
<script>
|
|
90
127
|
$(document).on('ready', () => {
|
|
91
|
-
$('iframes').each(() => {
|
|
128
|
+
$('iframes').each(async () => {
|
|
92
129
|
const player = new playerjs.Player(this);
|
|
93
|
-
player.on('ready', () =>
|
|
130
|
+
player.on('ready', async () => {
|
|
131
|
+
await player.play();
|
|
132
|
+
});
|
|
94
133
|
});
|
|
95
134
|
});
|
|
96
135
|
</script>
|
|
97
136
|
```
|
|
98
137
|
|
|
99
|
-
At this point we can reasonably assume that the iframe's been loaded and
|
|
100
|
-
the ready. Player.js will take care of listening for ready events that
|
|
101
|
-
were fired before the player is set up.
|
|
138
|
+
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.
|
|
102
139
|
|
|
103
140
|
Methods
|
|
104
141
|
-------
|
|
105
142
|
|
|
106
|
-
|
|
143
|
+
All methods return promises for modern async/await patterns:
|
|
144
|
+
|
|
145
|
+
### `play(): Promise<void>`
|
|
107
146
|
Play the media:
|
|
108
147
|
|
|
109
148
|
```js
|
|
110
|
-
player.play();
|
|
149
|
+
await player.play();
|
|
111
150
|
```
|
|
112
151
|
|
|
113
|
-
`pause
|
|
152
|
+
### `pause(): Promise<void>`
|
|
114
153
|
Pause the media:
|
|
115
154
|
|
|
116
155
|
```js
|
|
117
|
-
player.pause();
|
|
156
|
+
await player.pause();
|
|
118
157
|
```
|
|
119
158
|
|
|
120
|
-
`getPaused
|
|
159
|
+
### `getPaused(): Promise<boolean>`
|
|
121
160
|
Determine if the media is paused:
|
|
122
161
|
|
|
123
162
|
```js
|
|
124
|
-
player.getPaused(
|
|
125
|
-
|
|
126
|
-
});
|
|
163
|
+
const isPaused = await player.getPaused();
|
|
164
|
+
console.log('paused:', isPaused);
|
|
127
165
|
```
|
|
128
166
|
|
|
129
|
-
`mute
|
|
167
|
+
### `mute(): Promise<void>`
|
|
130
168
|
Mute the media:
|
|
131
169
|
|
|
132
170
|
```js
|
|
133
|
-
player.mute();
|
|
171
|
+
await player.mute();
|
|
134
172
|
```
|
|
135
173
|
|
|
136
|
-
`unmute
|
|
174
|
+
### `unmute(): Promise<void>`
|
|
137
175
|
Unmute the media:
|
|
138
176
|
|
|
139
177
|
```js
|
|
140
|
-
player.unmute();
|
|
178
|
+
await player.unmute();
|
|
141
179
|
```
|
|
142
180
|
|
|
143
|
-
`getMuted
|
|
181
|
+
### `getMuted(): Promise<boolean>`
|
|
144
182
|
Determine if the media is muted:
|
|
145
183
|
|
|
146
184
|
```js
|
|
147
|
-
player.getMuted(
|
|
185
|
+
const isMuted = await player.getMuted();
|
|
186
|
+
console.log('muted:', isMuted);
|
|
148
187
|
```
|
|
149
188
|
|
|
150
|
-
`setVolume
|
|
189
|
+
### `setVolume(volume: number): Promise<void>`
|
|
151
190
|
Set the volume. Value needs to be between 0-100:
|
|
152
191
|
|
|
153
|
-
```
|
|
154
|
-
player.setVolume(50);
|
|
192
|
+
```js
|
|
193
|
+
await player.setVolume(50);
|
|
155
194
|
```
|
|
156
195
|
|
|
157
|
-
`getVolume
|
|
196
|
+
### `getVolume(): Promise<number>`
|
|
158
197
|
Get the volume. Value will be between 0-100:
|
|
159
198
|
|
|
160
199
|
```js
|
|
161
|
-
player.getVolume(
|
|
200
|
+
const volume = await player.getVolume();
|
|
201
|
+
console.log('volume:', volume);
|
|
162
202
|
```
|
|
163
203
|
|
|
164
|
-
`getDuration
|
|
165
|
-
Get the duration of the media
|
|
204
|
+
### `getDuration(): Promise<number>`
|
|
205
|
+
Get the duration of the media in seconds:
|
|
166
206
|
|
|
167
207
|
```js
|
|
168
|
-
player.getDuration(
|
|
208
|
+
const duration = await player.getDuration();
|
|
209
|
+
console.log('duration:', duration);
|
|
169
210
|
```
|
|
170
211
|
|
|
171
|
-
`setCurrentTime
|
|
212
|
+
### `setCurrentTime(time: number): Promise<void>`
|
|
172
213
|
Perform a seek to a particular time in seconds:
|
|
173
214
|
|
|
174
215
|
```js
|
|
175
|
-
player.setCurrentTime(50);
|
|
216
|
+
await player.setCurrentTime(50);
|
|
176
217
|
```
|
|
177
218
|
|
|
178
|
-
`getCurrentTime
|
|
219
|
+
### `getCurrentTime(): Promise<number>`
|
|
179
220
|
Get the current time in seconds of the video:
|
|
180
221
|
|
|
181
222
|
```js
|
|
182
|
-
player.getCurrentTime(
|
|
223
|
+
const currentTime = await player.getCurrentTime();
|
|
224
|
+
console.log('currentTime:', currentTime);
|
|
183
225
|
```
|
|
184
226
|
|
|
185
|
-
`setPlaybackRate
|
|
186
|
-
Set the playback rate which are available in the player. Doesn't
|
|
227
|
+
### `setPlaybackRate(rate: number): Promise<void>`
|
|
228
|
+
Set the playback rate which are available in the player. Doesn't return an error if the passed playback rate is not available:
|
|
187
229
|
|
|
188
230
|
```js
|
|
189
|
-
player.setPlaybackRate(0.5);
|
|
231
|
+
await player.setPlaybackRate(0.5);
|
|
190
232
|
```
|
|
191
233
|
|
|
192
|
-
`getPlaybackRate
|
|
234
|
+
### `getPlaybackRate(): Promise<number>`
|
|
193
235
|
Get the current playback rate of the player:
|
|
194
236
|
|
|
195
237
|
```js
|
|
196
|
-
player.getPlaybackRate(
|
|
238
|
+
const rate = await player.getPlaybackRate();
|
|
239
|
+
console.log('playbackRate:', rate);
|
|
197
240
|
```
|
|
198
241
|
|
|
199
|
-
`
|
|
200
|
-
|
|
201
|
-
only that listener, otherwise remove all listeners:
|
|
242
|
+
### `setLoop(loop: boolean): Promise<void>`
|
|
243
|
+
Set whether the media should loop:
|
|
202
244
|
|
|
203
245
|
```js
|
|
204
|
-
player.
|
|
246
|
+
await player.setLoop(true);
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### `getLoop(): Promise<boolean>`
|
|
250
|
+
Get whether the media is set to loop:
|
|
251
|
+
|
|
252
|
+
```js
|
|
253
|
+
const isLooping = await player.getLoop();
|
|
254
|
+
console.log('looping:', isLooping);
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### `off(event: string, callback?: Function): void`
|
|
258
|
+
Remove an event listener. If the listener is specified it should remove only that listener, otherwise remove all listeners:
|
|
205
259
|
|
|
260
|
+
```js
|
|
261
|
+
player.off('play');
|
|
206
262
|
player.off('play', playCallback);
|
|
207
263
|
```
|
|
208
264
|
|
|
209
|
-
`on
|
|
265
|
+
### `on(event: string, callback: Function): void`
|
|
210
266
|
Add an event listener:
|
|
211
267
|
|
|
212
268
|
```js
|
|
213
269
|
player.on('play', () => console.log('play'));
|
|
214
270
|
```
|
|
215
271
|
|
|
216
|
-
`supports
|
|
217
|
-
Determines if the player supports a given event or method
|
|
272
|
+
### `supports(type: 'method' | 'event', name: string | string[]): boolean`
|
|
273
|
+
Determines if the player supports a given event or method:
|
|
218
274
|
|
|
219
275
|
```js
|
|
220
276
|
player.supports('method', 'getDuration');
|
|
221
277
|
player.supports('event', 'ended');
|
|
278
|
+
player.supports('method', ['play', 'pause']);
|
|
222
279
|
```
|
|
223
280
|
|
|
224
281
|
Events
|
|
225
282
|
------
|
|
226
283
|
|
|
227
|
-
|
|
284
|
+
Player.js provides comprehensive event handling to monitor playback state and user interactions. All events can be listened to using the `on()` method.
|
|
228
285
|
|
|
229
|
-
|
|
230
|
-
fired when the media is ready to receive commands. This is fired
|
|
231
|
-
regardless of listening to the event. Note: As outlined in the PlayerJs
|
|
232
|
-
Spec, you may run into inconsistencies if you have multiple players on
|
|
233
|
-
the page with the same `src`. To get around this, simply append a UUID
|
|
234
|
-
or a timestamp to the iframe's src to guarantee that all players on the
|
|
235
|
-
page have a unique `src`.
|
|
286
|
+
### Core Events
|
|
236
287
|
|
|
237
|
-
`
|
|
238
|
-
|
|
288
|
+
#### `ready`
|
|
289
|
+
Fired when the media is ready to receive commands. Always wait for this event before calling player methods.
|
|
239
290
|
|
|
240
291
|
```js
|
|
241
|
-
{
|
|
242
|
-
|
|
243
|
-
|
|
292
|
+
player.on('ready', async () => {
|
|
293
|
+
console.log('Player is ready!');
|
|
294
|
+
// Safe to call player methods now
|
|
295
|
+
await player.play();
|
|
296
|
+
});
|
|
244
297
|
```
|
|
245
298
|
|
|
246
|
-
`
|
|
247
|
-
|
|
299
|
+
**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.
|
|
300
|
+
|
|
301
|
+
#### `play`
|
|
302
|
+
Fired when playback starts.
|
|
248
303
|
|
|
249
304
|
```js
|
|
250
|
-
{
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}
|
|
305
|
+
player.on('play', () => {
|
|
306
|
+
console.log('Video started playing');
|
|
307
|
+
});
|
|
254
308
|
```
|
|
255
309
|
|
|
256
|
-
`
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
`pause`
|
|
260
|
-
fires when the video is paused.
|
|
261
|
-
|
|
262
|
-
`ended`
|
|
263
|
-
fires when the video is finished.
|
|
264
|
-
|
|
265
|
-
`fullscreenChange`
|
|
266
|
-
fires when the video fullscreen is changed:
|
|
310
|
+
#### `pause`
|
|
311
|
+
Fired when playback is paused.
|
|
267
312
|
|
|
268
313
|
```js
|
|
269
|
-
{
|
|
270
|
-
|
|
271
|
-
}
|
|
314
|
+
player.on('pause', () => {
|
|
315
|
+
console.log('Video paused');
|
|
316
|
+
});
|
|
272
317
|
```
|
|
273
318
|
|
|
274
|
-
`
|
|
275
|
-
|
|
319
|
+
#### `ended`
|
|
320
|
+
Fired when playback reaches the end of the media.
|
|
276
321
|
|
|
277
322
|
```js
|
|
278
|
-
{
|
|
279
|
-
|
|
280
|
-
|
|
323
|
+
player.on('ended', async () => {
|
|
324
|
+
console.log('Video finished');
|
|
325
|
+
// Reset to beginning if needed
|
|
326
|
+
await player.setCurrentTime(0);
|
|
327
|
+
});
|
|
281
328
|
```
|
|
282
329
|
|
|
283
|
-
|
|
284
|
-
fires when the video playback rate is changed by user.
|
|
285
|
-
|
|
286
|
-
`audioChange`
|
|
287
|
-
fires when the audio track of video is changed.
|
|
330
|
+
### Progress Events
|
|
288
331
|
|
|
289
|
-
`
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
`volumeChange`
|
|
293
|
-
fires when the volume level of the player is changed. It also gets fired when the player is muted or unmuted, along with muted and unmuted events respectively.
|
|
332
|
+
#### `timeupdate`
|
|
333
|
+
Fired regularly during playback with current time information.
|
|
294
334
|
|
|
295
335
|
```js
|
|
296
|
-
{
|
|
297
|
-
|
|
336
|
+
player.on('timeupdate', (data) => {
|
|
337
|
+
const { seconds, duration } = data;
|
|
338
|
+
const progress = (seconds / duration) * 100;
|
|
339
|
+
|
|
340
|
+
console.log(`Progress: ${progress.toFixed(1)}%`);
|
|
341
|
+
console.log(`Current time: ${formatTime(seconds)} / ${formatTime(duration)}`);
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
function formatTime(seconds) {
|
|
345
|
+
const mins = Math.floor(seconds / 60);
|
|
346
|
+
const secs = Math.floor(seconds % 60);
|
|
347
|
+
return `${mins}:${secs.toString().padStart(2, '0')}`;
|
|
298
348
|
}
|
|
299
349
|
```
|
|
300
350
|
|
|
301
|
-
`
|
|
302
|
-
|
|
351
|
+
#### `progress`
|
|
352
|
+
Fired when the media is buffering/loading additional content.
|
|
303
353
|
|
|
304
354
|
```js
|
|
305
|
-
{
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
355
|
+
player.on('progress', (data) => {
|
|
356
|
+
const { percent } = data;
|
|
357
|
+
console.log(`Buffered: ${(percent * 100).toFixed(1)}%`);
|
|
358
|
+
});
|
|
309
359
|
```
|
|
310
360
|
|
|
311
|
-
`
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
Receiver
|
|
315
|
-
--------
|
|
316
|
-
|
|
317
|
-
If you are looking to implement the Player.js spec, we include a
|
|
318
|
-
Receiver that will allow you to easily listen to events and takes care
|
|
319
|
-
of the house keeping.
|
|
361
|
+
#### `seeked`
|
|
362
|
+
Fired when the user seeks to a different time position.
|
|
320
363
|
|
|
321
364
|
```js
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
video.play();
|
|
326
|
-
receiver.emit('play');
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
receiver.on('pause', () => {
|
|
330
|
-
video.pause();
|
|
331
|
-
receiver.emit('pause');
|
|
365
|
+
player.on('seeked', (data) => {
|
|
366
|
+
const { seconds, duration } = data;
|
|
367
|
+
console.log(`Seeked to ${seconds}s of ${duration}s`);
|
|
332
368
|
});
|
|
369
|
+
```
|
|
333
370
|
|
|
334
|
-
|
|
371
|
+
### Audio/Video Control Events
|
|
335
372
|
|
|
336
|
-
|
|
373
|
+
#### `volumeChange`
|
|
374
|
+
Fired when the volume level changes, including mute/unmute actions.
|
|
337
375
|
|
|
338
|
-
|
|
376
|
+
```js
|
|
377
|
+
player.on('volumeChange', async () => {
|
|
378
|
+
const volume = await player.getVolume();
|
|
379
|
+
const isMuted = await player.getMuted();
|
|
380
|
+
|
|
381
|
+
console.log(`Volume: ${volume}%, Muted: ${isMuted}`);
|
|
382
|
+
});
|
|
383
|
+
```
|
|
339
384
|
|
|
340
|
-
|
|
385
|
+
#### `playbackRateChange`
|
|
386
|
+
Fired when playback speed is changed.
|
|
341
387
|
|
|
342
|
-
|
|
388
|
+
```js
|
|
389
|
+
player.on('playbackRateChange', async () => {
|
|
390
|
+
const rate = await player.getPlaybackRate();
|
|
391
|
+
console.log(`Playback rate: ${rate}x`);
|
|
392
|
+
});
|
|
393
|
+
```
|
|
343
394
|
|
|
344
|
-
|
|
395
|
+
### Display Events
|
|
345
396
|
|
|
346
|
-
|
|
397
|
+
#### `fullscreenChange`
|
|
398
|
+
Fired when fullscreen mode is toggled.
|
|
347
399
|
|
|
348
|
-
|
|
400
|
+
```js
|
|
401
|
+
player.on('fullscreenChange', (data) => {
|
|
402
|
+
const { isFullScreen } = data;
|
|
403
|
+
console.log(`Fullscreen: ${isFullScreen}`);
|
|
404
|
+
});
|
|
405
|
+
```
|
|
349
406
|
|
|
350
|
-
|
|
407
|
+
#### `pipChange`
|
|
408
|
+
Fired when Picture-in-Picture mode is toggled.
|
|
351
409
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
});
|
|
410
|
+
```js
|
|
411
|
+
player.on('pipChange', (data) => {
|
|
412
|
+
const { isPIP } = data;
|
|
413
|
+
console.log(`Picture-in-Picture: ${isPIP}`);
|
|
357
414
|
});
|
|
358
|
-
|
|
359
|
-
receiver.ready();
|
|
360
415
|
```
|
|
361
416
|
|
|
362
|
-
|
|
363
|
-
-------
|
|
417
|
+
### Quality Events
|
|
364
418
|
|
|
365
|
-
`
|
|
366
|
-
|
|
367
|
-
implemented. If the event expects a return value a callback will be
|
|
368
|
-
passed into the function call:
|
|
419
|
+
#### `qualityChange`
|
|
420
|
+
Fired when video quality/resolution is changed.
|
|
369
421
|
|
|
370
422
|
```js
|
|
371
|
-
|
|
423
|
+
player.on('qualityChange', (data) => {
|
|
424
|
+
const { quality } = data;
|
|
425
|
+
console.log(`Quality changed to: ${quality}`);
|
|
426
|
+
});
|
|
372
427
|
```
|
|
373
428
|
|
|
374
|
-
|
|
429
|
+
#### `audioChange`
|
|
430
|
+
Fired when the audio track is changed.
|
|
375
431
|
|
|
376
432
|
```js
|
|
377
|
-
|
|
433
|
+
player.on('audioChange', (data) => {
|
|
434
|
+
console.log('Audio track changed:', data);
|
|
435
|
+
});
|
|
378
436
|
```
|
|
379
437
|
|
|
380
|
-
|
|
381
|
-
Sends events to the parent as long as someone is listing. The above
|
|
382
|
-
player events should be implemented. If a value is expected, it should
|
|
383
|
-
be passed in as the second argument:
|
|
438
|
+
### Error Handling
|
|
384
439
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
`ready`
|
|
388
|
-
Once everything is in place and you are ready to start responding to
|
|
389
|
-
events, call this method. It performs some house keeping, along with
|
|
390
|
-
emitting `ready`:
|
|
440
|
+
#### `error`
|
|
441
|
+
Fired when an error occurs during playback.
|
|
391
442
|
|
|
392
443
|
```js
|
|
393
|
-
|
|
444
|
+
player.on('error', (error) => {
|
|
445
|
+
console.error('Playback error:', error);
|
|
446
|
+
// Handle error appropriately for your application
|
|
447
|
+
});
|
|
394
448
|
```
|
|
395
|
-
Adapters
|
|
396
|
-
--------
|
|
397
|
-
|
|
398
|
-
In order to make it super easy to add Player.js to any embed, we have
|
|
399
|
-
written adapters for common video libraries. We currently have adapters
|
|
400
|
-
for [Video.js](http://www.videojs.com/),
|
|
401
|
-
[JWPlayer](https://www.jwplayer.com/) and [HTML5
|
|
402
|
-
Video](http://dev.w3.org/html5/spec-author-view/video.html). An Adapter
|
|
403
|
-
wraps the Receiver and wires up all the events so your iframe is
|
|
404
|
-
Player.js compatible.
|
|
405
449
|
|
|
406
|
-
###
|
|
450
|
+
### Complete Example
|
|
407
451
|
|
|
408
|
-
|
|
452
|
+
Here's a comprehensive example showing how to listen to multiple events:
|
|
409
453
|
|
|
410
454
|
```js
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
455
|
+
const player = new playerjs.Player('video-iframe');
|
|
456
|
+
|
|
457
|
+
player.on('ready', async () => {
|
|
458
|
+
console.log('Player is ready!');
|
|
459
|
+
|
|
460
|
+
// Get initial player state
|
|
461
|
+
const duration = await player.getDuration();
|
|
462
|
+
const volume = await player.getVolume();
|
|
463
|
+
const isPaused = await player.getPaused();
|
|
464
|
+
|
|
465
|
+
console.log(`Duration: ${duration}s, Volume: ${volume}%, Paused: ${isPaused}`);
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
// Listen to playback events
|
|
469
|
+
player.on('play', () => console.log('Started playing'));
|
|
470
|
+
player.on('pause', () => console.log('Paused'));
|
|
471
|
+
player.on('ended', () => console.log('Playback finished'));
|
|
414
472
|
|
|
415
|
-
|
|
416
|
-
|
|
473
|
+
// Listen to progress events
|
|
474
|
+
player.on('timeupdate', (data) => {
|
|
475
|
+
const { seconds, duration } = data;
|
|
476
|
+
console.log(`${seconds.toFixed(1)}s / ${duration.toFixed(1)}s`);
|
|
417
477
|
});
|
|
418
|
-
```
|
|
419
|
-
### HTML5Adapter
|
|
420
478
|
|
|
421
|
-
|
|
422
|
-
|
|
479
|
+
// Listen to user interaction events
|
|
480
|
+
player.on('volumeChange', async () => {
|
|
481
|
+
const volume = await player.getVolume();
|
|
482
|
+
const muted = await player.getMuted();
|
|
483
|
+
console.log(`Volume: ${volume}%, Muted: ${muted}`);
|
|
484
|
+
});
|
|
423
485
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
486
|
+
player.on('seeked', (data) => {
|
|
487
|
+
console.log(`Seeked to: ${data.seconds}s`);
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
// Listen to display events
|
|
491
|
+
player.on('fullscreenChange', (data) => {
|
|
492
|
+
console.log(`Fullscreen: ${data.isFullScreen}`);
|
|
493
|
+
});
|
|
427
494
|
|
|
428
|
-
|
|
495
|
+
player.on('pipChange', (data) => {
|
|
496
|
+
console.log(`Picture-in-Picture: ${data.isPIP}`);
|
|
497
|
+
});
|
|
429
498
|
|
|
430
|
-
//
|
|
431
|
-
|
|
499
|
+
// Handle errors
|
|
500
|
+
player.on('error', (error) => {
|
|
501
|
+
console.error('Player error:', error);
|
|
502
|
+
});
|
|
432
503
|
```
|
|
504
|
+
|
|
505
|
+
## Related Documentation
|
|
506
|
+
|
|
507
|
+
- [Receiver Implementation Guide](./RECEIVER.md) - For implementing the Player.js spec in your video player
|
|
508
|
+
- [Legacy Callback API](./CALLBACK_API.md) - Documentation for backward-compatible callback-based methods
|