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
package/lib/players/index.cjs
CHANGED
|
@@ -75,7 +75,167 @@ var canPlay = {
|
|
|
75
75
|
var import_react2 = require("react");
|
|
76
76
|
|
|
77
77
|
// src/player/StormcloudVideoPlayer.ts
|
|
78
|
-
var
|
|
78
|
+
var import_hls2 = __toESM(require("hls.js"), 1);
|
|
79
|
+
|
|
80
|
+
// src/utils/browserCompat.ts
|
|
81
|
+
function getChromeVersion(ua) {
|
|
82
|
+
const match = ua.match(/Chrome\/(\d+)/);
|
|
83
|
+
return match && match[1] ? parseInt(match[1], 10) : 0;
|
|
84
|
+
}
|
|
85
|
+
function getWebKitVersion(ua) {
|
|
86
|
+
const match = ua.match(/AppleWebKit\/(\d+)/);
|
|
87
|
+
return match && match[1] ? parseInt(match[1], 10) : 0;
|
|
88
|
+
}
|
|
89
|
+
function getPlatform() {
|
|
90
|
+
var _a;
|
|
91
|
+
if ("userAgentData" in navigator && ((_a = navigator.userAgentData) == null ? void 0 : _a.platform)) {
|
|
92
|
+
return navigator.userAgentData.platform;
|
|
93
|
+
}
|
|
94
|
+
const ua = navigator.userAgent;
|
|
95
|
+
if (/Mac|iPhone|iPad|iPod/i.test(ua)) {
|
|
96
|
+
return /iPhone|iPad|iPod/i.test(ua) ? "iPhone" : "MacIntel";
|
|
97
|
+
}
|
|
98
|
+
if (/Win/i.test(ua)) {
|
|
99
|
+
return "Win32";
|
|
100
|
+
}
|
|
101
|
+
if (/Linux/i.test(ua)) {
|
|
102
|
+
return /Android/i.test(ua) ? "Linux armv8l" : "Linux x86_64";
|
|
103
|
+
}
|
|
104
|
+
if (/CrOS/i.test(ua)) {
|
|
105
|
+
return "CrOS";
|
|
106
|
+
}
|
|
107
|
+
return navigator.platform || "Unknown";
|
|
108
|
+
}
|
|
109
|
+
function detectBrowser() {
|
|
110
|
+
const ua = navigator.userAgent;
|
|
111
|
+
const platform = getPlatform();
|
|
112
|
+
let name = "Unknown";
|
|
113
|
+
let version = "0";
|
|
114
|
+
let majorVersion = 0;
|
|
115
|
+
let isSmartTV = false;
|
|
116
|
+
let isLegacyTV = false;
|
|
117
|
+
let supportsIMA = true;
|
|
118
|
+
let supportsModernJS = true;
|
|
119
|
+
let recommendedAdPlayer = "ima";
|
|
120
|
+
if (/Web0S|webOS/i.test(ua)) {
|
|
121
|
+
name = "LG WebOS";
|
|
122
|
+
isSmartTV = true;
|
|
123
|
+
const match = ua.match(/Web0S[/\s]*([\d.]+)/i);
|
|
124
|
+
version = match && match[1] ? match[1] : "Unknown";
|
|
125
|
+
if (version !== "Unknown") {
|
|
126
|
+
const parts = version.split(".");
|
|
127
|
+
majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;
|
|
128
|
+
}
|
|
129
|
+
} else if (/Tizen/i.test(ua)) {
|
|
130
|
+
name = "Samsung Tizen";
|
|
131
|
+
isSmartTV = true;
|
|
132
|
+
const match = ua.match(/Tizen[/\s]*([\d.]+)/i);
|
|
133
|
+
version = match && match[1] ? match[1] : "Unknown";
|
|
134
|
+
if (version !== "Unknown") {
|
|
135
|
+
const parts = version.split(".");
|
|
136
|
+
majorVersion = parts[0] ? parseInt(parts[0], 10) : 0;
|
|
137
|
+
}
|
|
138
|
+
} else if (/SMART-TV|SmartTV/i.test(ua)) {
|
|
139
|
+
name = "Smart TV";
|
|
140
|
+
isSmartTV = true;
|
|
141
|
+
} else if (/NetCast/i.test(ua)) {
|
|
142
|
+
name = "LG NetCast";
|
|
143
|
+
isSmartTV = true;
|
|
144
|
+
isLegacyTV = true;
|
|
145
|
+
} else if (/BRAVIA/i.test(ua)) {
|
|
146
|
+
name = "Sony BRAVIA";
|
|
147
|
+
isSmartTV = true;
|
|
148
|
+
}
|
|
149
|
+
const chromeVersion = getChromeVersion(ua);
|
|
150
|
+
const webkitVersion = getWebKitVersion(ua);
|
|
151
|
+
if (chromeVersion > 0) {
|
|
152
|
+
if (!isSmartTV) {
|
|
153
|
+
name = "Chrome";
|
|
154
|
+
version = chromeVersion.toString();
|
|
155
|
+
majorVersion = chromeVersion;
|
|
156
|
+
}
|
|
157
|
+
if (chromeVersion < 50) {
|
|
158
|
+
supportsIMA = false;
|
|
159
|
+
supportsModernJS = false;
|
|
160
|
+
isLegacyTV = true;
|
|
161
|
+
recommendedAdPlayer = "hls";
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (webkitVersion > 0 && webkitVersion < 600) {
|
|
165
|
+
supportsModernJS = false;
|
|
166
|
+
if (isSmartTV) {
|
|
167
|
+
isLegacyTV = true;
|
|
168
|
+
supportsIMA = false;
|
|
169
|
+
recommendedAdPlayer = "hls";
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (typeof Promise === "undefined" || typeof Map === "undefined" || typeof Set === "undefined") {
|
|
173
|
+
supportsModernJS = false;
|
|
174
|
+
supportsIMA = false;
|
|
175
|
+
recommendedAdPlayer = "hls";
|
|
176
|
+
}
|
|
177
|
+
if (typeof URLSearchParams === "undefined") {
|
|
178
|
+
supportsModernJS = false;
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
name,
|
|
182
|
+
version,
|
|
183
|
+
majorVersion,
|
|
184
|
+
isSmartTV,
|
|
185
|
+
isLegacyTV,
|
|
186
|
+
platform,
|
|
187
|
+
supportsIMA,
|
|
188
|
+
supportsModernJS,
|
|
189
|
+
recommendedAdPlayer
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function supportsGoogleIMA() {
|
|
193
|
+
const browser = detectBrowser();
|
|
194
|
+
if (browser.isLegacyTV) {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
if (typeof document === "undefined" || typeof document.createElement !== "function") {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
const video = document.createElement("video");
|
|
202
|
+
if (!video) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
} catch (e) {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
if (typeof Promise === "undefined") {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
return browser.supportsIMA;
|
|
212
|
+
}
|
|
213
|
+
function logBrowserInfo(debug = false) {
|
|
214
|
+
if (!debug) return;
|
|
215
|
+
const browser = detectBrowser();
|
|
216
|
+
const imaSupport = supportsGoogleIMA();
|
|
217
|
+
console.log("[StormcloudVideoPlayer] Browser Compatibility Info:", {
|
|
218
|
+
browser: `${browser.name} ${browser.version}`,
|
|
219
|
+
platform: browser.platform,
|
|
220
|
+
isSmartTV: browser.isSmartTV,
|
|
221
|
+
isLegacyTV: browser.isLegacyTV,
|
|
222
|
+
supportsIMA: imaSupport,
|
|
223
|
+
supportsModernJS: browser.supportsModernJS,
|
|
224
|
+
recommendedAdPlayer: browser.recommendedAdPlayer,
|
|
225
|
+
userAgent: navigator.userAgent
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
function getBrowserConfigOverrides() {
|
|
229
|
+
const browser = detectBrowser();
|
|
230
|
+
const overrides = {};
|
|
231
|
+
if (browser.isLegacyTV || !browser.supportsIMA) {
|
|
232
|
+
overrides.adPlayerType = "hls";
|
|
233
|
+
}
|
|
234
|
+
if (browser.isSmartTV) {
|
|
235
|
+
overrides.allowNativeHls = true;
|
|
236
|
+
}
|
|
237
|
+
return overrides;
|
|
238
|
+
}
|
|
79
239
|
|
|
80
240
|
// src/sdk/ima.ts
|
|
81
241
|
function createImaController(video, options) {
|
|
@@ -93,9 +253,18 @@ function createImaController(video, options) {
|
|
|
93
253
|
}
|
|
94
254
|
}
|
|
95
255
|
function ensureImaLoaded() {
|
|
256
|
+
var _a, _b, _c;
|
|
257
|
+
if (!supportsGoogleIMA()) {
|
|
258
|
+
console.warn(
|
|
259
|
+
"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead."
|
|
260
|
+
);
|
|
261
|
+
return Promise.reject(
|
|
262
|
+
new Error("Google IMA SDK not supported on this browser")
|
|
263
|
+
);
|
|
264
|
+
}
|
|
96
265
|
try {
|
|
97
266
|
const frameEl = window.frameElement;
|
|
98
|
-
const sandboxAttr = frameEl
|
|
267
|
+
const sandboxAttr = ((_a = frameEl == null ? void 0 : frameEl.getAttribute) == null ? void 0 : _a.call(frameEl, "sandbox")) || "";
|
|
99
268
|
if (sandboxAttr) {
|
|
100
269
|
const tokens = new Set(
|
|
101
270
|
sandboxAttr.split(/\s+/).map((t) => t.trim()).filter((t) => t.length > 0)
|
|
@@ -109,13 +278,13 @@ function createImaController(video, options) {
|
|
|
109
278
|
}
|
|
110
279
|
} catch {
|
|
111
280
|
}
|
|
112
|
-
if (typeof window !== "undefined" && window.google
|
|
281
|
+
if (typeof window !== "undefined" && ((_b = window.google) == null ? void 0 : _b.ima))
|
|
113
282
|
return Promise.resolve();
|
|
114
283
|
const existing = document.querySelector(
|
|
115
284
|
'script[data-ima="true"]'
|
|
116
285
|
);
|
|
117
286
|
if (existing) {
|
|
118
|
-
if (window.google
|
|
287
|
+
if ((_c = window.google) == null ? void 0 : _c.ima) {
|
|
119
288
|
return Promise.resolve();
|
|
120
289
|
}
|
|
121
290
|
return new Promise((resolve, reject) => {
|
|
@@ -173,6 +342,7 @@ function createImaController(video, options) {
|
|
|
173
342
|
return {
|
|
174
343
|
initialize() {
|
|
175
344
|
ensureImaLoaded().then(() => {
|
|
345
|
+
var _a, _b;
|
|
176
346
|
const google = window.google;
|
|
177
347
|
if (!adDisplayContainer) {
|
|
178
348
|
const container = document.createElement("div");
|
|
@@ -186,14 +356,14 @@ function createImaController(video, options) {
|
|
|
186
356
|
container.style.justifyContent = "center";
|
|
187
357
|
container.style.pointerEvents = "none";
|
|
188
358
|
container.style.zIndex = "2";
|
|
189
|
-
video.parentElement
|
|
359
|
+
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
190
360
|
adContainerEl = container;
|
|
191
361
|
adDisplayContainer = new google.ima.AdDisplayContainer(
|
|
192
362
|
container,
|
|
193
363
|
video
|
|
194
364
|
);
|
|
195
365
|
try {
|
|
196
|
-
adDisplayContainer.initialize
|
|
366
|
+
(_b = adDisplayContainer.initialize) == null ? void 0 : _b.call(adDisplayContainer);
|
|
197
367
|
} catch {
|
|
198
368
|
}
|
|
199
369
|
}
|
|
@@ -278,6 +448,7 @@ function createImaController(video, options) {
|
|
|
278
448
|
adsManager.addEventListener(
|
|
279
449
|
AdErrorEvent.AD_ERROR,
|
|
280
450
|
(errorEvent) => {
|
|
451
|
+
var _a;
|
|
281
452
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
282
453
|
destroyAdsManager();
|
|
283
454
|
adPlaying = false;
|
|
@@ -308,10 +479,10 @@ function createImaController(video, options) {
|
|
|
308
479
|
"[IMA] Max retries reached, emitting ad_error"
|
|
309
480
|
);
|
|
310
481
|
emit("ad_error");
|
|
311
|
-
if (!options
|
|
482
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
312
483
|
if (video.paused) {
|
|
313
484
|
console.log("[IMA] Resuming paused video after ad error");
|
|
314
|
-
video.play()
|
|
485
|
+
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
315
486
|
});
|
|
316
487
|
}
|
|
317
488
|
}
|
|
@@ -322,7 +493,7 @@ function createImaController(video, options) {
|
|
|
322
493
|
AdEvent.CONTENT_PAUSE_REQUESTED,
|
|
323
494
|
() => {
|
|
324
495
|
console.log("[IMA] Content pause requested");
|
|
325
|
-
if (!options
|
|
496
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
326
497
|
video.pause();
|
|
327
498
|
console.log("[IMA] Video paused (VOD mode)");
|
|
328
499
|
} else {
|
|
@@ -348,6 +519,7 @@ function createImaController(video, options) {
|
|
|
348
519
|
adsManager.addEventListener(
|
|
349
520
|
AdEvent.CONTENT_RESUME_REQUESTED,
|
|
350
521
|
() => {
|
|
522
|
+
var _a;
|
|
351
523
|
console.log("[IMA] Content resume requested");
|
|
352
524
|
adPlaying = false;
|
|
353
525
|
video.muted = originalMutedState;
|
|
@@ -358,8 +530,8 @@ function createImaController(video, options) {
|
|
|
358
530
|
"[IMA] Ad container hidden - pointer events disabled"
|
|
359
531
|
);
|
|
360
532
|
}
|
|
361
|
-
if (!options
|
|
362
|
-
video.play()
|
|
533
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
534
|
+
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
363
535
|
});
|
|
364
536
|
console.log("[IMA] Video resumed (VOD mode)");
|
|
365
537
|
} else {
|
|
@@ -381,7 +553,7 @@ function createImaController(video, options) {
|
|
|
381
553
|
"[IMA] Ad container hidden after all ads completed"
|
|
382
554
|
);
|
|
383
555
|
}
|
|
384
|
-
if (!options
|
|
556
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
385
557
|
video.play().catch(() => {
|
|
386
558
|
});
|
|
387
559
|
console.log(
|
|
@@ -409,7 +581,7 @@ function createImaController(video, options) {
|
|
|
409
581
|
adContainerEl.style.display = "none";
|
|
410
582
|
console.log("[IMA] Ad container hidden after setup error");
|
|
411
583
|
}
|
|
412
|
-
if (!options
|
|
584
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
413
585
|
if (video.paused) {
|
|
414
586
|
console.log("[IMA] Resuming paused video after setup error");
|
|
415
587
|
video.play().catch(() => {
|
|
@@ -437,7 +609,7 @@ function createImaController(video, options) {
|
|
|
437
609
|
adContainerEl.style.display = "none";
|
|
438
610
|
console.log("[IMA] Ad container hidden after loader error");
|
|
439
611
|
}
|
|
440
|
-
if (!options
|
|
612
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
441
613
|
if (video.paused) {
|
|
442
614
|
console.log("[IMA] Resuming paused video after loader error");
|
|
443
615
|
video.play().catch(() => {
|
|
@@ -459,14 +631,15 @@ function createImaController(video, options) {
|
|
|
459
631
|
return adsLoadedPromise;
|
|
460
632
|
} catch (error) {
|
|
461
633
|
console.error("[IMA] Failed to request ads:", error);
|
|
462
|
-
currentReject
|
|
634
|
+
currentReject == null ? void 0 : currentReject(error);
|
|
463
635
|
adsLoadedReject = void 0;
|
|
464
636
|
adsLoadedResolve = void 0;
|
|
465
637
|
return Promise.reject(error);
|
|
466
638
|
}
|
|
467
639
|
},
|
|
468
640
|
async play() {
|
|
469
|
-
|
|
641
|
+
var _a, _b;
|
|
642
|
+
if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
|
|
470
643
|
console.warn(
|
|
471
644
|
"[IMA] Cannot play ad: IMA SDK or ad container not available"
|
|
472
645
|
);
|
|
@@ -488,14 +661,15 @@ function createImaController(video, options) {
|
|
|
488
661
|
} catch (error) {
|
|
489
662
|
console.error("[IMA] Error starting ad playback:", error);
|
|
490
663
|
adPlaying = false;
|
|
491
|
-
if (!options
|
|
492
|
-
video.play()
|
|
664
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
665
|
+
(_b = video.play()) == null ? void 0 : _b.catch(() => {
|
|
493
666
|
});
|
|
494
667
|
}
|
|
495
668
|
return Promise.reject(error);
|
|
496
669
|
}
|
|
497
670
|
},
|
|
498
671
|
async stop() {
|
|
672
|
+
var _a;
|
|
499
673
|
adPlaying = false;
|
|
500
674
|
video.muted = originalMutedState;
|
|
501
675
|
if (adContainerEl) {
|
|
@@ -504,11 +678,11 @@ function createImaController(video, options) {
|
|
|
504
678
|
console.log("[IMA] Ad container hidden after stop");
|
|
505
679
|
}
|
|
506
680
|
try {
|
|
507
|
-
adsManager
|
|
681
|
+
(_a = adsManager == null ? void 0 : adsManager.stop) == null ? void 0 : _a.call(adsManager);
|
|
508
682
|
} catch {
|
|
509
683
|
}
|
|
510
684
|
destroyAdsManager();
|
|
511
|
-
if (!options
|
|
685
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
512
686
|
video.play().catch(() => {
|
|
513
687
|
});
|
|
514
688
|
console.log("[IMA] Video resumed after stop (VOD mode)");
|
|
@@ -517,6 +691,7 @@ function createImaController(video, options) {
|
|
|
517
691
|
}
|
|
518
692
|
},
|
|
519
693
|
destroy() {
|
|
694
|
+
var _a;
|
|
520
695
|
destroyAdsManager();
|
|
521
696
|
adPlaying = false;
|
|
522
697
|
video.muted = originalMutedState;
|
|
@@ -525,10 +700,10 @@ function createImaController(video, options) {
|
|
|
525
700
|
adContainerEl.style.display = "none";
|
|
526
701
|
}
|
|
527
702
|
try {
|
|
528
|
-
adsLoader
|
|
703
|
+
(_a = adsLoader == null ? void 0 : adsLoader.destroy) == null ? void 0 : _a.call(adsLoader);
|
|
529
704
|
} catch {
|
|
530
705
|
}
|
|
531
|
-
if (adContainerEl
|
|
706
|
+
if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
|
|
532
707
|
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
533
708
|
}
|
|
534
709
|
adContainerEl = void 0;
|
|
@@ -539,7 +714,8 @@ function createImaController(video, options) {
|
|
|
539
714
|
return adPlaying;
|
|
540
715
|
},
|
|
541
716
|
resize(width, height) {
|
|
542
|
-
|
|
717
|
+
var _a;
|
|
718
|
+
if (!adsManager || !((_a = window.google) == null ? void 0 : _a.ima)) {
|
|
543
719
|
console.warn(
|
|
544
720
|
"[IMA] Cannot resize: No ads manager or IMA SDK available"
|
|
545
721
|
);
|
|
@@ -557,7 +733,8 @@ function createImaController(video, options) {
|
|
|
557
733
|
listeners.get(event).add(listener);
|
|
558
734
|
},
|
|
559
735
|
off(event, listener) {
|
|
560
|
-
|
|
736
|
+
var _a;
|
|
737
|
+
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
561
738
|
},
|
|
562
739
|
updateOriginalMutedState(muted) {
|
|
563
740
|
originalMutedState = muted;
|
|
@@ -588,9 +765,533 @@ function createImaController(video, options) {
|
|
|
588
765
|
};
|
|
589
766
|
}
|
|
590
767
|
|
|
768
|
+
// src/sdk/hlsAdPlayer.ts
|
|
769
|
+
var import_hls = __toESM(require("hls.js"), 1);
|
|
770
|
+
function createHlsAdPlayer(contentVideo, options) {
|
|
771
|
+
let adPlaying = false;
|
|
772
|
+
let originalMutedState = false;
|
|
773
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
774
|
+
const licenseKey = options == null ? void 0 : options.licenseKey;
|
|
775
|
+
const mainHlsInstance = options == null ? void 0 : options.mainHlsInstance;
|
|
776
|
+
let adVideoElement;
|
|
777
|
+
let adHls;
|
|
778
|
+
let adContainerEl;
|
|
779
|
+
let currentAd;
|
|
780
|
+
let sessionId;
|
|
781
|
+
let trackingFired = {
|
|
782
|
+
impression: false,
|
|
783
|
+
start: false,
|
|
784
|
+
firstQuartile: false,
|
|
785
|
+
midpoint: false,
|
|
786
|
+
thirdQuartile: false,
|
|
787
|
+
complete: false
|
|
788
|
+
};
|
|
789
|
+
function emit(event, payload) {
|
|
790
|
+
const set = listeners.get(event);
|
|
791
|
+
if (!set) return;
|
|
792
|
+
for (const fn of Array.from(set)) {
|
|
793
|
+
try {
|
|
794
|
+
fn(payload);
|
|
795
|
+
} catch (error) {
|
|
796
|
+
console.warn(`[HlsAdPlayer] Error in event listener for ${event}:`, error);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
function generateSessionId() {
|
|
801
|
+
return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
802
|
+
}
|
|
803
|
+
function fireTrackingPixels(urls) {
|
|
804
|
+
if (!urls || urls.length === 0) return;
|
|
805
|
+
urls.forEach((url) => {
|
|
806
|
+
try {
|
|
807
|
+
let trackingUrl = url;
|
|
808
|
+
if (sessionId) {
|
|
809
|
+
trackingUrl = `${trackingUrl}${trackingUrl.includes("?") ? "&" : "?"}session_id=${sessionId}`;
|
|
810
|
+
}
|
|
811
|
+
if (licenseKey) {
|
|
812
|
+
trackingUrl = `${trackingUrl}${trackingUrl.includes("?") ? "&" : "?"}license_key=${licenseKey}`;
|
|
813
|
+
}
|
|
814
|
+
const img = new Image(1, 1);
|
|
815
|
+
img.src = trackingUrl;
|
|
816
|
+
console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);
|
|
817
|
+
} catch (error) {
|
|
818
|
+
console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);
|
|
819
|
+
}
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
function getMainStreamQuality() {
|
|
823
|
+
if (!mainHlsInstance || !mainHlsInstance.levels) {
|
|
824
|
+
return null;
|
|
825
|
+
}
|
|
826
|
+
const currentLevel = mainHlsInstance.currentLevel;
|
|
827
|
+
if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {
|
|
828
|
+
const autoLevel = mainHlsInstance.loadLevel;
|
|
829
|
+
if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {
|
|
830
|
+
const level2 = mainHlsInstance.levels[autoLevel];
|
|
831
|
+
return {
|
|
832
|
+
width: level2.width || 1920,
|
|
833
|
+
height: level2.height || 1080,
|
|
834
|
+
bitrate: level2.bitrate || 5e6
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
return null;
|
|
838
|
+
}
|
|
839
|
+
const level = mainHlsInstance.levels[currentLevel];
|
|
840
|
+
return {
|
|
841
|
+
width: level.width || 1920,
|
|
842
|
+
height: level.height || 1080,
|
|
843
|
+
bitrate: level.bitrate || 5e6
|
|
844
|
+
};
|
|
845
|
+
}
|
|
846
|
+
function selectBestMediaFile(mediaFiles) {
|
|
847
|
+
if (mediaFiles.length === 0) {
|
|
848
|
+
throw new Error("No media files available");
|
|
849
|
+
}
|
|
850
|
+
const firstFile = mediaFiles[0];
|
|
851
|
+
if (!firstFile) {
|
|
852
|
+
throw new Error("No media files available");
|
|
853
|
+
}
|
|
854
|
+
if (mediaFiles.length === 1) {
|
|
855
|
+
return firstFile;
|
|
856
|
+
}
|
|
857
|
+
const mainQuality = getMainStreamQuality();
|
|
858
|
+
if (!mainQuality) {
|
|
859
|
+
console.log("[HlsAdPlayer] No main stream quality info, using first media file");
|
|
860
|
+
return firstFile;
|
|
861
|
+
}
|
|
862
|
+
console.log("[HlsAdPlayer] Main stream quality:", mainQuality);
|
|
863
|
+
const scoredFiles = mediaFiles.map((file) => {
|
|
864
|
+
const widthDiff = Math.abs(file.width - mainQuality.width);
|
|
865
|
+
const heightDiff = Math.abs(file.height - mainQuality.height);
|
|
866
|
+
const resolutionDiff = widthDiff + heightDiff;
|
|
867
|
+
const fileBitrate = (file.bitrate || 5e3) * 1e3;
|
|
868
|
+
const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);
|
|
869
|
+
const score = resolutionDiff * 2 + bitrateDiff / 1e3;
|
|
870
|
+
return { file, score, resolutionDiff, bitrateDiff };
|
|
871
|
+
});
|
|
872
|
+
scoredFiles.sort((a, b) => a.score - b.score);
|
|
873
|
+
const bestMatch = scoredFiles[0];
|
|
874
|
+
if (!bestMatch) {
|
|
875
|
+
console.log("[HlsAdPlayer] No best match found, using first media file");
|
|
876
|
+
return firstFile;
|
|
877
|
+
}
|
|
878
|
+
console.log("[HlsAdPlayer] Selected media file:", {
|
|
879
|
+
url: bestMatch.file.url,
|
|
880
|
+
resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,
|
|
881
|
+
bitrate: bestMatch.file.bitrate,
|
|
882
|
+
score: bestMatch.score,
|
|
883
|
+
resolutionDiff: bestMatch.resolutionDiff,
|
|
884
|
+
bitrateDiff: bestMatch.bitrateDiff
|
|
885
|
+
});
|
|
886
|
+
return bestMatch.file;
|
|
887
|
+
}
|
|
888
|
+
function parseVastXml(xmlString) {
|
|
889
|
+
var _a, _b, _c, _d;
|
|
890
|
+
try {
|
|
891
|
+
const parser = new DOMParser();
|
|
892
|
+
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
|
|
893
|
+
const parserError = xmlDoc.querySelector("parsererror");
|
|
894
|
+
if (parserError) {
|
|
895
|
+
console.error("[HlsAdPlayer] XML parsing error:", parserError.textContent);
|
|
896
|
+
return null;
|
|
897
|
+
}
|
|
898
|
+
const adElement = xmlDoc.querySelector("Ad");
|
|
899
|
+
if (!adElement) {
|
|
900
|
+
console.warn("[HlsAdPlayer] No Ad element found in VAST XML");
|
|
901
|
+
return null;
|
|
902
|
+
}
|
|
903
|
+
const adId = adElement.getAttribute("id") || "unknown";
|
|
904
|
+
const title = ((_a = xmlDoc.querySelector("AdTitle")) == null ? void 0 : _a.textContent) || "Ad";
|
|
905
|
+
const durationText = ((_b = xmlDoc.querySelector("Duration")) == null ? void 0 : _b.textContent) || "00:00:30";
|
|
906
|
+
const durationParts = durationText.split(":");
|
|
907
|
+
const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
|
|
908
|
+
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
909
|
+
const mediaFiles = [];
|
|
910
|
+
mediaFileElements.forEach((mf) => {
|
|
911
|
+
var _a2;
|
|
912
|
+
const type = mf.getAttribute("type") || "";
|
|
913
|
+
if (type === "application/x-mpegURL" || type.includes("m3u8")) {
|
|
914
|
+
const bitrateAttr = mf.getAttribute("bitrate");
|
|
915
|
+
const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
|
|
916
|
+
mediaFiles.push({
|
|
917
|
+
url: ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "",
|
|
918
|
+
type,
|
|
919
|
+
width: parseInt(mf.getAttribute("width") || "1920", 10),
|
|
920
|
+
height: parseInt(mf.getAttribute("height") || "1080", 10),
|
|
921
|
+
bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
});
|
|
925
|
+
if (mediaFiles.length === 0) {
|
|
926
|
+
console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
|
|
927
|
+
return null;
|
|
928
|
+
}
|
|
929
|
+
const trackingUrls = {
|
|
930
|
+
impression: [],
|
|
931
|
+
start: [],
|
|
932
|
+
firstQuartile: [],
|
|
933
|
+
midpoint: [],
|
|
934
|
+
thirdQuartile: [],
|
|
935
|
+
complete: [],
|
|
936
|
+
mute: [],
|
|
937
|
+
unmute: [],
|
|
938
|
+
pause: [],
|
|
939
|
+
resume: [],
|
|
940
|
+
fullscreen: [],
|
|
941
|
+
exitFullscreen: [],
|
|
942
|
+
skip: [],
|
|
943
|
+
error: []
|
|
944
|
+
};
|
|
945
|
+
xmlDoc.querySelectorAll("Impression").forEach((el) => {
|
|
946
|
+
var _a2;
|
|
947
|
+
const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
|
|
948
|
+
if (url) trackingUrls.impression.push(url);
|
|
949
|
+
});
|
|
950
|
+
xmlDoc.querySelectorAll("Tracking").forEach((el) => {
|
|
951
|
+
var _a2;
|
|
952
|
+
const event = el.getAttribute("event");
|
|
953
|
+
const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
|
|
954
|
+
if (event && url) {
|
|
955
|
+
const eventKey = event;
|
|
956
|
+
if (trackingUrls[eventKey]) {
|
|
957
|
+
trackingUrls[eventKey].push(url);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
});
|
|
961
|
+
const clickThrough = (_d = (_c = xmlDoc.querySelector("ClickThrough")) == null ? void 0 : _c.textContent) == null ? void 0 : _d.trim();
|
|
962
|
+
return {
|
|
963
|
+
id: adId,
|
|
964
|
+
title,
|
|
965
|
+
duration,
|
|
966
|
+
mediaFiles,
|
|
967
|
+
trackingUrls,
|
|
968
|
+
clickThrough
|
|
969
|
+
};
|
|
970
|
+
} catch (error) {
|
|
971
|
+
console.error("[HlsAdPlayer] Error parsing VAST XML:", error);
|
|
972
|
+
return null;
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
function createAdVideoElement() {
|
|
976
|
+
const video = document.createElement("video");
|
|
977
|
+
video.style.position = "absolute";
|
|
978
|
+
video.style.left = "0";
|
|
979
|
+
video.style.top = "0";
|
|
980
|
+
video.style.width = "100%";
|
|
981
|
+
video.style.height = "100%";
|
|
982
|
+
video.style.objectFit = "contain";
|
|
983
|
+
video.style.backgroundColor = "#000";
|
|
984
|
+
video.playsInline = true;
|
|
985
|
+
video.muted = false;
|
|
986
|
+
return video;
|
|
987
|
+
}
|
|
988
|
+
function setupAdEventListeners() {
|
|
989
|
+
if (!adVideoElement || !currentAd) return;
|
|
990
|
+
adVideoElement.addEventListener("timeupdate", () => {
|
|
991
|
+
if (!currentAd || !adVideoElement) return;
|
|
992
|
+
const progress = adVideoElement.currentTime / currentAd.duration;
|
|
993
|
+
if (progress >= 0.25 && !trackingFired.firstQuartile) {
|
|
994
|
+
trackingFired.firstQuartile = true;
|
|
995
|
+
fireTrackingPixels(currentAd.trackingUrls.firstQuartile);
|
|
996
|
+
}
|
|
997
|
+
if (progress >= 0.5 && !trackingFired.midpoint) {
|
|
998
|
+
trackingFired.midpoint = true;
|
|
999
|
+
fireTrackingPixels(currentAd.trackingUrls.midpoint);
|
|
1000
|
+
}
|
|
1001
|
+
if (progress >= 0.75 && !trackingFired.thirdQuartile) {
|
|
1002
|
+
trackingFired.thirdQuartile = true;
|
|
1003
|
+
fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
|
|
1004
|
+
}
|
|
1005
|
+
});
|
|
1006
|
+
adVideoElement.addEventListener("playing", () => {
|
|
1007
|
+
if (!currentAd || trackingFired.start) return;
|
|
1008
|
+
trackingFired.start = true;
|
|
1009
|
+
fireTrackingPixels(currentAd.trackingUrls.start);
|
|
1010
|
+
console.log("[HlsAdPlayer] Ad started playing");
|
|
1011
|
+
});
|
|
1012
|
+
adVideoElement.addEventListener("ended", () => {
|
|
1013
|
+
if (!currentAd || trackingFired.complete) return;
|
|
1014
|
+
trackingFired.complete = true;
|
|
1015
|
+
fireTrackingPixels(currentAd.trackingUrls.complete);
|
|
1016
|
+
console.log("[HlsAdPlayer] Ad completed");
|
|
1017
|
+
handleAdComplete();
|
|
1018
|
+
});
|
|
1019
|
+
adVideoElement.addEventListener("error", (e) => {
|
|
1020
|
+
console.error("[HlsAdPlayer] Ad video error:", e);
|
|
1021
|
+
if (currentAd) {
|
|
1022
|
+
fireTrackingPixels(currentAd.trackingUrls.error);
|
|
1023
|
+
}
|
|
1024
|
+
handleAdError();
|
|
1025
|
+
});
|
|
1026
|
+
adVideoElement.addEventListener("volumechange", () => {
|
|
1027
|
+
if (!currentAd) return;
|
|
1028
|
+
if (adVideoElement.muted) {
|
|
1029
|
+
fireTrackingPixels(currentAd.trackingUrls.mute);
|
|
1030
|
+
} else {
|
|
1031
|
+
fireTrackingPixels(currentAd.trackingUrls.unmute);
|
|
1032
|
+
}
|
|
1033
|
+
});
|
|
1034
|
+
adVideoElement.addEventListener("pause", () => {
|
|
1035
|
+
if (currentAd && !adVideoElement.ended) {
|
|
1036
|
+
fireTrackingPixels(currentAd.trackingUrls.pause);
|
|
1037
|
+
}
|
|
1038
|
+
});
|
|
1039
|
+
adVideoElement.addEventListener("play", () => {
|
|
1040
|
+
if (currentAd && adVideoElement.currentTime > 0) {
|
|
1041
|
+
fireTrackingPixels(currentAd.trackingUrls.resume);
|
|
1042
|
+
}
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
function handleAdComplete() {
|
|
1046
|
+
console.log("[HlsAdPlayer] Handling ad completion");
|
|
1047
|
+
adPlaying = false;
|
|
1048
|
+
contentVideo.muted = originalMutedState;
|
|
1049
|
+
if (adContainerEl) {
|
|
1050
|
+
adContainerEl.style.display = "none";
|
|
1051
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1052
|
+
}
|
|
1053
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1054
|
+
contentVideo.play().catch(() => {
|
|
1055
|
+
});
|
|
1056
|
+
console.log("[HlsAdPlayer] Content resumed (VOD mode)");
|
|
1057
|
+
} else {
|
|
1058
|
+
console.log("[HlsAdPlayer] Content unmuted (Live mode)");
|
|
1059
|
+
}
|
|
1060
|
+
emit("content_resume");
|
|
1061
|
+
emit("all_ads_completed");
|
|
1062
|
+
}
|
|
1063
|
+
function handleAdError() {
|
|
1064
|
+
console.log("[HlsAdPlayer] Handling ad error");
|
|
1065
|
+
adPlaying = false;
|
|
1066
|
+
contentVideo.muted = originalMutedState;
|
|
1067
|
+
if (adContainerEl) {
|
|
1068
|
+
adContainerEl.style.display = "none";
|
|
1069
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1070
|
+
}
|
|
1071
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1072
|
+
if (contentVideo.paused) {
|
|
1073
|
+
contentVideo.play().catch(() => {
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
emit("ad_error");
|
|
1078
|
+
}
|
|
1079
|
+
return {
|
|
1080
|
+
initialize() {
|
|
1081
|
+
var _a;
|
|
1082
|
+
console.log("[HlsAdPlayer] Initializing");
|
|
1083
|
+
if (!adContainerEl) {
|
|
1084
|
+
const container = document.createElement("div");
|
|
1085
|
+
container.style.position = "absolute";
|
|
1086
|
+
container.style.left = "0";
|
|
1087
|
+
container.style.top = "0";
|
|
1088
|
+
container.style.right = "0";
|
|
1089
|
+
container.style.bottom = "0";
|
|
1090
|
+
container.style.display = "none";
|
|
1091
|
+
container.style.alignItems = "center";
|
|
1092
|
+
container.style.justifyContent = "center";
|
|
1093
|
+
container.style.pointerEvents = "none";
|
|
1094
|
+
container.style.zIndex = "2";
|
|
1095
|
+
container.style.backgroundColor = "#000";
|
|
1096
|
+
(_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
1097
|
+
adContainerEl = container;
|
|
1098
|
+
}
|
|
1099
|
+
},
|
|
1100
|
+
async requestAds(vastTagUrl) {
|
|
1101
|
+
console.log("[HlsAdPlayer] Requesting ads:", vastTagUrl);
|
|
1102
|
+
if (adPlaying) {
|
|
1103
|
+
console.warn("[HlsAdPlayer] Cannot request new ads while an ad is playing");
|
|
1104
|
+
return Promise.reject(new Error("Ad already playing"));
|
|
1105
|
+
}
|
|
1106
|
+
try {
|
|
1107
|
+
sessionId = generateSessionId();
|
|
1108
|
+
const response = await fetch(vastTagUrl);
|
|
1109
|
+
if (!response.ok) {
|
|
1110
|
+
throw new Error(`Failed to fetch VAST: ${response.statusText}`);
|
|
1111
|
+
}
|
|
1112
|
+
const vastXml = await response.text();
|
|
1113
|
+
console.log("[HlsAdPlayer] VAST XML received");
|
|
1114
|
+
const ad = parseVastXml(vastXml);
|
|
1115
|
+
if (!ad) {
|
|
1116
|
+
throw new Error("Failed to parse VAST XML or no ads available");
|
|
1117
|
+
}
|
|
1118
|
+
currentAd = ad;
|
|
1119
|
+
console.log(`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`);
|
|
1120
|
+
fireTrackingPixels(ad.trackingUrls.impression);
|
|
1121
|
+
trackingFired.impression = true;
|
|
1122
|
+
return Promise.resolve();
|
|
1123
|
+
} catch (error) {
|
|
1124
|
+
console.error("[HlsAdPlayer] Error requesting ads:", error);
|
|
1125
|
+
emit("ad_error");
|
|
1126
|
+
return Promise.reject(error);
|
|
1127
|
+
}
|
|
1128
|
+
},
|
|
1129
|
+
async play() {
|
|
1130
|
+
if (!currentAd) {
|
|
1131
|
+
console.warn("[HlsAdPlayer] Cannot play: No ad loaded");
|
|
1132
|
+
return Promise.reject(new Error("No ad loaded"));
|
|
1133
|
+
}
|
|
1134
|
+
console.log("[HlsAdPlayer] Starting ad playback");
|
|
1135
|
+
try {
|
|
1136
|
+
if (!adVideoElement) {
|
|
1137
|
+
adVideoElement = createAdVideoElement();
|
|
1138
|
+
adContainerEl == null ? void 0 : adContainerEl.appendChild(adVideoElement);
|
|
1139
|
+
setupAdEventListeners();
|
|
1140
|
+
}
|
|
1141
|
+
trackingFired = {
|
|
1142
|
+
impression: trackingFired.impression,
|
|
1143
|
+
start: false,
|
|
1144
|
+
firstQuartile: false,
|
|
1145
|
+
midpoint: false,
|
|
1146
|
+
thirdQuartile: false,
|
|
1147
|
+
complete: false
|
|
1148
|
+
};
|
|
1149
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1150
|
+
contentVideo.pause();
|
|
1151
|
+
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
1152
|
+
} else {
|
|
1153
|
+
console.log("[HlsAdPlayer] Content continues (Live mode)");
|
|
1154
|
+
}
|
|
1155
|
+
contentVideo.muted = true;
|
|
1156
|
+
adPlaying = true;
|
|
1157
|
+
if (adContainerEl) {
|
|
1158
|
+
adContainerEl.style.display = "flex";
|
|
1159
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
1160
|
+
}
|
|
1161
|
+
emit("content_pause");
|
|
1162
|
+
const mediaFile = selectBestMediaFile(currentAd.mediaFiles);
|
|
1163
|
+
if (!mediaFile) {
|
|
1164
|
+
throw new Error("No media file available for ad");
|
|
1165
|
+
}
|
|
1166
|
+
console.log(`[HlsAdPlayer] Loading ad from: ${mediaFile.url}`);
|
|
1167
|
+
if (import_hls.default.isSupported()) {
|
|
1168
|
+
if (adHls) {
|
|
1169
|
+
adHls.destroy();
|
|
1170
|
+
}
|
|
1171
|
+
adHls = new import_hls.default({
|
|
1172
|
+
enableWorker: true,
|
|
1173
|
+
lowLatencyMode: false
|
|
1174
|
+
});
|
|
1175
|
+
adHls.loadSource(mediaFile.url);
|
|
1176
|
+
adHls.attachMedia(adVideoElement);
|
|
1177
|
+
adHls.on(import_hls.default.Events.MANIFEST_PARSED, () => {
|
|
1178
|
+
console.log("[HlsAdPlayer] HLS manifest parsed, starting playback");
|
|
1179
|
+
adVideoElement.play().catch((error) => {
|
|
1180
|
+
console.error("[HlsAdPlayer] Error starting ad playback:", error);
|
|
1181
|
+
handleAdError();
|
|
1182
|
+
});
|
|
1183
|
+
});
|
|
1184
|
+
adHls.on(import_hls.default.Events.ERROR, (event, data) => {
|
|
1185
|
+
console.error("[HlsAdPlayer] HLS error:", data);
|
|
1186
|
+
if (data.fatal) {
|
|
1187
|
+
handleAdError();
|
|
1188
|
+
}
|
|
1189
|
+
});
|
|
1190
|
+
} else if (adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
|
|
1191
|
+
adVideoElement.src = mediaFile.url;
|
|
1192
|
+
adVideoElement.play().catch((error) => {
|
|
1193
|
+
console.error("[HlsAdPlayer] Error starting ad playback:", error);
|
|
1194
|
+
handleAdError();
|
|
1195
|
+
});
|
|
1196
|
+
} else {
|
|
1197
|
+
throw new Error("HLS not supported");
|
|
1198
|
+
}
|
|
1199
|
+
return Promise.resolve();
|
|
1200
|
+
} catch (error) {
|
|
1201
|
+
console.error("[HlsAdPlayer] Error playing ad:", error);
|
|
1202
|
+
handleAdError();
|
|
1203
|
+
return Promise.reject(error);
|
|
1204
|
+
}
|
|
1205
|
+
},
|
|
1206
|
+
async stop() {
|
|
1207
|
+
console.log("[HlsAdPlayer] Stopping ad");
|
|
1208
|
+
adPlaying = false;
|
|
1209
|
+
contentVideo.muted = originalMutedState;
|
|
1210
|
+
if (adContainerEl) {
|
|
1211
|
+
adContainerEl.style.display = "none";
|
|
1212
|
+
adContainerEl.style.pointerEvents = "none";
|
|
1213
|
+
}
|
|
1214
|
+
if (adHls) {
|
|
1215
|
+
adHls.destroy();
|
|
1216
|
+
adHls = void 0;
|
|
1217
|
+
}
|
|
1218
|
+
if (adVideoElement) {
|
|
1219
|
+
adVideoElement.pause();
|
|
1220
|
+
adVideoElement.src = "";
|
|
1221
|
+
}
|
|
1222
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
1223
|
+
contentVideo.play().catch(() => {
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1226
|
+
currentAd = void 0;
|
|
1227
|
+
},
|
|
1228
|
+
destroy() {
|
|
1229
|
+
console.log("[HlsAdPlayer] Destroying");
|
|
1230
|
+
adPlaying = false;
|
|
1231
|
+
contentVideo.muted = originalMutedState;
|
|
1232
|
+
if (adHls) {
|
|
1233
|
+
adHls.destroy();
|
|
1234
|
+
adHls = void 0;
|
|
1235
|
+
}
|
|
1236
|
+
if (adVideoElement) {
|
|
1237
|
+
adVideoElement.pause();
|
|
1238
|
+
adVideoElement.src = "";
|
|
1239
|
+
adVideoElement.remove();
|
|
1240
|
+
adVideoElement = void 0;
|
|
1241
|
+
}
|
|
1242
|
+
if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
|
|
1243
|
+
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
1244
|
+
}
|
|
1245
|
+
adContainerEl = void 0;
|
|
1246
|
+
currentAd = void 0;
|
|
1247
|
+
listeners.clear();
|
|
1248
|
+
},
|
|
1249
|
+
isAdPlaying() {
|
|
1250
|
+
return adPlaying;
|
|
1251
|
+
},
|
|
1252
|
+
resize(width, height) {
|
|
1253
|
+
console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);
|
|
1254
|
+
if (adContainerEl) {
|
|
1255
|
+
adContainerEl.style.width = `${width}px`;
|
|
1256
|
+
adContainerEl.style.height = `${height}px`;
|
|
1257
|
+
}
|
|
1258
|
+
if (adVideoElement) {
|
|
1259
|
+
adVideoElement.style.width = `${width}px`;
|
|
1260
|
+
adVideoElement.style.height = `${height}px`;
|
|
1261
|
+
}
|
|
1262
|
+
},
|
|
1263
|
+
on(event, listener) {
|
|
1264
|
+
if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
|
|
1265
|
+
listeners.get(event).add(listener);
|
|
1266
|
+
},
|
|
1267
|
+
off(event, listener) {
|
|
1268
|
+
var _a;
|
|
1269
|
+
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
1270
|
+
},
|
|
1271
|
+
updateOriginalMutedState(muted) {
|
|
1272
|
+
originalMutedState = muted;
|
|
1273
|
+
},
|
|
1274
|
+
getOriginalMutedState() {
|
|
1275
|
+
return originalMutedState;
|
|
1276
|
+
},
|
|
1277
|
+
setAdVolume(volume) {
|
|
1278
|
+
if (adVideoElement && adPlaying) {
|
|
1279
|
+
adVideoElement.volume = Math.max(0, Math.min(1, volume));
|
|
1280
|
+
}
|
|
1281
|
+
},
|
|
1282
|
+
getAdVolume() {
|
|
1283
|
+
if (adVideoElement && adPlaying) {
|
|
1284
|
+
return adVideoElement.volume;
|
|
1285
|
+
}
|
|
1286
|
+
return 1;
|
|
1287
|
+
}
|
|
1288
|
+
};
|
|
1289
|
+
}
|
|
1290
|
+
|
|
591
1291
|
// src/utils/tracking.ts
|
|
592
1292
|
var cachedBrowserId = null;
|
|
593
1293
|
function getClientInfo() {
|
|
1294
|
+
var _a, _b, _c, _d;
|
|
594
1295
|
const ua = navigator.userAgent;
|
|
595
1296
|
const platform = navigator.platform;
|
|
596
1297
|
const vendor = navigator.vendor || "";
|
|
@@ -598,12 +1299,12 @@ function getClientInfo() {
|
|
|
598
1299
|
const memory = navigator.deviceMemory || null;
|
|
599
1300
|
const hardwareConcurrency = navigator.hardwareConcurrency || 1;
|
|
600
1301
|
const screenInfo = {
|
|
601
|
-
width: screen
|
|
602
|
-
height: screen
|
|
603
|
-
availWidth: screen
|
|
604
|
-
availHeight: screen
|
|
605
|
-
orientation: screen
|
|
606
|
-
pixelDepth: screen
|
|
1302
|
+
width: screen == null ? void 0 : screen.width,
|
|
1303
|
+
height: screen == null ? void 0 : screen.height,
|
|
1304
|
+
availWidth: screen == null ? void 0 : screen.availWidth,
|
|
1305
|
+
availHeight: screen == null ? void 0 : screen.availHeight,
|
|
1306
|
+
orientation: ((_a = screen == null ? void 0 : screen.orientation) == null ? void 0 : _a.type) || "",
|
|
1307
|
+
pixelDepth: screen == null ? void 0 : screen.pixelDepth
|
|
607
1308
|
};
|
|
608
1309
|
let deviceType = "desktop";
|
|
609
1310
|
let brand = "Unknown";
|
|
@@ -700,10 +1401,10 @@ function getClientInfo() {
|
|
|
700
1401
|
if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
|
|
701
1402
|
}
|
|
702
1403
|
isWebView = /wv|WebView|Linux; U;/.test(ua);
|
|
703
|
-
if (window
|
|
1404
|
+
if ((window == null ? void 0 : window.outerHeight) === 0 && (window == null ? void 0 : window.outerWidth) === 0) {
|
|
704
1405
|
isWebView = true;
|
|
705
1406
|
}
|
|
706
|
-
isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || window.screen
|
|
1407
|
+
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;
|
|
707
1408
|
return {
|
|
708
1409
|
brand,
|
|
709
1410
|
os,
|
|
@@ -724,7 +1425,7 @@ function getClientInfo() {
|
|
|
724
1425
|
deviceMemory: memory,
|
|
725
1426
|
maxTouchPoints,
|
|
726
1427
|
language: navigator.language,
|
|
727
|
-
languages: navigator.languages
|
|
1428
|
+
languages: ((_d = navigator.languages) == null ? void 0 : _d.join(",")) || "",
|
|
728
1429
|
cookieEnabled: navigator.cookieEnabled,
|
|
729
1430
|
doNotTrack: navigator.doNotTrack || "",
|
|
730
1431
|
referrer: document.referrer,
|
|
@@ -837,6 +1538,215 @@ async function sendHeartbeat(licenseKey) {
|
|
|
837
1538
|
}
|
|
838
1539
|
}
|
|
839
1540
|
|
|
1541
|
+
// src/utils/polyfills.ts
|
|
1542
|
+
function polyfillURLSearchParams() {
|
|
1543
|
+
if (typeof URLSearchParams !== "undefined") {
|
|
1544
|
+
return;
|
|
1545
|
+
}
|
|
1546
|
+
class URLSearchParamsPolyfill {
|
|
1547
|
+
constructor(init) {
|
|
1548
|
+
this.params = /* @__PURE__ */ new Map();
|
|
1549
|
+
if (typeof init === "string") {
|
|
1550
|
+
this.parseQueryString(init);
|
|
1551
|
+
} else if (init instanceof URLSearchParamsPolyfill) {
|
|
1552
|
+
init.forEach((value, key) => {
|
|
1553
|
+
this.append(key, value);
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
parseQueryString(query) {
|
|
1558
|
+
const cleanQuery = query.startsWith("?") ? query.slice(1) : query;
|
|
1559
|
+
if (!cleanQuery) return;
|
|
1560
|
+
cleanQuery.split("&").forEach((param) => {
|
|
1561
|
+
const [key, value] = param.split("=");
|
|
1562
|
+
if (key) {
|
|
1563
|
+
const decodedKey = this.safeDecodeURIComponent(key);
|
|
1564
|
+
const decodedValue = value ? this.safeDecodeURIComponent(value) : "";
|
|
1565
|
+
this.append(decodedKey, decodedValue);
|
|
1566
|
+
}
|
|
1567
|
+
});
|
|
1568
|
+
}
|
|
1569
|
+
safeDecodeURIComponent(str) {
|
|
1570
|
+
try {
|
|
1571
|
+
return decodeURIComponent(str.replace(/\+/g, " "));
|
|
1572
|
+
} catch (e) {
|
|
1573
|
+
return str;
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
append(name, value) {
|
|
1577
|
+
const values = this.params.get(name) || [];
|
|
1578
|
+
values.push(String(value));
|
|
1579
|
+
this.params.set(name, values);
|
|
1580
|
+
}
|
|
1581
|
+
delete(name) {
|
|
1582
|
+
this.params.delete(name);
|
|
1583
|
+
}
|
|
1584
|
+
get(name) {
|
|
1585
|
+
const values = this.params.get(name);
|
|
1586
|
+
return values && values.length > 0 && values[0] !== void 0 ? values[0] : null;
|
|
1587
|
+
}
|
|
1588
|
+
getAll(name) {
|
|
1589
|
+
return this.params.get(name) || [];
|
|
1590
|
+
}
|
|
1591
|
+
has(name) {
|
|
1592
|
+
return this.params.has(name);
|
|
1593
|
+
}
|
|
1594
|
+
set(name, value) {
|
|
1595
|
+
this.params.set(name, [String(value)]);
|
|
1596
|
+
}
|
|
1597
|
+
forEach(callback) {
|
|
1598
|
+
this.params.forEach((values, key) => {
|
|
1599
|
+
values.forEach((value) => {
|
|
1600
|
+
callback(value, key, this);
|
|
1601
|
+
});
|
|
1602
|
+
});
|
|
1603
|
+
}
|
|
1604
|
+
toString() {
|
|
1605
|
+
const parts = [];
|
|
1606
|
+
this.params.forEach((values, key) => {
|
|
1607
|
+
values.forEach((value) => {
|
|
1608
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
|
|
1609
|
+
});
|
|
1610
|
+
});
|
|
1611
|
+
return parts.join("&");
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
window.URLSearchParams = URLSearchParamsPolyfill;
|
|
1615
|
+
}
|
|
1616
|
+
function polyfillTextEncoder() {
|
|
1617
|
+
if (typeof TextEncoder !== "undefined") {
|
|
1618
|
+
return;
|
|
1619
|
+
}
|
|
1620
|
+
class TextEncoderPolyfill {
|
|
1621
|
+
constructor() {
|
|
1622
|
+
this.encoding = "utf-8";
|
|
1623
|
+
}
|
|
1624
|
+
encode(str) {
|
|
1625
|
+
const utf8 = [];
|
|
1626
|
+
for (let i = 0; i < str.length; i++) {
|
|
1627
|
+
let charcode = str.charCodeAt(i);
|
|
1628
|
+
if (charcode < 128) {
|
|
1629
|
+
utf8.push(charcode);
|
|
1630
|
+
} else if (charcode < 2048) {
|
|
1631
|
+
utf8.push(192 | charcode >> 6, 128 | charcode & 63);
|
|
1632
|
+
} else if (charcode < 55296 || charcode >= 57344) {
|
|
1633
|
+
utf8.push(
|
|
1634
|
+
224 | charcode >> 12,
|
|
1635
|
+
128 | charcode >> 6 & 63,
|
|
1636
|
+
128 | charcode & 63
|
|
1637
|
+
);
|
|
1638
|
+
} else {
|
|
1639
|
+
i++;
|
|
1640
|
+
charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023);
|
|
1641
|
+
utf8.push(
|
|
1642
|
+
240 | charcode >> 18,
|
|
1643
|
+
128 | charcode >> 12 & 63,
|
|
1644
|
+
128 | charcode >> 6 & 63,
|
|
1645
|
+
128 | charcode & 63
|
|
1646
|
+
);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
return new Uint8Array(utf8);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
window.TextEncoder = TextEncoderPolyfill;
|
|
1653
|
+
}
|
|
1654
|
+
function polyfillPromiseFinally() {
|
|
1655
|
+
if (typeof Promise !== "undefined" && !Promise.prototype.finally) {
|
|
1656
|
+
Promise.prototype.finally = function(callback) {
|
|
1657
|
+
const constructor = this.constructor;
|
|
1658
|
+
return this.then(
|
|
1659
|
+
(value) => constructor.resolve(callback()).then(() => value),
|
|
1660
|
+
(reason) => constructor.resolve(callback()).then(() => {
|
|
1661
|
+
throw reason;
|
|
1662
|
+
})
|
|
1663
|
+
);
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
function polyfillObjectAssign() {
|
|
1668
|
+
if (typeof Object.assign !== "function") {
|
|
1669
|
+
Object.assign = function(target, ...sources) {
|
|
1670
|
+
if (target == null) {
|
|
1671
|
+
throw new TypeError("Cannot convert undefined or null to object");
|
|
1672
|
+
}
|
|
1673
|
+
const to = Object(target);
|
|
1674
|
+
for (let i = 0; i < sources.length; i++) {
|
|
1675
|
+
const nextSource = sources[i];
|
|
1676
|
+
if (nextSource != null) {
|
|
1677
|
+
for (const nextKey in nextSource) {
|
|
1678
|
+
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
|
|
1679
|
+
to[nextKey] = nextSource[nextKey];
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
return to;
|
|
1685
|
+
};
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
function polyfillArrayFrom() {
|
|
1689
|
+
if (!Array.from) {
|
|
1690
|
+
Array.from = function(arrayLike, mapFn, thisArg) {
|
|
1691
|
+
const items = Object(arrayLike);
|
|
1692
|
+
if (arrayLike == null) {
|
|
1693
|
+
throw new TypeError("Array.from requires an array-like object");
|
|
1694
|
+
}
|
|
1695
|
+
const len = items.length >>> 0;
|
|
1696
|
+
const result = new Array(len);
|
|
1697
|
+
for (let i = 0; i < len; i++) {
|
|
1698
|
+
if (mapFn) {
|
|
1699
|
+
result[i] = mapFn.call(thisArg, items[i], i);
|
|
1700
|
+
} else {
|
|
1701
|
+
result[i] = items[i];
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
return result;
|
|
1705
|
+
};
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
function polyfillStringStartsWith() {
|
|
1709
|
+
if (!String.prototype.startsWith) {
|
|
1710
|
+
String.prototype.startsWith = function(search, pos) {
|
|
1711
|
+
pos = !pos || pos < 0 ? 0 : +pos;
|
|
1712
|
+
return this.substring(pos, pos + search.length) === search;
|
|
1713
|
+
};
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
function polyfillStringEndsWith() {
|
|
1717
|
+
if (!String.prototype.endsWith) {
|
|
1718
|
+
String.prototype.endsWith = function(search, length) {
|
|
1719
|
+
if (length === void 0 || length > this.length) {
|
|
1720
|
+
length = this.length;
|
|
1721
|
+
}
|
|
1722
|
+
return this.substring(length - search.length, length) === search;
|
|
1723
|
+
};
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
function polyfillStringIncludes() {
|
|
1727
|
+
if (!String.prototype.includes) {
|
|
1728
|
+
String.prototype.includes = function(search, start) {
|
|
1729
|
+
if (typeof start !== "number") {
|
|
1730
|
+
start = 0;
|
|
1731
|
+
}
|
|
1732
|
+
if (start + search.length > this.length) {
|
|
1733
|
+
return false;
|
|
1734
|
+
}
|
|
1735
|
+
return this.indexOf(search, start) !== -1;
|
|
1736
|
+
};
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
function initializePolyfills() {
|
|
1740
|
+
polyfillObjectAssign();
|
|
1741
|
+
polyfillArrayFrom();
|
|
1742
|
+
polyfillStringStartsWith();
|
|
1743
|
+
polyfillStringEndsWith();
|
|
1744
|
+
polyfillStringIncludes();
|
|
1745
|
+
polyfillURLSearchParams();
|
|
1746
|
+
polyfillTextEncoder();
|
|
1747
|
+
polyfillPromiseFinally();
|
|
1748
|
+
}
|
|
1749
|
+
|
|
840
1750
|
// src/player/StormcloudVideoPlayer.ts
|
|
841
1751
|
var StormcloudVideoPlayer = class {
|
|
842
1752
|
constructor(config) {
|
|
@@ -849,13 +1759,44 @@ var StormcloudVideoPlayer = class {
|
|
|
849
1759
|
this.totalAdsInBreak = 0;
|
|
850
1760
|
this.showAds = false;
|
|
851
1761
|
this.isLiveStream = false;
|
|
852
|
-
|
|
1762
|
+
initializePolyfills();
|
|
1763
|
+
const browserOverrides = getBrowserConfigOverrides();
|
|
1764
|
+
this.config = { ...config, ...browserOverrides };
|
|
853
1765
|
this.video = config.videoElement;
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
1766
|
+
logBrowserInfo(config.debugAdTiming);
|
|
1767
|
+
this.ima = this.createAdPlayer(false);
|
|
1768
|
+
}
|
|
1769
|
+
createAdPlayer(continueLiveStreamDuringAds) {
|
|
1770
|
+
const vastMode = this.config.vastMode || "default";
|
|
1771
|
+
let adPlayerType = this.config.adPlayerType || (vastMode === "adstorm" ? "hls" : "ima");
|
|
1772
|
+
if (adPlayerType === "ima" && !supportsGoogleIMA()) {
|
|
1773
|
+
if (this.config.debugAdTiming) {
|
|
1774
|
+
console.warn(
|
|
1775
|
+
"[StormcloudVideoPlayer] Google IMA SDK not supported on this browser, falling back to HLS ad player"
|
|
1776
|
+
);
|
|
1777
|
+
}
|
|
1778
|
+
adPlayerType = "hls";
|
|
1779
|
+
}
|
|
1780
|
+
if (adPlayerType === "hls") {
|
|
1781
|
+
if (this.config.debugAdTiming) {
|
|
1782
|
+
console.log("[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)");
|
|
1783
|
+
}
|
|
1784
|
+
return createHlsAdPlayer(this.video, {
|
|
1785
|
+
continueLiveStreamDuringAds,
|
|
1786
|
+
...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {},
|
|
1787
|
+
...this.hls ? { mainHlsInstance: this.hls } : {}
|
|
1788
|
+
});
|
|
1789
|
+
} else {
|
|
1790
|
+
if (this.config.debugAdTiming) {
|
|
1791
|
+
console.log("[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)");
|
|
1792
|
+
}
|
|
1793
|
+
return createImaController(this.video, {
|
|
1794
|
+
continueLiveStreamDuringAds
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
857
1797
|
}
|
|
858
1798
|
async load() {
|
|
1799
|
+
var _a, _b;
|
|
859
1800
|
if (!this.attached) {
|
|
860
1801
|
this.attach();
|
|
861
1802
|
}
|
|
@@ -872,7 +1813,7 @@ var StormcloudVideoPlayer = class {
|
|
|
872
1813
|
this.initializeTracking();
|
|
873
1814
|
if (this.shouldUseNativeHls()) {
|
|
874
1815
|
this.video.src = this.config.src;
|
|
875
|
-
this.isLiveStream = this.config.lowLatencyMode
|
|
1816
|
+
this.isLiveStream = (_a = this.config.lowLatencyMode) != null ? _a : false;
|
|
876
1817
|
if (this.config.debugAdTiming) {
|
|
877
1818
|
console.log(
|
|
878
1819
|
"[StormcloudVideoPlayer] allowNativeHls: true - VOD mode detected:",
|
|
@@ -884,17 +1825,15 @@ var StormcloudVideoPlayer = class {
|
|
|
884
1825
|
);
|
|
885
1826
|
}
|
|
886
1827
|
this.ima.destroy();
|
|
887
|
-
this.ima =
|
|
888
|
-
continueLiveStreamDuringAds: false
|
|
889
|
-
});
|
|
1828
|
+
this.ima = this.createAdPlayer(false);
|
|
890
1829
|
this.ima.initialize();
|
|
891
1830
|
if (this.config.autoplay) {
|
|
892
|
-
await this.video.play()
|
|
893
|
-
});
|
|
1831
|
+
await ((_b = this.video.play()) == null ? void 0 : _b.catch(() => {
|
|
1832
|
+
}));
|
|
894
1833
|
}
|
|
895
1834
|
return;
|
|
896
1835
|
}
|
|
897
|
-
this.hls = new
|
|
1836
|
+
this.hls = new import_hls2.default({
|
|
898
1837
|
enableWorker: true,
|
|
899
1838
|
backBufferLength: 30,
|
|
900
1839
|
liveDurationInfinity: true,
|
|
@@ -902,13 +1841,18 @@ var StormcloudVideoPlayer = class {
|
|
|
902
1841
|
maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1,
|
|
903
1842
|
...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}
|
|
904
1843
|
});
|
|
905
|
-
this.hls.on(
|
|
906
|
-
|
|
1844
|
+
this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, () => {
|
|
1845
|
+
var _a2;
|
|
1846
|
+
(_a2 = this.hls) == null ? void 0 : _a2.loadSource(this.config.src);
|
|
907
1847
|
});
|
|
908
|
-
this.hls.on(
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
1848
|
+
this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, async (_, data) => {
|
|
1849
|
+
var _a2, _b2, _c, _d;
|
|
1850
|
+
this.isLiveStream = (_c = (_b2 = (_a2 = this.hls) == null ? void 0 : _a2.levels) == null ? void 0 : _b2.some(
|
|
1851
|
+
(level) => {
|
|
1852
|
+
var _a3, _b3;
|
|
1853
|
+
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";
|
|
1854
|
+
}
|
|
1855
|
+
)) != null ? _c : false;
|
|
912
1856
|
if (this.config.debugAdTiming) {
|
|
913
1857
|
const adBehavior = this.shouldContinueLiveStreamDuringAds() ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
|
|
914
1858
|
console.log("[StormcloudVideoPlayer] Stream type detected:", {
|
|
@@ -918,33 +1862,32 @@ var StormcloudVideoPlayer = class {
|
|
|
918
1862
|
});
|
|
919
1863
|
}
|
|
920
1864
|
this.ima.destroy();
|
|
921
|
-
this.ima =
|
|
922
|
-
continueLiveStreamDuringAds: this.shouldContinueLiveStreamDuringAds()
|
|
923
|
-
});
|
|
1865
|
+
this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());
|
|
924
1866
|
this.ima.initialize();
|
|
925
1867
|
if (this.config.autoplay) {
|
|
926
|
-
await this.video.play()
|
|
927
|
-
});
|
|
1868
|
+
await ((_d = this.video.play()) == null ? void 0 : _d.catch(() => {
|
|
1869
|
+
}));
|
|
928
1870
|
}
|
|
929
1871
|
});
|
|
930
|
-
this.hls.on(
|
|
931
|
-
const id3Tags = (data
|
|
1872
|
+
this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, (_evt, data) => {
|
|
1873
|
+
const id3Tags = ((data == null ? void 0 : data.samples) || []).map((s) => ({
|
|
932
1874
|
key: "ID3",
|
|
933
|
-
value: s
|
|
934
|
-
ptsSeconds: s
|
|
1875
|
+
value: s == null ? void 0 : s.data,
|
|
1876
|
+
ptsSeconds: s == null ? void 0 : s.pts
|
|
935
1877
|
}));
|
|
936
1878
|
id3Tags.forEach((tag) => this.onId3Tag(tag));
|
|
937
1879
|
});
|
|
938
|
-
this.hls.on(
|
|
939
|
-
|
|
940
|
-
const
|
|
1880
|
+
this.hls.on(import_hls2.default.Events.FRAG_CHANGED, (_evt, data) => {
|
|
1881
|
+
var _a2, _b2, _c;
|
|
1882
|
+
const frag = data == null ? void 0 : data.frag;
|
|
1883
|
+
const tagList = frag == null ? void 0 : frag.tagList;
|
|
941
1884
|
if (!Array.isArray(tagList)) return;
|
|
942
1885
|
for (const entry of tagList) {
|
|
943
1886
|
let tag = "";
|
|
944
1887
|
let value = "";
|
|
945
1888
|
if (Array.isArray(entry)) {
|
|
946
|
-
tag = String(entry[0]
|
|
947
|
-
value = String(entry[1]
|
|
1889
|
+
tag = String((_a2 = entry[0]) != null ? _a2 : "");
|
|
1890
|
+
value = String((_b2 = entry[1]) != null ? _b2 : "");
|
|
948
1891
|
} else if (typeof entry === "string") {
|
|
949
1892
|
const idx = entry.indexOf(":");
|
|
950
1893
|
if (idx >= 0) {
|
|
@@ -968,8 +1911,8 @@ var StormcloudVideoPlayer = class {
|
|
|
968
1911
|
const prog = this.parseCueOutCont(value);
|
|
969
1912
|
const marker = {
|
|
970
1913
|
type: "progress",
|
|
971
|
-
...prog
|
|
972
|
-
...prog
|
|
1914
|
+
...(prog == null ? void 0 : prog.duration) !== void 0 ? { durationSeconds: prog.duration } : {},
|
|
1915
|
+
...(prog == null ? void 0 : prog.elapsed) !== void 0 ? { ptsSeconds: prog.elapsed } : {},
|
|
973
1916
|
raw: { tag, value }
|
|
974
1917
|
};
|
|
975
1918
|
this.onScte35Marker(marker);
|
|
@@ -979,7 +1922,7 @@ var StormcloudVideoPlayer = class {
|
|
|
979
1922
|
const attrs = this.parseAttributeList(value);
|
|
980
1923
|
const hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
|
|
981
1924
|
const hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
|
|
982
|
-
const klass = String(attrs["CLASS"]
|
|
1925
|
+
const klass = String((_c = attrs["CLASS"]) != null ? _c : "");
|
|
983
1926
|
const duration = this.toNumber(attrs["DURATION"]);
|
|
984
1927
|
if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
|
|
985
1928
|
const marker = {
|
|
@@ -995,14 +1938,15 @@ var StormcloudVideoPlayer = class {
|
|
|
995
1938
|
}
|
|
996
1939
|
}
|
|
997
1940
|
});
|
|
998
|
-
this.hls.on(
|
|
999
|
-
|
|
1941
|
+
this.hls.on(import_hls2.default.Events.ERROR, (_evt, data) => {
|
|
1942
|
+
var _a2, _b2;
|
|
1943
|
+
if (data == null ? void 0 : data.fatal) {
|
|
1000
1944
|
switch (data.type) {
|
|
1001
|
-
case
|
|
1002
|
-
this.hls
|
|
1945
|
+
case import_hls2.default.ErrorTypes.NETWORK_ERROR:
|
|
1946
|
+
(_a2 = this.hls) == null ? void 0 : _a2.startLoad();
|
|
1003
1947
|
break;
|
|
1004
|
-
case
|
|
1005
|
-
this.hls
|
|
1948
|
+
case import_hls2.default.ErrorTypes.MEDIA_ERROR:
|
|
1949
|
+
(_b2 = this.hls) == null ? void 0 : _b2.recoverMediaError();
|
|
1006
1950
|
break;
|
|
1007
1951
|
default:
|
|
1008
1952
|
this.destroy();
|
|
@@ -1104,11 +2048,12 @@ var StormcloudVideoPlayer = class {
|
|
|
1104
2048
|
}
|
|
1105
2049
|
}
|
|
1106
2050
|
parseScte35FromId3(tag) {
|
|
2051
|
+
var _a, _b, _c, _d;
|
|
1107
2052
|
const text = this.decodeId3ValueToText(tag.value);
|
|
1108
2053
|
if (!text) return void 0;
|
|
1109
2054
|
const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\r\n]*))?/i) || text.match(/CUE-OUT(?::([^\r\n]*))?/i);
|
|
1110
2055
|
if (cueOutMatch) {
|
|
1111
|
-
const arg = (cueOutMatch[1]
|
|
2056
|
+
const arg = ((_a = cueOutMatch[1]) != null ? _a : "").trim();
|
|
1112
2057
|
const dur = this.parseCueOutDuration(arg);
|
|
1113
2058
|
const marker = {
|
|
1114
2059
|
type: "start",
|
|
@@ -1120,12 +2065,12 @@ var StormcloudVideoPlayer = class {
|
|
|
1120
2065
|
}
|
|
1121
2066
|
const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\r\n]*)/i);
|
|
1122
2067
|
if (cueOutContMatch) {
|
|
1123
|
-
const arg = (cueOutContMatch[1]
|
|
2068
|
+
const arg = ((_b = cueOutContMatch[1]) != null ? _b : "").trim();
|
|
1124
2069
|
const cont = this.parseCueOutCont(arg);
|
|
1125
2070
|
const marker = {
|
|
1126
2071
|
type: "progress",
|
|
1127
2072
|
...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},
|
|
1128
|
-
...cont
|
|
2073
|
+
...(cont == null ? void 0 : cont.duration) !== void 0 ? { durationSeconds: cont.duration } : {},
|
|
1129
2074
|
raw: { id3: text }
|
|
1130
2075
|
};
|
|
1131
2076
|
return marker;
|
|
@@ -1141,10 +2086,10 @@ var StormcloudVideoPlayer = class {
|
|
|
1141
2086
|
}
|
|
1142
2087
|
const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\r\n]*)/i);
|
|
1143
2088
|
if (daterangeMatch) {
|
|
1144
|
-
const attrs = this.parseAttributeList(daterangeMatch[1]
|
|
2089
|
+
const attrs = this.parseAttributeList((_c = daterangeMatch[1]) != null ? _c : "");
|
|
1145
2090
|
const hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
|
|
1146
2091
|
const hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
|
|
1147
|
-
const klass = String(attrs["CLASS"]
|
|
2092
|
+
const klass = String((_d = attrs["CLASS"]) != null ? _d : "");
|
|
1148
2093
|
const duration = this.toNumber(attrs["DURATION"]);
|
|
1149
2094
|
if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
|
|
1150
2095
|
const marker = {
|
|
@@ -1201,6 +2146,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1201
2146
|
}
|
|
1202
2147
|
}
|
|
1203
2148
|
onScte35Marker(marker) {
|
|
2149
|
+
var _a, _b;
|
|
1204
2150
|
if (this.config.debugAdTiming) {
|
|
1205
2151
|
console.log("[StormcloudVideoPlayer] SCTE-35 marker detected:", {
|
|
1206
2152
|
type: marker.type,
|
|
@@ -1216,7 +2162,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1216
2162
|
this.expectedAdBreakDurationMs = durationMs;
|
|
1217
2163
|
this.currentAdBreakStartWallClockMs = Date.now();
|
|
1218
2164
|
const isManifestMarker = this.isManifestBasedMarker(marker);
|
|
1219
|
-
const forceImmediate = this.config.immediateManifestAds
|
|
2165
|
+
const forceImmediate = (_a = this.config.immediateManifestAds) != null ? _a : true;
|
|
1220
2166
|
if (this.config.debugAdTiming) {
|
|
1221
2167
|
console.log("[StormcloudVideoPlayer] Ad start decision:", {
|
|
1222
2168
|
isManifestMarker,
|
|
@@ -1233,7 +2179,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1233
2179
|
this.clearAdStartTimer();
|
|
1234
2180
|
this.handleAdStart(marker);
|
|
1235
2181
|
} else if (typeof marker.ptsSeconds === "number") {
|
|
1236
|
-
const tol = this.config.driftToleranceMs
|
|
2182
|
+
const tol = (_b = this.config.driftToleranceMs) != null ? _b : 1e3;
|
|
1237
2183
|
const nowMs = this.video.currentTime * 1e3;
|
|
1238
2184
|
const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
|
|
1239
2185
|
const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);
|
|
@@ -1343,12 +2289,13 @@ var StormcloudVideoPlayer = class {
|
|
|
1343
2289
|
return void 0;
|
|
1344
2290
|
}
|
|
1345
2291
|
parseAttributeList(value) {
|
|
2292
|
+
var _a, _b, _c;
|
|
1346
2293
|
const attrs = {};
|
|
1347
2294
|
const regex = /([A-Z0-9-]+)=(("[^"]*")|([^",]*))(?:,|$)/gi;
|
|
1348
2295
|
let match;
|
|
1349
2296
|
while ((match = regex.exec(value)) !== null) {
|
|
1350
|
-
const key = match[1]
|
|
1351
|
-
let rawVal = match[3]
|
|
2297
|
+
const key = (_a = match[1]) != null ? _a : "";
|
|
2298
|
+
let rawVal = (_c = (_b = match[3]) != null ? _b : match[4]) != null ? _c : "";
|
|
1352
2299
|
if (rawVal.startsWith('"') && rawVal.endsWith('"')) {
|
|
1353
2300
|
rawVal = rawVal.slice(1, -1);
|
|
1354
2301
|
}
|
|
@@ -1512,6 +2459,43 @@ var StormcloudVideoPlayer = class {
|
|
|
1512
2459
|
}
|
|
1513
2460
|
}
|
|
1514
2461
|
async fetchAdConfiguration() {
|
|
2462
|
+
var _a, _b, _c;
|
|
2463
|
+
const vastMode = this.config.vastMode || "default";
|
|
2464
|
+
if (this.config.debugAdTiming) {
|
|
2465
|
+
console.log(
|
|
2466
|
+
"[StormcloudVideoPlayer] VAST mode:",
|
|
2467
|
+
vastMode
|
|
2468
|
+
);
|
|
2469
|
+
}
|
|
2470
|
+
if (vastMode === "adstorm") {
|
|
2471
|
+
if (!this.config.licenseKey) {
|
|
2472
|
+
if (this.config.debugAdTiming) {
|
|
2473
|
+
console.warn(
|
|
2474
|
+
"[StormcloudVideoPlayer] AdStorm mode requires a license key"
|
|
2475
|
+
);
|
|
2476
|
+
}
|
|
2477
|
+
return;
|
|
2478
|
+
}
|
|
2479
|
+
const vastEndpoint = `https://adstorm.co/api-adstorm-dev/adstorm/vast/${this.config.licenseKey}`;
|
|
2480
|
+
this.apiVastTagUrl = vastEndpoint;
|
|
2481
|
+
if (this.config.debugAdTiming) {
|
|
2482
|
+
console.log(
|
|
2483
|
+
"[StormcloudVideoPlayer] Using AdStorm VAST endpoint:",
|
|
2484
|
+
vastEndpoint
|
|
2485
|
+
);
|
|
2486
|
+
}
|
|
2487
|
+
return;
|
|
2488
|
+
}
|
|
2489
|
+
if (this.config.vastTagUrl) {
|
|
2490
|
+
this.apiVastTagUrl = this.config.vastTagUrl;
|
|
2491
|
+
if (this.config.debugAdTiming) {
|
|
2492
|
+
console.log(
|
|
2493
|
+
"[StormcloudVideoPlayer] Using custom VAST tag URL:",
|
|
2494
|
+
this.apiVastTagUrl
|
|
2495
|
+
);
|
|
2496
|
+
}
|
|
2497
|
+
return;
|
|
2498
|
+
}
|
|
1515
2499
|
const apiUrl = "https://adstorm.co/api-adstorm-dev/adstorm/ads/web";
|
|
1516
2500
|
if (this.config.debugAdTiming) {
|
|
1517
2501
|
console.log(
|
|
@@ -1525,25 +2509,29 @@ var StormcloudVideoPlayer = class {
|
|
|
1525
2509
|
}
|
|
1526
2510
|
const response = await fetch(apiUrl, { headers });
|
|
1527
2511
|
if (!response.ok) {
|
|
1528
|
-
|
|
2512
|
+
if (this.config.debugAdTiming) {
|
|
2513
|
+
console.warn(
|
|
2514
|
+
`[StormcloudVideoPlayer] Failed to fetch ad configuration: ${response.status}`
|
|
2515
|
+
);
|
|
2516
|
+
}
|
|
2517
|
+
return;
|
|
1529
2518
|
}
|
|
1530
2519
|
const data = await response.json();
|
|
1531
|
-
const imaPayload = data.response
|
|
2520
|
+
const imaPayload = (_c = (_b = (_a = data.response) == null ? void 0 : _a.ima) == null ? void 0 : _b["publisherdesk.ima"]) == null ? void 0 : _c.payload;
|
|
1532
2521
|
if (imaPayload) {
|
|
1533
2522
|
this.apiVastTagUrl = decodeURIComponent(imaPayload);
|
|
1534
2523
|
if (this.config.debugAdTiming) {
|
|
1535
2524
|
console.log(
|
|
1536
|
-
"[StormcloudVideoPlayer] Extracted VAST tag URL:",
|
|
2525
|
+
"[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:",
|
|
1537
2526
|
this.apiVastTagUrl
|
|
1538
2527
|
);
|
|
1539
2528
|
}
|
|
1540
|
-
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
});
|
|
2529
|
+
} else {
|
|
2530
|
+
if (this.config.debugAdTiming) {
|
|
2531
|
+
console.warn(
|
|
2532
|
+
"[StormcloudVideoPlayer] No VAST tag URL found in /ads/web response"
|
|
2533
|
+
);
|
|
2534
|
+
}
|
|
1547
2535
|
}
|
|
1548
2536
|
}
|
|
1549
2537
|
getCurrentAdIndex() {
|
|
@@ -1566,11 +2554,12 @@ var StormcloudVideoPlayer = class {
|
|
|
1566
2554
|
return "other";
|
|
1567
2555
|
}
|
|
1568
2556
|
shouldShowNativeControls() {
|
|
2557
|
+
var _a, _b;
|
|
1569
2558
|
const streamType = this.getStreamType();
|
|
1570
2559
|
if (streamType === "other") {
|
|
1571
|
-
return !(this.config.showCustomControls
|
|
2560
|
+
return !((_a = this.config.showCustomControls) != null ? _a : false);
|
|
1572
2561
|
}
|
|
1573
|
-
return !!(this.config.allowNativeHls && !(this.config.showCustomControls
|
|
2562
|
+
return !!(this.config.allowNativeHls && !((_b = this.config.showCustomControls) != null ? _b : false));
|
|
1574
2563
|
}
|
|
1575
2564
|
shouldContinueLiveStreamDuringAds() {
|
|
1576
2565
|
if (this.config.allowNativeHls) {
|
|
@@ -1582,28 +2571,20 @@ var StormcloudVideoPlayer = class {
|
|
|
1582
2571
|
return true;
|
|
1583
2572
|
}
|
|
1584
2573
|
async handleAdStart(_marker) {
|
|
2574
|
+
var _a;
|
|
1585
2575
|
const scheduled = this.findCurrentOrNextBreak(
|
|
1586
2576
|
this.video.currentTime * 1e3
|
|
1587
2577
|
);
|
|
1588
2578
|
const tags = this.selectVastTagsForBreak(scheduled);
|
|
1589
2579
|
let vastTagUrl;
|
|
1590
|
-
let adsNumber = 1;
|
|
1591
2580
|
if (this.apiVastTagUrl) {
|
|
1592
2581
|
vastTagUrl = this.apiVastTagUrl;
|
|
1593
|
-
|
|
1594
|
-
const isHls = this.config.src.includes(".m3u8") || this.config.src.includes("hls");
|
|
1595
|
-
if (isHls && this.vastConfig.cue_tones?.number_ads) {
|
|
1596
|
-
adsNumber = this.vastConfig.cue_tones.number_ads;
|
|
1597
|
-
} else if (!isHls && this.vastConfig.timer_vod?.number_ads) {
|
|
1598
|
-
adsNumber = this.vastConfig.timer_vod.number_ads;
|
|
1599
|
-
}
|
|
1600
|
-
}
|
|
1601
|
-
this.adPodQueue = new Array(adsNumber - 1).fill(vastTagUrl);
|
|
2582
|
+
this.adPodQueue = [];
|
|
1602
2583
|
this.currentAdIndex = 0;
|
|
1603
|
-
this.totalAdsInBreak =
|
|
2584
|
+
this.totalAdsInBreak = 1;
|
|
1604
2585
|
if (this.config.debugAdTiming) {
|
|
1605
2586
|
console.log(
|
|
1606
|
-
|
|
2587
|
+
"[StormcloudVideoPlayer] Using VAST endpoint:",
|
|
1607
2588
|
vastTagUrl
|
|
1608
2589
|
);
|
|
1609
2590
|
}
|
|
@@ -1641,17 +2622,18 @@ var StormcloudVideoPlayer = class {
|
|
|
1641
2622
|
this.handleAdFailure();
|
|
1642
2623
|
}
|
|
1643
2624
|
}
|
|
1644
|
-
if (this.expectedAdBreakDurationMs == null && scheduled
|
|
2625
|
+
if (this.expectedAdBreakDurationMs == null && (scheduled == null ? void 0 : scheduled.durationMs) != null) {
|
|
1645
2626
|
this.expectedAdBreakDurationMs = scheduled.durationMs;
|
|
1646
|
-
this.currentAdBreakStartWallClockMs = this.currentAdBreakStartWallClockMs
|
|
2627
|
+
this.currentAdBreakStartWallClockMs = (_a = this.currentAdBreakStartWallClockMs) != null ? _a : Date.now();
|
|
1647
2628
|
this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
|
|
1648
2629
|
}
|
|
1649
2630
|
}
|
|
1650
2631
|
findCurrentOrNextBreak(nowMs) {
|
|
2632
|
+
var _a;
|
|
1651
2633
|
const schedule = [];
|
|
1652
2634
|
let candidate;
|
|
1653
2635
|
for (const b of schedule) {
|
|
1654
|
-
const tol = this.config.driftToleranceMs
|
|
2636
|
+
const tol = (_a = this.config.driftToleranceMs) != null ? _a : 1e3;
|
|
1655
2637
|
if (b.startTimeMs <= nowMs + tol && (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))) {
|
|
1656
2638
|
candidate = b;
|
|
1657
2639
|
}
|
|
@@ -1667,7 +2649,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1667
2649
|
}
|
|
1668
2650
|
}
|
|
1669
2651
|
async handleMidAdJoin(adBreak, nowMs) {
|
|
1670
|
-
|
|
2652
|
+
var _a;
|
|
2653
|
+
const durationMs = (_a = adBreak.durationMs) != null ? _a : 0;
|
|
1671
2654
|
const endMs = adBreak.startTimeMs + durationMs;
|
|
1672
2655
|
if (durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs) {
|
|
1673
2656
|
const remainingMs = endMs - nowMs;
|
|
@@ -1768,6 +2751,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1768
2751
|
}
|
|
1769
2752
|
}
|
|
1770
2753
|
handleAdFailure() {
|
|
2754
|
+
var _a;
|
|
1771
2755
|
if (this.config.debugAdTiming) {
|
|
1772
2756
|
console.log(
|
|
1773
2757
|
"[StormcloudVideoPlayer] Handling ad failure - resuming content",
|
|
@@ -1800,7 +2784,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1800
2784
|
if (this.config.debugAdTiming) {
|
|
1801
2785
|
console.log("[StormcloudVideoPlayer] Resuming paused video");
|
|
1802
2786
|
}
|
|
1803
|
-
this.video.play()
|
|
2787
|
+
(_a = this.video.play()) == null ? void 0 : _a.catch((error) => {
|
|
1804
2788
|
if (this.config.debugAdTiming) {
|
|
1805
2789
|
console.error(
|
|
1806
2790
|
"[StormcloudVideoPlayer] Failed to resume video after ad failure:",
|
|
@@ -1815,8 +2799,9 @@ var StormcloudVideoPlayer = class {
|
|
|
1815
2799
|
}
|
|
1816
2800
|
}
|
|
1817
2801
|
startAdFailsafeTimer() {
|
|
2802
|
+
var _a;
|
|
1818
2803
|
this.clearAdFailsafeTimer();
|
|
1819
|
-
const failsafeMs = this.config.adFailsafeTimeoutMs
|
|
2804
|
+
const failsafeMs = (_a = this.config.adFailsafeTimeoutMs) != null ? _a : 1e4;
|
|
1820
2805
|
if (this.config.debugAdTiming) {
|
|
1821
2806
|
console.log(
|
|
1822
2807
|
`[StormcloudVideoPlayer] Starting failsafe timer (${failsafeMs}ms)`
|
|
@@ -1952,6 +2937,7 @@ var StormcloudVideoPlayer = class {
|
|
|
1952
2937
|
}
|
|
1953
2938
|
}
|
|
1954
2939
|
destroy() {
|
|
2940
|
+
var _a, _b;
|
|
1955
2941
|
this.clearAdStartTimer();
|
|
1956
2942
|
this.clearAdStopTimer();
|
|
1957
2943
|
this.clearAdFailsafeTimer();
|
|
@@ -1959,8 +2945,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1959
2945
|
clearInterval(this.heartbeatInterval);
|
|
1960
2946
|
this.heartbeatInterval = void 0;
|
|
1961
2947
|
}
|
|
1962
|
-
this.hls
|
|
1963
|
-
this.ima
|
|
2948
|
+
(_a = this.hls) == null ? void 0 : _a.destroy();
|
|
2949
|
+
(_b = this.ima) == null ? void 0 : _b.destroy();
|
|
1964
2950
|
}
|
|
1965
2951
|
};
|
|
1966
2952
|
|
|
@@ -1971,6 +2957,7 @@ var HlsPlayer = class extends import_react2.Component {
|
|
|
1971
2957
|
this.player = null;
|
|
1972
2958
|
this.mounted = false;
|
|
1973
2959
|
this.load = async () => {
|
|
2960
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1974
2961
|
if (!this.props.videoElement || !this.props.src) return;
|
|
1975
2962
|
try {
|
|
1976
2963
|
if (this.player) {
|
|
@@ -2007,27 +2994,29 @@ var HlsPlayer = class extends import_react2.Component {
|
|
|
2007
2994
|
if (this.props.adFailsafeTimeoutMs !== void 0)
|
|
2008
2995
|
config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;
|
|
2009
2996
|
this.player = new StormcloudVideoPlayer(config);
|
|
2010
|
-
this.props.onMount
|
|
2997
|
+
(_b = (_a = this.props).onMount) == null ? void 0 : _b.call(_a, this);
|
|
2011
2998
|
await this.player.load();
|
|
2012
2999
|
if (this.mounted) {
|
|
2013
|
-
this.props.onReady
|
|
3000
|
+
(_d = (_c = this.props).onReady) == null ? void 0 : _d.call(_c);
|
|
2014
3001
|
}
|
|
2015
3002
|
} catch (error) {
|
|
2016
3003
|
if (this.mounted) {
|
|
2017
|
-
this.props.onError
|
|
3004
|
+
(_f = (_e = this.props).onError) == null ? void 0 : _f.call(_e, error);
|
|
2018
3005
|
}
|
|
2019
3006
|
}
|
|
2020
3007
|
};
|
|
2021
3008
|
this.play = () => {
|
|
3009
|
+
var _a, _b;
|
|
2022
3010
|
if (this.props.videoElement) {
|
|
2023
3011
|
this.props.videoElement.play();
|
|
2024
|
-
this.props.onPlay
|
|
3012
|
+
(_b = (_a = this.props).onPlay) == null ? void 0 : _b.call(_a);
|
|
2025
3013
|
}
|
|
2026
3014
|
};
|
|
2027
3015
|
this.pause = () => {
|
|
3016
|
+
var _a, _b;
|
|
2028
3017
|
if (this.props.videoElement) {
|
|
2029
3018
|
this.props.videoElement.pause();
|
|
2030
|
-
this.props.onPause
|
|
3019
|
+
(_b = (_a = this.props).onPause) == null ? void 0 : _b.call(_a);
|
|
2031
3020
|
}
|
|
2032
3021
|
};
|
|
2033
3022
|
this.stop = () => {
|
|
@@ -2122,37 +3111,44 @@ var FilePlayer = class extends import_react3.Component {
|
|
|
2122
3111
|
this.mounted = false;
|
|
2123
3112
|
this.ready = false;
|
|
2124
3113
|
this.load = () => {
|
|
3114
|
+
var _a, _b;
|
|
2125
3115
|
if (!this.props.videoElement || !this.props.src) return;
|
|
2126
3116
|
const video = this.props.videoElement;
|
|
2127
3117
|
const handleLoadedMetadata = () => {
|
|
3118
|
+
var _a2, _b2;
|
|
2128
3119
|
if (this.mounted && !this.ready) {
|
|
2129
3120
|
this.ready = true;
|
|
2130
|
-
this.props.onReady
|
|
3121
|
+
(_b2 = (_a2 = this.props).onReady) == null ? void 0 : _b2.call(_a2);
|
|
2131
3122
|
}
|
|
2132
3123
|
};
|
|
2133
3124
|
const handlePlay = () => {
|
|
3125
|
+
var _a2, _b2;
|
|
2134
3126
|
if (this.mounted) {
|
|
2135
|
-
this.props.onPlay
|
|
3127
|
+
(_b2 = (_a2 = this.props).onPlay) == null ? void 0 : _b2.call(_a2);
|
|
2136
3128
|
}
|
|
2137
3129
|
};
|
|
2138
3130
|
const handlePause = () => {
|
|
3131
|
+
var _a2, _b2;
|
|
2139
3132
|
if (this.mounted) {
|
|
2140
|
-
this.props.onPause
|
|
3133
|
+
(_b2 = (_a2 = this.props).onPause) == null ? void 0 : _b2.call(_a2);
|
|
2141
3134
|
}
|
|
2142
3135
|
};
|
|
2143
3136
|
const handleEnded = () => {
|
|
3137
|
+
var _a2, _b2;
|
|
2144
3138
|
if (this.mounted) {
|
|
2145
|
-
this.props.onEnded
|
|
3139
|
+
(_b2 = (_a2 = this.props).onEnded) == null ? void 0 : _b2.call(_a2);
|
|
2146
3140
|
}
|
|
2147
3141
|
};
|
|
2148
3142
|
const handleError = (error) => {
|
|
3143
|
+
var _a2, _b2;
|
|
2149
3144
|
if (this.mounted) {
|
|
2150
|
-
this.props.onError
|
|
3145
|
+
(_b2 = (_a2 = this.props).onError) == null ? void 0 : _b2.call(_a2, error);
|
|
2151
3146
|
}
|
|
2152
3147
|
};
|
|
2153
3148
|
const handleLoadedData = () => {
|
|
3149
|
+
var _a2, _b2;
|
|
2154
3150
|
if (this.mounted) {
|
|
2155
|
-
this.props.onLoaded
|
|
3151
|
+
(_b2 = (_a2 = this.props).onLoaded) == null ? void 0 : _b2.call(_a2);
|
|
2156
3152
|
}
|
|
2157
3153
|
};
|
|
2158
3154
|
video.addEventListener("loadedmetadata", handleLoadedMetadata);
|
|
@@ -2171,7 +3167,7 @@ var FilePlayer = class extends import_react3.Component {
|
|
|
2171
3167
|
if (this.props.preload !== void 0)
|
|
2172
3168
|
video.preload = this.props.preload;
|
|
2173
3169
|
if (this.props.poster !== void 0) video.poster = this.props.poster;
|
|
2174
|
-
this.props.onMount
|
|
3170
|
+
(_b = (_a = this.props).onMount) == null ? void 0 : _b.call(_a, this);
|
|
2175
3171
|
return () => {
|
|
2176
3172
|
video.removeEventListener("loadedmetadata", handleLoadedMetadata);
|
|
2177
3173
|
video.removeEventListener("play", handlePlay);
|