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