stormcloud-video-player 0.7.2 → 0.7.4

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.
@@ -347,185 +347,8 @@ __export(StormcloudVideoPlayer_exports, {
347
347
  }
348
348
  });
349
349
  module.exports = __toCommonJS(StormcloudVideoPlayer_exports);
350
- var import_hls2 = __toESM(require("hls.js"), 1);
350
+ var import_hls = __toESM(require("hls.js"), 1);
351
351
  // src/sdk/vastParser.ts
352
- function isHlsType(type) {
353
- return type === "application/x-mpegURL" || type.includes("m3u8");
354
- }
355
- function isMp4Type(type) {
356
- return type === "video/mp4" || type.includes("mp4");
357
- }
358
- function parseVastXml(xmlString) {
359
- var filter = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "all", logPrefix = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "[VastParser]";
360
- try {
361
- var _xmlDoc_querySelector, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector2;
362
- var parser = new DOMParser();
363
- var xmlDoc = parser.parseFromString(xmlString, "text/xml");
364
- var parserError = xmlDoc.querySelector("parsererror");
365
- if (parserError) {
366
- console.error("".concat(logPrefix, " XML parsing error (malformed VAST XML):"), parserError.textContent);
367
- return null;
368
- }
369
- var adElement = xmlDoc.querySelector("Ad");
370
- if (!adElement) {
371
- console.warn("".concat(logPrefix, " No Ad element found in VAST XML"));
372
- return null;
373
- }
374
- var adId = adElement.getAttribute("id") || "unknown";
375
- var title = ((_xmlDoc_querySelector = xmlDoc.querySelector("AdTitle")) === null || _xmlDoc_querySelector === void 0 ? void 0 : _xmlDoc_querySelector.textContent) || "Ad";
376
- var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
377
- var durationText = ((_xmlDoc_querySelector1 = xmlDoc.querySelector("Duration")) === null || _xmlDoc_querySelector1 === void 0 ? void 0 : _xmlDoc_querySelector1.textContent) || "00:00:30";
378
- var durationParts = durationText.split(":");
379
- var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + Math.round(parseFloat(durationParts[2] || "0"));
380
- var mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
381
- var mediaFiles = [];
382
- console.log("".concat(logPrefix, " Found ").concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
383
- mediaFileElements.forEach(function(mf, index) {
384
- var _mf_textContent;
385
- var type = mf.getAttribute("type") || "";
386
- var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
387
- var width = mf.getAttribute("width") || "";
388
- var height = mf.getAttribute("height") || "";
389
- console.log("".concat(logPrefix, " MediaFile ").concat(index, ': type="').concat(type, '", url="').concat(url.substring(0, 80), '...", width="').concat(width, '", height="').concat(height, '"'));
390
- if (!url) {
391
- console.warn("".concat(logPrefix, " MediaFile ").concat(index, " has empty URL"));
392
- return;
393
- }
394
- var isHls = isHlsType(type);
395
- var isMp4 = isMp4Type(type);
396
- var accepted = false;
397
- if (filter === "hls-only") {
398
- accepted = isHls;
399
- } else if (filter === "mp4-first") {
400
- accepted = isMp4 || isHls;
401
- } else {
402
- accepted = true;
403
- }
404
- if (!accepted) {
405
- console.log("".concat(logPrefix, " MediaFile ").concat(index, ' ignored (type="').concat(type, '" not accepted by filter "').concat(filter, '")'));
406
- return;
407
- }
408
- var bitrateAttr = mf.getAttribute("bitrate");
409
- var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
410
- mediaFiles.push({
411
- url: url,
412
- type: type,
413
- width: parseInt(width || "1920", 10),
414
- height: parseInt(height || "1080", 10),
415
- bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
416
- });
417
- console.log("".concat(logPrefix, ' Added MediaFile: type="').concat(type, '" url="').concat(url.substring(0, 80), '..."'));
418
- });
419
- if (filter === "mp4-first" && mediaFiles.length > 1) {
420
- mediaFiles.sort(function(a, b) {
421
- var aIsMp4 = isMp4Type(a.type) ? 0 : 1;
422
- var bIsMp4 = isMp4Type(b.type) ? 0 : 1;
423
- return aIsMp4 - bIsMp4;
424
- });
425
- }
426
- if (mediaFiles.length === 0) {
427
- if (isNoAdAvailable) {
428
- console.warn("".concat(logPrefix, " No ads available (VAST response indicates no ads)"));
429
- } else {
430
- console.warn("".concat(logPrefix, " No compatible media files found in VAST XML"));
431
- }
432
- return null;
433
- }
434
- var trackingUrls = {
435
- impression: [],
436
- start: [],
437
- firstQuartile: [],
438
- midpoint: [],
439
- thirdQuartile: [],
440
- complete: [],
441
- mute: [],
442
- unmute: [],
443
- pause: [],
444
- resume: [],
445
- fullscreen: [],
446
- exitFullscreen: [],
447
- skip: [],
448
- error: []
449
- };
450
- xmlDoc.querySelectorAll("Impression").forEach(function(el) {
451
- var _el_textContent;
452
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
453
- if (url) trackingUrls.impression.push(url);
454
- });
455
- xmlDoc.querySelectorAll("Tracking").forEach(function(el) {
456
- var _el_textContent;
457
- var event = el.getAttribute("event");
458
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
459
- if (event && url) {
460
- var eventKey = event;
461
- if (trackingUrls[eventKey]) {
462
- trackingUrls[eventKey].push(url);
463
- }
464
- }
465
- });
466
- 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();
467
- return {
468
- id: adId,
469
- title: title,
470
- duration: duration,
471
- mediaFiles: mediaFiles,
472
- trackingUrls: trackingUrls,
473
- clickThrough: clickThrough
474
- };
475
- } catch (error) {
476
- console.error("".concat(logPrefix, " Error parsing VAST XML:"), error);
477
- return null;
478
- }
479
- }
480
- function fetchAndParseVastAd(vastTagUrl) {
481
- var filter = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "all", logPrefix = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "[VastParser]";
482
- return _async_to_generator(function() {
483
- var response, vastXml;
484
- return _ts_generator(this, function(_state) {
485
- switch(_state.label){
486
- case 0:
487
- return [
488
- 4,
489
- fetch(vastTagUrl, {
490
- mode: "cors",
491
- credentials: "include",
492
- headers: {
493
- Accept: "application/xml, text/xml, */*"
494
- },
495
- referrerPolicy: "no-referrer-when-downgrade"
496
- })
497
- ];
498
- case 1:
499
- response = _state.sent();
500
- if (!response.ok) {
501
- throw new Error("Failed to fetch VAST: ".concat(response.statusText));
502
- }
503
- return [
504
- 4,
505
- response.text()
506
- ];
507
- case 2:
508
- vastXml = _state.sent();
509
- console.log("".concat(logPrefix, " VAST XML received"));
510
- console.log("".concat(logPrefix, " VAST XML content (first 2000 chars):"), vastXml.substring(0, 2e3));
511
- return [
512
- 2,
513
- parseVastXml(vastXml, filter, logPrefix)
514
- ];
515
- }
516
- });
517
- })();
518
- }
519
- function createEmptyTrackingState() {
520
- return {
521
- impression: false,
522
- start: false,
523
- firstQuartile: false,
524
- midpoint: false,
525
- thirdQuartile: false,
526
- complete: false
527
- };
528
- }
529
352
  function firePixelWithRetry(url) {
530
353
  var retries = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 2, delayMs = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 500, logPrefix = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : "[VastParser]";
531
354
  return _async_to_generator(function() {
@@ -648,16 +471,164 @@ function fireTrackingPixels(urls, sessionId) {
648
471
  }
649
472
  });
650
473
  }
651
- // src/sdk/vastManager.ts
652
- var VAST_TAG_URL = "https://pubads.g.doubleclick.net/gampad/ads?iu=/21821455290/Airy-Android&description_url=http%3A%2F%2Fairy.tv&tfcd=0&npa=0&sz=1x1%7C300x250%7C400x300%7C640x480&gdfp_req=1&unviewed_position_start=1&correlator=[placeholder]&vpos=preroll&output=vast&env=vp&vpmute=0&vpa=click";
653
- var DEFAULT_TIMEOUT_MS = 5e3;
654
- var MAX_RETRIES = 3;
655
- var RETRY_BACKOFF_MS = 1500;
656
- function createVastManager() {
657
- var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
658
- var _options_debug;
659
- var initialized = false;
660
- var debug = (_options_debug = options.debug) !== null && _options_debug !== void 0 ? _options_debug : false;
474
+ // src/sdk/adstormPlayer.ts
475
+ var SUPPORTED_VIDEO_EXTENSIONS = [
476
+ ".mp4",
477
+ ".webm",
478
+ ".ogg",
479
+ ".m3u8",
480
+ ".ts"
481
+ ];
482
+ var UNSUPPORTED_VIDEO_EXTENSIONS = [
483
+ ".flv",
484
+ ".f4v",
485
+ ".swf",
486
+ ".wmv",
487
+ ".avi",
488
+ ".mov",
489
+ ".mkv"
490
+ ];
491
+ var REQUEST_TIMEOUT_MS = 5e3;
492
+ var REQUEST_MAX_RETRIES = 3;
493
+ var REQUEST_RETRY_BACKOFF_MS = 1500;
494
+ var AD_LAYER_Z_INDEX = "2147483646";
495
+ var COUNTDOWN_Z_INDEX = "2147483647";
496
+ var STALL_TIMEOUT_MS = 8e3;
497
+ function getFileExtension(url) {
498
+ try {
499
+ var pathname = new URL(url, "http://dummy").pathname;
500
+ var lastDot = pathname.lastIndexOf(".");
501
+ if (lastDot === -1) return "";
502
+ return pathname.slice(lastDot).toLowerCase();
503
+ } catch (unused) {
504
+ var lastDot1 = url.lastIndexOf(".");
505
+ if (lastDot1 === -1) return "";
506
+ var ext = url.slice(lastDot1).split(/[?#]/)[0];
507
+ return (ext || "").toLowerCase();
508
+ }
509
+ }
510
+ function isUnsupportedFormat(url) {
511
+ var ext = getFileExtension(url);
512
+ return UNSUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1;
513
+ }
514
+ function replaceFlvExtension(url) {
515
+ var ext = getFileExtension(url);
516
+ if (ext === ".flv") {
517
+ return url.replace(/\.flv(\?|$)/i, ".mp4$1");
518
+ }
519
+ return url;
520
+ }
521
+ function isSupportedFormat(url, mimeType) {
522
+ if (isUnsupportedFormat(url)) {
523
+ return false;
524
+ }
525
+ var ext = getFileExtension(url);
526
+ if (SUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1) {
527
+ return true;
528
+ }
529
+ if (ext === "" || ext === ".") {
530
+ return mimeType.includes("video/mp4") || mimeType.includes("video/webm") || mimeType.includes("m3u8") || mimeType.includes("application/x-mpegurl");
531
+ }
532
+ return false;
533
+ }
534
+ function createAdStormPlayer(contentVideo, options) {
535
+ var licenseKey = options.licenseKey, _options_debug = options.debug, debug = _options_debug === void 0 ? false : _options_debug;
536
+ var adPlaying = false;
537
+ var originalMutedState = false;
538
+ var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
539
+ var listeners = /* @__PURE__ */ new Map();
540
+ var adVideoElement;
541
+ var adContainerEl;
542
+ var adCountdownEl;
543
+ var currentAd;
544
+ var destroyed = false;
545
+ var tornDown = false;
546
+ var continueLiveStreamDuringAds = false;
547
+ var sessionId;
548
+ var adStallTimerId;
549
+ var adCountdownTimerId;
550
+ var adHideTimerId;
551
+ var lastCountdownSecond = -1;
552
+ var adListenersBound = false;
553
+ var parentPositionOverridden = false;
554
+ var adHandlers = {
555
+ timeupdate: function timeupdate() {
556
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
557
+ var progress = adVideoElement.currentTime / currentAd.duration;
558
+ if (progress >= 0.25 && !trackingFired.firstQuartile) {
559
+ trackingFired.firstQuartile = true;
560
+ fireTrackingPixels2(currentAd.trackingUrls.firstQuartile);
561
+ }
562
+ if (progress >= 0.5 && !trackingFired.midpoint) {
563
+ trackingFired.midpoint = true;
564
+ fireTrackingPixels2(currentAd.trackingUrls.midpoint);
565
+ }
566
+ if (progress >= 0.75 && !trackingFired.thirdQuartile) {
567
+ trackingFired.thirdQuartile = true;
568
+ fireTrackingPixels2(currentAd.trackingUrls.thirdQuartile);
569
+ }
570
+ updateAdCountdown();
571
+ },
572
+ playing: function playing() {
573
+ clearAdStallTimer();
574
+ if (!currentAd || trackingFired.start || destroyed || tornDown) return;
575
+ trackingFired.start = true;
576
+ fireTrackingPixels2(currentAd.trackingUrls.start);
577
+ startAdCountdown();
578
+ log("Ad started playing");
579
+ },
580
+ ended: function ended() {
581
+ if (!currentAd || trackingFired.complete || destroyed || tornDown) return;
582
+ trackingFired.complete = true;
583
+ fireTrackingPixels2(currentAd.trackingUrls.complete);
584
+ log("Ad completed");
585
+ handleAdComplete();
586
+ },
587
+ error: function error(e) {
588
+ if (destroyed || tornDown) return;
589
+ console.error("[AdStormPlayer] Ad video error:", e);
590
+ if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);
591
+ handleAdError();
592
+ },
593
+ waiting: function waiting() {
594
+ clearAdStallTimer();
595
+ adStallTimerId = setTimeout(function() {
596
+ adStallTimerId = void 0;
597
+ if (!adPlaying || destroyed || tornDown) return;
598
+ console.warn("[AdStormPlayer] Ad playback stalled too long");
599
+ handleAdError();
600
+ }, STALL_TIMEOUT_MS);
601
+ },
602
+ volumechange: function volumechange() {
603
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
604
+ if (adVideoElement.muted || adVideoElement.volume <= 0) {
605
+ fireTrackingPixels2(currentAd.trackingUrls.mute);
606
+ } else {
607
+ fireTrackingPixels2(currentAd.trackingUrls.unmute);
608
+ }
609
+ },
610
+ pause: function pause() {
611
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
612
+ if (!adVideoElement.ended) {
613
+ fireTrackingPixels2(currentAd.trackingUrls.pause);
614
+ }
615
+ },
616
+ play: function play() {
617
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
618
+ if (adVideoElement.currentTime > 0) {
619
+ fireTrackingPixels2(currentAd.trackingUrls.resume);
620
+ }
621
+ }
622
+ };
623
+ var trackingFired = {
624
+ impression: false,
625
+ start: false,
626
+ firstQuartile: false,
627
+ midpoint: false,
628
+ thirdQuartile: false,
629
+ complete: false
630
+ };
631
+ var preloadSlots = /* @__PURE__ */ new Map();
661
632
  function log() {
662
633
  for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
663
634
  args[_key] = arguments[_key];
@@ -665,58 +636,340 @@ function createVastManager() {
665
636
  if (debug) {
666
637
  var _console;
667
638
  (_console = console).log.apply(_console, [
668
- "[VastManager]"
639
+ "[AdStormPlayer]"
669
640
  ].concat(_to_consumable_array(args)));
670
641
  }
671
642
  }
672
- function warn() {
673
- for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
674
- args[_key] = arguments[_key];
643
+ function emit(event, payload) {
644
+ var set = listeners.get(event);
645
+ if (!set) return;
646
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
647
+ try {
648
+ for(var _iterator = Array.from(set)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
649
+ var fn = _step.value;
650
+ try {
651
+ fn(payload);
652
+ } catch (error) {
653
+ console.warn("[AdStormPlayer] Error in event listener for ".concat(event, ":"), error);
654
+ }
655
+ }
656
+ } catch (err) {
657
+ _didIteratorError = true;
658
+ _iteratorError = err;
659
+ } finally{
660
+ try {
661
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
662
+ _iterator.return();
663
+ }
664
+ } finally{
665
+ if (_didIteratorError) {
666
+ throw _iteratorError;
667
+ }
668
+ }
675
669
  }
676
- var _console;
677
- (_console = console).warn.apply(_console, [
678
- "[VastManager]"
679
- ].concat(_to_consumable_array(args)));
680
670
  }
681
- function initialize() {
682
- return _async_to_generator(function() {
683
- return _ts_generator(this, function(_state) {
684
- if (initialized) return [
685
- 2
686
- ];
687
- initialized = true;
688
- log("Initialized, VAST tag URL:", VAST_TAG_URL.split("?")[0]);
689
- return [
690
- 2
691
- ];
671
+ function fireTrackingPixels2(urls) {
672
+ fireTrackingPixels(urls, sessionId, "[AdStormPlayer]");
673
+ }
674
+ function clearAdStallTimer() {
675
+ if (adStallTimerId) {
676
+ clearTimeout(adStallTimerId);
677
+ adStallTimerId = void 0;
678
+ }
679
+ }
680
+ function clearAdCountdownTimer() {
681
+ if (adCountdownTimerId) {
682
+ clearInterval(adCountdownTimerId);
683
+ adCountdownTimerId = void 0;
684
+ }
685
+ lastCountdownSecond = -1;
686
+ }
687
+ function updateAdCountdown() {
688
+ if (!adCountdownEl || !adVideoElement || !currentAd || !adPlaying) return;
689
+ var remainingSec = Math.max(0, Math.ceil((currentAd.duration || 0) - adVideoElement.currentTime));
690
+ if (remainingSec === lastCountdownSecond) return;
691
+ lastCountdownSecond = remainingSec;
692
+ adCountdownEl.textContent = "Ad ".concat(remainingSec, "s");
693
+ emit("ad_countdown", {
694
+ remainingSec: remainingSec,
695
+ durationSec: currentAd.duration,
696
+ currentTimeSec: adVideoElement.currentTime
697
+ });
698
+ }
699
+ function startAdCountdown() {
700
+ clearAdCountdownTimer();
701
+ updateAdCountdown();
702
+ adCountdownTimerId = setInterval(updateAdCountdown, 250);
703
+ }
704
+ function generateSessionId() {
705
+ return "adstorm-".concat(Date.now(), "-").concat(Math.random().toString(36).slice(2, 10));
706
+ }
707
+ function bindAdEventListeners() {
708
+ if (!adVideoElement || adListenersBound) return;
709
+ adVideoElement.addEventListener("timeupdate", adHandlers.timeupdate);
710
+ adVideoElement.addEventListener("playing", adHandlers.playing);
711
+ adVideoElement.addEventListener("ended", adHandlers.ended);
712
+ adVideoElement.addEventListener("error", adHandlers.error);
713
+ adVideoElement.addEventListener("waiting", adHandlers.waiting);
714
+ adVideoElement.addEventListener("volumechange", adHandlers.volumechange);
715
+ adVideoElement.addEventListener("pause", adHandlers.pause);
716
+ adVideoElement.addEventListener("play", adHandlers.play);
717
+ adListenersBound = true;
718
+ }
719
+ function unbindAdEventListeners() {
720
+ if (!adVideoElement || !adListenersBound) return;
721
+ adVideoElement.removeEventListener("timeupdate", adHandlers.timeupdate);
722
+ adVideoElement.removeEventListener("playing", adHandlers.playing);
723
+ adVideoElement.removeEventListener("ended", adHandlers.ended);
724
+ adVideoElement.removeEventListener("error", adHandlers.error);
725
+ adVideoElement.removeEventListener("waiting", adHandlers.waiting);
726
+ adVideoElement.removeEventListener("volumechange", adHandlers.volumechange);
727
+ adVideoElement.removeEventListener("pause", adHandlers.pause);
728
+ adVideoElement.removeEventListener("play", adHandlers.play);
729
+ adListenersBound = false;
730
+ }
731
+ function teardownCurrentPlayback() {
732
+ unbindAdEventListeners();
733
+ clearAdStallTimer();
734
+ clearAdCountdownTimer();
735
+ if (!adVideoElement) return;
736
+ adVideoElement.pause();
737
+ adVideoElement.removeAttribute("src");
738
+ adVideoElement.load();
739
+ }
740
+ function buildVastUrl(durationSeconds, metadata) {
741
+ var baseUrl = "https://adstorm.co/api-adstorm-dev/adstorm/vast/".concat(licenseKey, "/pod");
742
+ var defaultMetadata = {
743
+ video: {
744
+ codec: "h264",
745
+ width: contentVideo.videoWidth || 1280,
746
+ height: contentVideo.videoHeight || 720,
747
+ fps: 29.97,
748
+ bitrate: 5e3,
749
+ profile: "high",
750
+ pix_fmt: "yuv420p",
751
+ has_b_frames: 0
752
+ },
753
+ audio: {
754
+ codec: "aac",
755
+ sample_rate: 48e3,
756
+ bitrate: 128
757
+ }
758
+ };
759
+ var finalMetadata = metadata || defaultMetadata;
760
+ var metadataStr = encodeURIComponent(JSON.stringify(finalMetadata));
761
+ return "".concat(baseUrl, "?duration=").concat(Math.ceil(durationSeconds), "&metadata=").concat(metadataStr);
762
+ }
763
+ function parseVastXml(xmlString) {
764
+ var ads = [];
765
+ try {
766
+ var parser = new DOMParser();
767
+ var xmlDoc = parser.parseFromString(xmlString, "text/xml");
768
+ var parserError = xmlDoc.querySelector("parsererror");
769
+ if (parserError) {
770
+ console.error("[AdStormPlayer] XML parsing error:", parserError.textContent);
771
+ return [];
772
+ }
773
+ var adElements = xmlDoc.querySelectorAll("Ad");
774
+ adElements.forEach(function(adElement) {
775
+ var _adElement_querySelector, _adElement_querySelector1, _adElement_querySelector_textContent, _adElement_querySelector2;
776
+ var adId = adElement.getAttribute("id") || "unknown";
777
+ var title = ((_adElement_querySelector = adElement.querySelector("AdTitle")) === null || _adElement_querySelector === void 0 ? void 0 : _adElement_querySelector.textContent) || "Ad";
778
+ var durationText = ((_adElement_querySelector1 = adElement.querySelector("Duration")) === null || _adElement_querySelector1 === void 0 ? void 0 : _adElement_querySelector1.textContent) || "00:00:30";
779
+ var durationParts = durationText.split(":");
780
+ var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseFloat(durationParts[2] || "0");
781
+ var mediaFileElements = adElement.querySelectorAll("MediaFile");
782
+ var mediaFiles = [];
783
+ mediaFileElements.forEach(function(mf) {
784
+ var _mf_textContent;
785
+ var type = mf.getAttribute("type") || "";
786
+ var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
787
+ var width = parseInt(mf.getAttribute("width") || "1920", 10);
788
+ var height = parseInt(mf.getAttribute("height") || "1080", 10);
789
+ var bitrate = mf.getAttribute("bitrate") ? parseInt(mf.getAttribute("bitrate"), 10) : void 0;
790
+ if (!url) {
791
+ log("Skipping empty MediaFile URL");
792
+ return;
793
+ }
794
+ var originalUrl = url;
795
+ url = replaceFlvExtension(url);
796
+ if (url !== originalUrl) {
797
+ log("Converted FLV to MP4: ".concat(originalUrl, " -> ").concat(url));
798
+ }
799
+ if (isUnsupportedFormat(url)) {
800
+ var ext = getFileExtension(url);
801
+ log("Skipping unsupported format: ".concat(url, " (extension: ").concat(ext, ", declared type: ").concat(type, ")"));
802
+ return;
803
+ }
804
+ if (isSupportedFormat(url, type)) {
805
+ mediaFiles.push({
806
+ url: url,
807
+ type: type,
808
+ width: width,
809
+ height: height,
810
+ bitrate: bitrate
811
+ });
812
+ log("Found media file: ".concat(url, " (").concat(type, ", ").concat(width, "x").concat(height, ")"));
813
+ } else {
814
+ log("Skipping incompatible media file: ".concat(url, " (type: ").concat(type, ")"));
815
+ }
816
+ });
817
+ if (mediaFiles.length === 0) {
818
+ log("No valid media files found in ad:", adId);
819
+ return;
820
+ }
821
+ var trackingUrls = {
822
+ impression: [],
823
+ start: [],
824
+ firstQuartile: [],
825
+ midpoint: [],
826
+ thirdQuartile: [],
827
+ complete: [],
828
+ mute: [],
829
+ unmute: [],
830
+ pause: [],
831
+ resume: [],
832
+ error: []
833
+ };
834
+ adElement.querySelectorAll("Impression").forEach(function(el) {
835
+ var _el_textContent;
836
+ var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
837
+ if (url) trackingUrls.impression.push(url);
838
+ });
839
+ adElement.querySelectorAll("Tracking").forEach(function(el) {
840
+ var _el_textContent;
841
+ var event = el.getAttribute("event");
842
+ var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
843
+ if (event && url) {
844
+ var eventKey = event;
845
+ if (trackingUrls[eventKey]) {
846
+ trackingUrls[eventKey].push(url);
847
+ }
848
+ }
849
+ });
850
+ var clickThrough = (_adElement_querySelector2 = adElement.querySelector("ClickThrough")) === null || _adElement_querySelector2 === void 0 ? void 0 : (_adElement_querySelector_textContent = _adElement_querySelector2.textContent) === null || _adElement_querySelector_textContent === void 0 ? void 0 : _adElement_querySelector_textContent.trim();
851
+ ads.push({
852
+ id: adId,
853
+ title: title,
854
+ duration: duration,
855
+ mediaFiles: mediaFiles,
856
+ trackingUrls: trackingUrls,
857
+ clickThrough: clickThrough
858
+ });
859
+ log("Parsed ad: ".concat(title, ", duration: ").concat(duration, "s, media files: ").concat(mediaFiles.length));
692
860
  });
693
- })();
861
+ } catch (error) {
862
+ console.error("[AdStormPlayer] Error parsing VAST XML:", error);
863
+ }
864
+ return ads;
865
+ }
866
+ function selectBestMediaFile(mediaFiles) {
867
+ if (mediaFiles.length === 0) return null;
868
+ if (mediaFiles.length === 1) return mediaFiles[0];
869
+ var mp4Files = mediaFiles.filter(function(mf) {
870
+ return mf.type.includes("video/mp4");
871
+ });
872
+ var candidates = mp4Files.length > 0 ? mp4Files : mediaFiles;
873
+ var targetWidth = contentVideo.videoWidth || 1280;
874
+ var targetHeight = contentVideo.videoHeight || 720;
875
+ candidates.sort(function(a, b) {
876
+ var diffA = Math.abs(a.width - targetWidth) + Math.abs(a.height - targetHeight);
877
+ var diffB = Math.abs(b.width - targetWidth) + Math.abs(b.height - targetHeight);
878
+ return diffA - diffB;
879
+ });
880
+ return candidates[0] || null;
881
+ }
882
+ function createAdVideoElement() {
883
+ var video = document.createElement("video");
884
+ video.style.position = "absolute";
885
+ video.style.left = "0";
886
+ video.style.top = "0";
887
+ video.style.width = "100%";
888
+ video.style.height = "100%";
889
+ video.style.objectFit = "contain";
890
+ video.style.backgroundColor = "#000";
891
+ video.style.zIndex = "1";
892
+ video.playsInline = true;
893
+ video.preload = "auto";
894
+ video.muted = originalMutedState;
895
+ video.volume = originalMutedState ? 0 : originalVolume;
896
+ return video;
897
+ }
898
+ function setAdPlayingFlag(isPlaying) {
899
+ if (isPlaying) {
900
+ contentVideo.dataset.stormcloudAdPlaying = "true";
901
+ } else {
902
+ delete contentVideo.dataset.stormcloudAdPlaying;
903
+ }
904
+ }
905
+ function setupAdEventListeners() {
906
+ bindAdEventListeners();
907
+ }
908
+ function handleAdComplete() {
909
+ if (destroyed || tornDown) return;
910
+ log("Handling ad completion");
911
+ adPlaying = false;
912
+ setAdPlayingFlag(false);
913
+ clearAdStallTimer();
914
+ clearAdCountdownTimer();
915
+ if (adContainerEl) {
916
+ adContainerEl.style.opacity = "0";
917
+ adHideTimerId = setTimeout(function() {
918
+ if (adContainerEl) {
919
+ adContainerEl.style.display = "none";
920
+ adContainerEl.style.pointerEvents = "none";
921
+ }
922
+ }, 300);
923
+ }
924
+ contentVideo.style.visibility = "visible";
925
+ contentVideo.style.opacity = "1";
926
+ contentVideo.muted = originalMutedState;
927
+ contentVideo.volume = originalVolume;
928
+ currentAd = void 0;
929
+ emit("content_resume");
930
+ emit("all_ads_completed");
931
+ }
932
+ function handleAdError() {
933
+ if (destroyed || tornDown) return;
934
+ log("Handling ad error");
935
+ if (!adPlaying) return;
936
+ adPlaying = false;
937
+ setAdPlayingFlag(false);
938
+ clearAdStallTimer();
939
+ clearAdCountdownTimer();
940
+ contentVideo.muted = originalMutedState;
941
+ contentVideo.volume = originalVolume;
942
+ contentVideo.style.visibility = "visible";
943
+ contentVideo.style.opacity = "1";
944
+ if (adContainerEl) {
945
+ adContainerEl.style.display = "none";
946
+ adContainerEl.style.pointerEvents = "none";
947
+ }
948
+ currentAd = void 0;
949
+ emit("ad_error");
950
+ emit("content_resume");
694
951
  }
695
- function requestBids(_context) {
952
+ function fetchVastOnce(durationSeconds) {
696
953
  return _async_to_generator(function() {
697
- var correlator, url, controller, timeoutId, _ref, _ref1, _vastAd_mediaFiles_, _vastAd_mediaFiles_1, fetchOptions, response, vastXml, vastAd, bid, error;
954
+ var vastUrl, controller, timeoutId, requestInit, response, xmlText;
698
955
  return _ts_generator(this, function(_state) {
699
956
  switch(_state.label){
700
957
  case 0:
701
- if (!initialized) {
702
- throw new Error("VastManager not initialized. Call initialize() first.");
703
- }
704
- correlator = Math.floor(Math.random() * 1e12).toString();
705
- url = VAST_TAG_URL.replace("[placeholder]", correlator);
706
- log("Fetching VAST tag, correlator:", correlator);
958
+ vastUrl = buildVastUrl(durationSeconds);
959
+ log("Fetching VAST from:", vastUrl);
707
960
  controller = typeof AbortController !== "undefined" ? new AbortController() : null;
708
961
  timeoutId = setTimeout(function() {
709
962
  return controller === null || controller === void 0 ? void 0 : controller.abort();
710
- }, DEFAULT_TIMEOUT_MS);
963
+ }, REQUEST_TIMEOUT_MS);
711
964
  _state.label = 1;
712
965
  case 1:
713
966
  _state.trys.push([
714
967
  1,
715
- 4,
716
968
  ,
969
+ 4,
717
970
  5
718
971
  ]);
719
- fetchOptions = {
972
+ requestInit = {
720
973
  method: "GET",
721
974
  mode: "cors",
722
975
  credentials: "omit",
@@ -725,62 +978,34 @@ function createVastManager() {
725
978
  },
726
979
  referrerPolicy: "no-referrer-when-downgrade"
727
980
  };
728
- if (controller) fetchOptions.signal = controller.signal;
981
+ if (controller) {
982
+ requestInit.signal = controller.signal;
983
+ }
729
984
  return [
730
985
  4,
731
- fetch(url, fetchOptions)
986
+ fetch(vastUrl, requestInit)
732
987
  ];
733
988
  case 2:
734
989
  response = _state.sent();
735
- clearTimeout(timeoutId);
736
990
  if (!response.ok) {
737
- throw new Error("VAST request returned HTTP ".concat(response.status));
991
+ throw new Error("Failed to fetch VAST: ".concat(response.status, " ").concat(response.statusText));
738
992
  }
739
993
  return [
740
994
  4,
741
995
  response.text()
742
996
  ];
743
997
  case 3:
744
- vastXml = _state.sent();
745
- log("VAST XML received, length:", vastXml.length);
746
- vastAd = parseVastXml(vastXml, "mp4-first", "[VastManager]");
747
- if (!vastAd) {
748
- log("VAST parsed but no usable ad found");
749
- return [
750
- 2,
751
- []
752
- ];
753
- }
754
- log("Ad parsed: id=".concat(vastAd.id, ", duration=").concat(vastAd.duration, "s, mediaFiles=").concat(vastAd.mediaFiles.length));
755
- bid = {
756
- bidder: "vast-direct",
757
- cpm: 0,
758
- vastXml: vastXml,
759
- width: (_ref = (_vastAd_mediaFiles_ = vastAd.mediaFiles[0]) === null || _vastAd_mediaFiles_ === void 0 ? void 0 : _vastAd_mediaFiles_.width) !== null && _ref !== void 0 ? _ref : 0,
760
- height: (_ref1 = (_vastAd_mediaFiles_1 = vastAd.mediaFiles[0]) === null || _vastAd_mediaFiles_1 === void 0 ? void 0 : _vastAd_mediaFiles_1.height) !== null && _ref1 !== void 0 ? _ref1 : 0,
761
- adId: vastAd.id,
762
- impId: correlator,
763
- creativeId: vastAd.id,
764
- currency: "USD",
765
- durationSec: vastAd.duration
766
- };
998
+ xmlText = _state.sent();
999
+ log("VAST response received, length:", xmlText.length);
767
1000
  return [
768
1001
  2,
769
- [
770
- bid
771
- ]
1002
+ parseVastXml(xmlText)
772
1003
  ];
773
1004
  case 4:
774
- error = _state.sent();
775
1005
  clearTimeout(timeoutId);
776
- if ((error === null || error === void 0 ? void 0 : error.name) === "AbortError") {
777
- warn("VAST request timed out after ".concat(DEFAULT_TIMEOUT_MS, "ms"));
778
- return [
779
- 2,
780
- []
781
- ];
782
- }
783
- throw error;
1006
+ return [
1007
+ 7
1008
+ ];
784
1009
  case 5:
785
1010
  return [
786
1011
  2
@@ -789,14 +1014,14 @@ function createVastManager() {
789
1014
  });
790
1015
  })();
791
1016
  }
792
- function requestBidsUntilResponse(context) {
1017
+ function fetchVast(durationSeconds) {
793
1018
  return _async_to_generator(function() {
794
1019
  var _loop, lastError, attempt, _ret;
795
1020
  return _ts_generator(this, function(_state) {
796
1021
  switch(_state.label){
797
1022
  case 0:
798
1023
  _loop = function(attempt) {
799
- var bids, err, delay;
1024
+ var ads, error, delay;
800
1025
  return _ts_generator(this, function(_state) {
801
1026
  switch(_state.label){
802
1027
  case 0:
@@ -808,39 +1033,39 @@ function createVastManager() {
808
1033
  ]);
809
1034
  return [
810
1035
  4,
811
- requestBids(context)
1036
+ fetchVastOnce(durationSeconds)
812
1037
  ];
813
1038
  case 1:
814
- bids = _state.sent();
815
- if (bids.length > 0) {
816
- log("requestBidsUntilResponse: got ".concat(bids.length, " ad(s) on attempt ").concat(attempt));
817
- return [
818
- 2,
819
- {
820
- v: bids
821
- }
822
- ];
823
- }
824
- log("requestBidsUntilResponse: no ads on attempt ".concat(attempt, "/").concat(MAX_RETRIES));
1039
+ ads = _state.sent();
1040
+ if (ads.length > 0) return [
1041
+ 2,
1042
+ {
1043
+ v: ads
1044
+ }
1045
+ ];
1046
+ log("No ad returned from VAST on attempt ".concat(attempt, "/").concat(REQUEST_MAX_RETRIES));
825
1047
  return [
826
1048
  3,
827
1049
  3
828
1050
  ];
829
1051
  case 2:
830
- err = _state.sent();
831
- lastError = err;
832
- warn("requestBidsUntilResponse: attempt ".concat(attempt, "/").concat(MAX_RETRIES, " failed:"), err);
1052
+ error = _state.sent();
1053
+ lastError = error;
1054
+ if ((error === null || error === void 0 ? void 0 : error.name) === "AbortError") {
1055
+ console.warn("[AdStormPlayer] VAST request timed out (".concat(REQUEST_TIMEOUT_MS, "ms), attempt ").concat(attempt, "/").concat(REQUEST_MAX_RETRIES));
1056
+ } else {
1057
+ console.warn("[AdStormPlayer] VAST request failed on attempt ".concat(attempt, "/").concat(REQUEST_MAX_RETRIES, ":"), error);
1058
+ }
833
1059
  return [
834
1060
  3,
835
1061
  3
836
1062
  ];
837
1063
  case 3:
838
- if (!(attempt < MAX_RETRIES)) return [
1064
+ if (!(attempt < REQUEST_MAX_RETRIES)) return [
839
1065
  3,
840
1066
  5
841
1067
  ];
842
- delay = RETRY_BACKOFF_MS * attempt;
843
- log("requestBidsUntilResponse: waiting ".concat(delay, "ms before retry"));
1068
+ delay = REQUEST_RETRY_BACKOFF_MS * attempt;
844
1069
  return [
845
1070
  4,
846
1071
  new Promise(function(resolve) {
@@ -857,13 +1082,10 @@ function createVastManager() {
857
1082
  }
858
1083
  });
859
1084
  };
860
- if (!initialized) {
861
- throw new Error("VastManager not initialized. Call initialize() first.");
862
- }
863
1085
  attempt = 1;
864
1086
  _state.label = 1;
865
1087
  case 1:
866
- if (!(attempt <= MAX_RETRIES)) return [
1088
+ if (!(attempt <= REQUEST_MAX_RETRIES)) return [
867
1089
  3,
868
1090
  4
869
1091
  ];
@@ -885,7 +1107,9 @@ function createVastManager() {
885
1107
  1
886
1108
  ];
887
1109
  case 4:
888
- if (_instanceof(lastError, Error)) throw lastError;
1110
+ if (_instanceof(lastError, Error)) {
1111
+ throw lastError;
1112
+ }
889
1113
  return [
890
1114
  2,
891
1115
  []
@@ -894,971 +1118,468 @@ function createVastManager() {
894
1118
  });
895
1119
  })();
896
1120
  }
897
- function destroy() {
898
- initialized = false;
899
- log("Destroyed");
900
- }
901
- return {
902
- initialize: initialize,
903
- requestBids: requestBids,
904
- requestBidsUntilResponse: requestBidsUntilResponse,
905
- destroy: destroy,
906
- get isInitialized () {
907
- return initialized;
1121
+ function getDurationSecondsFromContext(requestContext) {
1122
+ var _ctx_remainingBreakSec;
1123
+ if (!requestContext || (typeof requestContext === "undefined" ? "undefined" : _type_of(requestContext)) !== "object") {
1124
+ return 30;
908
1125
  }
909
- };
910
- }
911
- // src/sdk/vastAdLayer.ts
912
- var import_hls = __toESM(require("hls.js"), 1);
913
- var LOG = "[VastAdLayer]";
914
- function resolveBidToVastAd(winner, logPrefix) {
915
- if (winner.vastXml) {
916
- var ad = parseVastXml(winner.vastXml, "mp4-first", logPrefix);
917
- return Promise.resolve(ad);
918
- }
919
- if (winner.vastUrl) {
920
- return fetchAndParseVastAd(winner.vastUrl, "mp4-first", logPrefix);
921
- }
922
- return Promise.resolve(null);
923
- }
924
- function createVastAdLayer(contentVideo, options) {
925
- var _ref, _ref1, _ref2, _ref3, _ref4;
926
- var adPlaying = false;
927
- var originalMutedState = false;
928
- var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
929
- var listeners = /* @__PURE__ */ new Map();
930
- var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
931
- var continueLiveStreamDuringAds = (_ref = options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) !== null && _ref !== void 0 ? _ref : false;
932
- var smartTVMode = (_ref1 = options === null || options === void 0 ? void 0 : options.smartTVMode) !== null && _ref1 !== void 0 ? _ref1 : false;
933
- var singleElementMode = (_ref2 = options === null || options === void 0 ? void 0 : options.singleElementMode) !== null && _ref2 !== void 0 ? _ref2 : false;
934
- var forceMP4Ads = (_ref3 = options === null || options === void 0 ? void 0 : options.forceMP4Ads) !== null && _ref3 !== void 0 ? _ref3 : smartTVMode || singleElementMode;
935
- var debug = (_ref4 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref4 !== void 0 ? _ref4 : false;
936
- var adVideoElement;
937
- var adHls;
938
- var adContainerEl;
939
- var currentAd;
940
- var sessionId;
941
- var destroyed = false;
942
- var tornDown = false;
943
- var trackingFired = createEmptyTrackingState();
944
- var adStallTimerId;
945
- var savedContentVideoStyles;
946
- var currentAdEventHandlers;
947
- var preloadSlots = /* @__PURE__ */ new Map();
948
- function emit(event, payload) {
949
- var set = listeners.get(event);
950
- if (!set) return;
951
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
952
- try {
953
- for(var _iterator = Array.from(set)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
954
- var fn = _step.value;
955
- try {
956
- fn(payload);
957
- } catch (error) {
958
- console.warn("".concat(LOG, " Error in event listener for ").concat(event, ":"), error);
959
- }
960
- }
961
- } catch (err) {
962
- _didIteratorError = true;
963
- _iteratorError = err;
964
- } finally{
965
- try {
966
- if (!_iteratorNormalCompletion && _iterator.return != null) {
967
- _iterator.return();
968
- }
969
- } finally{
970
- if (_didIteratorError) {
971
- throw _iteratorError;
972
- }
973
- }
974
- }
975
- }
976
- function generateSessionId() {
977
- return "session-".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
978
- }
979
- function fireTrackingPixels2(urls) {
980
- fireTrackingPixels(urls, sessionId, LOG);
981
- }
982
- function getMainStreamQuality() {
983
- if (!(mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.levels)) return null;
984
- var currentLevel = mainHlsInstance.currentLevel;
985
- if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {
986
- var autoLevel = mainHlsInstance.loadLevel;
987
- if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {
988
- var level2 = mainHlsInstance.levels[autoLevel];
989
- return {
990
- width: level2.width || 1920,
991
- height: level2.height || 1080,
992
- bitrate: level2.bitrate || 5e6
993
- };
994
- }
995
- return null;
996
- }
997
- var level = mainHlsInstance.levels[currentLevel];
998
- return {
999
- width: level.width || 1920,
1000
- height: level.height || 1080,
1001
- bitrate: level.bitrate || 5e6
1002
- };
1003
- }
1004
- function selectBestMediaFile(mediaFiles) {
1005
- var _ref;
1006
- var _scoredFiles_;
1007
- if (mediaFiles.length === 0) throw new Error("No media files available");
1008
- var candidates = mediaFiles;
1009
- if (forceMP4Ads) {
1010
- var mp4Only = candidates.filter(function(f) {
1011
- return !isHlsMediaFile(f);
1012
- });
1013
- if (mp4Only.length > 0) {
1014
- candidates = mp4Only;
1015
- if (debug) console.log("".concat(LOG, " forceMP4Ads: filtered to ").concat(mp4Only.length, " MP4-only file(s)"));
1016
- } else if (debug) {
1017
- console.warn("".concat(LOG, " forceMP4Ads: no MP4 files available, falling back to all media files"));
1018
- }
1019
- } else {
1020
- var mp4Only1 = candidates.filter(function(f) {
1021
- return !isHlsMediaFile(f);
1022
- });
1023
- if (mp4Only1.length > 0) {
1024
- candidates = mp4Only1;
1025
- if (debug) console.log("".concat(LOG, " Preferring ").concat(mp4Only1.length, " MP4 file(s) over HLS (mp4-first)"));
1026
- }
1027
- }
1028
- var firstFile = candidates[0];
1029
- if (candidates.length === 1) return firstFile;
1030
- var mainQuality = getMainStreamQuality();
1031
- if (!mainQuality) {
1032
- if (debug) console.log("".concat(LOG, " No main stream quality info, using first media file"));
1033
- return firstFile;
1034
- }
1035
- var scoredFiles = candidates.map(function(file) {
1036
- var widthDiff = Math.abs(file.width - mainQuality.width);
1037
- var heightDiff = Math.abs(file.height - mainQuality.height);
1038
- var resolutionDiff = widthDiff + heightDiff;
1039
- var fileBitrate = (file.bitrate || 5e3) * 1e3;
1040
- var bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);
1041
- var score = resolutionDiff * 2 + bitrateDiff / 1e3;
1042
- return {
1043
- file: file,
1044
- score: score
1045
- };
1046
- });
1047
- scoredFiles.sort(function(a, b) {
1048
- return a.score - b.score;
1049
- });
1050
- return (_ref = (_scoredFiles_ = scoredFiles[0]) === null || _scoredFiles_ === void 0 ? void 0 : _scoredFiles_.file) !== null && _ref !== void 0 ? _ref : firstFile;
1051
- }
1052
- function isHlsMediaFile(file) {
1053
- return file.type === "application/x-mpegURL" || file.type.includes("m3u8");
1054
- }
1055
- function createAdVideoElement() {
1056
- var video = document.createElement("video");
1057
- video.style.position = "absolute";
1058
- video.style.left = "0";
1059
- video.style.top = "0";
1060
- video.style.width = "100%";
1061
- video.style.height = "100%";
1062
- video.style.objectFit = "cover";
1063
- video.style.backgroundColor = "#000";
1064
- video.playsInline = true;
1065
- video.muted = false;
1066
- video.volume = 1;
1067
- return video;
1068
- }
1069
- function clearAdStallTimer() {
1070
- if (adStallTimerId != null) {
1071
- clearTimeout(adStallTimerId);
1072
- adStallTimerId = void 0;
1073
- }
1074
- }
1075
- function removeAdEventListeners() {
1076
- clearAdStallTimer();
1077
- if (!currentAdEventHandlers || !adVideoElement) return;
1078
- var el = adVideoElement;
1079
- el.removeEventListener("timeupdate", currentAdEventHandlers.timeupdate);
1080
- el.removeEventListener("playing", currentAdEventHandlers.playing);
1081
- el.removeEventListener("ended", currentAdEventHandlers.ended);
1082
- el.removeEventListener("error", currentAdEventHandlers.error);
1083
- el.removeEventListener("volumechange", currentAdEventHandlers.volumechange);
1084
- el.removeEventListener("pause", currentAdEventHandlers.pause);
1085
- el.removeEventListener("play", currentAdEventHandlers.play);
1086
- el.removeEventListener("waiting", currentAdEventHandlers.waiting);
1087
- currentAdEventHandlers = void 0;
1088
- }
1089
- function setupAdEventListeners() {
1090
- if (!adVideoElement) return;
1091
- removeAdEventListeners();
1092
- var handlers = {
1093
- timeupdate: function timeupdate() {
1094
- var ad = currentAd;
1095
- if (!ad || !adVideoElement) return;
1096
- var progress = adVideoElement.currentTime / ad.duration;
1097
- if (progress >= 0.25 && !trackingFired.firstQuartile) {
1098
- trackingFired.firstQuartile = true;
1099
- fireTrackingPixels2(ad.trackingUrls.firstQuartile);
1100
- }
1101
- if (progress >= 0.5 && !trackingFired.midpoint) {
1102
- trackingFired.midpoint = true;
1103
- fireTrackingPixels2(ad.trackingUrls.midpoint);
1104
- }
1105
- if (progress >= 0.75 && !trackingFired.thirdQuartile) {
1106
- trackingFired.thirdQuartile = true;
1107
- fireTrackingPixels2(ad.trackingUrls.thirdQuartile);
1108
- }
1109
- },
1110
- playing: function playing() {
1111
- clearAdStallTimer();
1112
- var ad = currentAd;
1113
- if (!ad || trackingFired.start) return;
1114
- trackingFired.start = true;
1115
- fireTrackingPixels2(ad.trackingUrls.start);
1116
- if (debug) console.log("".concat(LOG, " Ad started playing"));
1117
- },
1118
- ended: function ended() {
1119
- if (tornDown || !currentAd || trackingFired.complete) return;
1120
- trackingFired.complete = true;
1121
- fireTrackingPixels2(currentAd.trackingUrls.complete);
1122
- if (debug) console.log("".concat(LOG, " Ad completed"));
1123
- handleAdComplete();
1124
- },
1125
- error: function error(e) {
1126
- if (tornDown) return;
1127
- console.error("".concat(LOG, " Ad video error:"), e);
1128
- if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);
1129
- handleAdError();
1130
- },
1131
- volumechange: function volumechange() {
1132
- if (!currentAd || !adVideoElement) return;
1133
- if (adVideoElement.muted) {
1134
- fireTrackingPixels2(currentAd.trackingUrls.mute);
1135
- } else {
1136
- fireTrackingPixels2(currentAd.trackingUrls.unmute);
1137
- }
1138
- },
1139
- pause: function pause() {
1140
- if (currentAd && adVideoElement && !adVideoElement.ended) {
1141
- fireTrackingPixels2(currentAd.trackingUrls.pause);
1142
- }
1143
- },
1144
- play: function play() {
1145
- if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1146
- fireTrackingPixels2(currentAd.trackingUrls.resume);
1147
- }
1148
- },
1149
- waiting: function waiting() {
1150
- clearAdStallTimer();
1151
- adStallTimerId = setTimeout(function() {
1152
- adStallTimerId = void 0;
1153
- if (adPlaying) {
1154
- if (debug) console.warn("".concat(LOG, " Ad video stalled for too long, treating as error"));
1155
- handleAdError();
1156
- }
1157
- }, 8e3);
1158
- }
1159
- };
1160
- adVideoElement.addEventListener("timeupdate", handlers.timeupdate);
1161
- adVideoElement.addEventListener("playing", handlers.playing);
1162
- adVideoElement.addEventListener("ended", handlers.ended);
1163
- adVideoElement.addEventListener("error", handlers.error);
1164
- adVideoElement.addEventListener("volumechange", handlers.volumechange);
1165
- adVideoElement.addEventListener("pause", handlers.pause);
1166
- adVideoElement.addEventListener("play", handlers.play);
1167
- adVideoElement.addEventListener("waiting", handlers.waiting);
1168
- currentAdEventHandlers = handlers;
1169
- }
1170
- function setAdPlayingFlag(isPlaying) {
1171
- if (isPlaying) {
1172
- contentVideo.dataset.stormcloudAdPlaying = "true";
1173
- } else {
1174
- delete contentVideo.dataset.stormcloudAdPlaying;
1175
- }
1176
- }
1177
- function applyContentVideoAdCoverStyles() {
1178
- if (!singleElementMode) return;
1179
- savedContentVideoStyles = {
1180
- objectFit: contentVideo.style.objectFit,
1181
- width: contentVideo.style.width,
1182
- height: contentVideo.style.height
1183
- };
1184
- contentVideo.style.objectFit = "cover";
1185
- contentVideo.style.width = "100%";
1186
- contentVideo.style.height = "100%";
1187
- }
1188
- function restoreContentVideoStyles() {
1189
- if (!singleElementMode || !savedContentVideoStyles) return;
1190
- contentVideo.style.objectFit = savedContentVideoStyles.objectFit;
1191
- contentVideo.style.width = savedContentVideoStyles.width;
1192
- contentVideo.style.height = savedContentVideoStyles.height;
1193
- savedContentVideoStyles = void 0;
1194
- }
1195
- function handleAdComplete() {
1196
- if (tornDown) return;
1197
- clearAdStallTimer();
1198
- if (debug) console.log("".concat(LOG, " Handling ad completion"));
1199
- adPlaying = false;
1200
- setAdPlayingFlag(false);
1201
- restoreContentVideoStyles();
1202
- if (adContainerEl) {
1203
- adContainerEl.style.display = "none";
1204
- adContainerEl.style.pointerEvents = "none";
1126
+ var ctx = requestContext;
1127
+ var value = (_ctx_remainingBreakSec = ctx.remainingBreakSec) !== null && _ctx_remainingBreakSec !== void 0 ? _ctx_remainingBreakSec : ctx.breakDurationSec;
1128
+ if (typeof value !== "number" || Number.isNaN(value)) {
1129
+ return 30;
1205
1130
  }
1206
- emit("ad_impression");
1207
- emit("content_resume");
1131
+ return Math.max(1, Math.ceil(value));
1208
1132
  }
1209
- function handleAdError() {
1210
- if (tornDown) return;
1211
- if (!adPlaying) return;
1212
- clearAdStallTimer();
1213
- if (debug) console.log("".concat(LOG, " Handling ad error"));
1214
- adPlaying = false;
1215
- setAdPlayingFlag(false);
1216
- restoreContentVideoStyles();
1217
- if (adContainerEl) {
1218
- adContainerEl.style.display = "none";
1219
- adContainerEl.style.pointerEvents = "none";
1220
- }
1221
- emit("ad_error");
1222
- }
1223
- function teardownCurrentPlayback() {
1224
- removeAdEventListeners();
1225
- if (adHls) {
1226
- adHls.destroy();
1227
- adHls = void 0;
1228
- }
1229
- if (adVideoElement) {
1230
- if (singleElementMode && adVideoElement === contentVideo) {
1231
- contentVideo.pause();
1232
- } else {
1233
- adVideoElement.pause();
1234
- adVideoElement.removeAttribute("src");
1235
- adVideoElement.load();
1236
- }
1237
- }
1238
- }
1239
- function startNativePlayback(mediaFile) {
1240
- if (!adVideoElement) return;
1241
- if (debug) console.log("".concat(LOG, " Starting native MP4 playback: ").concat(mediaFile.url));
1242
- adVideoElement.src = mediaFile.url;
1243
- adVideoElement.load();
1244
- adVideoElement.play().catch(function(error) {
1245
- console.error("".concat(LOG, " Error starting native ad playback:"), error);
1246
- handleAdError();
1247
- });
1248
- }
1249
- function startHlsPlayback(mediaFile) {
1250
- if (!adVideoElement) return;
1251
- if (debug) console.log("".concat(LOG, " Starting HLS playback: ").concat(mediaFile.url));
1252
- if (import_hls.default.isSupported()) {
1253
- if (adHls) {
1254
- adHls.destroy();
1255
- adHls = void 0;
1256
- }
1257
- adHls = new import_hls.default({
1258
- enableWorker: true,
1259
- lowLatencyMode: false
1260
- });
1261
- adHls.loadSource(mediaFile.url);
1262
- adHls.attachMedia(adVideoElement);
1263
- adHls.on(import_hls.default.Events.MANIFEST_PARSED, function() {
1264
- if (!adPlaying) return;
1265
- adVideoElement.play().catch(function(error) {
1266
- console.error("".concat(LOG, " Error starting HLS ad playback:"), error);
1267
- handleAdError();
1268
- });
1269
- });
1270
- var nonFatalNetworkErrors = 0;
1271
- adHls.on(import_hls.default.Events.ERROR, function(_event, data) {
1272
- if (data.fatal) {
1273
- handleAdError();
1274
- } else if (data.type === import_hls.default.ErrorTypes.NETWORK_ERROR) {
1275
- nonFatalNetworkErrors++;
1276
- if (nonFatalNetworkErrors >= 3) {
1277
- if (debug) console.warn("".concat(LOG, " Too many non-fatal HLS network errors (").concat(nonFatalNetworkErrors, "), treating as fatal"));
1278
- handleAdError();
1279
- }
1280
- }
1281
- });
1282
- } else if (adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
1283
- adVideoElement.src = mediaFile.url;
1284
- adVideoElement.play().catch(function(error) {
1285
- console.error("".concat(LOG, " Error starting native HLS ad playback:"), error);
1286
- handleAdError();
1287
- });
1288
- } else {
1289
- console.error("".concat(LOG, " HLS not supported on this platform"));
1290
- handleAdError();
1291
- }
1292
- }
1293
- function startPlayback(mediaFile) {
1294
- if (!adVideoElement) return;
1295
- if (singleElementMode && isHlsMediaFile(mediaFile)) {
1296
- var mp4Fallback = currentAd === null || currentAd === void 0 ? void 0 : currentAd.mediaFiles.find(function(f) {
1297
- return !isHlsMediaFile(f);
1298
- });
1299
- if (mp4Fallback) {
1300
- if (debug) console.log("".concat(LOG, " singleElementMode: HLS ad blocked, using MP4 fallback"));
1301
- startNativePlayback(mp4Fallback);
1302
- return;
1303
- }
1304
- }
1305
- if (isHlsMediaFile(mediaFile)) {
1306
- startHlsPlayback(mediaFile);
1307
- } else {
1308
- startNativePlayback(mediaFile);
1309
- }
1310
- }
1311
- function playAd(bids) {
1133
+ function requestAdFromApi(requestContext) {
1312
1134
  return _async_to_generator(function() {
1313
- var winner, ad, contentVolume, adVolume2, mediaFile2, _contentVideo_parentElement, container, adVolume, mediaFile;
1135
+ var durationSeconds, ads;
1314
1136
  return _ts_generator(this, function(_state) {
1315
1137
  switch(_state.label){
1316
1138
  case 0:
1317
- if (destroyed) {
1318
- return [
1319
- 2,
1320
- Promise.reject(new Error("Layer has been destroyed"))
1321
- ];
1322
- }
1323
- if (bids.length === 0) {
1324
- return [
1325
- 2,
1326
- Promise.reject(new Error("No bids provided"))
1327
- ];
1328
- }
1329
- winner = bids[0];
1330
- if (debug) {
1331
- console.log("".concat(LOG, " Winning bid: ").concat(winner.bidder, " $").concat(winner.cpm.toFixed(2), " ").concat(winner.currency));
1332
- }
1139
+ durationSeconds = getDurationSecondsFromContext(requestContext);
1333
1140
  return [
1334
1141
  4,
1335
- resolveBidToVastAd(winner, LOG)
1142
+ fetchVast(durationSeconds)
1336
1143
  ];
1337
1144
  case 1:
1338
- ad = _state.sent();
1339
- if (!ad) {
1340
- if (debug) console.warn("".concat(LOG, " Winning bid has no VAST URL or XML"));
1341
- emit("ad_error");
1342
- return [
1343
- 2,
1344
- Promise.reject(new Error("No VAST from bid"))
1345
- ];
1346
- }
1347
- if (debug) {
1348
- console.log("".concat(LOG, " Ad parsed: ").concat(ad.title, ", duration: ").concat(ad.duration, "s, mediaFiles: ").concat(ad.mediaFiles.length));
1349
- }
1350
- sessionId = generateSessionId();
1351
- currentAd = ad;
1352
- trackingFired = _object_spread({}, createEmptyTrackingState());
1353
- fireTrackingPixels2(ad.trackingUrls.impression);
1354
- trackingFired.impression = true;
1355
- contentVolume = contentVideo.volume;
1356
- originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1357
- if (!singleElementMode) return [
1358
- 3,
1359
- 3
1360
- ];
1361
- mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.detachMedia();
1362
- teardownCurrentPlayback();
1363
- adVideoElement = contentVideo;
1364
- adHls = void 0;
1365
- adPlaying = true;
1366
- setAdPlayingFlag(true);
1367
- contentVideo.removeAttribute("src");
1368
- contentVideo.load();
1369
- if (!continueLiveStreamDuringAds) {
1370
- contentVideo.pause();
1371
- }
1372
- contentVideo.muted = true;
1373
- contentVideo.volume = 0;
1145
+ ads = _state.sent();
1374
1146
  return [
1375
- 4,
1376
- new Promise(function(resolve) {
1377
- return setTimeout(resolve, 200);
1378
- })
1379
- ];
1380
- case 2:
1381
- _state.sent();
1382
- if (destroyed || tornDown) return [
1383
- 2
1384
- ];
1385
- contentVideo.style.visibility = "visible";
1386
- contentVideo.style.opacity = "1";
1387
- applyContentVideoAdCoverStyles();
1388
- emit("content_pause");
1389
- setupAdEventListeners();
1390
- adVolume2 = originalMutedState ? 1 : originalVolume;
1391
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume2));
1392
- adVideoElement.muted = false;
1393
- mediaFile2 = selectBestMediaFile(ad.mediaFiles);
1394
- if (debug) console.log("".concat(LOG, " Loading ad from: ").concat(mediaFile2.url));
1395
- startPlayback(mediaFile2);
1396
- return [
1397
- 2
1398
- ];
1399
- case 3:
1400
- if (!adContainerEl) {
1401
- ;
1402
- container = document.createElement("div");
1403
- container.style.position = "absolute";
1404
- container.style.left = "0";
1405
- container.style.top = "0";
1406
- container.style.right = "0";
1407
- container.style.bottom = "0";
1408
- container.style.display = "none";
1409
- container.style.alignItems = "center";
1410
- container.style.justifyContent = "center";
1411
- container.style.pointerEvents = "none";
1412
- container.style.zIndex = "10";
1413
- container.style.backgroundColor = "#000";
1414
- (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1415
- adContainerEl = container;
1416
- }
1417
- if (!adVideoElement) {
1418
- adVideoElement = createAdVideoElement();
1419
- adContainerEl.appendChild(adVideoElement);
1420
- setupAdEventListeners();
1421
- } else {
1422
- teardownCurrentPlayback();
1423
- }
1424
- if (!continueLiveStreamDuringAds) {
1425
- contentVideo.pause();
1426
- }
1427
- contentVideo.muted = true;
1428
- contentVideo.volume = 0;
1429
- adPlaying = true;
1430
- setAdPlayingFlag(true);
1431
- adVolume = originalMutedState ? 1 : originalVolume;
1432
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
1433
- adVideoElement.muted = false;
1434
- if (adContainerEl) {
1435
- adContainerEl.style.display = "flex";
1436
- adContainerEl.style.pointerEvents = "auto";
1437
- }
1438
- emit("content_pause");
1439
- mediaFile = selectBestMediaFile(ad.mediaFiles);
1440
- if (debug) console.log("".concat(LOG, " Loading ad from: ").concat(mediaFile.url));
1441
- startPlayback(mediaFile);
1442
- return [
1443
- 2
1147
+ 2,
1148
+ ads[0] || null
1444
1149
  ];
1445
1150
  }
1446
1151
  });
1447
1152
  })();
1448
1153
  }
1449
- function ensureAdContainer() {
1450
- if (!adContainerEl) {
1451
- var _contentVideo_parentElement;
1452
- var container = document.createElement("div");
1453
- container.style.position = "absolute";
1454
- container.style.left = "0";
1455
- container.style.top = "0";
1456
- container.style.right = "0";
1457
- container.style.bottom = "0";
1458
- container.style.display = "none";
1459
- container.style.alignItems = "center";
1460
- container.style.justifyContent = "center";
1461
- container.style.pointerEvents = "none";
1462
- container.style.zIndex = "10";
1463
- container.style.backgroundColor = "#000";
1464
- (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1465
- adContainerEl = container;
1466
- }
1467
- return adContainerEl;
1154
+ function assignCurrentAd(ad) {
1155
+ currentAd = ad;
1156
+ sessionId = generateSessionId();
1157
+ trackingFired = {
1158
+ impression: false,
1159
+ start: false,
1160
+ firstQuartile: false,
1161
+ midpoint: false,
1162
+ thirdQuartile: false,
1163
+ complete: false
1164
+ };
1165
+ fireTrackingPixels2(currentAd.trackingUrls.impression);
1166
+ trackingFired.impression = true;
1167
+ emit("ad_impression");
1468
1168
  }
1469
- function preloadAd(bids, token) {
1470
- return _async_to_generator(function() {
1471
- var winner, ad, mediaFile, slot, videoEl, container, hls, slot1, slot2;
1472
- return _ts_generator(this, function(_state) {
1473
- switch(_state.label){
1474
- case 0:
1475
- if (destroyed) return [
1476
- 2
1477
- ];
1478
- winner = bids[0];
1479
- if (!winner) return [
1480
- 2
1481
- ];
1482
- if (debug) console.log("".concat(LOG, " [preload] Resolving VAST for token=").concat(token));
1483
- return [
1484
- 4,
1485
- resolveBidToVastAd(winner, LOG)
1486
- ];
1487
- case 1:
1488
- ad = _state.sent();
1489
- if (!ad || destroyed) return [
1490
- 2
1491
- ];
1492
- mediaFile = selectBestMediaFile(ad.mediaFiles);
1493
- if (!mediaFile) return [
1494
- 2
1495
- ];
1496
- if (smartTVMode || singleElementMode) {
1497
- slot = {
1498
- bids: bids,
1499
- ad: ad,
1500
- mediaFile: mediaFile,
1501
- videoEl: null,
1502
- ready: true
1503
- };
1504
- preloadSlots.set(token, slot);
1505
- if (debug) console.log("".concat(LOG, " [preload] Metadata-only preload (smartTV/singleElement), token=").concat(token, ", url=").concat(mediaFile.url));
1169
+ return {
1170
+ initialize: function initialize() {
1171
+ log("Initializing");
1172
+ if (!adContainerEl) {
1173
+ var _contentVideo_parentElement;
1174
+ var parent = contentVideo.parentElement;
1175
+ if (parent) {
1176
+ var computed = window.getComputedStyle(parent).position;
1177
+ if (computed === "static") {
1178
+ parent.style.position = "relative";
1179
+ parentPositionOverridden = true;
1180
+ }
1181
+ }
1182
+ var container = document.createElement("div");
1183
+ container.style.position = "absolute";
1184
+ container.style.left = "0";
1185
+ container.style.top = "0";
1186
+ container.style.right = "0";
1187
+ container.style.bottom = "0";
1188
+ container.style.display = "none";
1189
+ container.style.alignItems = "center";
1190
+ container.style.justifyContent = "center";
1191
+ container.style.pointerEvents = "none";
1192
+ container.style.zIndex = AD_LAYER_Z_INDEX;
1193
+ container.style.backgroundColor = "#000";
1194
+ container.style.transition = "opacity 0.3s ease-in-out";
1195
+ container.style.opacity = "0";
1196
+ container.style.isolation = "isolate";
1197
+ var countdown = document.createElement("div");
1198
+ countdown.style.position = "absolute";
1199
+ countdown.style.right = "12px";
1200
+ countdown.style.top = "12px";
1201
+ countdown.style.padding = "4px 8px";
1202
+ countdown.style.borderRadius = "4px";
1203
+ countdown.style.background = "rgba(0,0,0,0.75)";
1204
+ countdown.style.color = "#fff";
1205
+ countdown.style.fontFamily = "sans-serif";
1206
+ countdown.style.fontSize = "12px";
1207
+ countdown.style.lineHeight = "1.2";
1208
+ countdown.style.pointerEvents = "none";
1209
+ countdown.style.zIndex = COUNTDOWN_Z_INDEX;
1210
+ countdown.textContent = "Ad";
1211
+ container.appendChild(countdown);
1212
+ (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1213
+ adContainerEl = container;
1214
+ adCountdownEl = countdown;
1215
+ }
1216
+ },
1217
+ requestAds: function requestAds(duration) {
1218
+ return _async_to_generator(function() {
1219
+ var durationSeconds, parsed, ads, error;
1220
+ return _ts_generator(this, function(_state) {
1221
+ switch(_state.label){
1222
+ case 0:
1223
+ log("Requesting ads for duration:", duration);
1224
+ if (adPlaying) {
1225
+ return [
1226
+ 2,
1227
+ Promise.reject(new Error("Ad already playing"))
1228
+ ];
1229
+ }
1230
+ if (destroyed) {
1231
+ return [
1232
+ 2,
1233
+ Promise.reject(new Error("Player has been destroyed"))
1234
+ ];
1235
+ }
1236
+ _state.label = 1;
1237
+ case 1:
1238
+ _state.trys.push([
1239
+ 1,
1240
+ 3,
1241
+ ,
1242
+ 4
1243
+ ]);
1244
+ tornDown = false;
1245
+ durationSeconds = 30;
1246
+ parsed = parseInt(duration || "", 10);
1247
+ if (!isNaN(parsed) && parsed > 0) {
1248
+ durationSeconds = parsed;
1249
+ }
1506
1250
  return [
1507
- 2
1251
+ 4,
1252
+ fetchVast(durationSeconds)
1508
1253
  ];
1509
- }
1510
- videoEl = createAdVideoElement();
1511
- videoEl.style.visibility = "hidden";
1512
- videoEl.style.pointerEvents = "none";
1513
- videoEl.preload = "auto";
1514
- container = ensureAdContainer();
1515
- container.appendChild(videoEl);
1516
- if (isHlsMediaFile(mediaFile) && import_hls.default.isSupported()) {
1517
- hls = new import_hls.default({
1518
- enableWorker: true,
1519
- lowLatencyMode: false
1520
- });
1521
- hls.loadSource(mediaFile.url);
1522
- hls.attachMedia(videoEl);
1523
- slot1 = {
1524
- bids: bids,
1525
- ad: ad,
1526
- mediaFile: mediaFile,
1527
- videoEl: videoEl,
1528
- hlsInstance: hls,
1529
- ready: false
1530
- };
1531
- preloadSlots.set(token, slot1);
1532
- hls.on(import_hls.default.Events.MANIFEST_PARSED, function() {
1533
- var s = preloadSlots.get(token);
1534
- if (s) s.ready = true;
1535
- if (debug) console.log("".concat(LOG, " [preload] HLS manifest parsed, token=").concat(token));
1536
- });
1537
- hls.on(import_hls.default.Events.ERROR, function(_evt, data) {
1538
- if (!preloadSlots.has(token)) return;
1539
- if (data.fatal) {
1540
- if (debug) console.warn("".concat(LOG, " [preload] HLS error for token=").concat(token));
1541
- preloadSlots.delete(token);
1542
- hls.destroy();
1543
- videoEl.remove();
1544
- }
1545
- });
1546
- } else {
1547
- videoEl.src = mediaFile.url;
1548
- videoEl.load();
1549
- slot2 = {
1550
- bids: bids,
1551
- ad: ad,
1552
- mediaFile: mediaFile,
1553
- videoEl: videoEl,
1554
- ready: false
1555
- };
1556
- preloadSlots.set(token, slot2);
1557
- videoEl.addEventListener("canplay", function() {
1558
- var s = preloadSlots.get(token);
1559
- if (s) s.ready = true;
1560
- if (debug) console.log("".concat(LOG, " [preload] canplay fired, token=").concat(token));
1561
- }, {
1562
- once: true
1563
- });
1564
- }
1565
- if (debug) console.log("".concat(LOG, " [preload] Started buffering token=").concat(token, ", url=").concat(mediaFile.url));
1566
- return [
1567
- 2
1568
- ];
1569
- }
1570
- });
1571
- })();
1572
- }
1573
- function playPreloaded(token) {
1574
- return _async_to_generator(function() {
1575
- var slot, contentVolume, adVolume2, videoEl, container2, adVolume21, nonFatalNetworkErrors, adVolume, container;
1576
- return _ts_generator(this, function(_state) {
1577
- switch(_state.label){
1578
- case 0:
1579
- if (destroyed) return [
1580
- 2,
1581
- Promise.reject(new Error("Layer has been destroyed"))
1582
- ];
1583
- slot = preloadSlots.get(token);
1584
- if (!slot) {
1585
- if (debug) console.warn("".concat(LOG, " [preload] No slot found for token=").concat(token, ", nothing to play"));
1254
+ case 2:
1255
+ ads = _state.sent();
1256
+ if (ads.length === 0) {
1257
+ log("No ads available from VAST response");
1258
+ emit("ad_error");
1259
+ return [
1260
+ 2,
1261
+ Promise.resolve()
1262
+ ];
1263
+ }
1264
+ assignCurrentAd(ads[0]);
1265
+ log("Ad loaded: ".concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1266
+ return [
1267
+ 2,
1268
+ Promise.resolve()
1269
+ ];
1270
+ case 3:
1271
+ error = _state.sent();
1272
+ console.error("[AdStormPlayer] Error requesting ads:", error);
1273
+ emit("ad_error");
1274
+ return [
1275
+ 2,
1276
+ Promise.reject(error)
1277
+ ];
1278
+ case 4:
1586
1279
  return [
1587
1280
  2
1588
1281
  ];
1589
- }
1590
- preloadSlots.delete(token);
1591
- if (debug) console.log("".concat(LOG, " [preload] Playing preloaded ad, token=").concat(token, ", ready=").concat(slot.ready));
1592
- contentVolume = contentVideo.volume;
1593
- originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1594
- sessionId = generateSessionId();
1595
- currentAd = slot.ad;
1596
- trackingFired = _object_spread({}, createEmptyTrackingState());
1597
- fireTrackingPixels2(slot.ad.trackingUrls.impression);
1598
- trackingFired.impression = true;
1599
- if (!singleElementMode) return [
1600
- 3,
1601
- 2
1602
- ];
1603
- mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.detachMedia();
1604
- teardownCurrentPlayback();
1605
- adVideoElement = contentVideo;
1606
- adHls = void 0;
1607
- adPlaying = true;
1608
- setAdPlayingFlag(true);
1609
- contentVideo.removeAttribute("src");
1610
- contentVideo.load();
1611
- contentVideo.muted = true;
1612
- contentVideo.volume = 0;
1613
- return [
1614
- 4,
1615
- new Promise(function(resolve) {
1616
- return setTimeout(resolve, 200);
1617
- })
1618
- ];
1619
- case 1:
1620
- _state.sent();
1621
- if (destroyed || tornDown) return [
1622
- 2
1623
- ];
1624
- contentVideo.style.visibility = "visible";
1625
- contentVideo.style.opacity = "1";
1626
- applyContentVideoAdCoverStyles();
1627
- emit("content_pause");
1628
- setupAdEventListeners();
1629
- adVolume2 = originalMutedState ? 1 : originalVolume;
1630
- contentVideo.volume = Math.max(0, Math.min(1, adVolume2));
1631
- contentVideo.muted = false;
1632
- if (debug) console.log("".concat(LOG, " [preload] singleElementMode: attaching ad to contentVideo, url=").concat(slot.mediaFile.url));
1633
- startPlayback(slot.mediaFile);
1634
- return [
1635
- 2
1636
- ];
1637
- case 2:
1638
- if (smartTVMode && !slot.videoEl) {
1639
- teardownCurrentPlayback();
1640
- if (adVideoElement) {
1641
- adVideoElement.remove();
1642
- adVideoElement = void 0;
1282
+ }
1283
+ });
1284
+ })();
1285
+ },
1286
+ play: function play() {
1287
+ return _async_to_generator(function() {
1288
+ var mediaFile, error;
1289
+ return _ts_generator(this, function(_state) {
1290
+ switch(_state.label){
1291
+ case 0:
1292
+ if (!currentAd) {
1293
+ return [
1294
+ 2,
1295
+ Promise.reject(new Error("No ad loaded"))
1296
+ ];
1297
+ }
1298
+ if (destroyed) {
1299
+ return [
1300
+ 2,
1301
+ Promise.reject(new Error("Player has been destroyed"))
1302
+ ];
1303
+ }
1304
+ log("Starting ad playback");
1305
+ _state.label = 1;
1306
+ case 1:
1307
+ _state.trys.push([
1308
+ 1,
1309
+ 3,
1310
+ ,
1311
+ 4
1312
+ ]);
1313
+ tornDown = false;
1314
+ if (adHideTimerId) {
1315
+ clearTimeout(adHideTimerId);
1316
+ adHideTimerId = void 0;
1317
+ }
1318
+ if (!adVideoElement) {
1319
+ adVideoElement = createAdVideoElement();
1320
+ adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.appendChild(adVideoElement);
1321
+ } else {
1322
+ teardownCurrentPlayback();
1643
1323
  }
1644
- videoEl = createAdVideoElement();
1645
- videoEl.style.visibility = "visible";
1646
- videoEl.style.pointerEvents = "none";
1647
- container2 = ensureAdContainer();
1648
- container2.appendChild(videoEl);
1649
- adVideoElement = videoEl;
1650
1324
  setupAdEventListeners();
1325
+ trackingFired = {
1326
+ impression: trackingFired.impression,
1327
+ start: false,
1328
+ firstQuartile: false,
1329
+ midpoint: false,
1330
+ thirdQuartile: false,
1331
+ complete: false
1332
+ };
1333
+ contentVideo.style.transition = "opacity 0.3s ease-in-out";
1334
+ contentVideo.style.opacity = "0";
1335
+ setTimeout(function() {
1336
+ contentVideo.style.visibility = "hidden";
1337
+ }, 300);
1338
+ contentVideo.muted = true;
1339
+ contentVideo.volume = 0;
1651
1340
  if (!continueLiveStreamDuringAds) {
1652
1341
  contentVideo.pause();
1653
1342
  }
1654
- contentVideo.muted = true;
1655
- contentVideo.volume = 0;
1656
1343
  adPlaying = true;
1657
1344
  setAdPlayingFlag(true);
1658
- adVolume21 = originalMutedState ? 1 : originalVolume;
1659
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume21));
1660
- adVideoElement.muted = false;
1661
- container2.style.display = "flex";
1662
- container2.style.pointerEvents = "auto";
1345
+ if (adVideoElement) {
1346
+ adVideoElement.volume = originalMutedState ? 0 : originalVolume;
1347
+ adVideoElement.muted = originalMutedState;
1348
+ }
1349
+ if (adContainerEl) {
1350
+ adContainerEl.style.display = "flex";
1351
+ adContainerEl.style.pointerEvents = "auto";
1352
+ adContainerEl.offsetHeight;
1353
+ adContainerEl.style.opacity = "1";
1354
+ }
1663
1355
  emit("content_pause");
1664
- if (debug) console.log("".concat(LOG, " [preload] smartTVMode deferred: creating video element and loading, url=").concat(slot.mediaFile.url));
1665
- startPlayback(slot.mediaFile);
1356
+ mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1357
+ if (!mediaFile) {
1358
+ throw new Error("No media file available");
1359
+ }
1360
+ log("Playing media file:", mediaFile.url);
1361
+ adVideoElement.src = mediaFile.url;
1362
+ adVideoElement.load();
1666
1363
  return [
1667
- 2
1364
+ 4,
1365
+ adVideoElement.play()
1668
1366
  ];
1669
- }
1670
- teardownCurrentPlayback();
1671
- if (adVideoElement && adVideoElement !== slot.videoEl) {
1672
- adVideoElement.remove();
1673
- }
1674
- slot.videoEl.style.visibility = "visible";
1675
- slot.videoEl.style.pointerEvents = "none";
1676
- adVideoElement = slot.videoEl;
1677
- adHls = slot.hlsInstance;
1678
- if (adHls) {
1679
- nonFatalNetworkErrors = 0;
1680
- adHls.on(import_hls.default.Events.ERROR, function(_event, data) {
1681
- if (!adPlaying) return;
1682
- if (data.fatal) {
1683
- handleAdError();
1684
- } else if (data.type === import_hls.default.ErrorTypes.NETWORK_ERROR) {
1685
- nonFatalNetworkErrors++;
1686
- if (nonFatalNetworkErrors >= 3) {
1687
- if (debug) console.warn("".concat(LOG, " [preload] Too many non-fatal HLS network errors during playback, treating as fatal"));
1688
- handleAdError();
1689
- }
1690
- }
1691
- });
1692
- }
1693
- setupAdEventListeners();
1694
- if (!continueLiveStreamDuringAds) {
1695
- contentVideo.pause();
1696
- }
1697
- contentVideo.muted = true;
1698
- contentVideo.volume = 0;
1699
- adPlaying = true;
1700
- setAdPlayingFlag(true);
1701
- adVolume = originalMutedState ? 1 : originalVolume;
1702
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
1703
- adVideoElement.muted = false;
1704
- container = ensureAdContainer();
1705
- container.style.display = "flex";
1706
- container.style.pointerEvents = "auto";
1707
- emit("content_pause");
1708
- adVideoElement.play().catch(function(error) {
1709
- console.error("".concat(LOG, " [preload] Error playing preloaded ad:"), error);
1367
+ case 2:
1368
+ _state.sent();
1369
+ return [
1370
+ 2,
1371
+ Promise.resolve()
1372
+ ];
1373
+ case 3:
1374
+ error = _state.sent();
1375
+ console.error("[AdStormPlayer] Error playing ad:", error);
1710
1376
  handleAdError();
1711
- });
1712
- return [
1713
- 2
1714
- ];
1715
- }
1716
- });
1717
- })();
1718
- }
1719
- function cancelPreload(token) {
1720
- var slot = preloadSlots.get(token);
1721
- if (!slot) return;
1722
- preloadSlots.delete(token);
1723
- if (slot.hlsInstance) {
1724
- slot.hlsInstance.destroy();
1725
- }
1726
- if (slot.videoEl) {
1727
- slot.videoEl.pause();
1728
- slot.videoEl.removeAttribute("src");
1729
- slot.videoEl.load();
1730
- slot.videoEl.remove();
1731
- }
1732
- if (debug) console.log("".concat(LOG, " [preload] Cancelled and cleaned up token=").concat(token));
1733
- }
1734
- return {
1735
- initialize: function initialize() {
1736
- if (debug) console.log("".concat(LOG, " Initializing"));
1737
- },
1738
- updateOptions: function updateOptions(opts) {
1739
- if (opts.continueLiveStreamDuringAds !== void 0) {
1740
- continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;
1741
- }
1742
- if (opts.mainHlsInstance !== void 0) {
1743
- var _opts_mainHlsInstance;
1744
- mainHlsInstance = (_opts_mainHlsInstance = opts.mainHlsInstance) !== null && _opts_mainHlsInstance !== void 0 ? _opts_mainHlsInstance : void 0;
1745
- }
1746
- },
1747
- playAd: playAd,
1748
- preloadAd: preloadAd,
1749
- playPreloaded: playPreloaded,
1750
- hasPreloaded: function hasPreloaded(token) {
1751
- return preloadSlots.has(token);
1752
- },
1753
- cancelPreload: cancelPreload,
1754
- pause: function pause() {
1755
- if (!adPlaying || !adVideoElement) return;
1756
- try {
1757
- if (!adVideoElement.paused) adVideoElement.pause();
1758
- } catch (error) {
1759
- if (debug) console.warn("".concat(LOG, " Error pausing ad:"), error);
1760
- }
1761
- },
1762
- resume: function resume() {
1763
- if (!adPlaying || !adVideoElement) return;
1764
- try {
1765
- if (adVideoElement.paused) adVideoElement.play().catch(function() {});
1766
- } catch (error) {
1767
- if (debug) console.warn("".concat(LOG, " Error resuming ad:"), error);
1768
- }
1377
+ return [
1378
+ 2,
1379
+ Promise.reject(error)
1380
+ ];
1381
+ case 4:
1382
+ return [
1383
+ 2
1384
+ ];
1385
+ }
1386
+ });
1387
+ })();
1769
1388
  },
1770
1389
  stop: function stop() {
1771
1390
  return _async_to_generator(function() {
1772
1391
  return _ts_generator(this, function(_state) {
1392
+ log("Stopping ad");
1773
1393
  tornDown = true;
1774
- if (debug) console.log("".concat(LOG, " Stopping ad"));
1775
1394
  adPlaying = false;
1776
1395
  setAdPlayingFlag(false);
1777
- restoreContentVideoStyles();
1778
- contentVideo.muted = originalMutedState;
1779
- contentVideo.volume = originalMutedState ? 0 : originalVolume;
1396
+ clearAdStallTimer();
1397
+ clearAdCountdownTimer();
1398
+ if (adContainerEl) {
1399
+ adContainerEl.style.opacity = "0";
1400
+ adHideTimerId = setTimeout(function() {
1401
+ if (adContainerEl) {
1402
+ adContainerEl.style.display = "none";
1403
+ adContainerEl.style.pointerEvents = "none";
1404
+ }
1405
+ }, 300);
1406
+ }
1407
+ teardownCurrentPlayback();
1780
1408
  contentVideo.style.visibility = "visible";
1781
1409
  contentVideo.style.opacity = "1";
1782
- if (singleElementMode) {
1783
- teardownCurrentPlayback();
1784
- contentVideo.removeAttribute("src");
1785
- contentVideo.load();
1786
- adVideoElement = void 0;
1787
- } else {
1788
- if (adContainerEl) {
1789
- adContainerEl.style.display = "none";
1790
- adContainerEl.style.pointerEvents = "none";
1791
- }
1792
- if (continueLiveStreamDuringAds) {
1793
- contentVideo.play().catch(function() {});
1794
- }
1795
- teardownCurrentPlayback();
1796
- if (adVideoElement) {
1797
- adVideoElement.pause();
1798
- adVideoElement.removeAttribute("src");
1799
- adVideoElement.load();
1800
- }
1801
- }
1410
+ contentVideo.muted = originalMutedState;
1411
+ contentVideo.volume = originalVolume;
1802
1412
  currentAd = void 0;
1803
1413
  tornDown = false;
1804
1414
  return [
1805
- 2
1415
+ 2,
1416
+ Promise.resolve()
1806
1417
  ];
1807
1418
  });
1808
1419
  })();
1809
1420
  },
1421
+ pause: function pause() {
1422
+ if (!adPlaying || !adVideoElement) return;
1423
+ try {
1424
+ if (!adVideoElement.paused) adVideoElement.pause();
1425
+ } catch (error) {
1426
+ console.warn("[AdStormPlayer] Error pausing ad:", error);
1427
+ }
1428
+ },
1429
+ resume: function resume() {
1430
+ if (!adPlaying || !adVideoElement) return;
1431
+ try {
1432
+ if (adVideoElement.paused) adVideoElement.play().catch(function() {});
1433
+ } catch (error) {
1434
+ console.warn("[AdStormPlayer] Error resuming ad:", error);
1435
+ }
1436
+ },
1810
1437
  destroy: function destroy() {
1811
- tornDown = true;
1812
- if (debug) console.log("".concat(LOG, " Destroying"));
1438
+ log("Destroying");
1813
1439
  destroyed = true;
1440
+ tornDown = true;
1814
1441
  adPlaying = false;
1815
1442
  setAdPlayingFlag(false);
1816
- restoreContentVideoStyles();
1443
+ clearAdStallTimer();
1444
+ clearAdCountdownTimer();
1445
+ if (adHideTimerId) {
1446
+ clearTimeout(adHideTimerId);
1447
+ adHideTimerId = void 0;
1448
+ }
1817
1449
  contentVideo.muted = originalMutedState;
1818
1450
  contentVideo.volume = originalVolume;
1819
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1820
- try {
1821
- for(var _iterator = Array.from(preloadSlots.entries())[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1822
- var _step_value = _sliced_to_array(_step.value, 1), token = _step_value[0];
1823
- cancelPreload(token);
1824
- }
1825
- } catch (err) {
1826
- _didIteratorError = true;
1827
- _iteratorError = err;
1828
- } finally{
1829
- try {
1830
- if (!_iteratorNormalCompletion && _iterator.return != null) {
1831
- _iterator.return();
1832
- }
1833
- } finally{
1834
- if (_didIteratorError) {
1835
- throw _iteratorError;
1836
- }
1837
- }
1838
- }
1451
+ contentVideo.style.visibility = "visible";
1452
+ contentVideo.style.opacity = "1";
1839
1453
  teardownCurrentPlayback();
1840
- if (adVideoElement) {
1841
- if (singleElementMode && adVideoElement === contentVideo) {
1842
- contentVideo.removeAttribute("src");
1843
- contentVideo.load();
1844
- } else {
1845
- adVideoElement.pause();
1846
- adVideoElement.removeAttribute("src");
1847
- adVideoElement.remove();
1848
- }
1849
- adVideoElement = void 0;
1850
- }
1454
+ adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.remove();
1455
+ adVideoElement = void 0;
1851
1456
  if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
1852
1457
  adContainerEl.parentElement.removeChild(adContainerEl);
1853
1458
  }
1854
1459
  adContainerEl = void 0;
1460
+ adCountdownEl = void 0;
1855
1461
  currentAd = void 0;
1462
+ sessionId = void 0;
1463
+ preloadSlots.clear();
1856
1464
  listeners.clear();
1465
+ if (parentPositionOverridden && contentVideo.parentElement) {
1466
+ contentVideo.parentElement.style.position = "";
1467
+ parentPositionOverridden = false;
1468
+ }
1469
+ },
1470
+ updateOptions: function updateOptions(opts) {
1471
+ if (opts.continueLiveStreamDuringAds !== void 0) {
1472
+ continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;
1473
+ }
1474
+ },
1475
+ playAd: function playAd(requestContext) {
1476
+ return _async_to_generator(function() {
1477
+ var ad;
1478
+ return _ts_generator(this, function(_state) {
1479
+ switch(_state.label){
1480
+ case 0:
1481
+ if (destroyed) return [
1482
+ 2,
1483
+ Promise.reject(new Error("Player has been destroyed"))
1484
+ ];
1485
+ if (!!currentAd) return [
1486
+ 3,
1487
+ 2
1488
+ ];
1489
+ return [
1490
+ 4,
1491
+ requestAdFromApi(requestContext)
1492
+ ];
1493
+ case 1:
1494
+ ad = _state.sent();
1495
+ if (!ad) {
1496
+ emit("ad_error", {
1497
+ message: "No valid ad from AdStorm API"
1498
+ });
1499
+ return [
1500
+ 2,
1501
+ Promise.reject(new Error("No valid ad from AdStorm API"))
1502
+ ];
1503
+ }
1504
+ assignCurrentAd(ad);
1505
+ _state.label = 2;
1506
+ case 2:
1507
+ return [
1508
+ 2,
1509
+ this.play()
1510
+ ];
1511
+ }
1512
+ });
1513
+ }).call(this);
1514
+ },
1515
+ preloadAd: function preloadAd(arg1, arg2) {
1516
+ return _async_to_generator(function() {
1517
+ var token, requestContext, ad;
1518
+ return _ts_generator(this, function(_state) {
1519
+ switch(_state.label){
1520
+ case 0:
1521
+ if (destroyed) return [
1522
+ 2
1523
+ ];
1524
+ token = typeof arg1 === "string" ? arg1 : typeof arg2 === "string" ? arg2 : void 0;
1525
+ if (!token) return [
1526
+ 2
1527
+ ];
1528
+ requestContext = typeof arg1 === "string" ? arg2 : arg1;
1529
+ return [
1530
+ 4,
1531
+ requestAdFromApi(requestContext)
1532
+ ];
1533
+ case 1:
1534
+ ad = _state.sent();
1535
+ if (!ad) return [
1536
+ 2
1537
+ ];
1538
+ preloadSlots.set(token, {
1539
+ ad: ad
1540
+ });
1541
+ return [
1542
+ 2
1543
+ ];
1544
+ }
1545
+ });
1546
+ })();
1547
+ },
1548
+ playPreloaded: function playPreloaded(token) {
1549
+ return _async_to_generator(function() {
1550
+ var slot;
1551
+ return _ts_generator(this, function(_state) {
1552
+ if (destroyed) return [
1553
+ 2,
1554
+ Promise.reject(new Error("Player has been destroyed"))
1555
+ ];
1556
+ slot = preloadSlots.get(token);
1557
+ if (!slot) {
1558
+ return [
1559
+ 2,
1560
+ Promise.reject(new Error("No preloaded ad for token ".concat(token)))
1561
+ ];
1562
+ }
1563
+ preloadSlots.delete(token);
1564
+ assignCurrentAd(slot.ad);
1565
+ return [
1566
+ 2,
1567
+ this.play()
1568
+ ];
1569
+ });
1570
+ }).call(this);
1571
+ },
1572
+ hasPreloaded: function hasPreloaded(token) {
1573
+ return preloadSlots.has(token);
1574
+ },
1575
+ cancelPreload: function cancelPreload(token) {
1576
+ preloadSlots.delete(token);
1857
1577
  },
1858
1578
  isAdPlaying: function isAdPlaying() {
1859
1579
  return adPlaying;
1860
1580
  },
1861
1581
  resize: function resize(width, height) {
1582
+ log("Resizing to ".concat(width, "x").concat(height));
1862
1583
  if (adContainerEl) {
1863
1584
  adContainerEl.style.width = "".concat(width, "px");
1864
1585
  adContainerEl.style.height = "".concat(height, "px");
@@ -1878,6 +1599,7 @@ function createVastAdLayer(contentVideo, options) {
1878
1599
  },
1879
1600
  updateOriginalMutedState: function updateOriginalMutedState(muted, volume) {
1880
1601
  var nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
1602
+ log("updateOriginalMutedState: muted=".concat(muted, ", volume=").concat(nextVolume));
1881
1603
  originalMutedState = muted;
1882
1604
  originalVolume = nextVolume;
1883
1605
  },
@@ -1890,6 +1612,7 @@ function createVastAdLayer(contentVideo, options) {
1890
1612
  setAdVolume: function setAdVolume(volume) {
1891
1613
  if (adVideoElement && adPlaying) {
1892
1614
  adVideoElement.volume = Math.max(0, Math.min(1, volume));
1615
+ adVideoElement.muted = volume === 0;
1893
1616
  }
1894
1617
  },
1895
1618
  getAdVolume: function getAdVolume() {
@@ -1899,11 +1622,16 @@ function createVastAdLayer(contentVideo, options) {
1899
1622
  return 1;
1900
1623
  },
1901
1624
  showPlaceholder: function showPlaceholder() {
1902
- if (singleElementMode) return;
1903
- contentVideo.style.opacity = "0";
1904
- contentVideo.style.visibility = "hidden";
1905
1625
  if (!adContainerEl) {
1906
1626
  var _contentVideo_parentElement;
1627
+ var parent = contentVideo.parentElement;
1628
+ if (parent) {
1629
+ var computed = window.getComputedStyle(parent).position;
1630
+ if (computed === "static") {
1631
+ parent.style.position = "relative";
1632
+ parentPositionOverridden = true;
1633
+ }
1634
+ }
1907
1635
  var container = document.createElement("div");
1908
1636
  container.style.position = "absolute";
1909
1637
  container.style.left = "0";
@@ -1914,24 +1642,43 @@ function createVastAdLayer(contentVideo, options) {
1914
1642
  container.style.alignItems = "center";
1915
1643
  container.style.justifyContent = "center";
1916
1644
  container.style.pointerEvents = "none";
1917
- container.style.zIndex = "10";
1645
+ container.style.zIndex = AD_LAYER_Z_INDEX;
1918
1646
  container.style.backgroundColor = "#000";
1647
+ container.style.isolation = "isolate";
1648
+ var countdown = document.createElement("div");
1649
+ countdown.style.position = "absolute";
1650
+ countdown.style.right = "12px";
1651
+ countdown.style.top = "12px";
1652
+ countdown.style.padding = "4px 8px";
1653
+ countdown.style.borderRadius = "4px";
1654
+ countdown.style.background = "rgba(0,0,0,0.75)";
1655
+ countdown.style.color = "#fff";
1656
+ countdown.style.fontFamily = "sans-serif";
1657
+ countdown.style.fontSize = "12px";
1658
+ countdown.style.lineHeight = "1.2";
1659
+ countdown.style.pointerEvents = "none";
1660
+ countdown.style.zIndex = COUNTDOWN_Z_INDEX;
1661
+ countdown.textContent = "Ad";
1662
+ container.appendChild(countdown);
1919
1663
  (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1920
1664
  adContainerEl = container;
1665
+ adCountdownEl = countdown;
1921
1666
  }
1922
1667
  if (adContainerEl) {
1923
1668
  adContainerEl.style.display = "flex";
1669
+ adContainerEl.style.opacity = "1";
1924
1670
  adContainerEl.style.pointerEvents = "auto";
1925
1671
  }
1926
1672
  },
1927
1673
  hidePlaceholder: function hidePlaceholder() {
1928
1674
  if (adContainerEl) {
1929
- adContainerEl.style.display = "none";
1930
- adContainerEl.style.pointerEvents = "none";
1931
- }
1932
- if (!adPlaying) {
1933
- contentVideo.style.visibility = "visible";
1934
- contentVideo.style.opacity = "1";
1675
+ adContainerEl.style.opacity = "0";
1676
+ setTimeout(function() {
1677
+ if (adContainerEl) {
1678
+ adContainerEl.style.display = "none";
1679
+ adContainerEl.style.pointerEvents = "none";
1680
+ }
1681
+ }, 300);
1935
1682
  }
1936
1683
  }
1937
1684
  };
@@ -3034,6 +2781,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3034
2781
  this.backoffBaseMs = 1e3;
3035
2782
  this.maxBackoffMs = 15e3;
3036
2783
  this.MIN_AD_REMAINING_MS = 15e3;
2784
+ this.adRequestTimeoutMs = 5e3;
2785
+ this.adRequestMaxRetries = 3;
2786
+ this.adRequestRetryBackoffMs = 1500;
3037
2787
  this.preloadedTokens = [];
3038
2788
  initializePolyfills();
3039
2789
  var browserOverrides = getBrowserConfigOverrides();
@@ -3041,24 +2791,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3041
2791
  this.video = config.videoElement;
3042
2792
  this.adTransitionGapMs = (_this_config_adTransitionGapMs = this.config.adTransitionGapMs) !== null && _this_config_adTransitionGapMs !== void 0 ? _this_config_adTransitionGapMs : 100;
3043
2793
  logBrowserInfo(config.debugAdTiming);
3044
- this.vastManager = createVastManager(config.debugAdTiming !== void 0 ? {
3045
- debug: !!config.debugAdTiming
3046
- } : {});
3047
2794
  var browserForAdLayer = detectBrowser();
3048
2795
  var isSinglePipeline = browserForAdLayer.isSmartTV || !!this.config.singlePipelineMode;
3049
- this.adLayer = createVastAdLayer(this.video, {
3050
- continueLiveStreamDuringAds: false,
3051
- smartTVMode: isSinglePipeline,
3052
- singleElementMode: isSinglePipeline,
3053
- forceMP4Ads: isSinglePipeline,
2796
+ this.adLayer = createAdStormPlayer(this.video, {
2797
+ licenseKey: this.config.licenseKey || "",
3054
2798
  debug: !!config.debugAdTiming
3055
2799
  });
2800
+ this.adLayer.updateOptions({
2801
+ continueLiveStreamDuringAds: !isSinglePipeline && this.shouldContinueLiveStreamDuringAds()
2802
+ });
3056
2803
  }
3057
2804
  _create_class(StormcloudVideoPlayer, [
3058
2805
  {
3059
2806
  key: "adRequest",
3060
2807
  value: function adRequest(context) {
3061
2808
  return _async_to_generator(function() {
2809
+ var _ref, _ref1, durationSeconds;
3062
2810
  return _ts_generator(this, function(_state) {
3063
2811
  switch(_state.label){
3064
2812
  case 0:
@@ -3066,15 +2814,28 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3066
2814
  2,
3067
2815
  []
3068
2816
  ];
2817
+ durationSeconds = Math.max(1, Math.ceil((_ref = (_ref1 = context === null || context === void 0 ? void 0 : context.remainingBreakSec) !== null && _ref1 !== void 0 ? _ref1 : context === null || context === void 0 ? void 0 : context.breakDurationSec) !== null && _ref !== void 0 ? _ref : 30));
3069
2818
  return [
3070
2819
  4,
3071
- this.vastManager.initialize()
2820
+ this.adLayer.requestAds(String(durationSeconds))
3072
2821
  ];
3073
2822
  case 1:
3074
2823
  _state.sent();
3075
2824
  return [
3076
2825
  2,
3077
- this.vastManager.requestBidsUntilResponse(context)
2826
+ [
2827
+ {
2828
+ bidder: "adstorm-direct",
2829
+ cpm: 0,
2830
+ width: 0,
2831
+ height: 0,
2832
+ adId: "adstorm",
2833
+ impId: "",
2834
+ creativeId: "adstorm",
2835
+ currency: "USD",
2836
+ durationSec: durationSeconds
2837
+ }
2838
+ ]
3078
2839
  ];
3079
2840
  }
3080
2841
  });
@@ -3131,7 +2892,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3131
2892
  2
3132
2893
  ];
3133
2894
  case 3:
3134
- this.hls = new import_hls2.default(_object_spread_props(_object_spread({
2895
+ this.hls = new import_hls.default(_object_spread_props(_object_spread({
3135
2896
  enableWorker: true,
3136
2897
  backBufferLength: 30,
3137
2898
  liveDurationInfinity: true,
@@ -3149,11 +2910,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3149
2910
  nudgeMaxRetry: 3,
3150
2911
  startPosition: -1
3151
2912
  }));
3152
- this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, function() {
2913
+ this.hls.on(import_hls.default.Events.MEDIA_ATTACHED, function() {
3153
2914
  var _this_hls;
3154
2915
  (_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.loadSource(_this.config.src);
3155
2916
  });
3156
- this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, function(_, data) {
2917
+ this.hls.on(import_hls.default.Events.MANIFEST_PARSED, function(_, data) {
3157
2918
  return _async_to_generator(function() {
3158
2919
  var _this_config_minSegmentsBeforePlay, _ref, _this_hls_levels, _this_hls, adBehavior, _this_hls1, minSegments, _this_video_play;
3159
2920
  return _ts_generator(this, function(_state) {
@@ -3215,7 +2976,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3215
2976
  });
3216
2977
  }).call(_this);
3217
2978
  });
3218
- this.hls.on(import_hls2.default.Events.LEVEL_LOADED, function(_evt, data) {
2979
+ this.hls.on(import_hls.default.Events.LEVEL_LOADED, function(_evt, data) {
3219
2980
  if (_this.inAdBreak || _this.pendingAdBreak) {
3220
2981
  return;
3221
2982
  }
@@ -3288,7 +3049,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3288
3049
  }
3289
3050
  }
3290
3051
  });
3291
- this.hls.on(import_hls2.default.Events.FRAG_BUFFERED, function(_evt, data) {
3052
+ this.hls.on(import_hls.default.Events.FRAG_BUFFERED, function(_evt, data) {
3292
3053
  return _async_to_generator(function() {
3293
3054
  var _this, _this_config_minSegmentsBeforePlay, minSegments, _this_video_play;
3294
3055
  return _ts_generator(this, function(_state) {
@@ -3348,7 +3109,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3348
3109
  });
3349
3110
  }).call(_this);
3350
3111
  });
3351
- this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, function(_evt, data) {
3112
+ this.hls.on(import_hls.default.Events.FRAG_PARSING_METADATA, function(_evt, data) {
3352
3113
  var id3Tags = ((data === null || data === void 0 ? void 0 : data.samples) || []).map(function(s) {
3353
3114
  return {
3354
3115
  key: "ID3",
@@ -3360,7 +3121,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3360
3121
  return _this.onId3Tag(tag);
3361
3122
  });
3362
3123
  });
3363
- this.hls.on(import_hls2.default.Events.FRAG_CHANGED, function(_evt, data) {
3124
+ this.hls.on(import_hls.default.Events.FRAG_CHANGED, function(_evt, data) {
3364
3125
  var frag = data === null || data === void 0 ? void 0 : data.frag;
3365
3126
  var tagList = frag === null || frag === void 0 ? void 0 : frag.tagList;
3366
3127
  if (!Array.isArray(tagList)) return;
@@ -3469,14 +3230,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3469
3230
  }
3470
3231
  }
3471
3232
  });
3472
- this.hls.on(import_hls2.default.Events.ERROR, function(_evt, data) {
3233
+ this.hls.on(import_hls.default.Events.ERROR, function(_evt, data) {
3473
3234
  if (data === null || data === void 0 ? void 0 : data.fatal) {
3474
3235
  switch(data.type){
3475
- case import_hls2.default.ErrorTypes.NETWORK_ERROR:
3236
+ case import_hls.default.ErrorTypes.NETWORK_ERROR:
3476
3237
  var _this_hls;
3477
3238
  (_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.startLoad();
3478
3239
  break;
3479
- case import_hls2.default.ErrorTypes.MEDIA_ERROR:
3240
+ case import_hls.default.ErrorTypes.MEDIA_ERROR:
3480
3241
  var _this_hls1;
3481
3242
  (_this_hls1 = _this.hls) === null || _this_hls1 === void 0 ? void 0 : _this_hls1.recoverMediaError();
3482
3243
  break;
@@ -3568,7 +3329,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3568
3329
  }
3569
3330
  });
3570
3331
  this.adLayer.on("content_resume", function() {
3332
+ var _ref, _ref1;
3333
+ var _this_savedMutedStateBeforeScte, _this_savedMutedStateBeforeScte1;
3571
3334
  var remaining = _this.getRemainingAdMs();
3335
+ var breakMuted = (_ref = (_this_savedMutedStateBeforeScte = _this.savedMutedStateBeforeScte) === null || _this_savedMutedStateBeforeScte === void 0 ? void 0 : _this_savedMutedStateBeforeScte.muted) !== null && _ref !== void 0 ? _ref : _this.adLayer.getOriginalMutedState();
3336
+ var breakVolume = (_ref1 = (_this_savedMutedStateBeforeScte1 = _this.savedMutedStateBeforeScte) === null || _this_savedMutedStateBeforeScte1 === void 0 ? void 0 : _this_savedMutedStateBeforeScte1.volume) !== null && _ref1 !== void 0 ? _ref1 : _this.adLayer.getOriginalVolume();
3572
3337
  if (_this.config.debugAdTiming) {
3573
3338
  console.log("[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s, preloadedTokens=%d, pendingNext=%s", _this.inAdBreak, remaining, _this.preloadedTokens.length, !!_this.pendingNextAdBids);
3574
3339
  }
@@ -3583,7 +3348,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3583
3348
  return;
3584
3349
  }
3585
3350
  _this.consecutiveFailures = 0;
3586
- if (!_this.video.muted) {
3351
+ if (!_this.config.disableFiller && !_this.video.muted) {
3587
3352
  _this.video.muted = true;
3588
3353
  _this.video.volume = 0;
3589
3354
  }
@@ -3650,6 +3415,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3650
3415
  if (!_this.config.disableFiller) {
3651
3416
  _this.showPlaceholderLayer();
3652
3417
  _this.adLayer.showPlaceholder();
3418
+ } else {
3419
+ _this.adLayer.hidePlaceholder();
3420
+ if (_this.video.muted !== breakMuted) {
3421
+ _this.video.muted = breakMuted;
3422
+ }
3423
+ if (Math.abs(_this.video.volume - breakVolume) > 0.01) {
3424
+ _this.video.volume = breakVolume;
3425
+ }
3426
+ if (_this.video.paused) {
3427
+ var _this_video_play;
3428
+ (_this_video_play = _this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
3429
+ }
3653
3430
  }
3654
3431
  _this.stopContinuousFetching();
3655
3432
  return;
@@ -4377,6 +4154,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4377
4154
  return this.totalAdsInBreak;
4378
4155
  }
4379
4156
  },
4157
+ {
4158
+ key: "getRemainingAdSeconds",
4159
+ value: function getRemainingAdSeconds() {
4160
+ var remainingMs = this.getRemainingAdMs();
4161
+ if (!Number.isFinite(remainingMs) || remainingMs <= 0 || remainingMs === Number.MAX_SAFE_INTEGER) {
4162
+ return 0;
4163
+ }
4164
+ return Math.ceil(remainingMs / 1e3);
4165
+ }
4166
+ },
4380
4167
  {
4381
4168
  key: "isAdPlaying",
4382
4169
  value: function isAdPlaying() {
@@ -5606,7 +5393,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5606
5393
  });
5607
5394
  };
5608
5395
  var onManifestParsedRestore = function onManifestParsedRestore1() {
5609
- hlsRef.off(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5396
+ hlsRef.off(import_hls.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5610
5397
  if (!_this.inAdBreak && !_this.adLayer.isAdPlaying()) {
5611
5398
  if (videoRef.muted !== savedMuted) videoRef.muted = savedMuted;
5612
5399
  if (Math.abs(videoRef.volume - savedVolume) > 0.01) videoRef.volume = savedVolume;
@@ -5619,7 +5406,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5619
5406
  }
5620
5407
  }
5621
5408
  };
5622
- hlsRef.on(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5409
+ hlsRef.on(import_hls.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5623
5410
  var pipelineDelayMs = 300;
5624
5411
  if (debugEnabled) {
5625
5412
  console.log("[StormcloudVideoPlayer] Smart TV: waiting ".concat(pipelineDelayMs, "ms for hardware pipeline release before re-attach"));