@eluvio/elv-player-js 1.0.140 → 2.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 +35 -6
- package/dist/.vite/manifest.json +67 -0
- package/dist/Analytics-HWXR7tWt.mjs +2028 -0
- package/dist/Analytics-IUVysdzU.js +29 -0
- package/dist/dash.all.min-1QS9Xbir.js +25 -0
- package/dist/dash.all.min-9V1xYBRv.mjs +19428 -0
- package/dist/elv-player-js.cjs.js +1 -0
- package/dist/elv-player-js.css +1 -0
- package/dist/elv-player-js.es.js +5 -0
- package/dist/hls-1eCRapWm.mjs +15461 -0
- package/dist/hls-6O5SV1FQ.js +26 -0
- package/dist/index-6cMQneJf.mjs +2273 -0
- package/dist/index-C8mwW09z.js +23 -0
- package/dist/index-J4QpmTkA.js +367 -0
- package/dist/index-hvQzQ6UX.mjs +67432 -0
- package/lib/index.js +7 -0
- package/{src → lib/player}/Analytics.js +9 -8
- package/lib/player/Controls.js +913 -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 +317 -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.js +0 -2
- package/dist/index.js.LICENSE.txt +0 -80
- package/src/BuildIcons.js +0 -27
- package/src/PlayerControls.js +0 -1478
- package/src/index.js +0 -1417
- 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/ELUV.IO white 20 px V2.png +0 -0
- 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/{dist/5897e28fa3e8ac0a2fae.png → lib/static/images/Logo.png} +0 -0
|
@@ -0,0 +1,881 @@
|
|
|
1
|
+
import EluvioPlayerParameters from "./PlayerParameters.js";
|
|
2
|
+
import {InitializeFairPlayStream} from "./FairPlay.js";
|
|
3
|
+
|
|
4
|
+
import {Utils} from "@eluvio/elv-client-js";
|
|
5
|
+
import PlayerControls from "./Controls.js";
|
|
6
|
+
import {MergeDefaultParameters} from "../ui/Common";
|
|
7
|
+
|
|
8
|
+
const PlayerProfiles = {
|
|
9
|
+
default: {
|
|
10
|
+
label: "Default",
|
|
11
|
+
hlsSettings: Utils.HLSJSSettings({profile: "default"}),
|
|
12
|
+
},
|
|
13
|
+
low_latency: {
|
|
14
|
+
label: "Low Latency Live",
|
|
15
|
+
hlsSettings: Utils.HLSJSSettings({profile: "ll"})
|
|
16
|
+
},
|
|
17
|
+
ultra_low_latency: {
|
|
18
|
+
label: "Ultra Low Latency Live",
|
|
19
|
+
hlsSettings: Utils.HLSJSSettings({profile: "ull"})
|
|
20
|
+
},
|
|
21
|
+
custom: {
|
|
22
|
+
label: "Custom",
|
|
23
|
+
hlsSettings: {}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export class EluvioPlayer {
|
|
28
|
+
// Register a listener for the specified video element event
|
|
29
|
+
__RegisterVideoEventListener(event, callback) {
|
|
30
|
+
this.video.addEventListener(event, callback);
|
|
31
|
+
|
|
32
|
+
this.__listenerDisposers.push(() => this.video.removeEventListener(event, callback));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Register a listener that will be called any time the video settings have changed
|
|
36
|
+
__RegisterSettingsListener(listener) {
|
|
37
|
+
this.__settingsListeners.push(listener);
|
|
38
|
+
|
|
39
|
+
return () => this.__settingsListeners = this.__settingsListeners.filter(l => l !== listener);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
constructor({target, video, parameters, SetErrorMessage}) {
|
|
43
|
+
this.loading = true;
|
|
44
|
+
this.target = target;
|
|
45
|
+
this.video = video;
|
|
46
|
+
this.SetErrorMessage = SetErrorMessage;
|
|
47
|
+
this.controls = new PlayerControls({player: this});
|
|
48
|
+
this.__settingsListeners = [];
|
|
49
|
+
this.__listenerDisposers = [];
|
|
50
|
+
this.__showPlayerProfileForm = false;
|
|
51
|
+
this.playbackStarted = false;
|
|
52
|
+
this.reloads = 0;
|
|
53
|
+
this.canPlay = false;
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
// If custom HLS parameters are specified, set profile to custom
|
|
57
|
+
if(
|
|
58
|
+
parameters.playerOptions.hlsjsOptions &&
|
|
59
|
+
Object.keys(parameters.playerOptions.hlsjsOptions).length > 0
|
|
60
|
+
) {
|
|
61
|
+
this.customHLSOptions = parameters.playerOptions.hlsjsOptions;
|
|
62
|
+
parameters.playerOptions.playerProfile = EluvioPlayerParameters.playerProfile.CUSTOM;
|
|
63
|
+
}
|
|
64
|
+
} catch (error) {
|
|
65
|
+
this.Log(error, true);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
this.__Initialize(parameters);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async __Client() {
|
|
72
|
+
if(this.clientPromise) {
|
|
73
|
+
await this.clientPromise;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if(!this.clientOptions.client) {
|
|
77
|
+
this.clientPromise = (async () => {
|
|
78
|
+
const {ElvClient} = await import("@eluvio/elv-client-js");
|
|
79
|
+
this.clientOptions.client = await ElvClient.FromConfigurationUrl({
|
|
80
|
+
configUrl: this.clientOptions.network
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
this.clientOptions.client.SetStaticToken({
|
|
84
|
+
token:
|
|
85
|
+
this.clientOptions.staticToken ||
|
|
86
|
+
this.clientOptions.client.utils.B64(JSON.stringify({qspace_id: await this.clientOptions.client.ContentSpaceId()}))
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return this.clientOptions.client;
|
|
90
|
+
})();
|
|
91
|
+
|
|
92
|
+
await this.clientPromise;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return this.clientOptions.client;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async __PlayoutOptions() {
|
|
99
|
+
const client = await this.__Client();
|
|
100
|
+
const playoutParameters = this.sourceOptions.playoutParameters || {};
|
|
101
|
+
|
|
102
|
+
if(this.collectionInfo) {
|
|
103
|
+
const activeMedia = this.collectionInfo.content[this.collectionInfo.mediaIndex];
|
|
104
|
+
playoutParameters.objectId = client.utils.DecodeVersionHash(activeMedia.mediaHash).objectId;
|
|
105
|
+
playoutParameters.versionHash = activeMedia.mediaHash;
|
|
106
|
+
this.sourceOptions.playoutOptions = undefined;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let offeringId, offeringURI, options = {};
|
|
110
|
+
if(playoutParameters.clipStart || playoutParameters.clipEnd) {
|
|
111
|
+
options.clip_start = parseFloat(playoutParameters.clipStart || 0);
|
|
112
|
+
|
|
113
|
+
if(playoutParameters.clipEnd) {
|
|
114
|
+
options.clip_end = parseFloat(playoutParameters.clipEnd);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
options.ignore_trimming = playoutParameters.ignoreTrimming;
|
|
119
|
+
options.resolve = playoutParameters.resolve;
|
|
120
|
+
|
|
121
|
+
if(playoutParameters.offering || playoutParameters.directLink || (playoutParameters.offerings || []).length > 0) {
|
|
122
|
+
let availableOfferings = (await client.AvailableOfferings({
|
|
123
|
+
objectId: playoutParameters.objectId,
|
|
124
|
+
versionHash: playoutParameters.versionHash,
|
|
125
|
+
writeToken: playoutParameters.writeToken,
|
|
126
|
+
linkPath: playoutParameters.linkPath,
|
|
127
|
+
directLink: playoutParameters.directLink,
|
|
128
|
+
resolveIncludeSource: true,
|
|
129
|
+
authorizationToken: playoutParameters.authorizationToken
|
|
130
|
+
})) || {};
|
|
131
|
+
|
|
132
|
+
offeringId = Object.keys(availableOfferings)[0];
|
|
133
|
+
if(playoutParameters.offering) {
|
|
134
|
+
offeringId = availableOfferings[playoutParameters.offering] ? playoutParameters.offering : undefined;
|
|
135
|
+
} else if((playoutParameters.offerings || []).length > 0) {
|
|
136
|
+
offeringId = playoutParameters.offerings.find(offeringId => availableOfferings[offeringId]);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if(!offeringId) {
|
|
140
|
+
throw new Error(`Unable to find offering from '${playoutParameters.offering || playoutParameters.offerings}'`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
offeringURI = availableOfferings[offeringId].uri;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if(playoutParameters.directLink) {
|
|
147
|
+
if(!this.sourceOptions.playoutOptions) {
|
|
148
|
+
this.sourceOptions.playoutOptions = await client.PlayoutOptions({
|
|
149
|
+
offeringURI,
|
|
150
|
+
options
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
} else {
|
|
154
|
+
if(!this.sourceOptions.playoutOptions) {
|
|
155
|
+
this.sourceOptions.playoutOptions = await client.PlayoutOptions({
|
|
156
|
+
...playoutParameters,
|
|
157
|
+
offering: offeringId,
|
|
158
|
+
options
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
let availableDRMs = (await client.AvailableDRMs()).filter(drm => (this.sourceOptions.drms || []).includes(drm));
|
|
164
|
+
let availableProtocols = this.sourceOptions.protocols;
|
|
165
|
+
|
|
166
|
+
let protocol, drm;
|
|
167
|
+
while(!(protocol && drm)) {
|
|
168
|
+
protocol = availableProtocols.find(protocol => this.sourceOptions.playoutOptions[protocol]);
|
|
169
|
+
drm = this.sourceOptions.drms.find(drm => availableDRMs.includes(drm) && this.sourceOptions.playoutOptions[protocol].playoutMethods[drm]);
|
|
170
|
+
|
|
171
|
+
if(!drm) {
|
|
172
|
+
availableProtocols = availableProtocols.filter(p => p !== protocol);
|
|
173
|
+
|
|
174
|
+
if(availableProtocols.length === 0) {
|
|
175
|
+
throw Error("No valid protocol / DRM combination available");
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const { playoutUrl, drms } = this.sourceOptions.playoutOptions[protocol].playoutMethods[drm];
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
protocol,
|
|
184
|
+
drm,
|
|
185
|
+
playoutUrl,
|
|
186
|
+
drms,
|
|
187
|
+
availableDRMs,
|
|
188
|
+
offeringURI,
|
|
189
|
+
offering: offeringId,
|
|
190
|
+
sessionId: this.sourceOptions.playoutOptions.sessionId,
|
|
191
|
+
multiviewOptions: {
|
|
192
|
+
enabled: this.sourceOptions.playoutOptions.multiview,
|
|
193
|
+
AvailableViews: this.sourceOptions.playoutOptions.AvailableViews,
|
|
194
|
+
SwitchView: this.sourceOptions.playoutOptions.SwitchView
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
__CollectionPlay({mediaIndex, mediaId, autoplay}) {
|
|
200
|
+
if(mediaId) {
|
|
201
|
+
mediaIndex = this.collectionInfo.content.find(media => media.id === mediaId);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this.collectionInfo.mediaIndex = mediaIndex;
|
|
205
|
+
|
|
206
|
+
this.__SettingsUpdate();
|
|
207
|
+
|
|
208
|
+
this.__Initialize(
|
|
209
|
+
this.originalParameters,
|
|
210
|
+
!this.video ? null :
|
|
211
|
+
{
|
|
212
|
+
muted: this.video.muted,
|
|
213
|
+
volume: this.video.volume,
|
|
214
|
+
playing: typeof autoplay !== "undefined" ? autoplay : !this.video.paused
|
|
215
|
+
}
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async __LoadCollection() {
|
|
220
|
+
if(this.collectionInfo) { return; }
|
|
221
|
+
|
|
222
|
+
let {mediaCatalogObjectId, mediaCatalogVersionHash, collectionId} = (this.sourceOptions && this.sourceOptions.mediaCollectionOptions) || {};
|
|
223
|
+
|
|
224
|
+
if(!collectionId) { return; }
|
|
225
|
+
|
|
226
|
+
if(!mediaCatalogObjectId && !mediaCatalogVersionHash) {
|
|
227
|
+
throw { displayMessage: "Invalid collection options: Media catalog not specified" };
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const client = await this.__Client();
|
|
231
|
+
|
|
232
|
+
try {
|
|
233
|
+
const authorizationToken = this.sourceOptions.playoutParameters.authorizationToken;
|
|
234
|
+
|
|
235
|
+
mediaCatalogVersionHash = mediaCatalogVersionHash || await client.LatestVersionHash({objectId: mediaCatalogObjectId});
|
|
236
|
+
const collections = (await client.ContentObjectMetadata({
|
|
237
|
+
versionHash: mediaCatalogVersionHash,
|
|
238
|
+
metadataSubtree: "public/asset_metadata/info/collections",
|
|
239
|
+
authorizationToken,
|
|
240
|
+
produceLinkUrls: true
|
|
241
|
+
})) || [];
|
|
242
|
+
|
|
243
|
+
const collectionInfo = collections.find(collection => collection.id === collectionId);
|
|
244
|
+
|
|
245
|
+
if(!collectionInfo) {
|
|
246
|
+
throw { displayMessage: `No collection with ID ${collectionId} found for media catalog ${mediaCatalogObjectId || mediaCatalogVersionHash}` };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
collectionInfo.content = collectionInfo.content
|
|
250
|
+
.filter(content => content.media)
|
|
251
|
+
.map((content, index) => ({
|
|
252
|
+
...content,
|
|
253
|
+
active: index === 0,
|
|
254
|
+
mediaId: content.id,
|
|
255
|
+
mediaIndex: index,
|
|
256
|
+
mediaHash: content.media && content.media["/"] && content.media["/"].split("/").find(segment => segment.startsWith("hq__"))
|
|
257
|
+
}));
|
|
258
|
+
|
|
259
|
+
this.collectionInfo = {
|
|
260
|
+
...collectionInfo,
|
|
261
|
+
isPlaylist: collectionInfo.type === "playlist",
|
|
262
|
+
mediaIndex: 0,
|
|
263
|
+
mediaLength: collectionInfo.content.length
|
|
264
|
+
};
|
|
265
|
+
} catch (error) {
|
|
266
|
+
this.Log("Failed to load collection:");
|
|
267
|
+
throw error;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async __Initialize(parameters, restartParameters) {
|
|
272
|
+
if(this.__destroyed) { return; }
|
|
273
|
+
|
|
274
|
+
this.__Reset();
|
|
275
|
+
|
|
276
|
+
this.loading = true;
|
|
277
|
+
this.initTime = Date.now();
|
|
278
|
+
|
|
279
|
+
this.__SettingsUpdate();
|
|
280
|
+
|
|
281
|
+
if(parameters) {
|
|
282
|
+
this.originalParameters = MergeDefaultParameters(parameters);
|
|
283
|
+
|
|
284
|
+
this.clientOptions = parameters.clientOptions;
|
|
285
|
+
this.sourceOptions = parameters.sourceOptions;
|
|
286
|
+
this.playerOptions = parameters.playerOptions;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
this.isLive = parameters.sourceOptions.contentInfo.type === EluvioPlayerParameters.type.LIVE;
|
|
290
|
+
|
|
291
|
+
this.errors = 0;
|
|
292
|
+
|
|
293
|
+
// Start client loading
|
|
294
|
+
this.__Client();
|
|
295
|
+
|
|
296
|
+
try {
|
|
297
|
+
if(restartParameters) {
|
|
298
|
+
this.video.volume = restartParameters.volume;
|
|
299
|
+
this.video.muted = restartParameters.muted;
|
|
300
|
+
|
|
301
|
+
if(restartParameters.playing) {
|
|
302
|
+
this.playerOptions.autoplay = EluvioPlayerParameters.autoplay.ON;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if(restartParameters.currentTime) {
|
|
306
|
+
this.__RegisterVideoEventListener(
|
|
307
|
+
"loadedmetadata",
|
|
308
|
+
() => this.video.currentTime = restartParameters.currentTime
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
this.__RegisterVideoEventListener("play", () => {
|
|
314
|
+
this.reloads = 0;
|
|
315
|
+
this.playbackStarted = true;
|
|
316
|
+
this.__SettingsUpdate();
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
const CheckIsLive = () => {
|
|
320
|
+
if(this.canPlay && !isFinite(this.video.duration)) {
|
|
321
|
+
this.isLive = true;
|
|
322
|
+
} else if(this.video.duration && this.videoDuration > 0 && Math.abs(this.video.duration - this.videoDuration) > 1) {
|
|
323
|
+
this.isLive = true;
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
this.__RegisterVideoEventListener("canplay", () => {
|
|
328
|
+
if(this.initTime && !this.initTimeLogged) {
|
|
329
|
+
this.Log(`Player initialization: ${((Date.now() - this.initTime) / 1000).toFixed(2)} seconds`);
|
|
330
|
+
this.initTimeLogged = true;
|
|
331
|
+
this.canPlay = true;
|
|
332
|
+
|
|
333
|
+
CheckIsLive();
|
|
334
|
+
|
|
335
|
+
if(this.playerOptions.autoplay === EluvioPlayerParameters.autoplay.ON) {
|
|
336
|
+
this.controls.Play();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
// Detect live video
|
|
342
|
+
this.__RegisterVideoEventListener("durationchange", () => {
|
|
343
|
+
CheckIsLive();
|
|
344
|
+
|
|
345
|
+
this.videoDuration = this.video.duration;
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// Load collection info, if present
|
|
349
|
+
await this.__LoadCollection();
|
|
350
|
+
|
|
351
|
+
if(this.collectionInfo && this.collectionInfo.isPlaylist && this.collectionInfo.mediaIndex < this.collectionInfo.mediaLength - 1) {
|
|
352
|
+
this.__RegisterVideoEventListener("ended", () => this.controls && this.controls.CollectionPlayNext({autoplay: true}));
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
let { protocol, drm, playoutUrl, drms, multiviewOptions } = await this.__PlayoutOptions();
|
|
356
|
+
|
|
357
|
+
//multiviewOptions.target = this.target;
|
|
358
|
+
|
|
359
|
+
playoutUrl = new URL(playoutUrl);
|
|
360
|
+
const authorizationToken =
|
|
361
|
+
this.sourceOptions.playoutParameters.authorizationToken ||
|
|
362
|
+
playoutUrl.searchParams.get("authorization");
|
|
363
|
+
|
|
364
|
+
if(this.__destroyed) { return; }
|
|
365
|
+
|
|
366
|
+
if(protocol === "hls") {
|
|
367
|
+
await this.__InitializeHLS({playoutUrl, authorizationToken, drm, drms, multiviewOptions});
|
|
368
|
+
} else {
|
|
369
|
+
await this.__InitializeDash({playoutUrl, authorizationToken, drm, drms, multiviewOptions});
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if(this.playerOptions.collectVideoAnalytics) {
|
|
373
|
+
import("./Analytics.js")
|
|
374
|
+
.then(({InitializeMuxMonitoring}) => InitializeMuxMonitoring({
|
|
375
|
+
appName: this.playerOptions.appName || "elv-player-js",
|
|
376
|
+
elvPlayer: this,
|
|
377
|
+
playoutUrl,
|
|
378
|
+
authorizationToken,
|
|
379
|
+
disableCookies: this.playerOptions.collectVideoAnalytics === EluvioPlayerParameters.collectVideoAnalytics.DISABLE_COOKIES
|
|
380
|
+
}));
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if(this.playerOptions.playerCallback) {
|
|
384
|
+
this.playerOptions.playerCallback({
|
|
385
|
+
player: this,
|
|
386
|
+
videoElement: this.video,
|
|
387
|
+
hlsPlayer: this.hlsPlayer,
|
|
388
|
+
dashPlayer: this.dashPlayer
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/* TODO: Account watermark
|
|
393
|
+
if(this.controls && this.playerOptions.accountWatermark) {
|
|
394
|
+
// Watermark
|
|
395
|
+
this.controls.InitializeAccountWatermark(
|
|
396
|
+
(await this.__Client()).CurrentAccountAddress()
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
*/
|
|
401
|
+
|
|
402
|
+
if(this.__destroyed) {
|
|
403
|
+
// If Destroy was called during the initialization process, ensure that the player is properly destroyed
|
|
404
|
+
this.__DestroyPlayer();
|
|
405
|
+
}
|
|
406
|
+
} catch (error) {
|
|
407
|
+
// If playout failed due to a permission issue, check the content to see if there is a message to display
|
|
408
|
+
let permissionErrorMessage;
|
|
409
|
+
if(error && [401, 403].includes(error.status) || [401, 403].includes(error.code)) {
|
|
410
|
+
try {
|
|
411
|
+
const client = await this.__Client();
|
|
412
|
+
|
|
413
|
+
const targetHash =
|
|
414
|
+
this.sourceOptions.playoutParameters.linkPath ?
|
|
415
|
+
await client.LinkTarget({...this.sourceOptions.playoutParameters}) :
|
|
416
|
+
this.sourceOptions.playoutParameters.versionHash ||
|
|
417
|
+
await client.LatestVersionHash({objectId: this.sourceOptions.playoutParameters.objectId});
|
|
418
|
+
|
|
419
|
+
permissionErrorMessage = await client.ContentObjectMetadata({
|
|
420
|
+
versionHash: targetHash,
|
|
421
|
+
metadataSubtree: "public/asset_metadata/permission_message",
|
|
422
|
+
authorizationToken: this.sourceOptions.playoutParameters.authorizationToken
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
if(permissionErrorMessage) {
|
|
426
|
+
error.permission_message = permissionErrorMessage;
|
|
427
|
+
this.SetErrorMessage(permissionErrorMessage);
|
|
428
|
+
|
|
429
|
+
if(typeof error === "object") {
|
|
430
|
+
error.permission_message = permissionErrorMessage;
|
|
431
|
+
} else {
|
|
432
|
+
this.Log(permissionErrorMessage, true);
|
|
433
|
+
}
|
|
434
|
+
} else {
|
|
435
|
+
this.SetErrorMessage(error.displayMessage || "Insufficient permissions");
|
|
436
|
+
}
|
|
437
|
+
// eslint-disable-next-line no-empty
|
|
438
|
+
} catch (error) {
|
|
439
|
+
this.SetErrorMessage(error.displayMessage || "Insufficient permissions");
|
|
440
|
+
}
|
|
441
|
+
} else if(error.status === 500) {
|
|
442
|
+
this.__HardReload(error, 10000);
|
|
443
|
+
} else {
|
|
444
|
+
this.SetErrorMessage(error.displayMessage || "Something went wrong");
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if(this.playerOptions.errorCallback) {
|
|
448
|
+
this.playerOptions.errorCallback(error, this);
|
|
449
|
+
}
|
|
450
|
+
} finally {
|
|
451
|
+
this.loading = false;
|
|
452
|
+
this.__SettingsUpdate();
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
async __InitializeHLS({playoutUrl, authorizationToken, drm, multiviewOptions}) {
|
|
457
|
+
this.HLS = (await import("hls.js")).default;
|
|
458
|
+
|
|
459
|
+
if(["fairplay", "sample-aes"].includes(drm) || !this.HLS.isSupported()) {
|
|
460
|
+
// HLS JS NOT SUPPORTED - Handle native player
|
|
461
|
+
this.nativeHLS = true;
|
|
462
|
+
|
|
463
|
+
if(drm === "fairplay") {
|
|
464
|
+
InitializeFairPlayStream({playoutOptions: this.sourceOptions.playoutOptions, video: this.video});
|
|
465
|
+
} else {
|
|
466
|
+
this.video.src = playoutUrl.toString();
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if(multiviewOptions.enabled) {
|
|
470
|
+
const Switch = multiviewOptions.SwitchView;
|
|
471
|
+
|
|
472
|
+
multiviewOptions.SwitchView = async (view) => {
|
|
473
|
+
await Switch(view);
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
/* TODO: Init multiview
|
|
477
|
+
if(this.controls) {
|
|
478
|
+
this.controls.InitializeMultiViewControls(multiviewOptions);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
*/
|
|
482
|
+
}
|
|
483
|
+
} else {
|
|
484
|
+
// HLS JS
|
|
485
|
+
playoutUrl.searchParams.delete("authorization");
|
|
486
|
+
|
|
487
|
+
const profileSettings = (PlayerProfiles[this.playerOptions.playerProfile] || {}).hlsSettings || {};
|
|
488
|
+
const customProfileSettings = this.playerOptions.playerProfile === EluvioPlayerParameters.playerProfile.CUSTOM ? this.customHLSOptions : {};
|
|
489
|
+
|
|
490
|
+
this.hlsOptions = {
|
|
491
|
+
capLevelToPlayerSize: this.playerOptions.capLevelToPlayerSize,
|
|
492
|
+
...profileSettings,
|
|
493
|
+
...customProfileSettings
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
const hlsPlayer = new this.HLS({
|
|
497
|
+
xhrSetup: xhr => {
|
|
498
|
+
xhr.setRequestHeader("Authorization", `Bearer ${authorizationToken}`);
|
|
499
|
+
|
|
500
|
+
if((this.playerOptions.hlsjsOptions || {}).xhrSetup) {
|
|
501
|
+
this.playerOptions.hlsjsOptions.xhrSetup(xhr);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
return xhr;
|
|
505
|
+
},
|
|
506
|
+
...this.hlsOptions
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
// Limit playback to maximum bitrate, if specified
|
|
510
|
+
if(this.playerOptions.maxBitrate) {
|
|
511
|
+
hlsPlayer.on(this.HLS.Events.MANIFEST_PARSED, (_, {levels, firstLevel}) => {
|
|
512
|
+
let levelsToRemove = levels
|
|
513
|
+
.map((level, i) => level.bitrate > this.playerOptions.maxBitrate ? i : undefined)
|
|
514
|
+
.filter(i => typeof i !== "undefined")
|
|
515
|
+
// Note: Remove levels from highest to lowest index
|
|
516
|
+
.reverse();
|
|
517
|
+
|
|
518
|
+
if(levelsToRemove.length === levels.length) {
|
|
519
|
+
this.Log(`Warning: Max bitrate '${this.playerOptions.maxBitrate}bps' is less than all available levels for this content.`);
|
|
520
|
+
// Keep first level
|
|
521
|
+
levelsToRemove = levelsToRemove.filter(i => i > 0);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
this.Log("Removing the following levels due to maxBitrate setting:");
|
|
525
|
+
this.Log(levelsToRemove.map(i => [levels[i].width, "x", levels[i].height, ` (${(levels[i].bitrate / 1000 / 1000).toFixed(1)}Mbps)`].join("")).join(", "));
|
|
526
|
+
|
|
527
|
+
if(levelsToRemove.find(i => firstLevel === i)) {
|
|
528
|
+
// Player will start on level that is being removed - switch to highest level that will not be removed
|
|
529
|
+
hlsPlayer.startLevel = levels.map((_, i) => i).filter(i => !levelsToRemove.includes(i)).reverse()[0];
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
levelsToRemove.map(i => hlsPlayer.removeLevel(i));
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
hlsPlayer.loadSource(playoutUrl.toString());
|
|
537
|
+
hlsPlayer.attachMedia(this.video);
|
|
538
|
+
|
|
539
|
+
if(this.controls && multiviewOptions.enabled) {
|
|
540
|
+
const Switch = multiviewOptions.SwitchView;
|
|
541
|
+
|
|
542
|
+
multiviewOptions.SwitchView = async (view) => {
|
|
543
|
+
await Switch(view);
|
|
544
|
+
hlsPlayer.nextLevel = hlsPlayer.currentLevel;
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
this.controls.InitializeMultiViewControls(multiviewOptions);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Keep track of relevant settings updates so the UI can react
|
|
551
|
+
[
|
|
552
|
+
this.HLS.Events.SUBTITLE_TRACKS_UPDATED,
|
|
553
|
+
this.HLS.Events.SUBTITLE_TRACK_SWITCH,
|
|
554
|
+
this.HLS.Events.LEVEL_UPDATED,
|
|
555
|
+
this.HLS.Events.LEVEL_SWITCHED,
|
|
556
|
+
this.HLS.Events.AUDIO_TRACKS_UPDATED,
|
|
557
|
+
this.HLS.Events.AUDIO_TRACK_SWITCHED,
|
|
558
|
+
this.HLS.Events.MANIFEST_LOADED
|
|
559
|
+
]
|
|
560
|
+
.map(event => hlsPlayer.on(event, () => this.__SettingsUpdate()));
|
|
561
|
+
|
|
562
|
+
// TODO: Refactor this somewhere else
|
|
563
|
+
this.SetPlayerProfile = async ({profile, customHLSOptions={}}) => {
|
|
564
|
+
this.videoDuration = undefined;
|
|
565
|
+
this.playerOptions.playerProfile = profile;
|
|
566
|
+
this.customHLSOptions = customHLSOptions;
|
|
567
|
+
|
|
568
|
+
const playing = !this.video.paused;
|
|
569
|
+
const currentTime = this.video.currentTime;
|
|
570
|
+
|
|
571
|
+
this.hlsPlayer.destroy();
|
|
572
|
+
await this.__InitializeHLS({
|
|
573
|
+
playoutUrl,
|
|
574
|
+
authorizationToken,
|
|
575
|
+
drm,
|
|
576
|
+
multiviewOptions
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
playing ? this.video.play() : this.video.pause();
|
|
580
|
+
|
|
581
|
+
if(!this.isLive) {
|
|
582
|
+
this.video.currentTime = currentTime;
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
// Error handling
|
|
587
|
+
hlsPlayer.on(this.HLS.Events.FRAG_LOADED, () =>
|
|
588
|
+
this.errors = 0
|
|
589
|
+
);
|
|
590
|
+
|
|
591
|
+
hlsPlayer.on(this.HLS.Events.ERROR, async (event, error) => {
|
|
592
|
+
this.errors += 1;
|
|
593
|
+
|
|
594
|
+
this.Log(`Encountered ${error.details}`, true);
|
|
595
|
+
this.Log(error, true);
|
|
596
|
+
|
|
597
|
+
if(error.response && error.response.code === 403) {
|
|
598
|
+
// Not allowed to access
|
|
599
|
+
this.SetErrorMessage("Insufficient permissions");
|
|
600
|
+
} else if(this.errors < 5) {
|
|
601
|
+
if(error.fatal) {
|
|
602
|
+
if(error.data && error.data.type === this.HLS.ErrorTypes.MEDIA_ERROR) {
|
|
603
|
+
this.Log("Attempting to recover using hlsPlayer.recoverMediaError");
|
|
604
|
+
hlsPlayer.recoverMediaError();
|
|
605
|
+
} else {
|
|
606
|
+
this.__HardReload(error);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
} else {
|
|
610
|
+
this.__HardReload(error);
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
this.hlsPlayer = hlsPlayer;
|
|
615
|
+
this.player = hlsPlayer;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
async __InitializeDash({playoutUrl, authorizationToken, drm, drms}) {
|
|
620
|
+
this.Dash = (await import("dashjs")).default;
|
|
621
|
+
const dashPlayer = this.Dash.MediaPlayer().create();
|
|
622
|
+
|
|
623
|
+
const customDashOptions = this.playerOptions.dashjsOptions || {};
|
|
624
|
+
dashPlayer.updateSettings({
|
|
625
|
+
...customDashOptions,
|
|
626
|
+
"streaming": {
|
|
627
|
+
"buffer": {
|
|
628
|
+
"fastSwitchEnabled": true,
|
|
629
|
+
"flushBufferAtTrackSwitch": true,
|
|
630
|
+
...((customDashOptions.streaming || {}).buffer || {})
|
|
631
|
+
},
|
|
632
|
+
"text": {
|
|
633
|
+
"defaultEnabled": false,
|
|
634
|
+
...((customDashOptions.streaming || {}).text || {})
|
|
635
|
+
},
|
|
636
|
+
...(customDashOptions.streaming || {})
|
|
637
|
+
}
|
|
638
|
+
});
|
|
639
|
+
|
|
640
|
+
if(this.playerOptions.capLevelToPlayerSize) {
|
|
641
|
+
dashPlayer.updateSettings({
|
|
642
|
+
"streaming": {
|
|
643
|
+
"abr": {
|
|
644
|
+
"limitBitrateByPortal": true
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
if(this.playerOptions.maxBitrate) {
|
|
651
|
+
dashPlayer.updateSettings({
|
|
652
|
+
"streaming": {
|
|
653
|
+
"abr": {
|
|
654
|
+
"maxBitrate": { "video": this.playerOptions.maxBitrate / 1000 }
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
playoutUrl.searchParams.delete("authorization");
|
|
661
|
+
dashPlayer.extend("RequestModifier", function () {
|
|
662
|
+
return {
|
|
663
|
+
modifyRequestHeader: xhr => {
|
|
664
|
+
xhr.setRequestHeader("Authorization", `Bearer ${authorizationToken}`);
|
|
665
|
+
|
|
666
|
+
return xhr;
|
|
667
|
+
},
|
|
668
|
+
modifyRequestURL: url => url
|
|
669
|
+
};
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
// Widevine
|
|
673
|
+
if(drm === EluvioPlayerParameters.drms.WIDEVINE) {
|
|
674
|
+
const widevineUrl = drms.widevine.licenseServers[0];
|
|
675
|
+
|
|
676
|
+
dashPlayer.setProtectionData({
|
|
677
|
+
"com.widevine.alpha": {
|
|
678
|
+
"serverURL": widevineUrl
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
dashPlayer.initialize(
|
|
684
|
+
this.video,
|
|
685
|
+
playoutUrl.toString(),
|
|
686
|
+
this.playerOptions.autoplay === EluvioPlayerParameters.autoplay.ON
|
|
687
|
+
);
|
|
688
|
+
|
|
689
|
+
/*
|
|
690
|
+
if(this.controls && multiviewOptions.enabled) {
|
|
691
|
+
this.controls.InitializeMultiViewControls(multiviewOptions);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
*/
|
|
695
|
+
|
|
696
|
+
// Keep track of relevant settings updates so the UI can react
|
|
697
|
+
[
|
|
698
|
+
this.Dash.MediaPlayer.events.TRACK_CHANGE_RENDERED,
|
|
699
|
+
this.Dash.MediaPlayer.events.QUALITY_CHANGE_RENDERED,
|
|
700
|
+
this.Dash.MediaPlayer.events.REPRESENTATION_SWITCH,
|
|
701
|
+
this.Dash.MediaPlayer.events.TEXT_TRACKS_ADDED,
|
|
702
|
+
this.Dash.MediaPlayer.events.TEXT_TRACK_ADDED,
|
|
703
|
+
this.Dash.MediaPlayer.events.MANIFEST_LOADED,
|
|
704
|
+
this.Dash.MediaPlayer.events.CAN_PLAY
|
|
705
|
+
]
|
|
706
|
+
.map(event => dashPlayer.on(event, () => this.__SettingsUpdate()));
|
|
707
|
+
|
|
708
|
+
this.player = dashPlayer;
|
|
709
|
+
this.dashPlayer = dashPlayer;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
async __Play() {
|
|
713
|
+
try {
|
|
714
|
+
await this.video.play();
|
|
715
|
+
return true;
|
|
716
|
+
} catch(error) {
|
|
717
|
+
this.Log("Unable to autoplay", true);
|
|
718
|
+
this.Log(error, true);
|
|
719
|
+
this.playbackStarted = false;
|
|
720
|
+
|
|
721
|
+
if(this.playerOptions.muted === EluvioPlayerParameters.muted.OFF_IF_POSSIBLE && this.video.paused && !this.video.muted) {
|
|
722
|
+
await new Promise(resolve => setTimeout(resolve, 250));
|
|
723
|
+
this.Log("Attempting to autoplay muted");
|
|
724
|
+
this.video.muted = true;
|
|
725
|
+
|
|
726
|
+
try {
|
|
727
|
+
await this.video.play();
|
|
728
|
+
return true;
|
|
729
|
+
} catch (error) {
|
|
730
|
+
this.playbackStarted = false;
|
|
731
|
+
return false;
|
|
732
|
+
}
|
|
733
|
+
} else {
|
|
734
|
+
this.playbackStarted = false;
|
|
735
|
+
return false;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// Indicate to controls that the settings have updated
|
|
741
|
+
__SettingsUpdate() {
|
|
742
|
+
this.__settingsListeners.forEach(listener => {
|
|
743
|
+
try {
|
|
744
|
+
listener();
|
|
745
|
+
} catch (error) {
|
|
746
|
+
this.Log("Failed to call settings listener", true);
|
|
747
|
+
this.Log(error, true);
|
|
748
|
+
}
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
__SetControlsVisibility(visible) {
|
|
753
|
+
if(this.controls.visible === visible) { return; }
|
|
754
|
+
|
|
755
|
+
this.controls.visible = visible;
|
|
756
|
+
this.__SettingsUpdate();
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
__DestroyPlayer() {
|
|
760
|
+
this.__destroyed = true;
|
|
761
|
+
this.__Reset();
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
__Reset() {
|
|
765
|
+
if(!this.player) { return; }
|
|
766
|
+
|
|
767
|
+
this.Log("Destroying player");
|
|
768
|
+
|
|
769
|
+
if(this.video) {
|
|
770
|
+
this.video.pause();
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
if(this.hlsPlayer) {
|
|
774
|
+
this.hlsPlayer.destroy();
|
|
775
|
+
} else if(this.dashPlayer) {
|
|
776
|
+
this.dashPlayer.destroy();
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
this.__listenerDisposers.forEach(Disposer => {
|
|
780
|
+
try {
|
|
781
|
+
Disposer();
|
|
782
|
+
} catch (error) {
|
|
783
|
+
this.Log("Failed to dispose of video event listener", true);
|
|
784
|
+
this.Log(error);
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
this.__listenerDisposers = [];
|
|
789
|
+
this.__showPlayerProfileForm = false;
|
|
790
|
+
|
|
791
|
+
if(this.video.mux) {
|
|
792
|
+
try {
|
|
793
|
+
this.video.mux.destroy();
|
|
794
|
+
} catch(error) {
|
|
795
|
+
this.Log("Error destroying mux monitoring:");
|
|
796
|
+
this.Log(error);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
this.nativeHLS = false;
|
|
801
|
+
this.hlsPlayer = undefined;
|
|
802
|
+
this.dashPlayer = undefined;
|
|
803
|
+
this.player = undefined;
|
|
804
|
+
this.initTimeLogged = false;
|
|
805
|
+
this.canPlay = false;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
async __HardReload(error, delay=6000) {
|
|
809
|
+
if(this.reloading) { return; }
|
|
810
|
+
|
|
811
|
+
this.reloading = true;
|
|
812
|
+
this.reloads += 1;
|
|
813
|
+
|
|
814
|
+
if(this.reloads > 2) {
|
|
815
|
+
this.SetErrorMessage(error.displayMessage || "Unable to play content");
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
try {
|
|
820
|
+
if(error && this.playerOptions.restartCallback) {
|
|
821
|
+
try {
|
|
822
|
+
const abort = await this.playerOptions.restartCallback(error);
|
|
823
|
+
|
|
824
|
+
if(abort && typeof abort === "boolean") {
|
|
825
|
+
this.Destroy();
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
} catch (error) {
|
|
829
|
+
this.Log("Restart callback failed:");
|
|
830
|
+
this.Log(error);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
this.SetErrorMessage(error.displayMessage || "Something went wrong, reloading player...");
|
|
835
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
836
|
+
|
|
837
|
+
if(this.__destroyed) { return; }
|
|
838
|
+
|
|
839
|
+
this.Log("Reloading stream");
|
|
840
|
+
|
|
841
|
+
// Recall config to get new nodes
|
|
842
|
+
const client = await this.__Client();
|
|
843
|
+
if(client) {
|
|
844
|
+
await client.ResetRegion();
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
this.restarted = true;
|
|
848
|
+
this.SetErrorMessage(undefined);
|
|
849
|
+
this.__Initialize(
|
|
850
|
+
this.originalParameters,
|
|
851
|
+
!this.video ? null :
|
|
852
|
+
{
|
|
853
|
+
muted: this.video.muted,
|
|
854
|
+
volume: this.video.volume,
|
|
855
|
+
currentTime: this.video.currentTime,
|
|
856
|
+
playing: !this.video.paused
|
|
857
|
+
}
|
|
858
|
+
);
|
|
859
|
+
} finally {
|
|
860
|
+
this.reloading = false;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
Log(message, error=false) {
|
|
865
|
+
if(error) {
|
|
866
|
+
// eslint-disable-next-line no-console
|
|
867
|
+
console.error("ELUVIO PLAYER:", message);
|
|
868
|
+
} else {
|
|
869
|
+
if(this.playerOptions.debugLogging) {
|
|
870
|
+
// eslint-disable-next-line no-console
|
|
871
|
+
console.warn("ELUVIO PLAYER:", message);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
EluvioPlayer.EluvioPlayerParameters = EluvioPlayerParameters;
|
|
878
|
+
EluvioPlayer.EluvioPlayer = EluvioPlayer;
|
|
879
|
+
|
|
880
|
+
export default EluvioPlayer;
|
|
881
|
+
|