@eluvio/elv-player-js 1.0.139 → 2.0.0
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 +35 -6
- package/dist/.vite/manifest.json +17 -17
- package/dist/{Analytics-cQC_NR8f.mjs → Analytics-MzZmvYgy.mjs} +1 -1
- package/dist/{Analytics-z6nAtuJx.js → Analytics-jM8HcyUa.js} +1 -1
- package/dist/{dash.all.min-Uvqi9PBX.js → dash.all.min-16Sl6Y0h.js} +1 -1
- package/dist/{dash.all.min-JeIXEd1s.mjs → dash.all.min-2ST8aEXP.mjs} +1 -1
- package/dist/elv-player-js.cjs.js +1 -1
- package/dist/elv-player-js.css +1 -1
- package/dist/elv-player-js.es.js +1 -1
- package/dist/{index-RKrb2ZFL.js → index-BThzGsbn.js} +1 -1
- package/dist/index-Cw8L2-NE.js +367 -0
- package/dist/{index-FpQhGSc8.mjs → index-herSXPMN.mjs} +1 -1
- package/dist/{index-FmpRD8ov.mjs → index-mO9GR6Op.mjs} +25278 -24415
- package/lib/index.js +7 -0
- package/{src → lib/player}/Analytics.js +9 -8
- package/lib/player/Controls.js +912 -0
- package/{src → lib/player}/FairPlay.js +2 -0
- package/lib/player/Player.js +881 -0
- package/lib/player/PlayerParameters.js +173 -0
- package/lib/static/icons/Icons.js +29 -0
- package/lib/static/icons/svgs/backward-circle.svg +5 -0
- package/lib/static/icons/svgs/backward.svg +4 -0
- package/lib/static/icons/svgs/captions-off.svg +7 -0
- package/lib/static/icons/svgs/captions.svg +6 -0
- package/lib/static/icons/svgs/check.svg +1 -0
- package/lib/static/icons/svgs/chevron-left.svg +1 -0
- package/lib/static/icons/svgs/chevron-right.svg +1 -0
- package/lib/static/icons/svgs/forward-circle.svg +5 -0
- package/lib/static/icons/svgs/forward.svg +4 -0
- package/{src/static/icons/media/Full Screen icon.svg → lib/static/icons/svgs/full-screen.svg} +1 -1
- package/lib/static/icons/svgs/large-play-circle.svg +4 -0
- package/lib/static/icons/svgs/list.svg +1 -0
- package/{src/static/icons → lib/static/icons/svgs}/minimize.svg +1 -1
- package/{src/static/icons/media/Pause icon.svg → lib/static/icons/svgs/pause-circle.svg} +3 -3
- package/lib/static/icons/svgs/pause.svg +1 -0
- package/{src/static/icons/media/Play icon.svg → lib/static/icons/svgs/play-circle.svg} +1 -1
- package/lib/static/icons/svgs/play.svg +1 -0
- package/lib/static/icons/svgs/rotate-cw.svg +1 -0
- package/lib/static/icons/svgs/settings.svg +11 -0
- package/{src/static/icons/media/skip back icon.svg → lib/static/icons/svgs/skip-backward.svg} +2 -3
- package/{src/static/icons/media/Skip forward icon.svg → lib/static/icons/svgs/skip-forward.svg} +2 -3
- package/{src/static/icons/media/Volume icon.svg → lib/static/icons/svgs/volume-high.svg} +3 -3
- package/lib/static/icons/svgs/volume-low.svg +10 -0
- package/{src/static/icons/media/low volume icon.svg → lib/static/icons/svgs/volume-medium.svg} +2 -2
- package/{src/static/icons/media/no volume icon.svg → lib/static/icons/svgs/volume-off.svg} +3 -3
- package/lib/static/stylesheets/common.module.scss +486 -0
- package/lib/static/stylesheets/controls-tv.module.scss +488 -0
- package/lib/static/stylesheets/controls-web.module.scss +422 -0
- package/lib/static/stylesheets/player-profile-form.module.scss +141 -0
- package/lib/static/stylesheets/player.module.scss +92 -0
- package/lib/static/stylesheets/reset.module.scss +79 -0
- package/lib/static/stylesheets/ticket-form.module.scss +123 -0
- package/lib/ui/BuildIcons.cjs +44 -0
- package/lib/ui/Common.js +210 -0
- package/lib/ui/Components.jsx +342 -0
- package/lib/ui/Observers.js +449 -0
- package/lib/ui/PlayerProfileForm.jsx +106 -0
- package/lib/ui/PlayerUI.jsx +316 -0
- package/lib/ui/TVControls.jsx +337 -0
- package/lib/ui/TicketForm.jsx +147 -0
- package/lib/ui/WebControls.jsx +290 -0
- package/package.json +35 -47
- package/dist/index-88AgCVwU.js +0 -367
- package/src/BuildIcons.js +0 -27
- package/src/PlayerControls.js +0 -1478
- package/src/index.js +0 -1416
- package/src/static/icons/Icons.js +0 -15
- package/src/static/icons/Settings icon.svg +0 -4
- package/src/static/icons/chat icon collapse.svg +0 -1
- package/src/static/icons/chat icon.svg +0 -11
- package/src/static/icons/chat send.svg +0 -1
- package/src/static/icons/full screen.svg +0 -1
- package/src/static/icons/media/LargePlayIcon.svg +0 -4
- package/src/static/icons/media/Settings icon.svg +0 -4
- package/src/static/icons/media/Skip backward icon.svg +0 -4
- package/src/static/icons/media/list.svg +0 -1
- package/src/static/icons/media/loop icon.svg +0 -12
- package/src/static/icons/media/shuffle icon.svg +0 -13
- package/src/static/icons/muted.svg +0 -11
- package/src/static/icons/pause.svg +0 -1
- package/src/static/icons/play circle.svg +0 -1
- package/src/static/icons/play.svg +0 -1
- package/src/static/icons/settings.svg +0 -1
- package/src/static/icons/slider circle.svg +0 -1
- package/src/static/icons/unmuted.svg +0 -10
- package/src/static/images/ELUV.IO logo embed player.png +0 -0
- package/src/static/images/ELUV.IO logo embed player.svg +0 -1
- package/src/static/images/ELUVIO white.svg +0 -26
- package/src/static/images/Logo.png +0 -0
- package/src/static/stylesheets/player.scss +0 -1065
- package/webpack.config.js +0 -152
- /package/{src/static/icons → lib/static/icons/svgs}/arrow-left.svg +0 -0
- /package/{src/static/icons/live icon.svg → lib/static/icons/svgs/live.svg} +0 -0
- /package/{src/static/icons → lib/static/icons/svgs}/multiview.svg +0 -0
- /package/{src/static/icons/media → lib/static/icons/svgs}/next.svg +0 -0
- /package/{src/static/icons/media → lib/static/icons/svgs}/previous.svg +0 -0
- /package/{src/static/icons → lib/static/icons/svgs}/x.svg +0 -0
- /package/{src/static/images/ELUV.IO white 20 px V2.png → lib/static/images/Logo.png} +0 -0
|
@@ -0,0 +1,912 @@
|
|
|
1
|
+
import {Utils} from "@eluvio/elv-client-js";
|
|
2
|
+
|
|
3
|
+
const PlayerProfiles = {
|
|
4
|
+
default: {
|
|
5
|
+
label: "Default",
|
|
6
|
+
hlsSettings: Utils.HLSJSSettings({profile: "default"}),
|
|
7
|
+
},
|
|
8
|
+
low_latency: {
|
|
9
|
+
label: "Low Latency Live",
|
|
10
|
+
hlsSettings: Utils.HLSJSSettings({profile: "ll"})
|
|
11
|
+
},
|
|
12
|
+
ultra_low_latency: {
|
|
13
|
+
label: "Ultra Low Latency Live",
|
|
14
|
+
hlsSettings: Utils.HLSJSSettings({profile: "ull"})
|
|
15
|
+
},
|
|
16
|
+
custom: {
|
|
17
|
+
label: "Custom",
|
|
18
|
+
hlsSettings: {}
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The Eluvio Player has a full set of APIs to control the video and retrieve information about the current state. Access player controls via `player.controls`
|
|
24
|
+
*/
|
|
25
|
+
class PlayerControls {
|
|
26
|
+
constructor({player}) {
|
|
27
|
+
this.player = player;
|
|
28
|
+
this.visible = true;
|
|
29
|
+
this.allowRotation = true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Check if the player controls are currently visible (not auto-hidden)
|
|
34
|
+
*
|
|
35
|
+
* @methodGroup Controls
|
|
36
|
+
* @returns {boolean} - Whether or not the controls are visible
|
|
37
|
+
*/
|
|
38
|
+
IsVisible() {
|
|
39
|
+
return this.visible;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Check if the player has finished loading
|
|
44
|
+
*
|
|
45
|
+
* @methodGroup Playback
|
|
46
|
+
* @returns {boolean} - Whether or not the player has finished loading
|
|
47
|
+
*/
|
|
48
|
+
IsReady() {
|
|
49
|
+
return !this.player.loading;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Check if the video is currently playing
|
|
54
|
+
*
|
|
55
|
+
* @methodGroup Playback
|
|
56
|
+
* @returns {boolean} - Whether or not the video is currently playing
|
|
57
|
+
*/
|
|
58
|
+
IsPlaying() {
|
|
59
|
+
return !this.player.video.paused;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Check if video playback has been started since the content was loaded
|
|
64
|
+
*
|
|
65
|
+
* @methodGroup Playback
|
|
66
|
+
* @returns {boolean} - Whether or not playback has been started
|
|
67
|
+
*/
|
|
68
|
+
HasPlaybackStarted() {
|
|
69
|
+
return this.player.playbackStarted;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Play the video
|
|
74
|
+
*
|
|
75
|
+
* @methodGroup Playback
|
|
76
|
+
*
|
|
77
|
+
* @returns {boolean} - Whether or not the video was able to start playing. Browser autoplay policies may block video from playing without user interaction.
|
|
78
|
+
*/
|
|
79
|
+
async Play() {
|
|
80
|
+
return await this.player.__Play();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Pause the video
|
|
85
|
+
*
|
|
86
|
+
* @methodGroup Playback
|
|
87
|
+
*/
|
|
88
|
+
Pause() {
|
|
89
|
+
this.player.video.pause();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Play the video if not playing, otherwise pause the video
|
|
94
|
+
*
|
|
95
|
+
* @methodGroup Playback
|
|
96
|
+
* @returns {boolean} - False if the video was paused, true if playback was started
|
|
97
|
+
*/
|
|
98
|
+
TogglePlay() {
|
|
99
|
+
if(this.player.video.paused) {
|
|
100
|
+
this.Play();
|
|
101
|
+
return true;
|
|
102
|
+
} else {
|
|
103
|
+
this.Pause();
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Stop playback, return the seek position to the start, and reset 'playback started' to false
|
|
110
|
+
*
|
|
111
|
+
* @methodGroup Playback
|
|
112
|
+
*/
|
|
113
|
+
Stop() {
|
|
114
|
+
this.Pause();
|
|
115
|
+
this.Seek({time: 0});
|
|
116
|
+
this.player.playbackStarted = false;
|
|
117
|
+
|
|
118
|
+
this.player.__SettingsUpdate();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Retrieve the current time of the video
|
|
123
|
+
*
|
|
124
|
+
* @methodGroup Seek
|
|
125
|
+
*
|
|
126
|
+
* @returns {number} - The current time of the video
|
|
127
|
+
*/
|
|
128
|
+
GetCurrentTime() {
|
|
129
|
+
return this.player.video.currentTime;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Retrieve the duration of the video
|
|
134
|
+
*
|
|
135
|
+
* @methodGroup Seek
|
|
136
|
+
*
|
|
137
|
+
* @returns {number} - The duration of the video. May be Infinity if content is live
|
|
138
|
+
*/
|
|
139
|
+
GetDuration() {
|
|
140
|
+
return this.player.video.duration;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Seek the video to the specified time
|
|
145
|
+
*
|
|
146
|
+
* @methodGroup Seek
|
|
147
|
+
* @namedParams
|
|
148
|
+
* @param {number=} time - Seek to the specified time
|
|
149
|
+
* @param {number=} relativeSeconds- Seek relative to the current time, e.g. `10` to skip 10 seconds ahead, or `-30` for 30 seconds back
|
|
150
|
+
* @param {number=} fraction - Specify a fraction of the video to seek to, e.g. `0.5` for the halfway point
|
|
151
|
+
*
|
|
152
|
+
* @returns {boolean} - False if the video was paused, true if playback was started
|
|
153
|
+
*/
|
|
154
|
+
Seek({fraction, time, relativeSeconds}) {
|
|
155
|
+
if(!this.player.video || (fraction && !this.player.video.duration)) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const originalTime = this.player.video.currentTime;
|
|
160
|
+
|
|
161
|
+
if(relativeSeconds) {
|
|
162
|
+
this.player.video.currentTime = Math.max(
|
|
163
|
+
0,
|
|
164
|
+
Math.min(
|
|
165
|
+
this.player.video.duration,
|
|
166
|
+
this.player.video.currentTime + relativeSeconds
|
|
167
|
+
)
|
|
168
|
+
);
|
|
169
|
+
} else if(typeof fraction !== "undefined") {
|
|
170
|
+
this.player.video.currentTime = this.player.video.duration * fraction;
|
|
171
|
+
} else {
|
|
172
|
+
this.player.video.currentTime = time;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return originalTime <= this.player.video.currentTime;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Retrieve the current volume of the video. Note that if the video is muted, this value may still be > 0
|
|
180
|
+
*
|
|
181
|
+
* @methodGroup Volume
|
|
182
|
+
*
|
|
183
|
+
* @returns {number} - The current volume of the video
|
|
184
|
+
*/
|
|
185
|
+
GetVolume() {
|
|
186
|
+
return this.player.video.volume;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Set the video volume
|
|
191
|
+
*
|
|
192
|
+
* @methodGroup Volume
|
|
193
|
+
* @namedParams
|
|
194
|
+
* @param {number=} fraction - Set the volume to the specified amount - `0` for muted, `1` for for volume
|
|
195
|
+
* @param {number=} relativeFraction - Adjust the volume by the specified fraction, e.g. `0.1` for +10%
|
|
196
|
+
*
|
|
197
|
+
* @returns {boolean} - The resulting volume of the video
|
|
198
|
+
*/
|
|
199
|
+
SetVolume({fraction, relativeFraction}) {
|
|
200
|
+
if(relativeFraction) {
|
|
201
|
+
this.player.video.volume = Math.min(1, Math.max(0, this.GetVolume() + relativeFraction));
|
|
202
|
+
} else {
|
|
203
|
+
this.player.video.volume = fraction;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if(this.player.video.volume > 0) {
|
|
207
|
+
this.Unmute(false);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return this.player.video.volume;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Retrieve whether or not the video is currently muted
|
|
215
|
+
*
|
|
216
|
+
* @methodGroup Volume
|
|
217
|
+
*
|
|
218
|
+
* @returns {boolean} - Whether or not the video is currently muted
|
|
219
|
+
*/
|
|
220
|
+
IsMuted() {
|
|
221
|
+
return this.player.video.muted;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Mute the video
|
|
226
|
+
*
|
|
227
|
+
* @methodGroup Volume
|
|
228
|
+
*/
|
|
229
|
+
Mute() {
|
|
230
|
+
this.player.video.muted = true;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Unmute the video
|
|
235
|
+
*
|
|
236
|
+
* @methodGroup Volume
|
|
237
|
+
*/
|
|
238
|
+
Unmute() {
|
|
239
|
+
this.player.video.muted = false;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Toggle whether or not the video is muted
|
|
244
|
+
*
|
|
245
|
+
* @methodGroup Volume
|
|
246
|
+
*
|
|
247
|
+
* @returns {boolean} - True if the video was muted, false if unmuted
|
|
248
|
+
*/
|
|
249
|
+
ToggleMuted() {
|
|
250
|
+
this.player.video.muted = !this.player.video.muted;
|
|
251
|
+
return this.player.video.muted;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Retrieve whether or not the player is currently fullscreen
|
|
256
|
+
*
|
|
257
|
+
* @methodGroup Fullscreen
|
|
258
|
+
*
|
|
259
|
+
* @returns {boolean} - Whether or not the player is currently fullscreen
|
|
260
|
+
*/
|
|
261
|
+
IsFullscreen() {
|
|
262
|
+
return (
|
|
263
|
+
document.fullscreenElement ||
|
|
264
|
+
document.mozFullScreenElement ||
|
|
265
|
+
document.webkitFullscreenElement ||
|
|
266
|
+
document.msFullscreenElement
|
|
267
|
+
) === this.player.target;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Request the player go fullscreen
|
|
272
|
+
*
|
|
273
|
+
* @methodGroup Fullscreen
|
|
274
|
+
*/
|
|
275
|
+
Fullscreen() {
|
|
276
|
+
if(this.player.target.requestFullscreen) {
|
|
277
|
+
this.player.target.requestFullscreen({navigationUI: "hide"});
|
|
278
|
+
} else if(this.player.target.mozRequestFullScreen) {
|
|
279
|
+
this.player.target.mozRequestFullScreen({navigationUI: "hide"});
|
|
280
|
+
} else if(this.player.target.webkitRequestFullscreen) {
|
|
281
|
+
this.player.target.webkitRequestFullscreen({navigationUI: "hide"});
|
|
282
|
+
} else if(this.player.target.msRequestFullscreen) {
|
|
283
|
+
this.player.target.msRequestFullscreen({navigationUI: "hide"});
|
|
284
|
+
} else {
|
|
285
|
+
// iPhone - Use native fullscreen on video element only
|
|
286
|
+
this.player.target.querySelector("video").webkitEnterFullScreen();
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Exit fullscreen
|
|
292
|
+
*
|
|
293
|
+
* @methodGroup Fullscreen
|
|
294
|
+
*/
|
|
295
|
+
ExitFullscreen() {
|
|
296
|
+
if(document.exitFullscreen) {
|
|
297
|
+
document.exitFullscreen();
|
|
298
|
+
} else if(document.webkitExitFullscreen) {
|
|
299
|
+
document.webkitExitFullscreen();
|
|
300
|
+
} else if(document.mozCancelFullScreen) {
|
|
301
|
+
document.mozCancelFullScreen();
|
|
302
|
+
} else if(document.msExitFullscreen) {
|
|
303
|
+
document.msExitFullscreen();
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Request the player go fullscreen if not currently, otherwise exit fullscreen
|
|
309
|
+
*
|
|
310
|
+
* @methodGroup Fullscreen
|
|
311
|
+
*
|
|
312
|
+
* @returns {boolean} - True if fullscreen video was requested, false if fullscreen was exited
|
|
313
|
+
*/
|
|
314
|
+
ToggleFullscreen() {
|
|
315
|
+
if(this.IsFullscreen()) {
|
|
316
|
+
this.ExitFullscreen();
|
|
317
|
+
return false;
|
|
318
|
+
} else {
|
|
319
|
+
this.Fullscreen();
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Collections
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Retrieve info about the current collection
|
|
328
|
+
*
|
|
329
|
+
* @methodGroup Collections
|
|
330
|
+
*
|
|
331
|
+
* @returns {Object | undefined} - Info about the current collection if present, undefined if no collection is present
|
|
332
|
+
*/
|
|
333
|
+
GetCollectionInfo() {
|
|
334
|
+
if(!this.player.collectionInfo) { return; }
|
|
335
|
+
|
|
336
|
+
const collectionInfo = {...this.player.collectionInfo };
|
|
337
|
+
collectionInfo.content = collectionInfo.content.map(content => ({
|
|
338
|
+
...content,
|
|
339
|
+
active: content.mediaIndex === collectionInfo.mediaIndex
|
|
340
|
+
}));
|
|
341
|
+
|
|
342
|
+
collectionInfo.active = collectionInfo.content[collectionInfo.mediaIndex];
|
|
343
|
+
|
|
344
|
+
return collectionInfo;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Play the specified collection item
|
|
349
|
+
*
|
|
350
|
+
* @methodGroup Collections
|
|
351
|
+
* @namedParams
|
|
352
|
+
* @param {number=} mediaIndex - Specify a collection item by its index in the collection
|
|
353
|
+
* @param {string=} mediaId - Specify a collection item by its ID
|
|
354
|
+
* @param {boolean=} autoplay - Whether or not the video should automatically start playing when the collection item starts. If omitted, autoplay state will depend on whether the video is currently playing.
|
|
355
|
+
*/
|
|
356
|
+
CollectionPlay({mediaIndex, mediaId, autoplay}) {
|
|
357
|
+
if(this.player.loading) { return; }
|
|
358
|
+
|
|
359
|
+
this.player.__CollectionPlay({mediaId, mediaIndex, autoplay});
|
|
360
|
+
|
|
361
|
+
this.player.__SettingsUpdate();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Play the next item in the collection, if present
|
|
366
|
+
*
|
|
367
|
+
* @methodGroup Collections
|
|
368
|
+
* @namedParams
|
|
369
|
+
* @param {boolean=} autoplay - Whether or not the video should automatically start playing when the collection item starts. If omitted, autoplay state will depend on whether the video is currently playing.
|
|
370
|
+
*/
|
|
371
|
+
CollectionPlayNext({autoplay}={}) {
|
|
372
|
+
const collectionInfo = this.GetCollectionInfo();
|
|
373
|
+
|
|
374
|
+
if(!collectionInfo) { return; }
|
|
375
|
+
|
|
376
|
+
const nextIndex = Math.min(collectionInfo.mediaIndex + 1, collectionInfo.mediaLength - 1);
|
|
377
|
+
|
|
378
|
+
if(nextIndex === collectionInfo.mediaIndex) { return; }
|
|
379
|
+
|
|
380
|
+
this.CollectionPlay({mediaIndex: nextIndex, autoplay});
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Play the previous item in the collection, if present
|
|
385
|
+
*
|
|
386
|
+
* @methodGroup Collections
|
|
387
|
+
* @namedParams
|
|
388
|
+
* @param {boolean=} autoplay - Whether or not the video should automatically start playing when the collection item starts. If omitted, autoplay state will depend on whether the video is currently playing.
|
|
389
|
+
*/
|
|
390
|
+
CollectionPlayPrevious({autoplay}={}) {
|
|
391
|
+
const collectionInfo = this.GetCollectionInfo();
|
|
392
|
+
|
|
393
|
+
if(!collectionInfo) { return; }
|
|
394
|
+
|
|
395
|
+
const previousIndex = Math.max(0, collectionInfo.mediaIndex - 1);
|
|
396
|
+
|
|
397
|
+
if(previousIndex === collectionInfo.mediaIndex) { return; }
|
|
398
|
+
|
|
399
|
+
this.CollectionPlay({mediaIndex: previousIndex, autoplay});
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Content
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Retrieve whether or not the current content is a live video
|
|
406
|
+
*
|
|
407
|
+
* @methodGroup Content Info
|
|
408
|
+
*
|
|
409
|
+
* @returns {boolean} - Whether or not the current content is a live video
|
|
410
|
+
*/
|
|
411
|
+
IsLive() {
|
|
412
|
+
return this.player.isLive;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Retrieve information about the current content, including title, description, icon and poster images, and header texts
|
|
417
|
+
*
|
|
418
|
+
* @methodGroup Content Info
|
|
419
|
+
*
|
|
420
|
+
* @returns {Object} - Information about the current content
|
|
421
|
+
*/
|
|
422
|
+
GetContentInfo() {
|
|
423
|
+
if(this.player.playerOptions.title !== false) {
|
|
424
|
+
const collectionInfo = this.GetCollectionInfo();
|
|
425
|
+
if(collectionInfo && collectionInfo.active) {
|
|
426
|
+
return {
|
|
427
|
+
title: collectionInfo.active.title || "",
|
|
428
|
+
subtitle: collectionInfo.active.title || "",
|
|
429
|
+
description: collectionInfo.active.description || "",
|
|
430
|
+
image: (collectionInfo.active.image && collectionInfo.active.image.url) || "",
|
|
431
|
+
posterImage: (collectionInfo.active.poster_image && collectionInfo.active.poster_image.url) || "",
|
|
432
|
+
headers: collectionInfo.active.headers || []
|
|
433
|
+
};
|
|
434
|
+
} else if(this.player.sourceOptions.contentInfo) {
|
|
435
|
+
return {
|
|
436
|
+
title: this.player.sourceOptions.contentInfo.title,
|
|
437
|
+
subtitle: this.player.sourceOptions.contentInfo.subtitle,
|
|
438
|
+
description: this.player.sourceOptions.contentInfo.description,
|
|
439
|
+
image: this.player.sourceOptions.contentInfo.image,
|
|
440
|
+
posterImage: this.player.sourceOptions.contentInfo.posterImage,
|
|
441
|
+
headers: this.player.sourceOptions.contentInfo.headers || []
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Menu items
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Retrieve the currently available video quality levels
|
|
451
|
+
*
|
|
452
|
+
* @methodGroup Quality
|
|
453
|
+
*
|
|
454
|
+
* @returns {Object} - All options, as well as the active option.
|
|
455
|
+
*/
|
|
456
|
+
GetQualityLevels() {
|
|
457
|
+
let levels = [];
|
|
458
|
+
if(this.player.hlsPlayer) {
|
|
459
|
+
levels = this.player.hlsPlayer.levels
|
|
460
|
+
.map((level, index) => ({
|
|
461
|
+
index,
|
|
462
|
+
active: this.player.hlsPlayer.currentLevel === index && !this.player.hlsPlayer.autoLevelEnabled,
|
|
463
|
+
resolution: level.attrs.RESOLUTION,
|
|
464
|
+
bitrate: level.bitrate,
|
|
465
|
+
audioTrack: !level.videoCodec,
|
|
466
|
+
label:
|
|
467
|
+
level.audioTrack ?
|
|
468
|
+
`${level.bitrate / 1000}kbps` :
|
|
469
|
+
`${level.attrs.RESOLUTION} (${(level.bitrate / 1000 / 1000).toFixed(1)}Mbps)`,
|
|
470
|
+
activeLabel:
|
|
471
|
+
level.audioTrack ?
|
|
472
|
+
`${level.bitrate / 1000}kbps` :
|
|
473
|
+
`${level.attrs.RESOLUTION}`
|
|
474
|
+
}))
|
|
475
|
+
.sort((a, b) => a.bitrate < b.bitrate ? 1 : -1);
|
|
476
|
+
|
|
477
|
+
if(levels.length > 0) {
|
|
478
|
+
const activeLevel = levels.find(level => this.player.hlsPlayer.currentLevel === level.index);
|
|
479
|
+
levels.unshift({
|
|
480
|
+
index: -1,
|
|
481
|
+
label: "Auto",
|
|
482
|
+
activeLabel: activeLevel ? `Auto (${activeLevel.activeLabel})` : "Auto",
|
|
483
|
+
active: this.player.hlsPlayer.autoLevelEnabled
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
} else if(this.player.dashPlayer) {
|
|
487
|
+
levels = this.player.dashPlayer.getBitrateInfoListFor("video")
|
|
488
|
+
.map((level) => ({
|
|
489
|
+
index: level.qualityIndex,
|
|
490
|
+
active: level.qualityIndex === this.player.dashPlayer.getQualityFor("video"),
|
|
491
|
+
resolution: `${level.width}x${level.height}`,
|
|
492
|
+
bitrate: level.bitrate,
|
|
493
|
+
label: `${level.width}x${level.height} (${(level.bitrate / 1000 / 1000).toFixed(1)}Mbps)`,
|
|
494
|
+
activeLabel: `${level.width}x${level.height}`,
|
|
495
|
+
}))
|
|
496
|
+
.sort((a, b) => a.bitrate < b.bitrate ? 1 : -1);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
return {
|
|
500
|
+
options: levels,
|
|
501
|
+
active: levels.find(level => level.active)
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Set the video quality to the specified level
|
|
507
|
+
*
|
|
508
|
+
* @methodGroup Quality
|
|
509
|
+
*
|
|
510
|
+
* @param levelIndex - The index of the quality level to set
|
|
511
|
+
*/
|
|
512
|
+
SetQualityLevel(levelIndex) {
|
|
513
|
+
if(this.player.hlsPlayer) {
|
|
514
|
+
this.player.hlsPlayer.nextLevel = levelIndex;
|
|
515
|
+
this.player.hlsPlayer.streamController.immediateLevelSwitch();
|
|
516
|
+
} else if(this.player.dashPlayer) {
|
|
517
|
+
this.player.dashPlayer.setQualityFor("video", levelIndex);
|
|
518
|
+
this.player.dashPlayer.updateSettings({
|
|
519
|
+
streaming: {
|
|
520
|
+
trackSwitchMode: "alwaysReplace",
|
|
521
|
+
buffer: {
|
|
522
|
+
fastSwitchEnabled: true,
|
|
523
|
+
flushBufferAtTrackSwitch: true
|
|
524
|
+
},
|
|
525
|
+
abr: {
|
|
526
|
+
autoSwitchBitrate: {
|
|
527
|
+
video: levelIndex === -1
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
this.player.__SettingsUpdate();
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Retrieve the currently available audio tracks
|
|
539
|
+
*
|
|
540
|
+
* @methodGroup Audio Tracks
|
|
541
|
+
*
|
|
542
|
+
* @returns {Object} - All options, as well as the active option.
|
|
543
|
+
*/
|
|
544
|
+
GetAudioTracks() {
|
|
545
|
+
let tracks = [];
|
|
546
|
+
if(this.player.nativeHLS) {
|
|
547
|
+
tracks = Array.from(this.player.video.audioTracks).map(track => ({
|
|
548
|
+
index: track.id,
|
|
549
|
+
label: track.label || track.language,
|
|
550
|
+
active: track.enabled
|
|
551
|
+
}));
|
|
552
|
+
} else if(this.player.hlsPlayer) {
|
|
553
|
+
tracks = this.player.hlsPlayer.audioTracks.map(track => ({
|
|
554
|
+
index: track.id,
|
|
555
|
+
label: track.name,
|
|
556
|
+
active: track.id === this.player.hlsPlayer.audioTrack
|
|
557
|
+
}));
|
|
558
|
+
} else if(this.player.dashPlayer) {
|
|
559
|
+
tracks = this.player.dashPlayer.getTracksFor("audio").map(track => ({
|
|
560
|
+
index: track.index,
|
|
561
|
+
label: track.labels && track.labels.length > 0 ? track.labels[0].text : track.lang,
|
|
562
|
+
active: track.index === this.player.dashPlayer.getCurrentTrackFor("audio").index
|
|
563
|
+
}));
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
return {
|
|
567
|
+
options: tracks,
|
|
568
|
+
active: tracks.find(track => track.active)
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Set the audio track to the specified level
|
|
574
|
+
*
|
|
575
|
+
* @methodGroup Audio Tracks
|
|
576
|
+
*
|
|
577
|
+
* @param index - The index of the audio track to set
|
|
578
|
+
*/
|
|
579
|
+
SetAudioTrack(index) {
|
|
580
|
+
if(this.player.nativeHLS) {
|
|
581
|
+
Array.from(this.player.video.audioTracks).forEach(track =>
|
|
582
|
+
track.enabled = index.toString() === track.id
|
|
583
|
+
);
|
|
584
|
+
} else if(this.player.hlsPlayer) {
|
|
585
|
+
this.player.hlsPlayer.audioTrack = index;
|
|
586
|
+
this.player.hlsPlayer.streamController.immediateLevelSwitch();
|
|
587
|
+
} else if(this.player.dashPlayer) {
|
|
588
|
+
const track = this.player.dashPlayer.getTracksFor("audio").find(track => track.index === index);
|
|
589
|
+
this.player.dashPlayer.setCurrentTrack(track);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Retrieve the currently available text/subtitle tracks
|
|
595
|
+
*
|
|
596
|
+
* @methodGroup Text Tracks
|
|
597
|
+
*
|
|
598
|
+
* @returns {Object} - All options, as well as the active option.
|
|
599
|
+
*/
|
|
600
|
+
GetTextTracks() {
|
|
601
|
+
let tracks = [];
|
|
602
|
+
let activeTrackIndex;
|
|
603
|
+
if(this.player.nativeHLS || this.player.hlsPlayer) {
|
|
604
|
+
activeTrackIndex = Array.from(this.player.video.textTracks).findIndex(track => track.mode === "showing");
|
|
605
|
+
|
|
606
|
+
tracks = Array.from(this.player.video.textTracks).map((track, index) => ({
|
|
607
|
+
index,
|
|
608
|
+
label: track.label || track.language,
|
|
609
|
+
language: track.language,
|
|
610
|
+
active: track.mode === "showing"
|
|
611
|
+
}));
|
|
612
|
+
} else if(this.player.dashPlayer) {
|
|
613
|
+
activeTrackIndex = this.player.dashPlayer.getCurrentTextTrackIndex();
|
|
614
|
+
tracks = this.player.dashPlayer.getTracksFor("text").map((track, index) => ({
|
|
615
|
+
index,
|
|
616
|
+
label: track.labels && track.labels.length > 0 ? track.labels[0].text : track.lang,
|
|
617
|
+
language: track.lang,
|
|
618
|
+
active: index === activeTrackIndex
|
|
619
|
+
}));
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
if(tracks.length > 0) {
|
|
623
|
+
tracks.unshift({
|
|
624
|
+
index: -1,
|
|
625
|
+
label: "Disabled",
|
|
626
|
+
active: activeTrackIndex < 0
|
|
627
|
+
});
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
return {
|
|
631
|
+
options: tracks,
|
|
632
|
+
active: tracks.find(track => track.active)
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Set the text track to the specified track
|
|
638
|
+
*
|
|
639
|
+
* @methodGroup Text Tracks
|
|
640
|
+
*
|
|
641
|
+
* @param index - The index of the text track to set
|
|
642
|
+
*/
|
|
643
|
+
SetTextTrack(index) {
|
|
644
|
+
index = parseInt(index);
|
|
645
|
+
|
|
646
|
+
if(this.player.nativeHLS || this.player.hlsPlayer) {
|
|
647
|
+
const tracks = Array.from(this.player.video.textTracks);
|
|
648
|
+
tracks.map(track => track.mode = "disabled");
|
|
649
|
+
|
|
650
|
+
if(index >= 0) {
|
|
651
|
+
tracks[index].mode = "showing";
|
|
652
|
+
}
|
|
653
|
+
} else if(this.player.dashPlayer) {
|
|
654
|
+
this.player.dashPlayer.setTextTrack(parseInt(index));
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
if(index >= 0) {
|
|
658
|
+
this.__lastTextTrackIndex = index;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Toggle the last used or most appropriate text track on or off.
|
|
664
|
+
*
|
|
665
|
+
* The text track will be selected based on the following:
|
|
666
|
+
* - The most recently enabled track
|
|
667
|
+
* - The first track matching the user's specified language as specified in `navigator.languages` in priority order (e.g. if the navigator.languages specifies `["pt-br", "en"]`, a pt-br track will be selected if present, otherwise an en track will be selected)
|
|
668
|
+
* - If no appropriate language tracks are found, the first available text track
|
|
669
|
+
*
|
|
670
|
+
* @methodGroup Text Tracks
|
|
671
|
+
*
|
|
672
|
+
* @returns {boolean} - Whether the text track was enabled or disabled
|
|
673
|
+
*/
|
|
674
|
+
ToggleTextTrack() {
|
|
675
|
+
const {active, options} = this.GetTextTracks();
|
|
676
|
+
|
|
677
|
+
if(options.length === 0) { return; }
|
|
678
|
+
|
|
679
|
+
if(active && active.index >= 0) {
|
|
680
|
+
this.SetTextTrack(-1);
|
|
681
|
+
return false;
|
|
682
|
+
} else if(this.__lastTextTrackIndex >= 0) {
|
|
683
|
+
this.SetTextTrack(this.__lastTextTrackIndex);
|
|
684
|
+
return true;
|
|
685
|
+
} else {
|
|
686
|
+
// Try to find a text track that matches one of the user's languages
|
|
687
|
+
for(const languageCode of navigator.languages) {
|
|
688
|
+
const matchingTrack = options.find(option => option.language === languageCode || option.language === languageCode.split("-")[0]);
|
|
689
|
+
|
|
690
|
+
if(matchingTrack) {
|
|
691
|
+
this.SetTextTrack(matchingTrack.index);
|
|
692
|
+
return true;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// No matching tracks found, just enable first in list
|
|
697
|
+
this.SetTextTrack(0);
|
|
698
|
+
return true;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* Retrieve the currently available playback rates
|
|
704
|
+
*
|
|
705
|
+
* @methodGroup Playback Rate
|
|
706
|
+
*
|
|
707
|
+
* @returns {Object} - All options, as well as the active option.
|
|
708
|
+
*/
|
|
709
|
+
GetPlaybackRates() {
|
|
710
|
+
const options = ["0.25", "0.5", "0.75", "1", "1.25", "1.5", "1.75", "2"]
|
|
711
|
+
.map((speed, index) => ({
|
|
712
|
+
index,
|
|
713
|
+
rate: parseFloat(speed),
|
|
714
|
+
label: `${speed}x`,
|
|
715
|
+
active: this.player.video.playbackRate.toFixed(2) === parseFloat(speed).toFixed(2)
|
|
716
|
+
}));
|
|
717
|
+
|
|
718
|
+
let active = options.find(option => option.active);
|
|
719
|
+
|
|
720
|
+
if(!active) {
|
|
721
|
+
active = {
|
|
722
|
+
index: -1,
|
|
723
|
+
rate: this.player.video.playbackRate,
|
|
724
|
+
label: `${this.player.video.playbackRate}x`,
|
|
725
|
+
active: true
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
return {
|
|
730
|
+
options,
|
|
731
|
+
active
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Set the player's playback rate
|
|
737
|
+
*
|
|
738
|
+
* @methodGroup Playback Rate
|
|
739
|
+
* @namedParams
|
|
740
|
+
* @param {number=} index - The index of the rate in the options list of `player.controls.GetPlaybackRates()`
|
|
741
|
+
* @param {number=} rate - The playback rate to set. Does not need to match any options in `player.controls.GetPlaybackRates()`
|
|
742
|
+
*
|
|
743
|
+
* @returns {Object} - The rate that was set, as well as whether the rate was increased or decreased
|
|
744
|
+
*/
|
|
745
|
+
SetPlaybackRate({index, rate}) {
|
|
746
|
+
const originalSpeed = this.player.video.playbackRate;
|
|
747
|
+
|
|
748
|
+
if(rate) {
|
|
749
|
+
this.player.video.playbackRate = rate;
|
|
750
|
+
|
|
751
|
+
this.player.__SettingsUpdate();
|
|
752
|
+
|
|
753
|
+
return { rate, increase: originalSpeed <= rate };
|
|
754
|
+
} else {
|
|
755
|
+
const option = this.GetPlaybackRates().options[index];
|
|
756
|
+
|
|
757
|
+
if(option) {
|
|
758
|
+
this.player.video.playbackRate = option.rate;
|
|
759
|
+
|
|
760
|
+
this.player.__SettingsUpdate();
|
|
761
|
+
|
|
762
|
+
return { rate: option.rate, increase: originalSpeed <= option.rate };
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* Retrieve the currently available player profiles
|
|
769
|
+
*
|
|
770
|
+
* @methodGroup Player Profile
|
|
771
|
+
*
|
|
772
|
+
* @returns {Object} - All options, as well as the active option.
|
|
773
|
+
*/
|
|
774
|
+
GetPlayerProfiles() {
|
|
775
|
+
let options = [];
|
|
776
|
+
if(this.player.hlsPlayer) {
|
|
777
|
+
options = Object.keys(PlayerProfiles)
|
|
778
|
+
.map(key => ({
|
|
779
|
+
index: key,
|
|
780
|
+
label: PlayerProfiles[key].label,
|
|
781
|
+
active: this.player.playerOptions.playerProfile === key,
|
|
782
|
+
}));
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
return {
|
|
786
|
+
options,
|
|
787
|
+
active: options.find(option => option.active)
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* Set the player profile
|
|
793
|
+
*
|
|
794
|
+
* @methodGroup Player Profile
|
|
795
|
+
* @namedParams
|
|
796
|
+
* @param {string} profile - The name of the profile to set
|
|
797
|
+
* @param {Object=} customOptions - If using a custom profile, custom player options to set
|
|
798
|
+
*/
|
|
799
|
+
SetPlayerProfile({profile, customOptions={}}) {
|
|
800
|
+
this.player.SetPlayerProfile({profile, customHLSOptions: customOptions});
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
/**
|
|
804
|
+
* Show the custom player profile form
|
|
805
|
+
*
|
|
806
|
+
* @methodGroup Player Profile
|
|
807
|
+
*/
|
|
808
|
+
ShowPlayerProfileForm() {
|
|
809
|
+
this.player.__showPlayerProfileForm = true;
|
|
810
|
+
this.player.__SettingsUpdate();
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
/**
|
|
814
|
+
* Hide the custom player profile form
|
|
815
|
+
*
|
|
816
|
+
* @methodGroup Player Profile
|
|
817
|
+
*/
|
|
818
|
+
HidePlayerProfileForm() {
|
|
819
|
+
this.player.__showPlayerProfileForm = false;
|
|
820
|
+
this.player.__SettingsUpdate();
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
GetOptions() {
|
|
824
|
+
let options = {
|
|
825
|
+
quality: this.GetQualityLevels(),
|
|
826
|
+
audio: this.GetAudioTracks(),
|
|
827
|
+
text: this.GetTextTracks(),
|
|
828
|
+
profile: this.GetPlayerProfiles(),
|
|
829
|
+
rate: this.GetPlaybackRates()
|
|
830
|
+
};
|
|
831
|
+
|
|
832
|
+
options.hasQualityOptions = options.quality.options.length > 0;
|
|
833
|
+
options.hasAudioOptions = options.audio.options.length > 0;
|
|
834
|
+
options.hasTextOptions = options.text.options.length > 0;
|
|
835
|
+
options.hasProfileOptons = options.profile.options.length > 0;
|
|
836
|
+
options.hasRateOptions = !this.IsLive();
|
|
837
|
+
|
|
838
|
+
options.hasAnyOptions =
|
|
839
|
+
options.hasQualityOptions ||
|
|
840
|
+
options.hasAudioOptions ||
|
|
841
|
+
options.hasTextOptions ||
|
|
842
|
+
options.hasProfileOptons ||
|
|
843
|
+
options.hasRateOptions;
|
|
844
|
+
|
|
845
|
+
return options;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
AllowRotation() {
|
|
849
|
+
return this.allowRotation;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
SetAllowRotation(allowRotation) {
|
|
853
|
+
this.allowRotation = allowRotation;
|
|
854
|
+
|
|
855
|
+
this.player.__SettingsUpdate();
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
IsRotatable() {
|
|
859
|
+
return (
|
|
860
|
+
this.IsFullscreen() &&
|
|
861
|
+
window.innerHeight > window.innerWidth &&
|
|
862
|
+
this.player.video.videoWidth > this.player.video.videoHeight
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
/**
|
|
867
|
+
* Register a listener for a <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#events" target="_blank">standard HTML video event on the player's video element.
|
|
868
|
+
*
|
|
869
|
+
* Equivalent to `video.addEventListener(event, callback)`, but returns a disposal function that can be used to remove the listener
|
|
870
|
+
*
|
|
871
|
+
* @methodGroup Events
|
|
872
|
+
* @param event - HTML video event name
|
|
873
|
+
* @param callback - Event callback
|
|
874
|
+
*
|
|
875
|
+
* @returns {function} - A disposal function that, when called, will remove the listener
|
|
876
|
+
*/
|
|
877
|
+
RegisterVideoEventListener(event, callback) {
|
|
878
|
+
return this.player.__RegisterVideoEventListener(event, callback);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
/**
|
|
882
|
+
* Register a listener to be called when player state changes. State includes controls visibility, play/pause state, manual quality/audio/subtitle/playback speed changes, track changes
|
|
883
|
+
*
|
|
884
|
+
* @methodGroup Events
|
|
885
|
+
* @param callback - Settings update callback
|
|
886
|
+
*
|
|
887
|
+
* @returns {function} - A disposal function that, when called, will remove the listener
|
|
888
|
+
*/
|
|
889
|
+
RegisterSettingsListener(callback) {
|
|
890
|
+
return this.player.__RegisterSettingsListener(callback);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
/**
|
|
894
|
+
* Fully reset the player to its initial state
|
|
895
|
+
*
|
|
896
|
+
* @methodGroup Constructor
|
|
897
|
+
*/
|
|
898
|
+
Reset() {
|
|
899
|
+
this.player.Reset();
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
/**
|
|
903
|
+
* Stop playback and fully remove the player.
|
|
904
|
+
*
|
|
905
|
+
* @methodGroup Constructor
|
|
906
|
+
*/
|
|
907
|
+
Destroy() {
|
|
908
|
+
this.player.Destroy();
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
export default PlayerControls;
|