stormcloud-video-player 0.2.12 → 0.2.14
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 +100 -1
- package/dist/stormcloud-vp.min.js +2 -2
- package/lib/index.cjs +1206 -151
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +77 -2
- package/lib/index.d.ts +77 -2
- package/lib/index.js +1196 -151
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +1100 -114
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +2 -2
- package/lib/players/FilePlayer.cjs +14 -7
- package/lib/players/FilePlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs +1108 -119
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +1122 -126
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +561 -0
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -0
- package/lib/sdk/hlsAdPlayer.d.cts +10 -0
- package/lib/sdk/ima.cjs +176 -23
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/sdk/ima.d.cts +1 -1
- package/lib/{types-GpA_hKek.d.cts → types-mVgmKmzM.d.cts} +3 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +1107 -119
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
- package/lib/utils/browserCompat.cjs +229 -0
- package/lib/utils/browserCompat.cjs.map +1 -0
- package/lib/utils/browserCompat.d.cts +36 -0
- package/lib/utils/polyfills.cjs +253 -0
- package/lib/utils/polyfills.cjs.map +1 -0
- package/lib/utils/polyfills.d.cts +11 -0
- package/lib/utils/tracking.cjs +10 -9
- package/lib/utils/tracking.cjs.map +1 -1
- package/lib/utils/tracking.d.cts +1 -1
- package/package.json +1 -1
|
@@ -36,7 +36,167 @@ module.exports = __toCommonJS(HlsPlayer_exports);
|
|
|
36
36
|
var import_react = require("react");
|
|
37
37
|
|
|
38
38
|
// src/player/StormcloudVideoPlayer.ts
|
|
39
|
-
var
|
|
39
|
+
var import_hls2 = __toESM(require("hls.js"), 1);
|
|
40
|
+
|
|
41
|
+
// src/utils/browserCompat.ts
|
|
42
|
+
function getChromeVersion(ua) {
|
|
43
|
+
const match = ua.match(/Chrome\/(\d+)/);
|
|
44
|
+
return match && match[1] ? parseInt(match[1], 10) : 0;
|
|
45
|
+
}
|
|
46
|
+
function getWebKitVersion(ua) {
|
|
47
|
+
const match = ua.match(/AppleWebKit\/(\d+)/);
|
|
48
|
+
return match && match[1] ? parseInt(match[1], 10) : 0;
|
|
49
|
+
}
|
|
50
|
+
function getPlatform() {
|
|
51
|
+
var _a;
|
|
52
|
+
if ("userAgentData" in navigator && ((_a = navigator.userAgentData) == null ? void 0 : _a.platform)) {
|
|
53
|
+
return navigator.userAgentData.platform;
|
|
54
|
+
}
|
|
55
|
+
const ua = navigator.userAgent;
|
|
56
|
+
if (/Mac|iPhone|iPad|iPod/i.test(ua)) {
|
|
57
|
+
return /iPhone|iPad|iPod/i.test(ua) ? "iPhone" : "MacIntel";
|
|
58
|
+
}
|
|
59
|
+
if (/Win/i.test(ua)) {
|
|
60
|
+
return "Win32";
|
|
61
|
+
}
|
|
62
|
+
if (/Linux/i.test(ua)) {
|
|
63
|
+
return /Android/i.test(ua) ? "Linux armv8l" : "Linux x86_64";
|
|
64
|
+
}
|
|
65
|
+
if (/CrOS/i.test(ua)) {
|
|
66
|
+
return "CrOS";
|
|
67
|
+
}
|
|
68
|
+
return navigator.platform || "Unknown";
|
|
69
|
+
}
|
|
70
|
+
function detectBrowser() {
|
|
71
|
+
const ua = navigator.userAgent;
|
|
72
|
+
const platform = getPlatform();
|
|
73
|
+
let name = "Unknown";
|
|
74
|
+
let version = "0";
|
|
75
|
+
let majorVersion = 0;
|
|
76
|
+
let isSmartTV = false;
|
|
77
|
+
let isLegacyTV = false;
|
|
78
|
+
let supportsIMA = true;
|
|
79
|
+
let supportsModernJS = true;
|
|
80
|
+
let recommendedAdPlayer = "ima";
|
|
81
|
+
if (/Web0S|webOS/i.test(ua)) {
|
|
82
|
+
name = "LG WebOS";
|
|
83
|
+
isSmartTV = true;
|
|
84
|
+
const match = ua.match(/Web0S[/\s]*([\d.]+)/i);
|
|
85
|
+
version = match && match[1] ? match[1] : "Unknown";
|
|
86
|
+
if (version !== "Unknown") {
|
|
87
|
+
const parts = version.split(".");
|
|
88
|
+
majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;
|
|
89
|
+
}
|
|
90
|
+
} else if (/Tizen/i.test(ua)) {
|
|
91
|
+
name = "Samsung Tizen";
|
|
92
|
+
isSmartTV = true;
|
|
93
|
+
const match = ua.match(/Tizen[/\s]*([\d.]+)/i);
|
|
94
|
+
version = match && match[1] ? match[1] : "Unknown";
|
|
95
|
+
if (version !== "Unknown") {
|
|
96
|
+
const parts = version.split(".");
|
|
97
|
+
majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;
|
|
98
|
+
}
|
|
99
|
+
} else if (/SMART-TV|SmartTV/i.test(ua)) {
|
|
100
|
+
name = "Smart TV";
|
|
101
|
+
isSmartTV = true;
|
|
102
|
+
} else if (/NetCast/i.test(ua)) {
|
|
103
|
+
name = "LG NetCast";
|
|
104
|
+
isSmartTV = true;
|
|
105
|
+
isLegacyTV = true;
|
|
106
|
+
} else if (/BRAVIA/i.test(ua)) {
|
|
107
|
+
name = "Sony BRAVIA";
|
|
108
|
+
isSmartTV = true;
|
|
109
|
+
}
|
|
110
|
+
const chromeVersion = getChromeVersion(ua);
|
|
111
|
+
const webkitVersion = getWebKitVersion(ua);
|
|
112
|
+
if (chromeVersion > 0) {
|
|
113
|
+
if (!isSmartTV) {
|
|
114
|
+
name = "Chrome";
|
|
115
|
+
version = chromeVersion.toString();
|
|
116
|
+
majorVersion = chromeVersion;
|
|
117
|
+
}
|
|
118
|
+
if (chromeVersion < 50) {
|
|
119
|
+
supportsIMA = false;
|
|
120
|
+
supportsModernJS = false;
|
|
121
|
+
isLegacyTV = true;
|
|
122
|
+
recommendedAdPlayer = "hls";
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (webkitVersion > 0 && webkitVersion < 600) {
|
|
126
|
+
supportsModernJS = false;
|
|
127
|
+
if (isSmartTV) {
|
|
128
|
+
isLegacyTV = true;
|
|
129
|
+
supportsIMA = false;
|
|
130
|
+
recommendedAdPlayer = "hls";
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (typeof Promise === "undefined" || typeof Map === "undefined" || typeof Set === "undefined") {
|
|
134
|
+
supportsModernJS = false;
|
|
135
|
+
supportsIMA = false;
|
|
136
|
+
recommendedAdPlayer = "hls";
|
|
137
|
+
}
|
|
138
|
+
if (typeof URLSearchParams === "undefined") {
|
|
139
|
+
supportsModernJS = false;
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
name,
|
|
143
|
+
version,
|
|
144
|
+
majorVersion,
|
|
145
|
+
isSmartTV,
|
|
146
|
+
isLegacyTV,
|
|
147
|
+
platform,
|
|
148
|
+
supportsIMA,
|
|
149
|
+
supportsModernJS,
|
|
150
|
+
recommendedAdPlayer
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function supportsGoogleIMA() {
|
|
154
|
+
const browser = detectBrowser();
|
|
155
|
+
if (browser.isLegacyTV) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
if (typeof document === "undefined" || typeof document.createElement !== "function") {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
try {
|
|
162
|
+
const video = document.createElement("video");
|
|
163
|
+
if (!video) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
} catch (e) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
if (typeof Promise === "undefined") {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
return browser.supportsIMA;
|
|
173
|
+
}
|
|
174
|
+
function logBrowserInfo(debug = false) {
|
|
175
|
+
if (!debug) return;
|
|
176
|
+
const browser = detectBrowser();
|
|
177
|
+
const imaSupport = supportsGoogleIMA();
|
|
178
|
+
console.log("[StormcloudVideoPlayer] Browser Compatibility Info:", {
|
|
179
|
+
browser: `${browser.name} ${browser.version}`,
|
|
180
|
+
platform: browser.platform,
|
|
181
|
+
isSmartTV: browser.isSmartTV,
|
|
182
|
+
isLegacyTV: browser.isLegacyTV,
|
|
183
|
+
supportsIMA: imaSupport,
|
|
184
|
+
supportsModernJS: browser.supportsModernJS,
|
|
185
|
+
recommendedAdPlayer: browser.recommendedAdPlayer,
|
|
186
|
+
userAgent: navigator.userAgent
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
function getBrowserConfigOverrides() {
|
|
190
|
+
const browser = detectBrowser();
|
|
191
|
+
const overrides = {};
|
|
192
|
+
if (browser.isLegacyTV || !browser.supportsIMA) {
|
|
193
|
+
overrides.adPlayerType = "hls";
|
|
194
|
+
}
|
|
195
|
+
if (browser.isSmartTV) {
|
|
196
|
+
overrides.allowNativeHls = true;
|
|
197
|
+
}
|
|
198
|
+
return overrides;
|
|
199
|
+
}
|
|
40
200
|
|
|
41
201
|
// src/sdk/ima.ts
|
|
42
202
|
function createImaController(video, options) {
|
|
@@ -54,9 +214,18 @@ function createImaController(video, options) {
|
|
|
54
214
|
}
|
|
55
215
|
}
|
|
56
216
|
function ensureImaLoaded() {
|
|
217
|
+
var _a, _b, _c;
|
|
218
|
+
if (!supportsGoogleIMA()) {
|
|
219
|
+
console.warn(
|
|
220
|
+
"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead."
|
|
221
|
+
);
|
|
222
|
+
return Promise.reject(
|
|
223
|
+
new Error("Google IMA SDK not supported on this browser")
|
|
224
|
+
);
|
|
225
|
+
}
|
|
57
226
|
try {
|
|
58
227
|
const frameEl = window.frameElement;
|
|
59
|
-
const sandboxAttr = frameEl
|
|
228
|
+
const sandboxAttr = ((_a = frameEl == null ? void 0 : frameEl.getAttribute) == null ? void 0 : _a.call(frameEl, "sandbox")) || "";
|
|
60
229
|
if (sandboxAttr) {
|
|
61
230
|
const tokens = new Set(
|
|
62
231
|
sandboxAttr.split(/\s+/).map((t) => t.trim()).filter((t) => t.length > 0)
|
|
@@ -70,13 +239,13 @@ function createImaController(video, options) {
|
|
|
70
239
|
}
|
|
71
240
|
} catch {
|
|
72
241
|
}
|
|
73
|
-
if (typeof window !== "undefined" && window.google
|
|
242
|
+
if (typeof window !== "undefined" && ((_b = window.google) == null ? void 0 : _b.ima))
|
|
74
243
|
return Promise.resolve();
|
|
75
244
|
const existing = document.querySelector(
|
|
76
245
|
'script[data-ima="true"]'
|
|
77
246
|
);
|
|
78
247
|
if (existing) {
|
|
79
|
-
if (window.google
|
|
248
|
+
if ((_c = window.google) == null ? void 0 : _c.ima) {
|
|
80
249
|
return Promise.resolve();
|
|
81
250
|
}
|
|
82
251
|
return new Promise((resolve, reject) => {
|
|
@@ -134,6 +303,7 @@ function createImaController(video, options) {
|
|
|
134
303
|
return {
|
|
135
304
|
initialize() {
|
|
136
305
|
ensureImaLoaded().then(() => {
|
|
306
|
+
var _a, _b;
|
|
137
307
|
const google = window.google;
|
|
138
308
|
if (!adDisplayContainer) {
|
|
139
309
|
const container = document.createElement("div");
|
|
@@ -147,14 +317,14 @@ function createImaController(video, options) {
|
|
|
147
317
|
container.style.justifyContent = "center";
|
|
148
318
|
container.style.pointerEvents = "none";
|
|
149
319
|
container.style.zIndex = "2";
|
|
150
|
-
video.parentElement
|
|
320
|
+
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
151
321
|
adContainerEl = container;
|
|
152
322
|
adDisplayContainer = new google.ima.AdDisplayContainer(
|
|
153
323
|
container,
|
|
154
324
|
video
|
|
155
325
|
);
|
|
156
326
|
try {
|
|
157
|
-
adDisplayContainer.initialize
|
|
327
|
+
(_b = adDisplayContainer.initialize) == null ? void 0 : _b.call(adDisplayContainer);
|
|
158
328
|
} catch {
|
|
159
329
|
}
|
|
160
330
|
}
|
|
@@ -239,6 +409,7 @@ function createImaController(video, options) {
|
|
|
239
409
|
adsManager.addEventListener(
|
|
240
410
|
AdErrorEvent.AD_ERROR,
|
|
241
411
|
(errorEvent) => {
|
|
412
|
+
var _a;
|
|
242
413
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
243
414
|
destroyAdsManager();
|
|
244
415
|
adPlaying = false;
|
|
@@ -269,10 +440,10 @@ function createImaController(video, options) {
|
|
|
269
440
|
"[IMA] Max retries reached, emitting ad_error"
|
|
270
441
|
);
|
|
271
442
|
emit("ad_error");
|
|
272
|
-
if (!options
|
|
443
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
273
444
|
if (video.paused) {
|
|
274
445
|
console.log("[IMA] Resuming paused video after ad error");
|
|
275
|
-
video.play()
|
|
446
|
+
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
276
447
|
});
|
|
277
448
|
}
|
|
278
449
|
}
|
|
@@ -283,7 +454,7 @@ function createImaController(video, options) {
|
|
|
283
454
|
AdEvent.CONTENT_PAUSE_REQUESTED,
|
|
284
455
|
() => {
|
|
285
456
|
console.log("[IMA] Content pause requested");
|
|
286
|
-
if (!options
|
|
457
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
287
458
|
video.pause();
|
|
288
459
|
console.log("[IMA] Video paused (VOD mode)");
|
|
289
460
|
} else {
|
|
@@ -309,6 +480,7 @@ function createImaController(video, options) {
|
|
|
309
480
|
adsManager.addEventListener(
|
|
310
481
|
AdEvent.CONTENT_RESUME_REQUESTED,
|
|
311
482
|
() => {
|
|
483
|
+
var _a;
|
|
312
484
|
console.log("[IMA] Content resume requested");
|
|
313
485
|
adPlaying = false;
|
|
314
486
|
video.muted = originalMutedState;
|
|
@@ -319,8 +491,8 @@ function createImaController(video, options) {
|
|
|
319
491
|
"[IMA] Ad container hidden - pointer events disabled"
|
|
320
492
|
);
|
|
321
493
|
}
|
|
322
|
-
if (!options
|
|
323
|
-
video.play()
|
|
494
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
495
|
+
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
324
496
|
});
|
|
325
497
|
console.log("[IMA] Video resumed (VOD mode)");
|
|
326
498
|
} else {
|
|
@@ -342,7 +514,7 @@ function createImaController(video, options) {
|
|
|
342
514
|
"[IMA] Ad container hidden after all ads completed"
|
|
343
515
|
);
|
|
344
516
|
}
|
|
345
|
-
if (!options
|
|
517
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
346
518
|
video.play().catch(() => {
|
|
347
519
|
});
|
|
348
520
|
console.log(
|
|
@@ -370,7 +542,7 @@ function createImaController(video, options) {
|
|
|
370
542
|
adContainerEl.style.display = "none";
|
|
371
543
|
console.log("[IMA] Ad container hidden after setup error");
|
|
372
544
|
}
|
|
373
|
-
if (!options
|
|
545
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
374
546
|
if (video.paused) {
|
|
375
547
|
console.log("[IMA] Resuming paused video after setup error");
|
|
376
548
|
video.play().catch(() => {
|
|
@@ -398,7 +570,7 @@ function createImaController(video, options) {
|
|
|
398
570
|
adContainerEl.style.display = "none";
|
|
399
571
|
console.log("[IMA] Ad container hidden after loader error");
|
|
400
572
|
}
|
|
401
|
-
if (!options
|
|
573
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
402
574
|
if (video.paused) {
|
|
403
575
|
console.log("[IMA] Resuming paused video after loader error");
|
|
404
576
|
video.play().catch(() => {
|
|
@@ -420,14 +592,15 @@ function createImaController(video, options) {
|
|
|
420
592
|
return adsLoadedPromise;
|
|
421
593
|
} catch (error) {
|
|
422
594
|
console.error("[IMA] Failed to request ads:", error);
|
|
423
|
-
currentReject
|
|
595
|
+
currentReject == null ? void 0 : currentReject(error);
|
|
424
596
|
adsLoadedReject = void 0;
|
|
425
597
|
adsLoadedResolve = void 0;
|
|
426
598
|
return Promise.reject(error);
|
|
427
599
|
}
|
|
428
600
|
},
|
|
429
601
|
async play() {
|
|
430
|
-
|
|
602
|
+
var _a, _b;
|
|
603
|
+
if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
|
|
431
604
|
console.warn(
|
|
432
605
|
"[IMA] Cannot play ad: IMA SDK or ad container not available"
|
|
433
606
|
);
|
|
@@ -449,14 +622,15 @@ function createImaController(video, options) {
|
|
|
449
622
|
} catch (error) {
|
|
450
623
|
console.error("[IMA] Error starting ad playback:", error);
|
|
451
624
|
adPlaying = false;
|
|
452
|
-
if (!options
|
|
453
|
-
video.play()
|
|
625
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
626
|
+
(_b = video.play()) == null ? void 0 : _b.catch(() => {
|
|
454
627
|
});
|
|
455
628
|
}
|
|
456
629
|
return Promise.reject(error);
|
|
457
630
|
}
|
|
458
631
|
},
|
|
459
632
|
async stop() {
|
|
633
|
+
var _a;
|
|
460
634
|
adPlaying = false;
|
|
461
635
|
video.muted = originalMutedState;
|
|
462
636
|
if (adContainerEl) {
|
|
@@ -465,11 +639,11 @@ function createImaController(video, options) {
|
|
|
465
639
|
console.log("[IMA] Ad container hidden after stop");
|
|
466
640
|
}
|
|
467
641
|
try {
|
|
468
|
-
adsManager
|
|
642
|
+
(_a = adsManager == null ? void 0 : adsManager.stop) == null ? void 0 : _a.call(adsManager);
|
|
469
643
|
} catch {
|
|
470
644
|
}
|
|
471
645
|
destroyAdsManager();
|
|
472
|
-
if (!options
|
|
646
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
473
647
|
video.play().catch(() => {
|
|
474
648
|
});
|
|
475
649
|
console.log("[IMA] Video resumed after stop (VOD mode)");
|
|
@@ -478,6 +652,7 @@ function createImaController(video, options) {
|
|
|
478
652
|
}
|
|
479
653
|
},
|
|
480
654
|
destroy() {
|
|
655
|
+
var _a;
|
|
481
656
|
destroyAdsManager();
|
|
482
657
|
adPlaying = false;
|
|
483
658
|
video.muted = originalMutedState;
|
|
@@ -486,10 +661,10 @@ function createImaController(video, options) {
|
|
|
486
661
|
adContainerEl.style.display = "none";
|
|
487
662
|
}
|
|
488
663
|
try {
|
|
489
|
-
adsLoader
|
|
664
|
+
(_a = adsLoader == null ? void 0 : adsLoader.destroy) == null ? void 0 : _a.call(adsLoader);
|
|
490
665
|
} catch {
|
|
491
666
|
}
|
|
492
|
-
if (adContainerEl
|
|
667
|
+
if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
|
|
493
668
|
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
494
669
|
}
|
|
495
670
|
adContainerEl = void 0;
|
|
@@ -500,7 +675,8 @@ function createImaController(video, options) {
|
|
|
500
675
|
return adPlaying;
|
|
501
676
|
},
|
|
502
677
|
resize(width, height) {
|
|
503
|
-
|
|
678
|
+
var _a;
|
|
679
|
+
if (!adsManager || !((_a = window.google) == null ? void 0 : _a.ima)) {
|
|
504
680
|
console.warn(
|
|
505
681
|
"[IMA] Cannot resize: No ads manager or IMA SDK available"
|
|
506
682
|
);
|
|
@@ -518,7 +694,8 @@ function createImaController(video, options) {
|
|
|
518
694
|
listeners.get(event).add(listener);
|
|
519
695
|
},
|
|
520
696
|
off(event, listener) {
|
|
521
|
-
|
|
697
|
+
var _a;
|
|
698
|
+
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
522
699
|
},
|
|
523
700
|
updateOriginalMutedState(muted) {
|
|
524
701
|
originalMutedState = muted;
|
|
@@ -549,9 +726,533 @@ function createImaController(video, options) {
|
|
|
549
726
|
};
|
|
550
727
|
}
|
|
551
728
|
|
|
729
|
+
// src/sdk/hlsAdPlayer.ts
|
|
730
|
+
var import_hls = __toESM(require("hls.js"), 1);
|
|
731
|
+
function createHlsAdPlayer(contentVideo, options) {
|
|
732
|
+
let adPlaying = false;
|
|
733
|
+
let originalMutedState = false;
|
|
734
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
735
|
+
const licenseKey = options == null ? void 0 : options.licenseKey;
|
|
736
|
+
const mainHlsInstance = options == null ? void 0 : options.mainHlsInstance;
|
|
737
|
+
let adVideoElement;
|
|
738
|
+
let adHls;
|
|
739
|
+
let adContainerEl;
|
|
740
|
+
let currentAd;
|
|
741
|
+
let sessionId;
|
|
742
|
+
let trackingFired = {
|
|
743
|
+
impression: false,
|
|
744
|
+
start: false,
|
|
745
|
+
firstQuartile: false,
|
|
746
|
+
midpoint: false,
|
|
747
|
+
thirdQuartile: false,
|
|
748
|
+
complete: false
|
|
749
|
+
};
|
|
750
|
+
function emit(event, payload) {
|
|
751
|
+
const set = listeners.get(event);
|
|
752
|
+
if (!set) return;
|
|
753
|
+
for (const fn of Array.from(set)) {
|
|
754
|
+
try {
|
|
755
|
+
fn(payload);
|
|
756
|
+
} catch (error) {
|
|
757
|
+
console.warn(`[HlsAdPlayer] Error in event listener for ${event}:`, error);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
function generateSessionId() {
|
|
762
|
+
return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
763
|
+
}
|
|
764
|
+
function fireTrackingPixels(urls) {
|
|
765
|
+
if (!urls || urls.length === 0) return;
|
|
766
|
+
urls.forEach((url) => {
|
|
767
|
+
try {
|
|
768
|
+
let trackingUrl = url;
|
|
769
|
+
if (sessionId) {
|
|
770
|
+
trackingUrl = `${trackingUrl}${trackingUrl.includes("?") ? "&" : "?"}session_id=${sessionId}`;
|
|
771
|
+
}
|
|
772
|
+
if (licenseKey) {
|
|
773
|
+
trackingUrl = `${trackingUrl}${trackingUrl.includes("?") ? "&" : "?"}license_key=${licenseKey}`;
|
|
774
|
+
}
|
|
775
|
+
const img = new Image(1, 1);
|
|
776
|
+
img.src = trackingUrl;
|
|
777
|
+
console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);
|
|
778
|
+
} catch (error) {
|
|
779
|
+
console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
function getMainStreamQuality() {
|
|
784
|
+
if (!mainHlsInstance || !mainHlsInstance.levels) {
|
|
785
|
+
return null;
|
|
786
|
+
}
|
|
787
|
+
const currentLevel = mainHlsInstance.currentLevel;
|
|
788
|
+
if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {
|
|
789
|
+
const autoLevel = mainHlsInstance.loadLevel;
|
|
790
|
+
if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {
|
|
791
|
+
const level2 = mainHlsInstance.levels[autoLevel];
|
|
792
|
+
return {
|
|
793
|
+
width: level2.width || 1920,
|
|
794
|
+
height: level2.height || 1080,
|
|
795
|
+
bitrate: level2.bitrate || 5e6
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
return null;
|
|
799
|
+
}
|
|
800
|
+
const level = mainHlsInstance.levels[currentLevel];
|
|
801
|
+
return {
|
|
802
|
+
width: level.width || 1920,
|
|
803
|
+
height: level.height || 1080,
|
|
804
|
+
bitrate: level.bitrate || 5e6
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
function selectBestMediaFile(mediaFiles) {
|
|
808
|
+
if (mediaFiles.length === 0) {
|
|
809
|
+
throw new Error("No media files available");
|
|
810
|
+
}
|
|
811
|
+
const firstFile = mediaFiles[0];
|
|
812
|
+
if (!firstFile) {
|
|
813
|
+
throw new Error("No media files available");
|
|
814
|
+
}
|
|
815
|
+
if (mediaFiles.length === 1) {
|
|
816
|
+
return firstFile;
|
|
817
|
+
}
|
|
818
|
+
const mainQuality = getMainStreamQuality();
|
|
819
|
+
if (!mainQuality) {
|
|
820
|
+
console.log("[HlsAdPlayer] No main stream quality info, using first media file");
|
|
821
|
+
return firstFile;
|
|
822
|
+
}
|
|
823
|
+
console.log("[HlsAdPlayer] Main stream quality:", mainQuality);
|
|
824
|
+
const scoredFiles = mediaFiles.map((file) => {
|
|
825
|
+
const widthDiff = Math.abs(file.width - mainQuality.width);
|
|
826
|
+
const heightDiff = Math.abs(file.height - mainQuality.height);
|
|
827
|
+
const resolutionDiff = widthDiff + heightDiff;
|
|
828
|
+
const fileBitrate = (file.bitrate || 5e3) * 1e3;
|
|
829
|
+
const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);
|
|
830
|
+
const score = resolutionDiff * 2 + bitrateDiff / 1e3;
|
|
831
|
+
return { file, score, resolutionDiff, bitrateDiff };
|
|
832
|
+
});
|
|
833
|
+
scoredFiles.sort((a, b) => a.score - b.score);
|
|
834
|
+
const bestMatch = scoredFiles[0];
|
|
835
|
+
if (!bestMatch) {
|
|
836
|
+
console.log("[HlsAdPlayer] No best match found, using first media file");
|
|
837
|
+
return firstFile;
|
|
838
|
+
}
|
|
839
|
+
console.log("[HlsAdPlayer] Selected media file:", {
|
|
840
|
+
url: bestMatch.file.url,
|
|
841
|
+
resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,
|
|
842
|
+
bitrate: bestMatch.file.bitrate,
|
|
843
|
+
score: bestMatch.score,
|
|
844
|
+
resolutionDiff: bestMatch.resolutionDiff,
|
|
845
|
+
bitrateDiff: bestMatch.bitrateDiff
|
|
846
|
+
});
|
|
847
|
+
return bestMatch.file;
|
|
848
|
+
}
|
|
849
|
+
function parseVastXml(xmlString) {
|
|
850
|
+
var _a, _b, _c, _d;
|
|
851
|
+
try {
|
|
852
|
+
const parser = new DOMParser();
|
|
853
|
+
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
|
|
854
|
+
const parserError = xmlDoc.querySelector("parsererror");
|
|
855
|
+
if (parserError) {
|
|
856
|
+
console.error("[HlsAdPlayer] XML parsing error:", parserError.textContent);
|
|
857
|
+
return null;
|
|
858
|
+
}
|
|
859
|
+
const adElement = xmlDoc.querySelector("Ad");
|
|
860
|
+
if (!adElement) {
|
|
861
|
+
console.warn("[HlsAdPlayer] No Ad element found in VAST XML");
|
|
862
|
+
return null;
|
|
863
|
+
}
|
|
864
|
+
const adId = adElement.getAttribute("id") || "unknown";
|
|
865
|
+
const title = ((_a = xmlDoc.querySelector("AdTitle")) == null ? void 0 : _a.textContent) || "Ad";
|
|
866
|
+
const durationText = ((_b = xmlDoc.querySelector("Duration")) == null ? void 0 : _b.textContent) || "00:00:30";
|
|
867
|
+
const durationParts = durationText.split(":");
|
|
868
|
+
const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
|
|
869
|
+
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
870
|
+
const mediaFiles = [];
|
|
871
|
+
mediaFileElements.forEach((mf) => {
|
|
872
|
+
var _a2;
|
|
873
|
+
const type = mf.getAttribute("type") || "";
|
|
874
|
+
if (type === "application/x-mpegURL" || type.includes("m3u8")) {
|
|
875
|
+
const bitrateAttr = mf.getAttribute("bitrate");
|
|
876
|
+
const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
|
|
877
|
+
mediaFiles.push({
|
|
878
|
+
url: ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "",
|
|
879
|
+
type,
|
|
880
|
+
width: parseInt(mf.getAttribute("width") || "1920", 10),
|
|
881
|
+
height: parseInt(mf.getAttribute("height") || "1080", 10),
|
|
882
|
+
bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
if (mediaFiles.length === 0) {
|
|
887
|
+
console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
|
|
888
|
+
return null;
|
|
889
|
+
}
|
|
890
|
+
const trackingUrls = {
|
|
891
|
+
impression: [],
|
|
892
|
+
start: [],
|
|
893
|
+
firstQuartile: [],
|
|
894
|
+
midpoint: [],
|
|
895
|
+
thirdQuartile: [],
|
|
896
|
+
complete: [],
|
|
897
|
+
mute: [],
|
|
898
|
+
unmute: [],
|
|
899
|
+
pause: [],
|
|
900
|
+
resume: [],
|
|
901
|
+
fullscreen: [],
|
|
902
|
+
exitFullscreen: [],
|
|
903
|
+
skip: [],
|
|
904
|
+
error: []
|
|
905
|
+
};
|
|
906
|
+
xmlDoc.querySelectorAll("Impression").forEach((el) => {
|
|
907
|
+
var _a2;
|
|
908
|
+
const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
|
|
909
|
+
if (url) trackingUrls.impression.push(url);
|
|
910
|
+
});
|
|
911
|
+
xmlDoc.querySelectorAll("Tracking").forEach((el) => {
|
|
912
|
+
var _a2;
|
|
913
|
+
const event = el.getAttribute("event");
|
|
914
|
+
const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
|
|
915
|
+
if (event && url) {
|
|
916
|
+
const eventKey = event;
|
|
917
|
+
if (trackingUrls[eventKey]) {
|
|
918
|
+
trackingUrls[eventKey].push(url);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
const clickThrough = (_d = (_c = xmlDoc.querySelector("ClickThrough")) == null ? void 0 : _c.textContent) == null ? void 0 : _d.trim();
|
|
923
|
+
return {
|
|
924
|
+
id: adId,
|
|
925
|
+
title,
|
|
926
|
+
duration,
|
|
927
|
+
mediaFiles,
|
|
928
|
+
trackingUrls,
|
|
929
|
+
clickThrough
|
|
930
|
+
};
|
|
931
|
+
} catch (error) {
|
|
932
|
+
console.error("[HlsAdPlayer] Error parsing VAST XML:", error);
|
|
933
|
+
return null;
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
function createAdVideoElement() {
|
|
937
|
+
const video = document.createElement("video");
|
|
938
|
+
video.style.position = "absolute";
|
|
939
|
+
video.style.left = "0";
|
|
940
|
+
video.style.top = "0";
|
|
941
|
+
video.style.width = "100%";
|
|
942
|
+
video.style.height = "100%";
|
|
943
|
+
video.style.objectFit = "contain";
|
|
944
|
+
video.style.backgroundColor = "#000";
|
|
945
|
+
video.playsInline = true;
|
|
946
|
+
video.muted = false;
|
|
947
|
+
return video;
|
|
948
|
+
}
|
|
949
|
+
function setupAdEventListeners() {
|
|
950
|
+
if (!adVideoElement || !currentAd) return;
|
|
951
|
+
adVideoElement.addEventListener("timeupdate", () => {
|
|
952
|
+
if (!currentAd || !adVideoElement) return;
|
|
953
|
+
const progress = adVideoElement.currentTime / currentAd.duration;
|
|
954
|
+
if (progress >= 0.25 && !trackingFired.firstQuartile) {
|
|
955
|
+
trackingFired.firstQuartile = true;
|
|
956
|
+
fireTrackingPixels(currentAd.trackingUrls.firstQuartile);
|
|
957
|
+
}
|
|
958
|
+
if (progress >= 0.5 && !trackingFired.midpoint) {
|
|
959
|
+
trackingFired.midpoint = true;
|
|
960
|
+
fireTrackingPixels(currentAd.trackingUrls.midpoint);
|
|
961
|
+
}
|
|
962
|
+
if (progress >= 0.75 && !trackingFired.thirdQuartile) {
|
|
963
|
+
trackingFired.thirdQuartile = true;
|
|
964
|
+
fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
|
|
965
|
+
}
|
|
966
|
+
});
|
|
967
|
+
adVideoElement.addEventListener("playing", () => {
|
|
968
|
+
if (!currentAd || trackingFired.start) return;
|
|
969
|
+
trackingFired.start = true;
|
|
970
|
+
fireTrackingPixels(currentAd.trackingUrls.start);
|
|
971
|
+
console.log("[HlsAdPlayer] Ad started playing");
|
|
972
|
+
});
|
|
973
|
+
adVideoElement.addEventListener("ended", () => {
|
|
974
|
+
if (!currentAd || trackingFired.complete) return;
|
|
975
|
+
trackingFired.complete = true;
|
|
976
|
+
fireTrackingPixels(currentAd.trackingUrls.complete);
|
|
977
|
+
console.log("[HlsAdPlayer] Ad completed");
|
|
978
|
+
handleAdComplete();
|
|
979
|
+
});
|
|
980
|
+
adVideoElement.addEventListener("error", (e) => {
|
|
981
|
+
console.error("[HlsAdPlayer] Ad video error:", e);
|
|
982
|
+
if (currentAd) {
|
|
983
|
+
fireTrackingPixels(currentAd.trackingUrls.error);
|
|
984
|
+
}
|
|
985
|
+
handleAdError();
|
|
986
|
+
});
|
|
987
|
+
adVideoElement.addEventListener("volumechange", () => {
|
|
988
|
+
if (!currentAd) return;
|
|
989
|
+
if (adVideoElement.muted) {
|
|
990
|
+
fireTrackingPixels(currentAd.trackingUrls.mute);
|
|
991
|
+
} else {
|
|
992
|
+
fireTrackingPixels(currentAd.trackingUrls.unmute);
|
|
993
|
+
}
|
|
994
|
+
});
|
|
995
|
+
adVideoElement.addEventListener("pause", () => {
|
|
996
|
+
if (currentAd && !adVideoElement.ended) {
|
|
997
|
+
fireTrackingPixels(currentAd.trackingUrls.pause);
|
|
998
|
+
}
|
|
999
|
+
});
|
|
1000
|
+
adVideoElement.addEventListener("play", () => {
|
|
1001
|
+
if (currentAd && adVideoElement.currentTime > 0) {
|
|
1002
|
+
fireTrackingPixels(currentAd.trackingUrls.resume);
|
|
1003
|
+
}
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
function handleAdComplete() {
|
|
1007
|
+
console.log("[HlsAdPlayer] Handling ad completion");
|
|
1008
|
+
adPlaying = false;
|
|
1009
|
+
contentVideo.muted = originalMutedState;
|
|
1010
|
+
if (adContainerEl) {
|
|
1011
|
+
adContainerEl.style.display = "none";
|
|
1012
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1013
|
+
}
|
|
1014
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1015
|
+
contentVideo.play().catch(() => {
|
|
1016
|
+
});
|
|
1017
|
+
console.log("[HlsAdPlayer] Content resumed (VOD mode)");
|
|
1018
|
+
} else {
|
|
1019
|
+
console.log("[HlsAdPlayer] Content unmuted (Live mode)");
|
|
1020
|
+
}
|
|
1021
|
+
emit("content_resume");
|
|
1022
|
+
emit("all_ads_completed");
|
|
1023
|
+
}
|
|
1024
|
+
function handleAdError() {
|
|
1025
|
+
console.log("[HlsAdPlayer] Handling ad error");
|
|
1026
|
+
adPlaying = false;
|
|
1027
|
+
contentVideo.muted = originalMutedState;
|
|
1028
|
+
if (adContainerEl) {
|
|
1029
|
+
adContainerEl.style.display = "none";
|
|
1030
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1031
|
+
}
|
|
1032
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1033
|
+
if (contentVideo.paused) {
|
|
1034
|
+
contentVideo.play().catch(() => {
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
emit("ad_error");
|
|
1039
|
+
}
|
|
1040
|
+
return {
|
|
1041
|
+
initialize() {
|
|
1042
|
+
var _a;
|
|
1043
|
+
console.log("[HlsAdPlayer] Initializing");
|
|
1044
|
+
if (!adContainerEl) {
|
|
1045
|
+
const container = document.createElement("div");
|
|
1046
|
+
container.style.position = "absolute";
|
|
1047
|
+
container.style.left = "0";
|
|
1048
|
+
container.style.top = "0";
|
|
1049
|
+
container.style.right = "0";
|
|
1050
|
+
container.style.bottom = "0";
|
|
1051
|
+
container.style.display = "none";
|
|
1052
|
+
container.style.alignItems = "center";
|
|
1053
|
+
container.style.justifyContent = "center";
|
|
1054
|
+
container.style.pointerEvents = "none";
|
|
1055
|
+
container.style.zIndex = "2";
|
|
1056
|
+
container.style.backgroundColor = "#000";
|
|
1057
|
+
(_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
1058
|
+
adContainerEl = container;
|
|
1059
|
+
}
|
|
1060
|
+
},
|
|
1061
|
+
async requestAds(vastTagUrl) {
|
|
1062
|
+
console.log("[HlsAdPlayer] Requesting ads:", vastTagUrl);
|
|
1063
|
+
if (adPlaying) {
|
|
1064
|
+
console.warn("[HlsAdPlayer] Cannot request new ads while an ad is playing");
|
|
1065
|
+
return Promise.reject(new Error("Ad already playing"));
|
|
1066
|
+
}
|
|
1067
|
+
try {
|
|
1068
|
+
sessionId = generateSessionId();
|
|
1069
|
+
const response = await fetch(vastTagUrl);
|
|
1070
|
+
if (!response.ok) {
|
|
1071
|
+
throw new Error(`Failed to fetch VAST: ${response.statusText}`);
|
|
1072
|
+
}
|
|
1073
|
+
const vastXml = await response.text();
|
|
1074
|
+
console.log("[HlsAdPlayer] VAST XML received");
|
|
1075
|
+
const ad = parseVastXml(vastXml);
|
|
1076
|
+
if (!ad) {
|
|
1077
|
+
throw new Error("Failed to parse VAST XML or no ads available");
|
|
1078
|
+
}
|
|
1079
|
+
currentAd = ad;
|
|
1080
|
+
console.log(`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`);
|
|
1081
|
+
fireTrackingPixels(ad.trackingUrls.impression);
|
|
1082
|
+
trackingFired.impression = true;
|
|
1083
|
+
return Promise.resolve();
|
|
1084
|
+
} catch (error) {
|
|
1085
|
+
console.error("[HlsAdPlayer] Error requesting ads:", error);
|
|
1086
|
+
emit("ad_error");
|
|
1087
|
+
return Promise.reject(error);
|
|
1088
|
+
}
|
|
1089
|
+
},
|
|
1090
|
+
async play() {
|
|
1091
|
+
if (!currentAd) {
|
|
1092
|
+
console.warn("[HlsAdPlayer] Cannot play: No ad loaded");
|
|
1093
|
+
return Promise.reject(new Error("No ad loaded"));
|
|
1094
|
+
}
|
|
1095
|
+
console.log("[HlsAdPlayer] Starting ad playback");
|
|
1096
|
+
try {
|
|
1097
|
+
if (!adVideoElement) {
|
|
1098
|
+
adVideoElement = createAdVideoElement();
|
|
1099
|
+
adContainerEl == null ? void 0 : adContainerEl.appendChild(adVideoElement);
|
|
1100
|
+
setupAdEventListeners();
|
|
1101
|
+
}
|
|
1102
|
+
trackingFired = {
|
|
1103
|
+
impression: trackingFired.impression,
|
|
1104
|
+
start: false,
|
|
1105
|
+
firstQuartile: false,
|
|
1106
|
+
midpoint: false,
|
|
1107
|
+
thirdQuartile: false,
|
|
1108
|
+
complete: false
|
|
1109
|
+
};
|
|
1110
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1111
|
+
contentVideo.pause();
|
|
1112
|
+
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
1113
|
+
} else {
|
|
1114
|
+
console.log("[HlsAdPlayer] Content continues (Live mode)");
|
|
1115
|
+
}
|
|
1116
|
+
contentVideo.muted = true;
|
|
1117
|
+
adPlaying = true;
|
|
1118
|
+
if (adContainerEl) {
|
|
1119
|
+
adContainerEl.style.display = "flex";
|
|
1120
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
1121
|
+
}
|
|
1122
|
+
emit("content_pause");
|
|
1123
|
+
const mediaFile = selectBestMediaFile(currentAd.mediaFiles);
|
|
1124
|
+
if (!mediaFile) {
|
|
1125
|
+
throw new Error("No media file available for ad");
|
|
1126
|
+
}
|
|
1127
|
+
console.log(`[HlsAdPlayer] Loading ad from: ${mediaFile.url}`);
|
|
1128
|
+
if (import_hls.default.isSupported()) {
|
|
1129
|
+
if (adHls) {
|
|
1130
|
+
adHls.destroy();
|
|
1131
|
+
}
|
|
1132
|
+
adHls = new import_hls.default({
|
|
1133
|
+
enableWorker: true,
|
|
1134
|
+
lowLatencyMode: false
|
|
1135
|
+
});
|
|
1136
|
+
adHls.loadSource(mediaFile.url);
|
|
1137
|
+
adHls.attachMedia(adVideoElement);
|
|
1138
|
+
adHls.on(import_hls.default.Events.MANIFEST_PARSED, () => {
|
|
1139
|
+
console.log("[HlsAdPlayer] HLS manifest parsed, starting playback");
|
|
1140
|
+
adVideoElement.play().catch((error) => {
|
|
1141
|
+
console.error("[HlsAdPlayer] Error starting ad playback:", error);
|
|
1142
|
+
handleAdError();
|
|
1143
|
+
});
|
|
1144
|
+
});
|
|
1145
|
+
adHls.on(import_hls.default.Events.ERROR, (event, data) => {
|
|
1146
|
+
console.error("[HlsAdPlayer] HLS error:", data);
|
|
1147
|
+
if (data.fatal) {
|
|
1148
|
+
handleAdError();
|
|
1149
|
+
}
|
|
1150
|
+
});
|
|
1151
|
+
} else if (adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
|
|
1152
|
+
adVideoElement.src = mediaFile.url;
|
|
1153
|
+
adVideoElement.play().catch((error) => {
|
|
1154
|
+
console.error("[HlsAdPlayer] Error starting ad playback:", error);
|
|
1155
|
+
handleAdError();
|
|
1156
|
+
});
|
|
1157
|
+
} else {
|
|
1158
|
+
throw new Error("HLS not supported");
|
|
1159
|
+
}
|
|
1160
|
+
return Promise.resolve();
|
|
1161
|
+
} catch (error) {
|
|
1162
|
+
console.error("[HlsAdPlayer] Error playing ad:", error);
|
|
1163
|
+
handleAdError();
|
|
1164
|
+
return Promise.reject(error);
|
|
1165
|
+
}
|
|
1166
|
+
},
|
|
1167
|
+
async stop() {
|
|
1168
|
+
console.log("[HlsAdPlayer] Stopping ad");
|
|
1169
|
+
adPlaying = false;
|
|
1170
|
+
contentVideo.muted = originalMutedState;
|
|
1171
|
+
if (adContainerEl) {
|
|
1172
|
+
adContainerEl.style.display = "none";
|
|
1173
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1174
|
+
}
|
|
1175
|
+
if (adHls) {
|
|
1176
|
+
adHls.destroy();
|
|
1177
|
+
adHls = void 0;
|
|
1178
|
+
}
|
|
1179
|
+
if (adVideoElement) {
|
|
1180
|
+
adVideoElement.pause();
|
|
1181
|
+
adVideoElement.src = "";
|
|
1182
|
+
}
|
|
1183
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1184
|
+
contentVideo.play().catch(() => {
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
currentAd = void 0;
|
|
1188
|
+
},
|
|
1189
|
+
destroy() {
|
|
1190
|
+
console.log("[HlsAdPlayer] Destroying");
|
|
1191
|
+
adPlaying = false;
|
|
1192
|
+
contentVideo.muted = originalMutedState;
|
|
1193
|
+
if (adHls) {
|
|
1194
|
+
adHls.destroy();
|
|
1195
|
+
adHls = void 0;
|
|
1196
|
+
}
|
|
1197
|
+
if (adVideoElement) {
|
|
1198
|
+
adVideoElement.pause();
|
|
1199
|
+
adVideoElement.src = "";
|
|
1200
|
+
adVideoElement.remove();
|
|
1201
|
+
adVideoElement = void 0;
|
|
1202
|
+
}
|
|
1203
|
+
if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
|
|
1204
|
+
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
1205
|
+
}
|
|
1206
|
+
adContainerEl = void 0;
|
|
1207
|
+
currentAd = void 0;
|
|
1208
|
+
listeners.clear();
|
|
1209
|
+
},
|
|
1210
|
+
isAdPlaying() {
|
|
1211
|
+
return adPlaying;
|
|
1212
|
+
},
|
|
1213
|
+
resize(width, height) {
|
|
1214
|
+
console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);
|
|
1215
|
+
if (adContainerEl) {
|
|
1216
|
+
adContainerEl.style.width = `${width}px`;
|
|
1217
|
+
adContainerEl.style.height = `${height}px`;
|
|
1218
|
+
}
|
|
1219
|
+
if (adVideoElement) {
|
|
1220
|
+
adVideoElement.style.width = `${width}px`;
|
|
1221
|
+
adVideoElement.style.height = `${height}px`;
|
|
1222
|
+
}
|
|
1223
|
+
},
|
|
1224
|
+
on(event, listener) {
|
|
1225
|
+
if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
|
|
1226
|
+
listeners.get(event).add(listener);
|
|
1227
|
+
},
|
|
1228
|
+
off(event, listener) {
|
|
1229
|
+
var _a;
|
|
1230
|
+
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
1231
|
+
},
|
|
1232
|
+
updateOriginalMutedState(muted) {
|
|
1233
|
+
originalMutedState = muted;
|
|
1234
|
+
},
|
|
1235
|
+
getOriginalMutedState() {
|
|
1236
|
+
return originalMutedState;
|
|
1237
|
+
},
|
|
1238
|
+
setAdVolume(volume) {
|
|
1239
|
+
if (adVideoElement && adPlaying) {
|
|
1240
|
+
adVideoElement.volume = Math.max(0, Math.min(1, volume));
|
|
1241
|
+
}
|
|
1242
|
+
},
|
|
1243
|
+
getAdVolume() {
|
|
1244
|
+
if (adVideoElement && adPlaying) {
|
|
1245
|
+
return adVideoElement.volume;
|
|
1246
|
+
}
|
|
1247
|
+
return 1;
|
|
1248
|
+
}
|
|
1249
|
+
};
|
|
1250
|
+
}
|
|
1251
|
+
|
|
552
1252
|
// src/utils/tracking.ts
|
|
553
1253
|
var cachedBrowserId = null;
|
|
554
1254
|
function getClientInfo() {
|
|
1255
|
+
var _a, _b, _c, _d;
|
|
555
1256
|
const ua = navigator.userAgent;
|
|
556
1257
|
const platform = navigator.platform;
|
|
557
1258
|
const vendor = navigator.vendor || "";
|
|
@@ -559,12 +1260,12 @@ function getClientInfo() {
|
|
|
559
1260
|
const memory = navigator.deviceMemory || null;
|
|
560
1261
|
const hardwareConcurrency = navigator.hardwareConcurrency || 1;
|
|
561
1262
|
const screenInfo = {
|
|
562
|
-
width: screen
|
|
563
|
-
height: screen
|
|
564
|
-
availWidth: screen
|
|
565
|
-
availHeight: screen
|
|
566
|
-
orientation: screen
|
|
567
|
-
pixelDepth: screen
|
|
1263
|
+
width: screen == null ? void 0 : screen.width,
|
|
1264
|
+
height: screen == null ? void 0 : screen.height,
|
|
1265
|
+
availWidth: screen == null ? void 0 : screen.availWidth,
|
|
1266
|
+
availHeight: screen == null ? void 0 : screen.availHeight,
|
|
1267
|
+
orientation: ((_a = screen == null ? void 0 : screen.orientation) == null ? void 0 : _a.type) || "",
|
|
1268
|
+
pixelDepth: screen == null ? void 0 : screen.pixelDepth
|
|
568
1269
|
};
|
|
569
1270
|
let deviceType = "desktop";
|
|
570
1271
|
let brand = "Unknown";
|
|
@@ -661,10 +1362,10 @@ function getClientInfo() {
|
|
|
661
1362
|
if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
|
|
662
1363
|
}
|
|
663
1364
|
isWebView = /wv|WebView|Linux; U;/.test(ua);
|
|
664
|
-
if (window
|
|
1365
|
+
if ((window == null ? void 0 : window.outerHeight) === 0 && (window == null ? void 0 : window.outerWidth) === 0) {
|
|
665
1366
|
isWebView = true;
|
|
666
1367
|
}
|
|
667
|
-
isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || window.screen
|
|
1368
|
+
isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || ((_c = (_b = window.screen) == null ? void 0 : _b.orientation) == null ? void 0 : _c.angle) !== void 0;
|
|
668
1369
|
return {
|
|
669
1370
|
brand,
|
|
670
1371
|
os,
|
|
@@ -685,7 +1386,7 @@ function getClientInfo() {
|
|
|
685
1386
|
deviceMemory: memory,
|
|
686
1387
|
maxTouchPoints,
|
|
687
1388
|
language: navigator.language,
|
|
688
|
-
languages: navigator.languages
|
|
1389
|
+
languages: ((_d = navigator.languages) == null ? void 0 : _d.join(",")) || "",
|
|
689
1390
|
cookieEnabled: navigator.cookieEnabled,
|
|
690
1391
|
doNotTrack: navigator.doNotTrack || "",
|
|
691
1392
|
referrer: document.referrer,
|
|
@@ -798,6 +1499,215 @@ async function sendHeartbeat(licenseKey) {
|
|
|
798
1499
|
}
|
|
799
1500
|
}
|
|
800
1501
|
|
|
1502
|
+
// src/utils/polyfills.ts
|
|
1503
|
+
function polyfillURLSearchParams() {
|
|
1504
|
+
if (typeof URLSearchParams !== "undefined") {
|
|
1505
|
+
return;
|
|
1506
|
+
}
|
|
1507
|
+
class URLSearchParamsPolyfill {
|
|
1508
|
+
constructor(init) {
|
|
1509
|
+
this.params = /* @__PURE__ */ new Map();
|
|
1510
|
+
if (typeof init === "string") {
|
|
1511
|
+
this.parseQueryString(init);
|
|
1512
|
+
} else if (init instanceof URLSearchParamsPolyfill) {
|
|
1513
|
+
init.forEach((value, key) => {
|
|
1514
|
+
this.append(key, value);
|
|
1515
|
+
});
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
parseQueryString(query) {
|
|
1519
|
+
const cleanQuery = query.startsWith("?") ? query.slice(1) : query;
|
|
1520
|
+
if (!cleanQuery) return;
|
|
1521
|
+
cleanQuery.split("&").forEach((param) => {
|
|
1522
|
+
const [key, value] = param.split("=");
|
|
1523
|
+
if (key) {
|
|
1524
|
+
const decodedKey = this.safeDecodeURIComponent(key);
|
|
1525
|
+
const decodedValue = value ? this.safeDecodeURIComponent(value) : "";
|
|
1526
|
+
this.append(decodedKey, decodedValue);
|
|
1527
|
+
}
|
|
1528
|
+
});
|
|
1529
|
+
}
|
|
1530
|
+
safeDecodeURIComponent(str) {
|
|
1531
|
+
try {
|
|
1532
|
+
return decodeURIComponent(str.replace(/\+/g, " "));
|
|
1533
|
+
} catch (e) {
|
|
1534
|
+
return str;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
append(name, value) {
|
|
1538
|
+
const values = this.params.get(name) || [];
|
|
1539
|
+
values.push(String(value));
|
|
1540
|
+
this.params.set(name, values);
|
|
1541
|
+
}
|
|
1542
|
+
delete(name) {
|
|
1543
|
+
this.params.delete(name);
|
|
1544
|
+
}
|
|
1545
|
+
get(name) {
|
|
1546
|
+
const values = this.params.get(name);
|
|
1547
|
+
return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;
|
|
1548
|
+
}
|
|
1549
|
+
getAll(name) {
|
|
1550
|
+
return this.params.get(name) || [];
|
|
1551
|
+
}
|
|
1552
|
+
has(name) {
|
|
1553
|
+
return this.params.has(name);
|
|
1554
|
+
}
|
|
1555
|
+
set(name, value) {
|
|
1556
|
+
this.params.set(name, [String(value)]);
|
|
1557
|
+
}
|
|
1558
|
+
forEach(callback) {
|
|
1559
|
+
this.params.forEach((values, key) => {
|
|
1560
|
+
values.forEach((value) => {
|
|
1561
|
+
callback(value, key, this);
|
|
1562
|
+
});
|
|
1563
|
+
});
|
|
1564
|
+
}
|
|
1565
|
+
toString() {
|
|
1566
|
+
const parts = [];
|
|
1567
|
+
this.params.forEach((values, key) => {
|
|
1568
|
+
values.forEach((value) => {
|
|
1569
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
|
|
1570
|
+
});
|
|
1571
|
+
});
|
|
1572
|
+
return parts.join("&");
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
window.URLSearchParams = URLSearchParamsPolyfill;
|
|
1576
|
+
}
|
|
1577
|
+
function polyfillTextEncoder() {
|
|
1578
|
+
if (typeof TextEncoder !== "undefined") {
|
|
1579
|
+
return;
|
|
1580
|
+
}
|
|
1581
|
+
class TextEncoderPolyfill {
|
|
1582
|
+
constructor() {
|
|
1583
|
+
this.encoding = "utf-8";
|
|
1584
|
+
}
|
|
1585
|
+
encode(str) {
|
|
1586
|
+
const utf8 = [];
|
|
1587
|
+
for (let i = 0; i < str.length; i++) {
|
|
1588
|
+
let charcode = str.charCodeAt(i);
|
|
1589
|
+
if (charcode < 128) {
|
|
1590
|
+
utf8.push(charcode);
|
|
1591
|
+
} else if (charcode < 2048) {
|
|
1592
|
+
utf8.push(192 | charcode >> 6, 128 | charcode & 63);
|
|
1593
|
+
} else if (charcode < 55296 || charcode >= 57344) {
|
|
1594
|
+
utf8.push(
|
|
1595
|
+
224 | charcode >> 12,
|
|
1596
|
+
128 | charcode >> 6 & 63,
|
|
1597
|
+
128 | charcode & 63
|
|
1598
|
+
);
|
|
1599
|
+
} else {
|
|
1600
|
+
i++;
|
|
1601
|
+
charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);
|
|
1602
|
+
utf8.push(
|
|
1603
|
+
240 | charcode >> 18,
|
|
1604
|
+
128 | charcode >> 12 & 63,
|
|
1605
|
+
128 | charcode >> 6 & 63,
|
|
1606
|
+
128 | charcode & 63
|
|
1607
|
+
);
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
return new Uint8Array(utf8);
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
window.TextEncoder = TextEncoderPolyfill;
|
|
1614
|
+
}
|
|
1615
|
+
function polyfillPromiseFinally() {
|
|
1616
|
+
if (typeof Promise !== "undefined" && !Promise.prototype.finally) {
|
|
1617
|
+
Promise.prototype.finally = function(callback) {
|
|
1618
|
+
const constructor = this.constructor;
|
|
1619
|
+
return this.then(
|
|
1620
|
+
(value) => constructor.resolve(callback()).then(() => value),
|
|
1621
|
+
(reason) => constructor.resolve(callback()).then(() => {
|
|
1622
|
+
throw reason;
|
|
1623
|
+
})
|
|
1624
|
+
);
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
function polyfillObjectAssign() {
|
|
1629
|
+
if (typeof Object.assign !== "function") {
|
|
1630
|
+
Object.assign = function(target, ...sources) {
|
|
1631
|
+
if (target == null) {
|
|
1632
|
+
throw new TypeError("Cannot convert undefined or null to object");
|
|
1633
|
+
}
|
|
1634
|
+
const to = Object(target);
|
|
1635
|
+
for (let i = 0; i < sources.length; i++) {
|
|
1636
|
+
const nextSource = sources[i];
|
|
1637
|
+
if (nextSource != null) {
|
|
1638
|
+
for (const nextKey in nextSource) {
|
|
1639
|
+
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
|
|
1640
|
+
to[nextKey] = nextSource[nextKey];
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
return to;
|
|
1646
|
+
};
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
function polyfillArrayFrom() {
|
|
1650
|
+
if (!Array.from) {
|
|
1651
|
+
Array.from = function(arrayLike, mapFn, thisArg) {
|
|
1652
|
+
const items = Object(arrayLike);
|
|
1653
|
+
if (arrayLike == null) {
|
|
1654
|
+
throw new TypeError("Array.from requires an array-like object");
|
|
1655
|
+
}
|
|
1656
|
+
const len = items.length >>> 0;
|
|
1657
|
+
const result = new Array(len);
|
|
1658
|
+
for (let i = 0; i < len; i++) {
|
|
1659
|
+
if (mapFn) {
|
|
1660
|
+
result[i] = mapFn.call(thisArg, items[i], i);
|
|
1661
|
+
} else {
|
|
1662
|
+
result[i] = items[i];
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
return result;
|
|
1666
|
+
};
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
function polyfillStringStartsWith() {
|
|
1670
|
+
if (!String.prototype.startsWith) {
|
|
1671
|
+
String.prototype.startsWith = function(search, pos) {
|
|
1672
|
+
pos = !pos || pos < 0 ? 0 : +pos;
|
|
1673
|
+
return this.substring(pos, pos + search.length) === search;
|
|
1674
|
+
};
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
function polyfillStringEndsWith() {
|
|
1678
|
+
if (!String.prototype.endsWith) {
|
|
1679
|
+
String.prototype.endsWith = function(search, length) {
|
|
1680
|
+
if (length === void 0 || length > this.length) {
|
|
1681
|
+
length = this.length;
|
|
1682
|
+
}
|
|
1683
|
+
return this.substring(length - search.length, length) === search;
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
function polyfillStringIncludes() {
|
|
1688
|
+
if (!String.prototype.includes) {
|
|
1689
|
+
String.prototype.includes = function(search, start) {
|
|
1690
|
+
if (typeof start !== "number") {
|
|
1691
|
+
start = 0;
|
|
1692
|
+
}
|
|
1693
|
+
if (start + search.length > this.length) {
|
|
1694
|
+
return false;
|
|
1695
|
+
}
|
|
1696
|
+
return this.indexOf(search, start) !== -1;
|
|
1697
|
+
};
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
function initializePolyfills() {
|
|
1701
|
+
polyfillObjectAssign();
|
|
1702
|
+
polyfillArrayFrom();
|
|
1703
|
+
polyfillStringStartsWith();
|
|
1704
|
+
polyfillStringEndsWith();
|
|
1705
|
+
polyfillStringIncludes();
|
|
1706
|
+
polyfillURLSearchParams();
|
|
1707
|
+
polyfillTextEncoder();
|
|
1708
|
+
polyfillPromiseFinally();
|
|
1709
|
+
}
|
|
1710
|
+
|
|
801
1711
|
// src/player/StormcloudVideoPlayer.ts
|
|
802
1712
|
var StormcloudVideoPlayer = class {
|
|
803
1713
|
constructor(config) {
|
|
@@ -810,13 +1720,44 @@ var StormcloudVideoPlayer = class {
|
|
|
810
1720
|
this.totalAdsInBreak = 0;
|
|
811
1721
|
this.showAds = false;
|
|
812
1722
|
this.isLiveStream = false;
|
|
813
|
-
|
|
1723
|
+
initializePolyfills();
|
|
1724
|
+
const browserOverrides = getBrowserConfigOverrides();
|
|
1725
|
+
this.config = { ...config, ...browserOverrides };
|
|
814
1726
|
this.video = config.videoElement;
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
1727
|
+
logBrowserInfo(config.debugAdTiming);
|
|
1728
|
+
this.ima = this.createAdPlayer(false);
|
|
1729
|
+
}
|
|
1730
|
+
createAdPlayer(continueLiveStreamDuringAds) {
|
|
1731
|
+
const vastMode = this.config.vastMode || "default";
|
|
1732
|
+
let adPlayerType = this.config.adPlayerType || (vastMode === "adstorm" ? "hls" : "ima");
|
|
1733
|
+
if (adPlayerType === "ima" && !supportsGoogleIMA()) {
|
|
1734
|
+
if (this.config.debugAdTiming) {
|
|
1735
|
+
console.warn(
|
|
1736
|
+
"[StormcloudVideoPlayer] Google IMA SDK not supported on this browser, falling back to HLS ad player"
|
|
1737
|
+
);
|
|
1738
|
+
}
|
|
1739
|
+
adPlayerType = "hls";
|
|
1740
|
+
}
|
|
1741
|
+
if (adPlayerType === "hls") {
|
|
1742
|
+
if (this.config.debugAdTiming) {
|
|
1743
|
+
console.log("[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)");
|
|
1744
|
+
}
|
|
1745
|
+
return createHlsAdPlayer(this.video, {
|
|
1746
|
+
continueLiveStreamDuringAds,
|
|
1747
|
+
...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {},
|
|
1748
|
+
...this.hls ? { mainHlsInstance: this.hls } : {}
|
|
1749
|
+
});
|
|
1750
|
+
} else {
|
|
1751
|
+
if (this.config.debugAdTiming) {
|
|
1752
|
+
console.log("[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)");
|
|
1753
|
+
}
|
|
1754
|
+
return createImaController(this.video, {
|
|
1755
|
+
continueLiveStreamDuringAds
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
818
1758
|
}
|
|
819
1759
|
async load() {
|
|
1760
|
+
var _a, _b;
|
|
820
1761
|
if (!this.attached) {
|
|
821
1762
|
this.attach();
|
|
822
1763
|
}
|
|
@@ -833,7 +1774,7 @@ var StormcloudVideoPlayer = class {
|
|
|
833
1774
|
this.initializeTracking();
|
|
834
1775
|
if (this.shouldUseNativeHls()) {
|
|
835
1776
|
this.video.src = this.config.src;
|
|
836
|
-
this.isLiveStream = this.config.lowLatencyMode
|
|
1777
|
+
this.isLiveStream = (_a = this.config.lowLatencyMode) != null ? _a : false;
|
|
837
1778
|
if (this.config.debugAdTiming) {
|
|
838
1779
|
console.log(
|
|
839
1780
|
"[StormcloudVideoPlayer] allowNativeHls: true - VOD mode detected:",
|
|
@@ -845,17 +1786,15 @@ var StormcloudVideoPlayer = class {
|
|
|
845
1786
|
);
|
|
846
1787
|
}
|
|
847
1788
|
this.ima.destroy();
|
|
848
|
-
this.ima =
|
|
849
|
-
continueLiveStreamDuringAds: false
|
|
850
|
-
});
|
|
1789
|
+
this.ima = this.createAdPlayer(false);
|
|
851
1790
|
this.ima.initialize();
|
|
852
1791
|
if (this.config.autoplay) {
|
|
853
|
-
await this.video.play()
|
|
854
|
-
});
|
|
1792
|
+
await ((_b = this.video.play()) == null ? void 0 : _b.catch(() => {
|
|
1793
|
+
}));
|
|
855
1794
|
}
|
|
856
1795
|
return;
|
|
857
1796
|
}
|
|
858
|
-
this.hls = new
|
|
1797
|
+
this.hls = new import_hls2.default({
|
|
859
1798
|
enableWorker: true,
|
|
860
1799
|
backBufferLength: 30,
|
|
861
1800
|
liveDurationInfinity: true,
|
|
@@ -863,13 +1802,18 @@ var StormcloudVideoPlayer = class {
|
|
|
863
1802
|
maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1,
|
|
864
1803
|
...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}
|
|
865
1804
|
});
|
|
866
|
-
this.hls.on(
|
|
867
|
-
|
|
1805
|
+
this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, () => {
|
|
1806
|
+
var _a2;
|
|
1807
|
+
(_a2 = this.hls) == null ? void 0 : _a2.loadSource(this.config.src);
|
|
868
1808
|
});
|
|
869
|
-
this.hls.on(
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
1809
|
+
this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, async (_, data) => {
|
|
1810
|
+
var _a2, _b2, _c, _d;
|
|
1811
|
+
this.isLiveStream = (_c = (_b2 = (_a2 = this.hls) == null ? void 0 : _a2.levels) == null ? void 0 : _b2.some(
|
|
1812
|
+
(level) => {
|
|
1813
|
+
var _a3, _b3;
|
|
1814
|
+
return ((_a3 = level == null ? void 0 : level.details) == null ? void 0 : _a3.live) === true || ((_b3 = level == null ? void 0 : level.details) == null ? void 0 : _b3.type) === "LIVE";
|
|
1815
|
+
}
|
|
1816
|
+
)) != null ? _c : false;
|
|
873
1817
|
if (this.config.debugAdTiming) {
|
|
874
1818
|
const adBehavior = this.shouldContinueLiveStreamDuringAds() ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
|
|
875
1819
|
console.log("[StormcloudVideoPlayer] Stream type detected:", {
|
|
@@ -879,33 +1823,32 @@ var StormcloudVideoPlayer = class {
|
|
|
879
1823
|
});
|
|
880
1824
|
}
|
|
881
1825
|
this.ima.destroy();
|
|
882
|
-
this.ima =
|
|
883
|
-
continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds()
|
|
884
|
-
});
|
|
1826
|
+
this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());
|
|
885
1827
|
this.ima.initialize();
|
|
886
1828
|
if (this.config.autoplay) {
|
|
887
|
-
await this.video.play()
|
|
888
|
-
});
|
|
1829
|
+
await ((_d = this.video.play()) == null ? void 0 : _d.catch(() => {
|
|
1830
|
+
}));
|
|
889
1831
|
}
|
|
890
1832
|
});
|
|
891
|
-
this.hls.on(
|
|
892
|
-
const id3Tags = (data
|
|
1833
|
+
this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, (_evt, data) => {
|
|
1834
|
+
const id3Tags = ((data == null ? void 0 : data.samples) || []).map((s) => ({
|
|
893
1835
|
key: "ID3",
|
|
894
|
-
value: s
|
|
895
|
-
ptsSeconds: s
|
|
1836
|
+
value: s == null ? void 0 : s.data,
|
|
1837
|
+
ptsSeconds: s == null ? void 0 : s.pts
|
|
896
1838
|
}));
|
|
897
1839
|
id3Tags.forEach((tag) => this.onId3Tag(tag));
|
|
898
1840
|
});
|
|
899
|
-
this.hls.on(
|
|
900
|
-
|
|
901
|
-
const
|
|
1841
|
+
this.hls.on(import_hls2.default.Events.FRAG_CHANGED, (_evt, data) => {
|
|
1842
|
+
var _a2, _b2, _c;
|
|
1843
|
+
const frag = data == null ? void 0 : data.frag;
|
|
1844
|
+
const tagList = frag == null ? void 0 : frag.tagList;
|
|
902
1845
|
if (!Array.isArray(tagList)) return;
|
|
903
1846
|
for (const entry of tagList) {
|
|
904
1847
|
let tag = "";
|
|
905
1848
|
let value = "";
|
|
906
1849
|
if (Array.isArray(entry)) {
|
|
907
|
-
tag = String(entry[0]
|
|
908
|
-
value = String(entry[1]
|
|
1850
|
+
tag = String((_a2 = entry[0]) != null ? _a2 : "");
|
|
1851
|
+
value = String((_b2 = entry[1]) != null ? _b2 : "");
|
|
909
1852
|
} else if (typeof entry === "string") {
|
|
910
1853
|
const idx = entry.indexOf(":");
|
|
911
1854
|
if (idx >= 0) {
|
|
@@ -929,8 +1872,8 @@ var StormcloudVideoPlayer = class {
|
|
|
929
1872
|
const prog = this.parseCueOutCont(value);
|
|
930
1873
|
const marker = {
|
|
931
1874
|
type: "progress",
|
|
932
|
-
...prog
|
|
933
|
-
...prog
|
|
1875
|
+
...(prog == null ? void 0 : prog.duration) !== void 0 ? { durationSeconds: prog.duration } : {},
|
|
1876
|
+
...(prog == null ? void 0 : prog.elapsed) !== void 0 ? { ptsSeconds: prog.elapsed } : {},
|
|
934
1877
|
raw: { tag, value }
|
|
935
1878
|
};
|
|
936
1879
|
this.onScte35Marker(marker);
|
|
@@ -940,7 +1883,7 @@ var StormcloudVideoPlayer = class {
|
|
|
940
1883
|
const attrs = this.parseAttributeList(value);
|
|
941
1884
|
const hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
|
|
942
1885
|
const hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
|
|
943
|
-
const klass = String(attrs["CLASS"]
|
|
1886
|
+
const klass = String((_c = attrs["CLASS"]) != null ? _c : "");
|
|
944
1887
|
const duration = this.toNumber(attrs["DURATION"]);
|
|
945
1888
|
if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
|
|
946
1889
|
const marker = {
|
|
@@ -956,14 +1899,15 @@ var StormcloudVideoPlayer = class {
|
|
|
956
1899
|
}
|
|
957
1900
|
}
|
|
958
1901
|
});
|
|
959
|
-
this.hls.on(
|
|
960
|
-
|
|
1902
|
+
this.hls.on(import_hls2.default.Events.ERROR, (_evt, data) => {
|
|
1903
|
+
var _a2, _b2;
|
|
1904
|
+
if (data == null ? void 0 : data.fatal) {
|
|
961
1905
|
switch (data.type) {
|
|
962
|
-
case
|
|
963
|
-
this.hls
|
|
1906
|
+
case import_hls2.default.ErrorTypes.NETWORK_ERROR:
|
|
1907
|
+
(_a2 = this.hls) == null ? void 0 : _a2.startLoad();
|
|
964
1908
|
break;
|
|
965
|
-
case
|
|
966
|
-
this.hls
|
|
1909
|
+
case import_hls2.default.ErrorTypes.MEDIA_ERROR:
|
|
1910
|
+
(_b2 = this.hls) == null ? void 0 : _b2.recoverMediaError();
|
|
967
1911
|
break;
|
|
968
1912
|
default:
|
|
969
1913
|
this.destroy();
|
|
@@ -1065,11 +2009,12 @@ var StormcloudVideoPlayer = class {
|
|
|
1065
2009
|
}
|
|
1066
2010
|
}
|
|
1067
2011
|
parseScte35FromId3(tag) {
|
|
2012
|
+
var _a, _b, _c, _d;
|
|
1068
2013
|
const text = this.decodeId3ValueToText(tag.value);
|
|
1069
2014
|
if (!text) return void 0;
|
|
1070
2015
|
const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\r\n]*))?/i) || text.match(/CUE-OUT(?::([^\r\n]*))?/i);
|
|
1071
2016
|
if (cueOutMatch) {
|
|
1072
|
-
const arg = (cueOutMatch[1]
|
|
2017
|
+
const arg = ((_a = cueOutMatch[1]) != null ? _a : "").trim();
|
|
1073
2018
|
const dur = this.parseCueOutDuration(arg);
|
|
1074
2019
|
const marker = {
|
|
1075
2020
|
type: "start",
|
|
@@ -1081,12 +2026,12 @@ var StormcloudVideoPlayer = class {
|
|
|
1081
2026
|
}
|
|
1082
2027
|
const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\r\n]*)/i);
|
|
1083
2028
|
if (cueOutContMatch) {
|
|
1084
|
-
const arg = (cueOutContMatch[1]
|
|
2029
|
+
const arg = ((_b = cueOutContMatch[1]) != null ? _b : "").trim();
|
|
1085
2030
|
const cont = this.parseCueOutCont(arg);
|
|
1086
2031
|
const marker = {
|
|
1087
2032
|
type: "progress",
|
|
1088
2033
|
...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},
|
|
1089
|
-
...cont
|
|
2034
|
+
...(cont == null ? void 0 : cont.duration) !== void 0 ? { durationSeconds: cont.duration } : {},
|
|
1090
2035
|
raw: { id3: text }
|
|
1091
2036
|
};
|
|
1092
2037
|
return marker;
|
|
@@ -1102,10 +2047,10 @@ var StormcloudVideoPlayer = class {
|
|
|
1102
2047
|
}
|
|
1103
2048
|
const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\r\n]*)/i);
|
|
1104
2049
|
if (daterangeMatch) {
|
|
1105
|
-
const attrs = this.parseAttributeList(daterangeMatch[1]
|
|
2050
|
+
const attrs = this.parseAttributeList((_c = daterangeMatch[1]) != null ? _c : "");
|
|
1106
2051
|
const hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
|
|
1107
2052
|
const hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
|
|
1108
|
-
const klass = String(attrs["CLASS"]
|
|
2053
|
+
const klass = String((_d = attrs["CLASS"]) != null ? _d : "");
|
|
1109
2054
|
const duration = this.toNumber(attrs["DURATION"]);
|
|
1110
2055
|
if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
|
|
1111
2056
|
const marker = {
|
|
@@ -1162,6 +2107,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1162
2107
|
}
|
|
1163
2108
|
}
|
|
1164
2109
|
onScte35Marker(marker) {
|
|
2110
|
+
var _a, _b;
|
|
1165
2111
|
if (this.config.debugAdTiming) {
|
|
1166
2112
|
console.log("[StormcloudVideoPlayer] SCTE-35 marker detected:", {
|
|
1167
2113
|
type: marker.type,
|
|
@@ -1177,7 +2123,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1177
2123
|
this.expectedAdBreakDurationMs = durationMs;
|
|
1178
2124
|
this.currentAdBreakStartWallClockMs = Date.now();
|
|
1179
2125
|
const isManifestMarker = this.isManifestBasedMarker(marker);
|
|
1180
|
-
const forceImmediate = this.config.immediateManifestAds
|
|
2126
|
+
const forceImmediate = (_a = this.config.immediateManifestAds) != null ? _a : true;
|
|
1181
2127
|
if (this.config.debugAdTiming) {
|
|
1182
2128
|
console.log("[StormcloudVideoPlayer] Ad start decision:", {
|
|
1183
2129
|
isManifestMarker,
|
|
@@ -1194,7 +2140,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1194
2140
|
this.clearAdStartTimer();
|
|
1195
2141
|
this.handleAdStart(marker);
|
|
1196
2142
|
} else if (typeof marker.ptsSeconds === "number") {
|
|
1197
|
-
const tol = this.config.driftToleranceMs
|
|
2143
|
+
const tol = (_b = this.config.driftToleranceMs) != null ? _b : 1e3;
|
|
1198
2144
|
const nowMs = this.video.currentTime * 1e3;
|
|
1199
2145
|
const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
|
|
1200
2146
|
const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);
|
|
@@ -1304,12 +2250,13 @@ var StormcloudVideoPlayer = class {
|
|
|
1304
2250
|
return void 0;
|
|
1305
2251
|
}
|
|
1306
2252
|
parseAttributeList(value) {
|
|
2253
|
+
var _a, _b, _c;
|
|
1307
2254
|
const attrs = {};
|
|
1308
2255
|
const regex = /([A-Z0-9-]+)=(("[^"]*")|([^",]*))(?:,|$)/gi;
|
|
1309
2256
|
let match;
|
|
1310
2257
|
while ((match = regex.exec(value)) !== null) {
|
|
1311
|
-
const key = match[1]
|
|
1312
|
-
let rawVal = match[3]
|
|
2258
|
+
const key = (_a = match[1]) != null ? _a : "";
|
|
2259
|
+
let rawVal = (_c = (_b = match[3]) != null ? _b : match[4]) != null ? _c : "";
|
|
1313
2260
|
if (rawVal.startsWith('"') && rawVal.endsWith('"')) {
|
|
1314
2261
|
rawVal = rawVal.slice(1, -1);
|
|
1315
2262
|
}
|
|
@@ -1473,6 +2420,43 @@ var StormcloudVideoPlayer = class {
|
|
|
1473
2420
|
}
|
|
1474
2421
|
}
|
|
1475
2422
|
async fetchAdConfiguration() {
|
|
2423
|
+
var _a, _b, _c;
|
|
2424
|
+
const vastMode = this.config.vastMode || "default";
|
|
2425
|
+
if (this.config.debugAdTiming) {
|
|
2426
|
+
console.log(
|
|
2427
|
+
"[StormcloudVideoPlayer] VAST mode:",
|
|
2428
|
+
vastMode
|
|
2429
|
+
);
|
|
2430
|
+
}
|
|
2431
|
+
if (vastMode === "adstorm") {
|
|
2432
|
+
if (!this.config.licenseKey) {
|
|
2433
|
+
if (this.config.debugAdTiming) {
|
|
2434
|
+
console.warn(
|
|
2435
|
+
"[StormcloudVideoPlayer] AdStorm mode requires a license key"
|
|
2436
|
+
);
|
|
2437
|
+
}
|
|
2438
|
+
return;
|
|
2439
|
+
}
|
|
2440
|
+
const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;
|
|
2441
|
+
this.apiVastTagUrl = vastEndpoint;
|
|
2442
|
+
if (this.config.debugAdTiming) {
|
|
2443
|
+
console.log(
|
|
2444
|
+
"[StormcloudVideoPlayer] Using AdStorm VAST endpoint:",
|
|
2445
|
+
vastEndpoint
|
|
2446
|
+
);
|
|
2447
|
+
}
|
|
2448
|
+
return;
|
|
2449
|
+
}
|
|
2450
|
+
if (this.config.vastTagUrl) {
|
|
2451
|
+
this.apiVastTagUrl = this.config.vastTagUrl;
|
|
2452
|
+
if (this.config.debugAdTiming) {
|
|
2453
|
+
console.log(
|
|
2454
|
+
"[StormcloudVideoPlayer] Using custom VAST tag URL:",
|
|
2455
|
+
this.apiVastTagUrl
|
|
2456
|
+
);
|
|
2457
|
+
}
|
|
2458
|
+
return;
|
|
2459
|
+
}
|
|
1476
2460
|
const apiUrl = "https://adstorm.co/api-adstorm-dev/adstorm/ads/web";
|
|
1477
2461
|
if (this.config.debugAdTiming) {
|
|
1478
2462
|
console.log(
|
|
@@ -1486,25 +2470,29 @@ var StormcloudVideoPlayer = class {
|
|
|
1486
2470
|
}
|
|
1487
2471
|
const response = await fetch(apiUrl, { headers });
|
|
1488
2472
|
if (!response.ok) {
|
|
1489
|
-
|
|
2473
|
+
if (this.config.debugAdTiming) {
|
|
2474
|
+
console.warn(
|
|
2475
|
+
`[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`
|
|
2476
|
+
);
|
|
2477
|
+
}
|
|
2478
|
+
return;
|
|
1490
2479
|
}
|
|
1491
2480
|
const data = await response.json();
|
|
1492
|
-
const imaPayload = data.response
|
|
2481
|
+
const imaPayload = (_c = (_b = (_a = data.response) == null ? void 0 : _a.ima) == null ? void 0 : _b["publisherdesk.ima"]) == null ? void 0 : _c.payload;
|
|
1493
2482
|
if (imaPayload) {
|
|
1494
2483
|
this.apiVastTagUrl = decodeURIComponent(imaPayload);
|
|
1495
2484
|
if (this.config.debugAdTiming) {
|
|
1496
2485
|
console.log(
|
|
1497
|
-
"[StormcloudVideoPlayer] Extracted VAST tag URL:",
|
|
2486
|
+
"[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:",
|
|
1498
2487
|
this.apiVastTagUrl
|
|
1499
2488
|
);
|
|
1500
2489
|
}
|
|
1501
|
-
}
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
});
|
|
2490
|
+
} else {
|
|
2491
|
+
if (this.config.debugAdTiming) {
|
|
2492
|
+
console.warn(
|
|
2493
|
+
"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response"
|
|
2494
|
+
);
|
|
2495
|
+
}
|
|
1508
2496
|
}
|
|
1509
2497
|
}
|
|
1510
2498
|
getCurrentAdIndex() {
|
|
@@ -1527,11 +2515,12 @@ var StormcloudVideoPlayer = class {
|
|
|
1527
2515
|
return "other";
|
|
1528
2516
|
}
|
|
1529
2517
|
shouldShowNativeControls() {
|
|
2518
|
+
var _a, _b;
|
|
1530
2519
|
const streamType = this.getStreamType();
|
|
1531
2520
|
if (streamType === "other") {
|
|
1532
|
-
return !(this.config.showCustomControls
|
|
2521
|
+
return !((_a = this.config.showCustomControls) != null ? _a : false);
|
|
1533
2522
|
}
|
|
1534
|
-
return !!(this.config.allowNativeHls && !(this.config.showCustomControls
|
|
2523
|
+
return !!(this.config.allowNativeHls && !((_b = this.config.showCustomControls) != null ? _b : false));
|
|
1535
2524
|
}
|
|
1536
2525
|
shouldContinueLiveStreamDuringAds() {
|
|
1537
2526
|
if (this.config.allowNativeHls) {
|
|
@@ -1543,28 +2532,20 @@ var StormcloudVideoPlayer = class {
|
|
|
1543
2532
|
return true;
|
|
1544
2533
|
}
|
|
1545
2534
|
async handleAdStart(_marker) {
|
|
2535
|
+
var _a;
|
|
1546
2536
|
const scheduled = this.findCurrentOrNextBreak(
|
|
1547
2537
|
this.video.currentTime * 1e3
|
|
1548
2538
|
);
|
|
1549
2539
|
const tags = this.selectVastTagsForBreak(scheduled);
|
|
1550
2540
|
let vastTagUrl;
|
|
1551
|
-
let adsNumber = 1;
|
|
1552
2541
|
if (this.apiVastTagUrl) {
|
|
1553
2542
|
vastTagUrl = this.apiVastTagUrl;
|
|
1554
|
-
|
|
1555
|
-
const isHls = this.config.src.includes(".m3u8") || this.config.src.includes("hls");
|
|
1556
|
-
if (isHls && this.vastConfig.cue_tones?.number_ads) {
|
|
1557
|
-
adsNumber = this.vastConfig.cue_tones.number_ads;
|
|
1558
|
-
} else if (!isHls && this.vastConfig.timer_vod?.number_ads) {
|
|
1559
|
-
adsNumber = this.vastConfig.timer_vod.number_ads;
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
this.adPodQueue = new Array(adsNumber - 1).fill(vastTagUrl);
|
|
2543
|
+
this.adPodQueue = [];
|
|
1563
2544
|
this.currentAdIndex = 0;
|
|
1564
|
-
this.totalAdsInBreak =
|
|
2545
|
+
this.totalAdsInBreak = 1;
|
|
1565
2546
|
if (this.config.debugAdTiming) {
|
|
1566
2547
|
console.log(
|
|
1567
|
-
|
|
2548
|
+
"[StormcloudVideoPlayer] Using VAST endpoint:",
|
|
1568
2549
|
vastTagUrl
|
|
1569
2550
|
);
|
|
1570
2551
|
}
|
|
@@ -1602,17 +2583,18 @@ var StormcloudVideoPlayer = class {
|
|
|
1602
2583
|
this.handleAdFailure();
|
|
1603
2584
|
}
|
|
1604
2585
|
}
|
|
1605
|
-
if (this.expectedAdBreakDurationMs == null && scheduled
|
|
2586
|
+
if (this.expectedAdBreakDurationMs == null && (scheduled == null ? void 0 : scheduled.durationMs) != null) {
|
|
1606
2587
|
this.expectedAdBreakDurationMs = scheduled.durationMs;
|
|
1607
|
-
this.currentAdBreakStartWallClockMs = this.currentAdBreakStartWallClockMs
|
|
2588
|
+
this.currentAdBreakStartWallClockMs = (_a = this.currentAdBreakStartWallClockMs) != null ? _a : Date.now();
|
|
1608
2589
|
this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
|
|
1609
2590
|
}
|
|
1610
2591
|
}
|
|
1611
2592
|
findCurrentOrNextBreak(nowMs) {
|
|
2593
|
+
var _a;
|
|
1612
2594
|
const schedule = [];
|
|
1613
2595
|
let candidate;
|
|
1614
2596
|
for (const b of schedule) {
|
|
1615
|
-
const tol = this.config.driftToleranceMs
|
|
2597
|
+
const tol = (_a = this.config.driftToleranceMs) != null ? _a : 1e3;
|
|
1616
2598
|
if (b.startTimeMs <= nowMs + tol && (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))) {
|
|
1617
2599
|
candidate = b;
|
|
1618
2600
|
}
|
|
@@ -1628,7 +2610,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1628
2610
|
}
|
|
1629
2611
|
}
|
|
1630
2612
|
async handleMidAdJoin(adBreak, nowMs) {
|
|
1631
|
-
|
|
2613
|
+
var _a;
|
|
2614
|
+
const durationMs = (_a = adBreak.durationMs) != null ? _a : 0;
|
|
1632
2615
|
const endMs = adBreak.startTimeMs + durationMs;
|
|
1633
2616
|
if (durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs) {
|
|
1634
2617
|
const remainingMs = endMs - nowMs;
|
|
@@ -1729,6 +2712,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1729
2712
|
}
|
|
1730
2713
|
}
|
|
1731
2714
|
handleAdFailure() {
|
|
2715
|
+
var _a;
|
|
1732
2716
|
if (this.config.debugAdTiming) {
|
|
1733
2717
|
console.log(
|
|
1734
2718
|
"[StormcloudVideoPlayer] Handling ad failure - resuming content",
|
|
@@ -1761,7 +2745,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1761
2745
|
if (this.config.debugAdTiming) {
|
|
1762
2746
|
console.log("[StormcloudVideoPlayer] Resuming paused video");
|
|
1763
2747
|
}
|
|
1764
|
-
this.video.play()
|
|
2748
|
+
(_a = this.video.play()) == null ? void 0 : _a.catch((error) => {
|
|
1765
2749
|
if (this.config.debugAdTiming) {
|
|
1766
2750
|
console.error(
|
|
1767
2751
|
"[StormcloudVideoPlayer] Failed to resume video after ad failure:",
|
|
@@ -1776,8 +2760,9 @@ var StormcloudVideoPlayer = class {
|
|
|
1776
2760
|
}
|
|
1777
2761
|
}
|
|
1778
2762
|
startAdFailsafeTimer() {
|
|
2763
|
+
var _a;
|
|
1779
2764
|
this.clearAdFailsafeTimer();
|
|
1780
|
-
const failsafeMs = this.config.adFailsafeTimeoutMs
|
|
2765
|
+
const failsafeMs = (_a = this.config.adFailsafeTimeoutMs) != null ? _a : 1e4;
|
|
1781
2766
|
if (this.config.debugAdTiming) {
|
|
1782
2767
|
console.log(
|
|
1783
2768
|
`[StormcloudVideoPlayer] Starting failsafe timer (${failsafeMs}ms)`
|
|
@@ -1913,6 +2898,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1913
2898
|
}
|
|
1914
2899
|
}
|
|
1915
2900
|
destroy() {
|
|
2901
|
+
var _a, _b;
|
|
1916
2902
|
this.clearAdStartTimer();
|
|
1917
2903
|
this.clearAdStopTimer();
|
|
1918
2904
|
this.clearAdFailsafeTimer();
|
|
@@ -1920,8 +2906,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1920
2906
|
clearInterval(this.heartbeatInterval);
|
|
1921
2907
|
this.heartbeatInterval = void 0;
|
|
1922
2908
|
}
|
|
1923
|
-
this.hls
|
|
1924
|
-
this.ima
|
|
2909
|
+
(_a = this.hls) == null ? void 0 : _a.destroy();
|
|
2910
|
+
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
1925
2911
|
}
|
|
1926
2912
|
};
|
|
1927
2913
|
|
|
@@ -1961,6 +2947,7 @@ var HlsPlayer = class extends import_react.Component {
|
|
|
1961
2947
|
this.player = null;
|
|
1962
2948
|
this.mounted = false;
|
|
1963
2949
|
this.load = async () => {
|
|
2950
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1964
2951
|
if (!this.props.videoElement || !this.props.src) return;
|
|
1965
2952
|
try {
|
|
1966
2953
|
if (this.player) {
|
|
@@ -1997,27 +2984,29 @@ var HlsPlayer = class extends import_react.Component {
|
|
|
1997
2984
|
if (this.props.adFailsafeTimeoutMs !== void 0)
|
|
1998
2985
|
config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;
|
|
1999
2986
|
this.player = new StormcloudVideoPlayer(config);
|
|
2000
|
-
this.props.onMount
|
|
2987
|
+
(_b = (_a = this.props).onMount) == null ? void 0 : _b.call(_a, this);
|
|
2001
2988
|
await this.player.load();
|
|
2002
2989
|
if (this.mounted) {
|
|
2003
|
-
this.props.onReady
|
|
2990
|
+
(_d = (_c = this.props).onReady) == null ? void 0 : _d.call(_c);
|
|
2004
2991
|
}
|
|
2005
2992
|
} catch (error) {
|
|
2006
2993
|
if (this.mounted) {
|
|
2007
|
-
this.props.onError
|
|
2994
|
+
(_f = (_e = this.props).onError) == null ? void 0 : _f.call(_e, error);
|
|
2008
2995
|
}
|
|
2009
2996
|
}
|
|
2010
2997
|
};
|
|
2011
2998
|
this.play = () => {
|
|
2999
|
+
var _a, _b;
|
|
2012
3000
|
if (this.props.videoElement) {
|
|
2013
3001
|
this.props.videoElement.play();
|
|
2014
|
-
this.props.onPlay
|
|
3002
|
+
(_b = (_a = this.props).onPlay) == null ? void 0 : _b.call(_a);
|
|
2015
3003
|
}
|
|
2016
3004
|
};
|
|
2017
3005
|
this.pause = () => {
|
|
3006
|
+
var _a, _b;
|
|
2018
3007
|
if (this.props.videoElement) {
|
|
2019
3008
|
this.props.videoElement.pause();
|
|
2020
|
-
this.props.onPause
|
|
3009
|
+
(_b = (_a = this.props).onPause) == null ? void 0 : _b.call(_a);
|
|
2021
3010
|
}
|
|
2022
3011
|
};
|
|
2023
3012
|
this.stop = () => {
|