stormcloud-video-player 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +245 -156
  2. package/dist/stormcloud-vp.min.js +1 -1
  3. package/lib/index.cjs +9759 -5311
  4. package/lib/index.cjs.map +1 -1
  5. package/lib/index.d.cts +193 -17
  6. package/lib/index.d.ts +193 -17
  7. package/lib/index.js +9761 -5329
  8. package/lib/index.js.map +1 -1
  9. package/lib/player/StormcloudVideoPlayer.cjs +7090 -1508
  10. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  11. package/lib/player/StormcloudVideoPlayer.d.cts +95 -9
  12. package/lib/players/HlsPlayer.cjs +7107 -1525
  13. package/lib/players/HlsPlayer.cjs.map +1 -1
  14. package/lib/players/HlsPlayer.d.cts +1 -1
  15. package/lib/players/index.cjs +7098 -1516
  16. package/lib/players/index.cjs.map +1 -1
  17. package/lib/sdk/hlsAdPlayer.cjs +302 -266
  18. package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
  19. package/lib/sdk/hlsAdPlayer.d.cts +2 -2
  20. package/lib/sdk/ima.cjs +1375 -0
  21. package/lib/sdk/ima.cjs.map +1 -0
  22. package/lib/sdk/ima.d.cts +12 -0
  23. package/lib/sdk/prebid.cjs +564 -0
  24. package/lib/sdk/prebid.cjs.map +1 -0
  25. package/lib/sdk/prebid.d.cts +5 -0
  26. package/lib/sdk/prebidController.cjs +1560 -0
  27. package/lib/sdk/prebidController.cjs.map +1 -0
  28. package/lib/sdk/prebidController.d.cts +11 -0
  29. package/lib/sdk/vastParser.cjs +393 -0
  30. package/lib/sdk/vastParser.cjs.map +1 -0
  31. package/lib/sdk/vastParser.d.cts +45 -0
  32. package/lib/{types-Ca4ZDaWw.d.cts → types-g2d4Akez.d.cts} +72 -3
  33. package/lib/ui/StormcloudVideoPlayer.cjs +7130 -1530
  34. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  35. package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
  36. package/lib/utils/browserCompat.cjs +222 -20
  37. package/lib/utils/browserCompat.cjs.map +1 -1
  38. package/lib/utils/browserCompat.d.cts +9 -1
  39. package/lib/utils/tracking.d.cts +1 -1
  40. package/package.json +2 -1
  41. package/lib/sdk/adstormPlayer.cjs +0 -908
  42. package/lib/sdk/adstormPlayer.cjs.map +0 -1
  43. package/lib/sdk/adstormPlayer.d.cts +0 -9
@@ -189,42 +189,196 @@ __export(hlsAdPlayer_exports, {
189
189
  }
190
190
  });
191
191
  module.exports = __toCommonJS(hlsAdPlayer_exports);
192
- var import_hls = __toESM(require("hls.js"), 1);
193
- var UNSUPPORTED_VIDEO_EXTENSIONS = [
194
- ".flv",
195
- ".f4v",
196
- ".swf",
197
- ".wmv",
198
- ".avi",
199
- ".mov",
200
- ".mkv",
201
- ".mp4",
202
- ".webm"
203
- ];
204
- function getFileExtension(url) {
192
+ // src/sdk/vastParser.ts
193
+ function isHlsType(type) {
194
+ return type === "application/x-mpegURL" || type.includes("m3u8");
195
+ }
196
+ function isMp4Type(type) {
197
+ return type === "video/mp4" || type.includes("mp4");
198
+ }
199
+ function parseVastXml(xmlString) {
200
+ var filter = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "all", logPrefix = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "[VastParser]";
205
201
  try {
206
- var pathname = new URL(url, "http://dummy").pathname;
207
- var lastDot = pathname.lastIndexOf(".");
208
- if (lastDot === -1) return "";
209
- return pathname.slice(lastDot).toLowerCase();
210
- } catch (e) {
211
- var lastDot1 = url.lastIndexOf(".");
212
- if (lastDot1 === -1) return "";
213
- var ext = url.slice(lastDot1).split(/[?#]/)[0];
214
- return (ext || "").toLowerCase();
202
+ var _xmlDoc_querySelector, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector2;
203
+ var parser = new DOMParser();
204
+ var xmlDoc = parser.parseFromString(xmlString, "text/xml");
205
+ var parserError = xmlDoc.querySelector("parsererror");
206
+ if (parserError) {
207
+ console.error("".concat(logPrefix, " XML parsing error (malformed VAST XML):"), parserError.textContent);
208
+ return null;
209
+ }
210
+ var adElement = xmlDoc.querySelector("Ad");
211
+ if (!adElement) {
212
+ console.warn("".concat(logPrefix, " No Ad element found in VAST XML"));
213
+ return null;
214
+ }
215
+ var adId = adElement.getAttribute("id") || "unknown";
216
+ var title = ((_xmlDoc_querySelector = xmlDoc.querySelector("AdTitle")) === null || _xmlDoc_querySelector === void 0 ? void 0 : _xmlDoc_querySelector.textContent) || "Ad";
217
+ var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
218
+ var durationText = ((_xmlDoc_querySelector1 = xmlDoc.querySelector("Duration")) === null || _xmlDoc_querySelector1 === void 0 ? void 0 : _xmlDoc_querySelector1.textContent) || "00:00:30";
219
+ var durationParts = durationText.split(":");
220
+ var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + Math.round(parseFloat(durationParts[2] || "0"));
221
+ var mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
222
+ var mediaFiles = [];
223
+ console.log("".concat(logPrefix, " Found ").concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
224
+ mediaFileElements.forEach(function(mf, index) {
225
+ var _mf_textContent;
226
+ var type = mf.getAttribute("type") || "";
227
+ var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
228
+ var width = mf.getAttribute("width") || "";
229
+ var height = mf.getAttribute("height") || "";
230
+ console.log("".concat(logPrefix, " MediaFile ").concat(index, ': type="').concat(type, '", url="').concat(url.substring(0, 80), '...", width="').concat(width, '", height="').concat(height, '"'));
231
+ if (!url) {
232
+ console.warn("".concat(logPrefix, " MediaFile ").concat(index, " has empty URL"));
233
+ return;
234
+ }
235
+ var isHls = isHlsType(type);
236
+ var isMp4 = isMp4Type(type);
237
+ var accepted = false;
238
+ if (filter === "hls-only") {
239
+ accepted = isHls;
240
+ } else if (filter === "mp4-first") {
241
+ accepted = isMp4 || isHls;
242
+ } else {
243
+ accepted = true;
244
+ }
245
+ if (!accepted) {
246
+ console.log("".concat(logPrefix, " MediaFile ").concat(index, ' ignored (type="').concat(type, '" not accepted by filter "').concat(filter, '")'));
247
+ return;
248
+ }
249
+ var bitrateAttr = mf.getAttribute("bitrate");
250
+ var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
251
+ mediaFiles.push({
252
+ url: url,
253
+ type: type,
254
+ width: parseInt(width || "1920", 10),
255
+ height: parseInt(height || "1080", 10),
256
+ bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
257
+ });
258
+ console.log("".concat(logPrefix, ' Added MediaFile: type="').concat(type, '" url="').concat(url.substring(0, 80), '..."'));
259
+ });
260
+ if (filter === "mp4-first" && mediaFiles.length > 1) {
261
+ mediaFiles.sort(function(a, b) {
262
+ var aIsMp4 = isMp4Type(a.type) ? 0 : 1;
263
+ var bIsMp4 = isMp4Type(b.type) ? 0 : 1;
264
+ return aIsMp4 - bIsMp4;
265
+ });
266
+ }
267
+ if (mediaFiles.length === 0) {
268
+ if (isNoAdAvailable) {
269
+ console.warn("".concat(logPrefix, " No ads available (VAST response indicates no ads)"));
270
+ } else {
271
+ console.warn("".concat(logPrefix, " No compatible media files found in VAST XML"));
272
+ }
273
+ return null;
274
+ }
275
+ var trackingUrls = {
276
+ impression: [],
277
+ start: [],
278
+ firstQuartile: [],
279
+ midpoint: [],
280
+ thirdQuartile: [],
281
+ complete: [],
282
+ mute: [],
283
+ unmute: [],
284
+ pause: [],
285
+ resume: [],
286
+ fullscreen: [],
287
+ exitFullscreen: [],
288
+ skip: [],
289
+ error: []
290
+ };
291
+ xmlDoc.querySelectorAll("Impression").forEach(function(el) {
292
+ var _el_textContent;
293
+ var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
294
+ if (url) trackingUrls.impression.push(url);
295
+ });
296
+ xmlDoc.querySelectorAll("Tracking").forEach(function(el) {
297
+ var _el_textContent;
298
+ var event = el.getAttribute("event");
299
+ var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
300
+ if (event && url) {
301
+ var eventKey = event;
302
+ if (trackingUrls[eventKey]) {
303
+ trackingUrls[eventKey].push(url);
304
+ }
305
+ }
306
+ });
307
+ var clickThrough = (_xmlDoc_querySelector2 = xmlDoc.querySelector("ClickThrough")) === null || _xmlDoc_querySelector2 === void 0 ? void 0 : (_xmlDoc_querySelector_textContent = _xmlDoc_querySelector2.textContent) === null || _xmlDoc_querySelector_textContent === void 0 ? void 0 : _xmlDoc_querySelector_textContent.trim();
308
+ return {
309
+ id: adId,
310
+ title: title,
311
+ duration: duration,
312
+ mediaFiles: mediaFiles,
313
+ trackingUrls: trackingUrls,
314
+ clickThrough: clickThrough
315
+ };
316
+ } catch (error) {
317
+ console.error("".concat(logPrefix, " Error parsing VAST XML:"), error);
318
+ return null;
215
319
  }
216
320
  }
217
- function isUnsupportedForHls(url) {
218
- var ext = getFileExtension(url);
219
- return UNSUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1;
321
+ function fetchAndParseVastAd(vastTagUrl) {
322
+ var filter = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "all", logPrefix = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "[VastParser]";
323
+ return _async_to_generator(function() {
324
+ var response, vastXml;
325
+ return _ts_generator(this, function(_state) {
326
+ switch(_state.label){
327
+ case 0:
328
+ return [
329
+ 4,
330
+ fetch(vastTagUrl, {
331
+ mode: "cors",
332
+ credentials: "include",
333
+ headers: {
334
+ Accept: "application/xml, text/xml, */*"
335
+ },
336
+ referrerPolicy: "no-referrer-when-downgrade"
337
+ })
338
+ ];
339
+ case 1:
340
+ response = _state.sent();
341
+ if (!response.ok) {
342
+ throw new Error("Failed to fetch VAST: ".concat(response.statusText));
343
+ }
344
+ return [
345
+ 4,
346
+ response.text()
347
+ ];
348
+ case 2:
349
+ vastXml = _state.sent();
350
+ console.log("".concat(logPrefix, " VAST XML received"));
351
+ console.log("".concat(logPrefix, " VAST XML content (first 2000 chars):"), vastXml.substring(0, 2e3));
352
+ return [
353
+ 2,
354
+ parseVastXml(vastXml, filter, logPrefix)
355
+ ];
356
+ }
357
+ });
358
+ })();
220
359
  }
221
- function replaceFlvExtension(url) {
222
- var ext = getFileExtension(url);
223
- if (ext === ".flv") {
224
- return url.replace(/\.flv(\?|$)/i, ".mp4$1");
225
- }
226
- return url;
360
+ function fireTrackingPixels(urls, sessionId, licenseKey) {
361
+ var logPrefix = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : "[VastParser]";
362
+ if (!urls || urls.length === 0) return;
363
+ urls.forEach(function(url) {
364
+ try {
365
+ var trackingUrl = url;
366
+ if (sessionId) {
367
+ trackingUrl = "".concat(trackingUrl).concat(trackingUrl.includes("?") ? "&" : "?", "session_id=").concat(sessionId);
368
+ }
369
+ if (licenseKey) {
370
+ trackingUrl = "".concat(trackingUrl).concat(trackingUrl.includes("?") ? "&" : "?", "license_key=").concat(licenseKey);
371
+ }
372
+ var img = new Image(1, 1);
373
+ img.src = trackingUrl;
374
+ console.log("".concat(logPrefix, " Fired tracking pixel: ").concat(trackingUrl));
375
+ } catch (error) {
376
+ console.warn("".concat(logPrefix, " Error firing tracking pixel:"), error);
377
+ }
378
+ });
227
379
  }
380
+ // src/sdk/hlsAdPlayer.ts
381
+ var import_hls = __toESM(require("hls.js"), 1);
228
382
  function createHlsAdPlayer(contentVideo, options) {
229
383
  var adPlaying = false;
230
384
  var originalMutedState = false;
@@ -237,6 +391,8 @@ function createHlsAdPlayer(contentVideo, options) {
237
391
  var adContainerEl;
238
392
  var currentAd;
239
393
  var sessionId;
394
+ var preloadedAds = /* @__PURE__ */ new Map();
395
+ var preloadingAds = /* @__PURE__ */ new Map();
240
396
  var destroyed = false;
241
397
  var pendingTimeouts = [];
242
398
  var trackingFired = {
@@ -278,46 +434,8 @@ function createHlsAdPlayer(contentVideo, options) {
278
434
  function generateSessionId() {
279
435
  return "session-".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
280
436
  }
281
- function buildVastUrl(durationSeconds) {
282
- var baseUrl = "https://adstorm.co/api-adstorm-dev/adstorm/vast/".concat(licenseKey, "/pod");
283
- var metadata = {
284
- video: {
285
- codec: "h264",
286
- width: contentVideo.videoWidth || 1280,
287
- height: contentVideo.videoHeight || 720,
288
- fps: 29.97,
289
- bitrate: 5e3,
290
- profile: "high",
291
- pix_fmt: "yuv420p",
292
- has_b_frames: 0
293
- },
294
- audio: {
295
- codec: "aac",
296
- sample_rate: 48e3,
297
- bitrate: 128
298
- }
299
- };
300
- var metadataStr = encodeURIComponent(JSON.stringify(metadata));
301
- return "".concat(baseUrl, "?duration=").concat(Math.ceil(durationSeconds), "&metadata=").concat(metadataStr);
302
- }
303
- function fireTrackingPixels(urls) {
304
- if (!urls || urls.length === 0) return;
305
- urls.forEach(function(url) {
306
- try {
307
- var trackingUrl = url;
308
- if (sessionId) {
309
- trackingUrl = "".concat(trackingUrl).concat(trackingUrl.includes("?") ? "&" : "?", "session_id=").concat(sessionId);
310
- }
311
- if (licenseKey) {
312
- trackingUrl = "".concat(trackingUrl).concat(trackingUrl.includes("?") ? "&" : "?", "license_key=").concat(licenseKey);
313
- }
314
- var img = new Image(1, 1);
315
- img.src = trackingUrl;
316
- console.log("[HlsAdPlayer] Fired tracking pixel: ".concat(trackingUrl));
317
- } catch (error) {
318
- console.warn("[HlsAdPlayer] Error firing tracking pixel:", error);
319
- }
320
- });
437
+ function fireTrackingPixels2(urls) {
438
+ fireTrackingPixels(urls, sessionId, licenseKey, "[HlsAdPlayer]");
321
439
  }
322
440
  function getMainStreamQuality() {
323
441
  if (!mainHlsInstance || !mainHlsInstance.levels) {
@@ -392,148 +510,13 @@ function createHlsAdPlayer(contentVideo, options) {
392
510
  });
393
511
  return bestMatch.file;
394
512
  }
395
- function parseVastXml(xmlString) {
396
- try {
397
- var _xmlDoc_querySelector, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector2;
398
- var parser = new DOMParser();
399
- var xmlDoc = parser.parseFromString(xmlString, "text/xml");
400
- var parserError = xmlDoc.querySelector("parsererror");
401
- if (parserError) {
402
- console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
403
- return null;
404
- }
405
- var adElement = xmlDoc.querySelector("Ad");
406
- if (!adElement) {
407
- console.warn("[HlsAdPlayer] No Ad element found in VAST XML");
408
- return null;
409
- }
410
- var adId = adElement.getAttribute("id") || "unknown";
411
- var title = ((_xmlDoc_querySelector = xmlDoc.querySelector("AdTitle")) === null || _xmlDoc_querySelector === void 0 ? void 0 : _xmlDoc_querySelector.textContent) || "Ad";
412
- var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
413
- var durationText = ((_xmlDoc_querySelector1 = xmlDoc.querySelector("Duration")) === null || _xmlDoc_querySelector1 === void 0 ? void 0 : _xmlDoc_querySelector1.textContent) || "00:00:30";
414
- var durationParts = durationText.split(":");
415
- var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
416
- var mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
417
- var mediaFiles = [];
418
- console.log("[HlsAdPlayer] Found ".concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
419
- mediaFileElements.forEach(function(mf, index) {
420
- var _mf_textContent;
421
- var type = mf.getAttribute("type") || "";
422
- var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
423
- var width = mf.getAttribute("width") || "";
424
- var height = mf.getAttribute("height") || "";
425
- console.log("[HlsAdPlayer] MediaFile ".concat(index, ': type="').concat(type, '", url="').concat(url, '", width="').concat(width, '", height="').concat(height, '"'));
426
- var originalUrl = url;
427
- url = replaceFlvExtension(url);
428
- if (url !== originalUrl) {
429
- console.log("[HlsAdPlayer] Converted FLV to MP4: ".concat(originalUrl, " -> ").concat(url));
430
- }
431
- if (isUnsupportedForHls(url)) {
432
- var ext = getFileExtension(url);
433
- console.log("[HlsAdPlayer] MediaFile ".concat(index, " ignored: unsupported format (extension: ").concat(ext, ", declared type: ").concat(type, ")"));
434
- return;
435
- }
436
- if (type === "application/x-mpegURL" || type.includes("m3u8")) {
437
- if (!url) {
438
- console.warn("[HlsAdPlayer] MediaFile ".concat(index, " has HLS type but empty URL"));
439
- return;
440
- }
441
- var bitrateAttr = mf.getAttribute("bitrate");
442
- var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
443
- mediaFiles.push({
444
- url: url,
445
- type: type,
446
- width: parseInt(width || "1920", 10),
447
- height: parseInt(height || "1080", 10),
448
- bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
449
- });
450
- console.log("[HlsAdPlayer] Added HLS MediaFile: ".concat(url));
451
- } else {
452
- console.log("[HlsAdPlayer] MediaFile ".concat(index, ' ignored (type="').concat(type, '" is not HLS)'));
453
- }
454
- });
455
- if (mediaFiles.length === 0) {
456
- if (isNoAdAvailable) {
457
- console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
458
- } else {
459
- console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
460
- }
461
- return null;
462
- }
463
- var trackingUrls = {
464
- impression: [],
465
- start: [],
466
- firstQuartile: [],
467
- midpoint: [],
468
- thirdQuartile: [],
469
- complete: [],
470
- mute: [],
471
- unmute: [],
472
- pause: [],
473
- resume: [],
474
- fullscreen: [],
475
- exitFullscreen: [],
476
- skip: [],
477
- error: []
478
- };
479
- xmlDoc.querySelectorAll("Impression").forEach(function(el) {
480
- var _el_textContent;
481
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
482
- if (url) trackingUrls.impression.push(url);
483
- });
484
- xmlDoc.querySelectorAll("Tracking").forEach(function(el) {
485
- var _el_textContent;
486
- var event = el.getAttribute("event");
487
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
488
- if (event && url) {
489
- var eventKey = event;
490
- if (trackingUrls[eventKey]) {
491
- trackingUrls[eventKey].push(url);
492
- }
493
- }
494
- });
495
- var clickThrough = (_xmlDoc_querySelector2 = xmlDoc.querySelector("ClickThrough")) === null || _xmlDoc_querySelector2 === void 0 ? void 0 : (_xmlDoc_querySelector_textContent = _xmlDoc_querySelector2.textContent) === null || _xmlDoc_querySelector_textContent === void 0 ? void 0 : _xmlDoc_querySelector_textContent.trim();
496
- return {
497
- id: adId,
498
- title: title,
499
- duration: duration,
500
- mediaFiles: mediaFiles,
501
- trackingUrls: trackingUrls,
502
- clickThrough: clickThrough
503
- };
504
- } catch (error) {
505
- console.error("[HlsAdPlayer] Error parsing VAST XML:", error);
506
- return null;
507
- }
508
- }
509
- function fetchAndParseVastAd(url) {
513
+ function fetchAndParseVastAdLocal(vastTagUrl) {
510
514
  return _async_to_generator(function() {
511
- var response, vastXml;
512
515
  return _ts_generator(this, function(_state) {
513
- switch(_state.label){
514
- case 0:
515
- return [
516
- 4,
517
- fetch(url)
518
- ];
519
- case 1:
520
- response = _state.sent();
521
- if (!response.ok) {
522
- throw new Error("Failed to fetch VAST: ".concat(response.statusText));
523
- }
524
- return [
525
- 4,
526
- response.text()
527
- ];
528
- case 2:
529
- vastXml = _state.sent();
530
- console.log("[HlsAdPlayer] VAST XML received");
531
- console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
532
- return [
533
- 2,
534
- parseVastXml(vastXml)
535
- ];
536
- }
516
+ return [
517
+ 2,
518
+ fetchAndParseVastAd(vastTagUrl, "hls-only", "[HlsAdPlayer]")
519
+ ];
537
520
  });
538
521
  })();
539
522
  }
@@ -559,53 +542,53 @@ function createHlsAdPlayer(contentVideo, options) {
559
542
  var progress = adVideoElement.currentTime / currentAd.duration;
560
543
  if (progress >= 0.25 && !trackingFired.firstQuartile) {
561
544
  trackingFired.firstQuartile = true;
562
- fireTrackingPixels(currentAd.trackingUrls.firstQuartile);
545
+ fireTrackingPixels2(currentAd.trackingUrls.firstQuartile);
563
546
  }
564
547
  if (progress >= 0.5 && !trackingFired.midpoint) {
565
548
  trackingFired.midpoint = true;
566
- fireTrackingPixels(currentAd.trackingUrls.midpoint);
549
+ fireTrackingPixels2(currentAd.trackingUrls.midpoint);
567
550
  }
568
551
  if (progress >= 0.75 && !trackingFired.thirdQuartile) {
569
552
  trackingFired.thirdQuartile = true;
570
- fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
553
+ fireTrackingPixels2(currentAd.trackingUrls.thirdQuartile);
571
554
  }
572
555
  });
573
556
  adVideoElement.addEventListener("playing", function() {
574
557
  if (!currentAd || trackingFired.start) return;
575
558
  trackingFired.start = true;
576
- fireTrackingPixels(currentAd.trackingUrls.start);
559
+ fireTrackingPixels2(currentAd.trackingUrls.start);
577
560
  console.log("[HlsAdPlayer] Ad started playing");
578
561
  });
579
562
  adVideoElement.addEventListener("ended", function() {
580
563
  if (!currentAd || trackingFired.complete) return;
581
564
  trackingFired.complete = true;
582
- fireTrackingPixels(currentAd.trackingUrls.complete);
565
+ fireTrackingPixels2(currentAd.trackingUrls.complete);
583
566
  console.log("[HlsAdPlayer] Ad completed");
584
567
  handleAdComplete();
585
568
  });
586
569
  adVideoElement.addEventListener("error", function(e) {
587
570
  console.error("[HlsAdPlayer] Ad video error:", e);
588
571
  if (currentAd) {
589
- fireTrackingPixels(currentAd.trackingUrls.error);
572
+ fireTrackingPixels2(currentAd.trackingUrls.error);
590
573
  }
591
574
  handleAdError();
592
575
  });
593
576
  adVideoElement.addEventListener("volumechange", function() {
594
577
  if (!currentAd) return;
595
578
  if (adVideoElement.muted) {
596
- fireTrackingPixels(currentAd.trackingUrls.mute);
579
+ fireTrackingPixels2(currentAd.trackingUrls.mute);
597
580
  } else {
598
- fireTrackingPixels(currentAd.trackingUrls.unmute);
581
+ fireTrackingPixels2(currentAd.trackingUrls.unmute);
599
582
  }
600
583
  });
601
584
  adVideoElement.addEventListener("pause", function() {
602
585
  if (currentAd && !adVideoElement.ended) {
603
- fireTrackingPixels(currentAd.trackingUrls.pause);
586
+ fireTrackingPixels2(currentAd.trackingUrls.pause);
604
587
  }
605
588
  });
606
589
  adVideoElement.addEventListener("play", function() {
607
590
  if (currentAd && adVideoElement.currentTime > 0) {
608
- fireTrackingPixels(currentAd.trackingUrls.resume);
591
+ fireTrackingPixels2(currentAd.trackingUrls.resume);
609
592
  }
610
593
  });
611
594
  }
@@ -620,44 +603,32 @@ function createHlsAdPlayer(contentVideo, options) {
620
603
  console.log("[HlsAdPlayer] Handling ad completion");
621
604
  adPlaying = false;
622
605
  setAdPlayingFlag(false);
623
- emit("content_resume");
624
- var timeoutId = window.setTimeout(function() {
625
- if (destroyed) {
626
- console.log("[HlsAdPlayer] Player destroyed, skipping post-completion check");
627
- return;
628
- }
629
- var stillInPod = contentVideo.dataset.stormcloudAdPlaying === "true";
630
- if (stillInPod) {
631
- console.log("[HlsAdPlayer] Still in ad pod - keeping ad container visible (black screen)");
632
- if (adContainerEl) {
633
- adContainerEl.style.display = "flex";
634
- adContainerEl.style.pointerEvents = "auto";
635
- }
636
- }
637
- var idx = pendingTimeouts.indexOf(timeoutId);
638
- if (idx !== -1) {
639
- pendingTimeouts.splice(idx, 1);
606
+ contentVideo.muted = true;
607
+ contentVideo.volume = 0;
608
+ if (adContainerEl) {
609
+ adContainerEl.style.display = "none";
610
+ adContainerEl.style.pointerEvents = "none";
611
+ }
612
+ if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
613
+ if (contentVideo.paused) {
614
+ console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback");
615
+ contentVideo.play().catch(function() {});
616
+ } else {
617
+ console.log("[HlsAdPlayer] Content video already playing in live mode");
640
618
  }
641
- }, 50);
642
- pendingTimeouts.push(timeoutId);
619
+ }
620
+ emit("content_resume");
643
621
  }
644
622
  function handleAdError() {
645
623
  console.log("[HlsAdPlayer] Handling ad error");
646
624
  adPlaying = false;
647
625
  setAdPlayingFlag(false);
648
- var previousMutedState = contentVideo.muted;
649
- contentVideo.muted = originalMutedState;
650
- contentVideo.volume = originalMutedState ? 0 : originalVolume;
651
- console.log("[HlsAdPlayer] Restored mute state: ".concat(previousMutedState, " -> ").concat(originalMutedState));
626
+ contentVideo.muted = true;
627
+ contentVideo.volume = 0;
652
628
  if (adContainerEl) {
653
629
  adContainerEl.style.display = "none";
654
630
  adContainerEl.style.pointerEvents = "none";
655
631
  }
656
- if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
657
- if (contentVideo.paused) {
658
- contentVideo.play().catch(function() {});
659
- }
660
- }
661
632
  emit("ad_error");
662
633
  }
663
634
  return {
@@ -681,13 +652,19 @@ function createHlsAdPlayer(contentVideo, options) {
681
652
  adContainerEl = container;
682
653
  }
683
654
  },
684
- requestAds: function requestAds(duration) {
655
+ requestAds: function requestAds(vastTagUrl) {
685
656
  return _async_to_generator(function() {
686
- var durationSeconds, parsed, vastUrl, ad, error;
657
+ var ad, error;
687
658
  return _ts_generator(this, function(_state) {
688
659
  switch(_state.label){
689
660
  case 0:
690
- console.log("[HlsAdPlayer] Requesting ads for duration:", duration);
661
+ if (destroyed) {
662
+ return [
663
+ 2,
664
+ Promise.reject(new Error("Controller has been destroyed"))
665
+ ];
666
+ }
667
+ console.log("[HlsAdPlayer] Requesting ads:", vastTagUrl);
691
668
  if (adPlaying) {
692
669
  console.warn("[HlsAdPlayer] Cannot request new ads while an ad is playing");
693
670
  return [
@@ -699,40 +676,48 @@ function createHlsAdPlayer(contentVideo, options) {
699
676
  case 1:
700
677
  _state.trys.push([
701
678
  1,
702
- 3,
679
+ 5,
703
680
  ,
704
- 4
681
+ 6
705
682
  ]);
706
683
  sessionId = generateSessionId();
707
- durationSeconds = 30;
708
- parsed = parseInt(duration, 10);
709
- if (!isNaN(parsed) && parsed > 0) {
710
- durationSeconds = parsed;
711
- }
712
- vastUrl = buildVastUrl(durationSeconds);
684
+ if (!preloadedAds.has(vastTagUrl)) return [
685
+ 3,
686
+ 2
687
+ ];
688
+ ad = preloadedAds.get(vastTagUrl);
689
+ preloadedAds.delete(vastTagUrl);
690
+ console.log("[HlsAdPlayer] Using preloaded VAST response:", vastTagUrl);
713
691
  return [
714
- 4,
715
- fetchAndParseVastAd(vastUrl)
692
+ 3,
693
+ 4
716
694
  ];
717
695
  case 2:
696
+ return [
697
+ 4,
698
+ fetchAndParseVastAdLocal(vastTagUrl)
699
+ ];
700
+ case 3:
718
701
  ad = _state.sent();
702
+ _state.label = 4;
703
+ case 4:
719
704
  if (!ad) {
720
705
  console.warn("[HlsAdPlayer] No ads available from VAST response");
721
706
  emit("ad_error");
722
707
  return [
723
708
  2,
724
- Promise.resolve()
709
+ Promise.reject(new Error("No ads available from VAST response"))
725
710
  ];
726
711
  }
727
712
  currentAd = ad;
728
713
  console.log("[HlsAdPlayer] Ad parsed: ".concat(ad.title, ", duration: ").concat(ad.duration, "s"));
729
- fireTrackingPixels(ad.trackingUrls.impression);
714
+ fireTrackingPixels2(ad.trackingUrls.impression);
730
715
  trackingFired.impression = true;
731
716
  return [
732
717
  2,
733
718
  Promise.resolve()
734
719
  ];
735
- case 3:
720
+ case 5:
736
721
  error = _state.sent();
737
722
  console.error("[HlsAdPlayer] Error requesting ads:", error);
738
723
  emit("ad_error");
@@ -740,7 +725,7 @@ function createHlsAdPlayer(contentVideo, options) {
740
725
  2,
741
726
  Promise.reject(error)
742
727
  ];
743
- case 4:
728
+ case 6:
744
729
  return [
745
730
  2
746
731
  ];
@@ -752,6 +737,12 @@ function createHlsAdPlayer(contentVideo, options) {
752
737
  return _async_to_generator(function() {
753
738
  var contentVolume, adVolume, mediaFile;
754
739
  return _ts_generator(this, function(_state) {
740
+ if (destroyed) {
741
+ return [
742
+ 2,
743
+ Promise.reject(new Error("Controller has been destroyed"))
744
+ ];
745
+ }
755
746
  if (!currentAd) {
756
747
  console.warn("[HlsAdPlayer] Cannot play: No ad loaded (no ads available)");
757
748
  return [
@@ -853,16 +844,53 @@ function createHlsAdPlayer(contentVideo, options) {
853
844
  });
854
845
  })();
855
846
  },
847
+ pause: function pause() {
848
+ if (!adPlaying || !adVideoElement) {
849
+ return;
850
+ }
851
+ try {
852
+ if (adVideoElement && !adVideoElement.paused) {
853
+ adVideoElement.pause();
854
+ }
855
+ } catch (error) {
856
+ console.warn("[HlsAdPlayer] Error pausing ad:", error);
857
+ }
858
+ },
859
+ resume: function resume() {
860
+ if (!adPlaying || !adVideoElement) {
861
+ return;
862
+ }
863
+ try {
864
+ if (adVideoElement && adVideoElement.paused) {
865
+ adVideoElement.play().catch(function() {});
866
+ }
867
+ } catch (error) {
868
+ console.warn("[HlsAdPlayer] Error resuming ad:", error);
869
+ }
870
+ },
856
871
  stop: function stop() {
857
872
  return _async_to_generator(function() {
873
+ var previousMutedState;
858
874
  return _ts_generator(this, function(_state) {
859
875
  console.log("[HlsAdPlayer] Stopping ad");
860
876
  adPlaying = false;
861
877
  setAdPlayingFlag(false);
878
+ previousMutedState = contentVideo.muted;
879
+ contentVideo.muted = originalMutedState;
880
+ contentVideo.volume = originalMutedState ? 0 : originalVolume;
881
+ console.log("[HlsAdPlayer] Restored mute state on stop: ".concat(previousMutedState, " -> ").concat(originalMutedState));
862
882
  if (adContainerEl) {
863
883
  adContainerEl.style.display = "none";
864
884
  adContainerEl.style.pointerEvents = "none";
865
885
  }
886
+ contentVideo.style.visibility = "visible";
887
+ contentVideo.style.opacity = "1";
888
+ if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
889
+ if (contentVideo.paused) {
890
+ console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback on stop");
891
+ contentVideo.play().catch(function() {});
892
+ }
893
+ }
866
894
  if (adHls) {
867
895
  adHls.destroy();
868
896
  adHls = void 0;
@@ -922,6 +950,8 @@ function createHlsAdPlayer(contentVideo, options) {
922
950
  adContainerEl = void 0;
923
951
  currentAd = void 0;
924
952
  listeners.clear();
953
+ preloadedAds.clear();
954
+ preloadingAds.clear();
925
955
  },
926
956
  isAdPlaying: function isAdPlaying() {
927
957
  return adPlaying;
@@ -969,6 +999,8 @@ function createHlsAdPlayer(contentVideo, options) {
969
999
  return 1;
970
1000
  },
971
1001
  showPlaceholder: function showPlaceholder() {
1002
+ contentVideo.style.opacity = "0";
1003
+ contentVideo.style.visibility = "hidden";
972
1004
  if (!adContainerEl) {
973
1005
  var _contentVideo_parentElement;
974
1006
  var container = document.createElement("div");
@@ -996,6 +1028,10 @@ function createHlsAdPlayer(contentVideo, options) {
996
1028
  adContainerEl.style.display = "none";
997
1029
  adContainerEl.style.pointerEvents = "none";
998
1030
  }
1031
+ if (!adPlaying) {
1032
+ contentVideo.style.visibility = "visible";
1033
+ contentVideo.style.opacity = "1";
1034
+ }
999
1035
  }
1000
1036
  };
1001
1037
  }