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.
@@ -435,185 +435,8 @@ var canPlay = {
435
435
  // src/players/HlsPlayer.tsx
436
436
  var import_react2 = require("react");
437
437
  // src/player/StormcloudVideoPlayer.ts
438
- var import_hls2 = __toESM(require("hls.js"), 1);
438
+ var import_hls = __toESM(require("hls.js"), 1);
439
439
  // src/sdk/vastParser.ts
440
- function isHlsType(type) {
441
- return type === "application/x-mpegURL" || type.includes("m3u8");
442
- }
443
- function isMp4Type(type) {
444
- return type === "video/mp4" || type.includes("mp4");
445
- }
446
- function parseVastXml(xmlString) {
447
- var filter = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "all", logPrefix = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "[VastParser]";
448
- try {
449
- var _xmlDoc_querySelector, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector2;
450
- var parser = new DOMParser();
451
- var xmlDoc = parser.parseFromString(xmlString, "text/xml");
452
- var parserError = xmlDoc.querySelector("parsererror");
453
- if (parserError) {
454
- console.error("".concat(logPrefix, " XML parsing error (malformed VAST XML):"), parserError.textContent);
455
- return null;
456
- }
457
- var adElement = xmlDoc.querySelector("Ad");
458
- if (!adElement) {
459
- console.warn("".concat(logPrefix, " No Ad element found in VAST XML"));
460
- return null;
461
- }
462
- var adId = adElement.getAttribute("id") || "unknown";
463
- var title = ((_xmlDoc_querySelector = xmlDoc.querySelector("AdTitle")) === null || _xmlDoc_querySelector === void 0 ? void 0 : _xmlDoc_querySelector.textContent) || "Ad";
464
- var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
465
- var durationText = ((_xmlDoc_querySelector1 = xmlDoc.querySelector("Duration")) === null || _xmlDoc_querySelector1 === void 0 ? void 0 : _xmlDoc_querySelector1.textContent) || "00:00:30";
466
- var durationParts = durationText.split(":");
467
- var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + Math.round(parseFloat(durationParts[2] || "0"));
468
- var mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
469
- var mediaFiles = [];
470
- console.log("".concat(logPrefix, " Found ").concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
471
- mediaFileElements.forEach(function(mf, index) {
472
- var _mf_textContent;
473
- var type = mf.getAttribute("type") || "";
474
- var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
475
- var width = mf.getAttribute("width") || "";
476
- var height = mf.getAttribute("height") || "";
477
- console.log("".concat(logPrefix, " MediaFile ").concat(index, ': type="').concat(type, '", url="').concat(url.substring(0, 80), '...", width="').concat(width, '", height="').concat(height, '"'));
478
- if (!url) {
479
- console.warn("".concat(logPrefix, " MediaFile ").concat(index, " has empty URL"));
480
- return;
481
- }
482
- var isHls = isHlsType(type);
483
- var isMp4 = isMp4Type(type);
484
- var accepted = false;
485
- if (filter === "hls-only") {
486
- accepted = isHls;
487
- } else if (filter === "mp4-first") {
488
- accepted = isMp4 || isHls;
489
- } else {
490
- accepted = true;
491
- }
492
- if (!accepted) {
493
- console.log("".concat(logPrefix, " MediaFile ").concat(index, ' ignored (type="').concat(type, '" not accepted by filter "').concat(filter, '")'));
494
- return;
495
- }
496
- var bitrateAttr = mf.getAttribute("bitrate");
497
- var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
498
- mediaFiles.push({
499
- url: url,
500
- type: type,
501
- width: parseInt(width || "1920", 10),
502
- height: parseInt(height || "1080", 10),
503
- bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
504
- });
505
- console.log("".concat(logPrefix, ' Added MediaFile: type="').concat(type, '" url="').concat(url.substring(0, 80), '..."'));
506
- });
507
- if (filter === "mp4-first" && mediaFiles.length > 1) {
508
- mediaFiles.sort(function(a, b) {
509
- var aIsMp4 = isMp4Type(a.type) ? 0 : 1;
510
- var bIsMp4 = isMp4Type(b.type) ? 0 : 1;
511
- return aIsMp4 - bIsMp4;
512
- });
513
- }
514
- if (mediaFiles.length === 0) {
515
- if (isNoAdAvailable) {
516
- console.warn("".concat(logPrefix, " No ads available (VAST response indicates no ads)"));
517
- } else {
518
- console.warn("".concat(logPrefix, " No compatible media files found in VAST XML"));
519
- }
520
- return null;
521
- }
522
- var trackingUrls = {
523
- impression: [],
524
- start: [],
525
- firstQuartile: [],
526
- midpoint: [],
527
- thirdQuartile: [],
528
- complete: [],
529
- mute: [],
530
- unmute: [],
531
- pause: [],
532
- resume: [],
533
- fullscreen: [],
534
- exitFullscreen: [],
535
- skip: [],
536
- error: []
537
- };
538
- xmlDoc.querySelectorAll("Impression").forEach(function(el) {
539
- var _el_textContent;
540
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
541
- if (url) trackingUrls.impression.push(url);
542
- });
543
- xmlDoc.querySelectorAll("Tracking").forEach(function(el) {
544
- var _el_textContent;
545
- var event = el.getAttribute("event");
546
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
547
- if (event && url) {
548
- var eventKey = event;
549
- if (trackingUrls[eventKey]) {
550
- trackingUrls[eventKey].push(url);
551
- }
552
- }
553
- });
554
- 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();
555
- return {
556
- id: adId,
557
- title: title,
558
- duration: duration,
559
- mediaFiles: mediaFiles,
560
- trackingUrls: trackingUrls,
561
- clickThrough: clickThrough
562
- };
563
- } catch (error) {
564
- console.error("".concat(logPrefix, " Error parsing VAST XML:"), error);
565
- return null;
566
- }
567
- }
568
- function fetchAndParseVastAd(vastTagUrl) {
569
- var filter = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "all", logPrefix = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "[VastParser]";
570
- return _async_to_generator(function() {
571
- var response, vastXml;
572
- return _ts_generator(this, function(_state) {
573
- switch(_state.label){
574
- case 0:
575
- return [
576
- 4,
577
- fetch(vastTagUrl, {
578
- mode: "cors",
579
- credentials: "include",
580
- headers: {
581
- Accept: "application/xml, text/xml, */*"
582
- },
583
- referrerPolicy: "no-referrer-when-downgrade"
584
- })
585
- ];
586
- case 1:
587
- response = _state.sent();
588
- if (!response.ok) {
589
- throw new Error("Failed to fetch VAST: ".concat(response.statusText));
590
- }
591
- return [
592
- 4,
593
- response.text()
594
- ];
595
- case 2:
596
- vastXml = _state.sent();
597
- console.log("".concat(logPrefix, " VAST XML received"));
598
- console.log("".concat(logPrefix, " VAST XML content (first 2000 chars):"), vastXml.substring(0, 2e3));
599
- return [
600
- 2,
601
- parseVastXml(vastXml, filter, logPrefix)
602
- ];
603
- }
604
- });
605
- })();
606
- }
607
- function createEmptyTrackingState() {
608
- return {
609
- impression: false,
610
- start: false,
611
- firstQuartile: false,
612
- midpoint: false,
613
- thirdQuartile: false,
614
- complete: false
615
- };
616
- }
617
440
  function firePixelWithRetry(url) {
618
441
  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]";
619
442
  return _async_to_generator(function() {
@@ -736,16 +559,164 @@ function fireTrackingPixels(urls, sessionId) {
736
559
  }
737
560
  });
738
561
  }
739
- // src/sdk/vastManager.ts
740
- 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";
741
- var DEFAULT_TIMEOUT_MS = 5e3;
742
- var MAX_RETRIES = 3;
743
- var RETRY_BACKOFF_MS = 1500;
744
- function createVastManager() {
745
- var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
746
- var _options_debug;
747
- var initialized = false;
748
- var debug = (_options_debug = options.debug) !== null && _options_debug !== void 0 ? _options_debug : false;
562
+ // src/sdk/adstormPlayer.ts
563
+ var SUPPORTED_VIDEO_EXTENSIONS = [
564
+ ".mp4",
565
+ ".webm",
566
+ ".ogg",
567
+ ".m3u8",
568
+ ".ts"
569
+ ];
570
+ var UNSUPPORTED_VIDEO_EXTENSIONS = [
571
+ ".flv",
572
+ ".f4v",
573
+ ".swf",
574
+ ".wmv",
575
+ ".avi",
576
+ ".mov",
577
+ ".mkv"
578
+ ];
579
+ var REQUEST_TIMEOUT_MS = 5e3;
580
+ var REQUEST_MAX_RETRIES = 3;
581
+ var REQUEST_RETRY_BACKOFF_MS = 1500;
582
+ var AD_LAYER_Z_INDEX = "2147483646";
583
+ var COUNTDOWN_Z_INDEX = "2147483647";
584
+ var STALL_TIMEOUT_MS = 8e3;
585
+ function getFileExtension(url) {
586
+ try {
587
+ var pathname = new URL(url, "http://dummy").pathname;
588
+ var lastDot = pathname.lastIndexOf(".");
589
+ if (lastDot === -1) return "";
590
+ return pathname.slice(lastDot).toLowerCase();
591
+ } catch (unused) {
592
+ var lastDot1 = url.lastIndexOf(".");
593
+ if (lastDot1 === -1) return "";
594
+ var ext = url.slice(lastDot1).split(/[?#]/)[0];
595
+ return (ext || "").toLowerCase();
596
+ }
597
+ }
598
+ function isUnsupportedFormat(url) {
599
+ var ext = getFileExtension(url);
600
+ return UNSUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1;
601
+ }
602
+ function replaceFlvExtension(url) {
603
+ var ext = getFileExtension(url);
604
+ if (ext === ".flv") {
605
+ return url.replace(/\.flv(\?|$)/i, ".mp4$1");
606
+ }
607
+ return url;
608
+ }
609
+ function isSupportedFormat(url, mimeType) {
610
+ if (isUnsupportedFormat(url)) {
611
+ return false;
612
+ }
613
+ var ext = getFileExtension(url);
614
+ if (SUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1) {
615
+ return true;
616
+ }
617
+ if (ext === "" || ext === ".") {
618
+ return mimeType.includes("video/mp4") || mimeType.includes("video/webm") || mimeType.includes("m3u8") || mimeType.includes("application/x-mpegurl");
619
+ }
620
+ return false;
621
+ }
622
+ function createAdStormPlayer(contentVideo, options) {
623
+ var licenseKey = options.licenseKey, _options_debug = options.debug, debug = _options_debug === void 0 ? false : _options_debug;
624
+ var adPlaying = false;
625
+ var originalMutedState = false;
626
+ var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
627
+ var listeners = /* @__PURE__ */ new Map();
628
+ var adVideoElement;
629
+ var adContainerEl;
630
+ var adCountdownEl;
631
+ var currentAd;
632
+ var destroyed = false;
633
+ var tornDown = false;
634
+ var continueLiveStreamDuringAds = false;
635
+ var sessionId;
636
+ var adStallTimerId;
637
+ var adCountdownTimerId;
638
+ var adHideTimerId;
639
+ var lastCountdownSecond = -1;
640
+ var adListenersBound = false;
641
+ var parentPositionOverridden = false;
642
+ var adHandlers = {
643
+ timeupdate: function timeupdate() {
644
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
645
+ var progress = adVideoElement.currentTime / currentAd.duration;
646
+ if (progress >= 0.25 && !trackingFired.firstQuartile) {
647
+ trackingFired.firstQuartile = true;
648
+ fireTrackingPixels2(currentAd.trackingUrls.firstQuartile);
649
+ }
650
+ if (progress >= 0.5 && !trackingFired.midpoint) {
651
+ trackingFired.midpoint = true;
652
+ fireTrackingPixels2(currentAd.trackingUrls.midpoint);
653
+ }
654
+ if (progress >= 0.75 && !trackingFired.thirdQuartile) {
655
+ trackingFired.thirdQuartile = true;
656
+ fireTrackingPixels2(currentAd.trackingUrls.thirdQuartile);
657
+ }
658
+ updateAdCountdown();
659
+ },
660
+ playing: function playing() {
661
+ clearAdStallTimer();
662
+ if (!currentAd || trackingFired.start || destroyed || tornDown) return;
663
+ trackingFired.start = true;
664
+ fireTrackingPixels2(currentAd.trackingUrls.start);
665
+ startAdCountdown();
666
+ log("Ad started playing");
667
+ },
668
+ ended: function ended() {
669
+ if (!currentAd || trackingFired.complete || destroyed || tornDown) return;
670
+ trackingFired.complete = true;
671
+ fireTrackingPixels2(currentAd.trackingUrls.complete);
672
+ log("Ad completed");
673
+ handleAdComplete();
674
+ },
675
+ error: function error(e) {
676
+ if (destroyed || tornDown) return;
677
+ console.error("[AdStormPlayer] Ad video error:", e);
678
+ if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);
679
+ handleAdError();
680
+ },
681
+ waiting: function waiting() {
682
+ clearAdStallTimer();
683
+ adStallTimerId = setTimeout(function() {
684
+ adStallTimerId = void 0;
685
+ if (!adPlaying || destroyed || tornDown) return;
686
+ console.warn("[AdStormPlayer] Ad playback stalled too long");
687
+ handleAdError();
688
+ }, STALL_TIMEOUT_MS);
689
+ },
690
+ volumechange: function volumechange() {
691
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
692
+ if (adVideoElement.muted || adVideoElement.volume <= 0) {
693
+ fireTrackingPixels2(currentAd.trackingUrls.mute);
694
+ } else {
695
+ fireTrackingPixels2(currentAd.trackingUrls.unmute);
696
+ }
697
+ },
698
+ pause: function pause() {
699
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
700
+ if (!adVideoElement.ended) {
701
+ fireTrackingPixels2(currentAd.trackingUrls.pause);
702
+ }
703
+ },
704
+ play: function play() {
705
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
706
+ if (adVideoElement.currentTime > 0) {
707
+ fireTrackingPixels2(currentAd.trackingUrls.resume);
708
+ }
709
+ }
710
+ };
711
+ var trackingFired = {
712
+ impression: false,
713
+ start: false,
714
+ firstQuartile: false,
715
+ midpoint: false,
716
+ thirdQuartile: false,
717
+ complete: false
718
+ };
719
+ var preloadSlots = /* @__PURE__ */ new Map();
749
720
  function log() {
750
721
  for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
751
722
  args[_key] = arguments[_key];
@@ -753,58 +724,340 @@ function createVastManager() {
753
724
  if (debug) {
754
725
  var _console;
755
726
  (_console = console).log.apply(_console, [
756
- "[VastManager]"
727
+ "[AdStormPlayer]"
757
728
  ].concat(_to_consumable_array(args)));
758
729
  }
759
730
  }
760
- function warn() {
761
- for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
762
- args[_key] = arguments[_key];
731
+ function emit(event, payload) {
732
+ var set = listeners.get(event);
733
+ if (!set) return;
734
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
735
+ try {
736
+ for(var _iterator = Array.from(set)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
737
+ var fn = _step.value;
738
+ try {
739
+ fn(payload);
740
+ } catch (error) {
741
+ console.warn("[AdStormPlayer] Error in event listener for ".concat(event, ":"), error);
742
+ }
743
+ }
744
+ } catch (err) {
745
+ _didIteratorError = true;
746
+ _iteratorError = err;
747
+ } finally{
748
+ try {
749
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
750
+ _iterator.return();
751
+ }
752
+ } finally{
753
+ if (_didIteratorError) {
754
+ throw _iteratorError;
755
+ }
756
+ }
763
757
  }
764
- var _console;
765
- (_console = console).warn.apply(_console, [
766
- "[VastManager]"
767
- ].concat(_to_consumable_array(args)));
768
758
  }
769
- function initialize() {
770
- return _async_to_generator(function() {
771
- return _ts_generator(this, function(_state) {
772
- if (initialized) return [
773
- 2
774
- ];
775
- initialized = true;
776
- log("Initialized, VAST tag URL:", VAST_TAG_URL.split("?")[0]);
777
- return [
778
- 2
779
- ];
759
+ function fireTrackingPixels2(urls) {
760
+ fireTrackingPixels(urls, sessionId, "[AdStormPlayer]");
761
+ }
762
+ function clearAdStallTimer() {
763
+ if (adStallTimerId) {
764
+ clearTimeout(adStallTimerId);
765
+ adStallTimerId = void 0;
766
+ }
767
+ }
768
+ function clearAdCountdownTimer() {
769
+ if (adCountdownTimerId) {
770
+ clearInterval(adCountdownTimerId);
771
+ adCountdownTimerId = void 0;
772
+ }
773
+ lastCountdownSecond = -1;
774
+ }
775
+ function updateAdCountdown() {
776
+ if (!adCountdownEl || !adVideoElement || !currentAd || !adPlaying) return;
777
+ var remainingSec = Math.max(0, Math.ceil((currentAd.duration || 0) - adVideoElement.currentTime));
778
+ if (remainingSec === lastCountdownSecond) return;
779
+ lastCountdownSecond = remainingSec;
780
+ adCountdownEl.textContent = "Ad ".concat(remainingSec, "s");
781
+ emit("ad_countdown", {
782
+ remainingSec: remainingSec,
783
+ durationSec: currentAd.duration,
784
+ currentTimeSec: adVideoElement.currentTime
785
+ });
786
+ }
787
+ function startAdCountdown() {
788
+ clearAdCountdownTimer();
789
+ updateAdCountdown();
790
+ adCountdownTimerId = setInterval(updateAdCountdown, 250);
791
+ }
792
+ function generateSessionId() {
793
+ return "adstorm-".concat(Date.now(), "-").concat(Math.random().toString(36).slice(2, 10));
794
+ }
795
+ function bindAdEventListeners() {
796
+ if (!adVideoElement || adListenersBound) return;
797
+ adVideoElement.addEventListener("timeupdate", adHandlers.timeupdate);
798
+ adVideoElement.addEventListener("playing", adHandlers.playing);
799
+ adVideoElement.addEventListener("ended", adHandlers.ended);
800
+ adVideoElement.addEventListener("error", adHandlers.error);
801
+ adVideoElement.addEventListener("waiting", adHandlers.waiting);
802
+ adVideoElement.addEventListener("volumechange", adHandlers.volumechange);
803
+ adVideoElement.addEventListener("pause", adHandlers.pause);
804
+ adVideoElement.addEventListener("play", adHandlers.play);
805
+ adListenersBound = true;
806
+ }
807
+ function unbindAdEventListeners() {
808
+ if (!adVideoElement || !adListenersBound) return;
809
+ adVideoElement.removeEventListener("timeupdate", adHandlers.timeupdate);
810
+ adVideoElement.removeEventListener("playing", adHandlers.playing);
811
+ adVideoElement.removeEventListener("ended", adHandlers.ended);
812
+ adVideoElement.removeEventListener("error", adHandlers.error);
813
+ adVideoElement.removeEventListener("waiting", adHandlers.waiting);
814
+ adVideoElement.removeEventListener("volumechange", adHandlers.volumechange);
815
+ adVideoElement.removeEventListener("pause", adHandlers.pause);
816
+ adVideoElement.removeEventListener("play", adHandlers.play);
817
+ adListenersBound = false;
818
+ }
819
+ function teardownCurrentPlayback() {
820
+ unbindAdEventListeners();
821
+ clearAdStallTimer();
822
+ clearAdCountdownTimer();
823
+ if (!adVideoElement) return;
824
+ adVideoElement.pause();
825
+ adVideoElement.removeAttribute("src");
826
+ adVideoElement.load();
827
+ }
828
+ function buildVastUrl(durationSeconds, metadata) {
829
+ var baseUrl = "https://adstorm.co/api-adstorm-dev/adstorm/vast/".concat(licenseKey, "/pod");
830
+ var defaultMetadata = {
831
+ video: {
832
+ codec: "h264",
833
+ width: contentVideo.videoWidth || 1280,
834
+ height: contentVideo.videoHeight || 720,
835
+ fps: 29.97,
836
+ bitrate: 5e3,
837
+ profile: "high",
838
+ pix_fmt: "yuv420p",
839
+ has_b_frames: 0
840
+ },
841
+ audio: {
842
+ codec: "aac",
843
+ sample_rate: 48e3,
844
+ bitrate: 128
845
+ }
846
+ };
847
+ var finalMetadata = metadata || defaultMetadata;
848
+ var metadataStr = encodeURIComponent(JSON.stringify(finalMetadata));
849
+ return "".concat(baseUrl, "?duration=").concat(Math.ceil(durationSeconds), "&metadata=").concat(metadataStr);
850
+ }
851
+ function parseVastXml(xmlString) {
852
+ var ads = [];
853
+ try {
854
+ var parser = new DOMParser();
855
+ var xmlDoc = parser.parseFromString(xmlString, "text/xml");
856
+ var parserError = xmlDoc.querySelector("parsererror");
857
+ if (parserError) {
858
+ console.error("[AdStormPlayer] XML parsing error:", parserError.textContent);
859
+ return [];
860
+ }
861
+ var adElements = xmlDoc.querySelectorAll("Ad");
862
+ adElements.forEach(function(adElement) {
863
+ var _adElement_querySelector, _adElement_querySelector1, _adElement_querySelector_textContent, _adElement_querySelector2;
864
+ var adId = adElement.getAttribute("id") || "unknown";
865
+ var title = ((_adElement_querySelector = adElement.querySelector("AdTitle")) === null || _adElement_querySelector === void 0 ? void 0 : _adElement_querySelector.textContent) || "Ad";
866
+ var durationText = ((_adElement_querySelector1 = adElement.querySelector("Duration")) === null || _adElement_querySelector1 === void 0 ? void 0 : _adElement_querySelector1.textContent) || "00:00:30";
867
+ var durationParts = durationText.split(":");
868
+ var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseFloat(durationParts[2] || "0");
869
+ var mediaFileElements = adElement.querySelectorAll("MediaFile");
870
+ var mediaFiles = [];
871
+ mediaFileElements.forEach(function(mf) {
872
+ var _mf_textContent;
873
+ var type = mf.getAttribute("type") || "";
874
+ var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
875
+ var width = parseInt(mf.getAttribute("width") || "1920", 10);
876
+ var height = parseInt(mf.getAttribute("height") || "1080", 10);
877
+ var bitrate = mf.getAttribute("bitrate") ? parseInt(mf.getAttribute("bitrate"), 10) : void 0;
878
+ if (!url) {
879
+ log("Skipping empty MediaFile URL");
880
+ return;
881
+ }
882
+ var originalUrl = url;
883
+ url = replaceFlvExtension(url);
884
+ if (url !== originalUrl) {
885
+ log("Converted FLV to MP4: ".concat(originalUrl, " -> ").concat(url));
886
+ }
887
+ if (isUnsupportedFormat(url)) {
888
+ var ext = getFileExtension(url);
889
+ log("Skipping unsupported format: ".concat(url, " (extension: ").concat(ext, ", declared type: ").concat(type, ")"));
890
+ return;
891
+ }
892
+ if (isSupportedFormat(url, type)) {
893
+ mediaFiles.push({
894
+ url: url,
895
+ type: type,
896
+ width: width,
897
+ height: height,
898
+ bitrate: bitrate
899
+ });
900
+ log("Found media file: ".concat(url, " (").concat(type, ", ").concat(width, "x").concat(height, ")"));
901
+ } else {
902
+ log("Skipping incompatible media file: ".concat(url, " (type: ").concat(type, ")"));
903
+ }
904
+ });
905
+ if (mediaFiles.length === 0) {
906
+ log("No valid media files found in ad:", adId);
907
+ return;
908
+ }
909
+ var trackingUrls = {
910
+ impression: [],
911
+ start: [],
912
+ firstQuartile: [],
913
+ midpoint: [],
914
+ thirdQuartile: [],
915
+ complete: [],
916
+ mute: [],
917
+ unmute: [],
918
+ pause: [],
919
+ resume: [],
920
+ error: []
921
+ };
922
+ adElement.querySelectorAll("Impression").forEach(function(el) {
923
+ var _el_textContent;
924
+ var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
925
+ if (url) trackingUrls.impression.push(url);
926
+ });
927
+ adElement.querySelectorAll("Tracking").forEach(function(el) {
928
+ var _el_textContent;
929
+ var event = el.getAttribute("event");
930
+ var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
931
+ if (event && url) {
932
+ var eventKey = event;
933
+ if (trackingUrls[eventKey]) {
934
+ trackingUrls[eventKey].push(url);
935
+ }
936
+ }
937
+ });
938
+ 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();
939
+ ads.push({
940
+ id: adId,
941
+ title: title,
942
+ duration: duration,
943
+ mediaFiles: mediaFiles,
944
+ trackingUrls: trackingUrls,
945
+ clickThrough: clickThrough
946
+ });
947
+ log("Parsed ad: ".concat(title, ", duration: ").concat(duration, "s, media files: ").concat(mediaFiles.length));
780
948
  });
781
- })();
949
+ } catch (error) {
950
+ console.error("[AdStormPlayer] Error parsing VAST XML:", error);
951
+ }
952
+ return ads;
953
+ }
954
+ function selectBestMediaFile(mediaFiles) {
955
+ if (mediaFiles.length === 0) return null;
956
+ if (mediaFiles.length === 1) return mediaFiles[0];
957
+ var mp4Files = mediaFiles.filter(function(mf) {
958
+ return mf.type.includes("video/mp4");
959
+ });
960
+ var candidates = mp4Files.length > 0 ? mp4Files : mediaFiles;
961
+ var targetWidth = contentVideo.videoWidth || 1280;
962
+ var targetHeight = contentVideo.videoHeight || 720;
963
+ candidates.sort(function(a, b) {
964
+ var diffA = Math.abs(a.width - targetWidth) + Math.abs(a.height - targetHeight);
965
+ var diffB = Math.abs(b.width - targetWidth) + Math.abs(b.height - targetHeight);
966
+ return diffA - diffB;
967
+ });
968
+ return candidates[0] || null;
969
+ }
970
+ function createAdVideoElement() {
971
+ var video = document.createElement("video");
972
+ video.style.position = "absolute";
973
+ video.style.left = "0";
974
+ video.style.top = "0";
975
+ video.style.width = "100%";
976
+ video.style.height = "100%";
977
+ video.style.objectFit = "contain";
978
+ video.style.backgroundColor = "#000";
979
+ video.style.zIndex = "1";
980
+ video.playsInline = true;
981
+ video.preload = "auto";
982
+ video.muted = originalMutedState;
983
+ video.volume = originalMutedState ? 0 : originalVolume;
984
+ return video;
985
+ }
986
+ function setAdPlayingFlag(isPlaying) {
987
+ if (isPlaying) {
988
+ contentVideo.dataset.stormcloudAdPlaying = "true";
989
+ } else {
990
+ delete contentVideo.dataset.stormcloudAdPlaying;
991
+ }
992
+ }
993
+ function setupAdEventListeners() {
994
+ bindAdEventListeners();
995
+ }
996
+ function handleAdComplete() {
997
+ if (destroyed || tornDown) return;
998
+ log("Handling ad completion");
999
+ adPlaying = false;
1000
+ setAdPlayingFlag(false);
1001
+ clearAdStallTimer();
1002
+ clearAdCountdownTimer();
1003
+ if (adContainerEl) {
1004
+ adContainerEl.style.opacity = "0";
1005
+ adHideTimerId = setTimeout(function() {
1006
+ if (adContainerEl) {
1007
+ adContainerEl.style.display = "none";
1008
+ adContainerEl.style.pointerEvents = "none";
1009
+ }
1010
+ }, 300);
1011
+ }
1012
+ contentVideo.style.visibility = "visible";
1013
+ contentVideo.style.opacity = "1";
1014
+ contentVideo.muted = originalMutedState;
1015
+ contentVideo.volume = originalVolume;
1016
+ currentAd = void 0;
1017
+ emit("content_resume");
1018
+ emit("all_ads_completed");
1019
+ }
1020
+ function handleAdError() {
1021
+ if (destroyed || tornDown) return;
1022
+ log("Handling ad error");
1023
+ if (!adPlaying) return;
1024
+ adPlaying = false;
1025
+ setAdPlayingFlag(false);
1026
+ clearAdStallTimer();
1027
+ clearAdCountdownTimer();
1028
+ contentVideo.muted = originalMutedState;
1029
+ contentVideo.volume = originalVolume;
1030
+ contentVideo.style.visibility = "visible";
1031
+ contentVideo.style.opacity = "1";
1032
+ if (adContainerEl) {
1033
+ adContainerEl.style.display = "none";
1034
+ adContainerEl.style.pointerEvents = "none";
1035
+ }
1036
+ currentAd = void 0;
1037
+ emit("ad_error");
1038
+ emit("content_resume");
782
1039
  }
783
- function requestBids(_context) {
1040
+ function fetchVastOnce(durationSeconds) {
784
1041
  return _async_to_generator(function() {
785
- var correlator, url, controller, timeoutId, _ref, _ref1, _vastAd_mediaFiles_, _vastAd_mediaFiles_1, fetchOptions, response, vastXml, vastAd, bid, error;
1042
+ var vastUrl, controller, timeoutId, requestInit, response, xmlText;
786
1043
  return _ts_generator(this, function(_state) {
787
1044
  switch(_state.label){
788
1045
  case 0:
789
- if (!initialized) {
790
- throw new Error("VastManager not initialized. Call initialize() first.");
791
- }
792
- correlator = Math.floor(Math.random() * 1e12).toString();
793
- url = VAST_TAG_URL.replace("[placeholder]", correlator);
794
- log("Fetching VAST tag, correlator:", correlator);
1046
+ vastUrl = buildVastUrl(durationSeconds);
1047
+ log("Fetching VAST from:", vastUrl);
795
1048
  controller = typeof AbortController !== "undefined" ? new AbortController() : null;
796
1049
  timeoutId = setTimeout(function() {
797
1050
  return controller === null || controller === void 0 ? void 0 : controller.abort();
798
- }, DEFAULT_TIMEOUT_MS);
1051
+ }, REQUEST_TIMEOUT_MS);
799
1052
  _state.label = 1;
800
1053
  case 1:
801
1054
  _state.trys.push([
802
1055
  1,
803
- 4,
804
1056
  ,
1057
+ 4,
805
1058
  5
806
1059
  ]);
807
- fetchOptions = {
1060
+ requestInit = {
808
1061
  method: "GET",
809
1062
  mode: "cors",
810
1063
  credentials: "omit",
@@ -813,62 +1066,34 @@ function createVastManager() {
813
1066
  },
814
1067
  referrerPolicy: "no-referrer-when-downgrade"
815
1068
  };
816
- if (controller) fetchOptions.signal = controller.signal;
1069
+ if (controller) {
1070
+ requestInit.signal = controller.signal;
1071
+ }
817
1072
  return [
818
1073
  4,
819
- fetch(url, fetchOptions)
1074
+ fetch(vastUrl, requestInit)
820
1075
  ];
821
1076
  case 2:
822
1077
  response = _state.sent();
823
- clearTimeout(timeoutId);
824
1078
  if (!response.ok) {
825
- throw new Error("VAST request returned HTTP ".concat(response.status));
1079
+ throw new Error("Failed to fetch VAST: ".concat(response.status, " ").concat(response.statusText));
826
1080
  }
827
1081
  return [
828
1082
  4,
829
1083
  response.text()
830
1084
  ];
831
1085
  case 3:
832
- vastXml = _state.sent();
833
- log("VAST XML received, length:", vastXml.length);
834
- vastAd = parseVastXml(vastXml, "mp4-first", "[VastManager]");
835
- if (!vastAd) {
836
- log("VAST parsed but no usable ad found");
837
- return [
838
- 2,
839
- []
840
- ];
841
- }
842
- log("Ad parsed: id=".concat(vastAd.id, ", duration=").concat(vastAd.duration, "s, mediaFiles=").concat(vastAd.mediaFiles.length));
843
- bid = {
844
- bidder: "vast-direct",
845
- cpm: 0,
846
- vastXml: vastXml,
847
- width: (_ref = (_vastAd_mediaFiles_ = vastAd.mediaFiles[0]) === null || _vastAd_mediaFiles_ === void 0 ? void 0 : _vastAd_mediaFiles_.width) !== null && _ref !== void 0 ? _ref : 0,
848
- 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,
849
- adId: vastAd.id,
850
- impId: correlator,
851
- creativeId: vastAd.id,
852
- currency: "USD",
853
- durationSec: vastAd.duration
854
- };
1086
+ xmlText = _state.sent();
1087
+ log("VAST response received, length:", xmlText.length);
855
1088
  return [
856
1089
  2,
857
- [
858
- bid
859
- ]
1090
+ parseVastXml(xmlText)
860
1091
  ];
861
1092
  case 4:
862
- error = _state.sent();
863
1093
  clearTimeout(timeoutId);
864
- if ((error === null || error === void 0 ? void 0 : error.name) === "AbortError") {
865
- warn("VAST request timed out after ".concat(DEFAULT_TIMEOUT_MS, "ms"));
866
- return [
867
- 2,
868
- []
869
- ];
870
- }
871
- throw error;
1094
+ return [
1095
+ 7
1096
+ ];
872
1097
  case 5:
873
1098
  return [
874
1099
  2
@@ -877,14 +1102,14 @@ function createVastManager() {
877
1102
  });
878
1103
  })();
879
1104
  }
880
- function requestBidsUntilResponse(context) {
1105
+ function fetchVast(durationSeconds) {
881
1106
  return _async_to_generator(function() {
882
1107
  var _loop, lastError, attempt, _ret;
883
1108
  return _ts_generator(this, function(_state) {
884
1109
  switch(_state.label){
885
1110
  case 0:
886
1111
  _loop = function(attempt) {
887
- var bids, err, delay;
1112
+ var ads, error, delay;
888
1113
  return _ts_generator(this, function(_state) {
889
1114
  switch(_state.label){
890
1115
  case 0:
@@ -896,39 +1121,39 @@ function createVastManager() {
896
1121
  ]);
897
1122
  return [
898
1123
  4,
899
- requestBids(context)
1124
+ fetchVastOnce(durationSeconds)
900
1125
  ];
901
1126
  case 1:
902
- bids = _state.sent();
903
- if (bids.length > 0) {
904
- log("requestBidsUntilResponse: got ".concat(bids.length, " ad(s) on attempt ").concat(attempt));
905
- return [
906
- 2,
907
- {
908
- v: bids
909
- }
910
- ];
911
- }
912
- log("requestBidsUntilResponse: no ads on attempt ".concat(attempt, "/").concat(MAX_RETRIES));
1127
+ ads = _state.sent();
1128
+ if (ads.length > 0) return [
1129
+ 2,
1130
+ {
1131
+ v: ads
1132
+ }
1133
+ ];
1134
+ log("No ad returned from VAST on attempt ".concat(attempt, "/").concat(REQUEST_MAX_RETRIES));
913
1135
  return [
914
1136
  3,
915
1137
  3
916
1138
  ];
917
1139
  case 2:
918
- err = _state.sent();
919
- lastError = err;
920
- warn("requestBidsUntilResponse: attempt ".concat(attempt, "/").concat(MAX_RETRIES, " failed:"), err);
1140
+ error = _state.sent();
1141
+ lastError = error;
1142
+ if ((error === null || error === void 0 ? void 0 : error.name) === "AbortError") {
1143
+ console.warn("[AdStormPlayer] VAST request timed out (".concat(REQUEST_TIMEOUT_MS, "ms), attempt ").concat(attempt, "/").concat(REQUEST_MAX_RETRIES));
1144
+ } else {
1145
+ console.warn("[AdStormPlayer] VAST request failed on attempt ".concat(attempt, "/").concat(REQUEST_MAX_RETRIES, ":"), error);
1146
+ }
921
1147
  return [
922
1148
  3,
923
1149
  3
924
1150
  ];
925
1151
  case 3:
926
- if (!(attempt < MAX_RETRIES)) return [
1152
+ if (!(attempt < REQUEST_MAX_RETRIES)) return [
927
1153
  3,
928
1154
  5
929
1155
  ];
930
- delay = RETRY_BACKOFF_MS * attempt;
931
- log("requestBidsUntilResponse: waiting ".concat(delay, "ms before retry"));
1156
+ delay = REQUEST_RETRY_BACKOFF_MS * attempt;
932
1157
  return [
933
1158
  4,
934
1159
  new Promise(function(resolve) {
@@ -945,13 +1170,10 @@ function createVastManager() {
945
1170
  }
946
1171
  });
947
1172
  };
948
- if (!initialized) {
949
- throw new Error("VastManager not initialized. Call initialize() first.");
950
- }
951
1173
  attempt = 1;
952
1174
  _state.label = 1;
953
1175
  case 1:
954
- if (!(attempt <= MAX_RETRIES)) return [
1176
+ if (!(attempt <= REQUEST_MAX_RETRIES)) return [
955
1177
  3,
956
1178
  4
957
1179
  ];
@@ -973,7 +1195,9 @@ function createVastManager() {
973
1195
  1
974
1196
  ];
975
1197
  case 4:
976
- if (_instanceof(lastError, Error)) throw lastError;
1198
+ if (_instanceof(lastError, Error)) {
1199
+ throw lastError;
1200
+ }
977
1201
  return [
978
1202
  2,
979
1203
  []
@@ -982,971 +1206,468 @@ function createVastManager() {
982
1206
  });
983
1207
  })();
984
1208
  }
985
- function destroy() {
986
- initialized = false;
987
- log("Destroyed");
988
- }
989
- return {
990
- initialize: initialize,
991
- requestBids: requestBids,
992
- requestBidsUntilResponse: requestBidsUntilResponse,
993
- destroy: destroy,
994
- get isInitialized () {
995
- return initialized;
996
- }
997
- };
998
- }
999
- // src/sdk/vastAdLayer.ts
1000
- var import_hls = __toESM(require("hls.js"), 1);
1001
- var LOG = "[VastAdLayer]";
1002
- function resolveBidToVastAd(winner, logPrefix) {
1003
- if (winner.vastXml) {
1004
- var ad = parseVastXml(winner.vastXml, "mp4-first", logPrefix);
1005
- return Promise.resolve(ad);
1006
- }
1007
- if (winner.vastUrl) {
1008
- return fetchAndParseVastAd(winner.vastUrl, "mp4-first", logPrefix);
1009
- }
1010
- return Promise.resolve(null);
1011
- }
1012
- function createVastAdLayer(contentVideo, options) {
1013
- var _ref, _ref1, _ref2, _ref3, _ref4;
1014
- var adPlaying = false;
1015
- var originalMutedState = false;
1016
- var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
1017
- var listeners = /* @__PURE__ */ new Map();
1018
- var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
1019
- var continueLiveStreamDuringAds = (_ref = options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) !== null && _ref !== void 0 ? _ref : false;
1020
- var smartTVMode = (_ref1 = options === null || options === void 0 ? void 0 : options.smartTVMode) !== null && _ref1 !== void 0 ? _ref1 : false;
1021
- var singleElementMode = (_ref2 = options === null || options === void 0 ? void 0 : options.singleElementMode) !== null && _ref2 !== void 0 ? _ref2 : false;
1022
- var forceMP4Ads = (_ref3 = options === null || options === void 0 ? void 0 : options.forceMP4Ads) !== null && _ref3 !== void 0 ? _ref3 : smartTVMode || singleElementMode;
1023
- var debug = (_ref4 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref4 !== void 0 ? _ref4 : false;
1024
- var adVideoElement;
1025
- var adHls;
1026
- var adContainerEl;
1027
- var currentAd;
1028
- var sessionId;
1029
- var destroyed = false;
1030
- var tornDown = false;
1031
- var trackingFired = createEmptyTrackingState();
1032
- var adStallTimerId;
1033
- var savedContentVideoStyles;
1034
- var currentAdEventHandlers;
1035
- var preloadSlots = /* @__PURE__ */ new Map();
1036
- function emit(event, payload) {
1037
- var set = listeners.get(event);
1038
- if (!set) return;
1039
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1040
- try {
1041
- for(var _iterator = Array.from(set)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1042
- var fn = _step.value;
1043
- try {
1044
- fn(payload);
1045
- } catch (error) {
1046
- console.warn("".concat(LOG, " Error in event listener for ").concat(event, ":"), error);
1047
- }
1048
- }
1049
- } catch (err) {
1050
- _didIteratorError = true;
1051
- _iteratorError = err;
1052
- } finally{
1053
- try {
1054
- if (!_iteratorNormalCompletion && _iterator.return != null) {
1055
- _iterator.return();
1056
- }
1057
- } finally{
1058
- if (_didIteratorError) {
1059
- throw _iteratorError;
1060
- }
1061
- }
1062
- }
1063
- }
1064
- function generateSessionId() {
1065
- return "session-".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
1066
- }
1067
- function fireTrackingPixels2(urls) {
1068
- fireTrackingPixels(urls, sessionId, LOG);
1069
- }
1070
- function getMainStreamQuality() {
1071
- if (!(mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.levels)) return null;
1072
- var currentLevel = mainHlsInstance.currentLevel;
1073
- if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {
1074
- var autoLevel = mainHlsInstance.loadLevel;
1075
- if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {
1076
- var level2 = mainHlsInstance.levels[autoLevel];
1077
- return {
1078
- width: level2.width || 1920,
1079
- height: level2.height || 1080,
1080
- bitrate: level2.bitrate || 5e6
1081
- };
1082
- }
1083
- return null;
1084
- }
1085
- var level = mainHlsInstance.levels[currentLevel];
1086
- return {
1087
- width: level.width || 1920,
1088
- height: level.height || 1080,
1089
- bitrate: level.bitrate || 5e6
1090
- };
1091
- }
1092
- function selectBestMediaFile(mediaFiles) {
1093
- var _ref;
1094
- var _scoredFiles_;
1095
- if (mediaFiles.length === 0) throw new Error("No media files available");
1096
- var candidates = mediaFiles;
1097
- if (forceMP4Ads) {
1098
- var mp4Only = candidates.filter(function(f) {
1099
- return !isHlsMediaFile(f);
1100
- });
1101
- if (mp4Only.length > 0) {
1102
- candidates = mp4Only;
1103
- if (debug) console.log("".concat(LOG, " forceMP4Ads: filtered to ").concat(mp4Only.length, " MP4-only file(s)"));
1104
- } else if (debug) {
1105
- console.warn("".concat(LOG, " forceMP4Ads: no MP4 files available, falling back to all media files"));
1106
- }
1107
- } else {
1108
- var mp4Only1 = candidates.filter(function(f) {
1109
- return !isHlsMediaFile(f);
1110
- });
1111
- if (mp4Only1.length > 0) {
1112
- candidates = mp4Only1;
1113
- if (debug) console.log("".concat(LOG, " Preferring ").concat(mp4Only1.length, " MP4 file(s) over HLS (mp4-first)"));
1114
- }
1115
- }
1116
- var firstFile = candidates[0];
1117
- if (candidates.length === 1) return firstFile;
1118
- var mainQuality = getMainStreamQuality();
1119
- if (!mainQuality) {
1120
- if (debug) console.log("".concat(LOG, " No main stream quality info, using first media file"));
1121
- return firstFile;
1122
- }
1123
- var scoredFiles = candidates.map(function(file) {
1124
- var widthDiff = Math.abs(file.width - mainQuality.width);
1125
- var heightDiff = Math.abs(file.height - mainQuality.height);
1126
- var resolutionDiff = widthDiff + heightDiff;
1127
- var fileBitrate = (file.bitrate || 5e3) * 1e3;
1128
- var bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);
1129
- var score = resolutionDiff * 2 + bitrateDiff / 1e3;
1130
- return {
1131
- file: file,
1132
- score: score
1133
- };
1134
- });
1135
- scoredFiles.sort(function(a, b) {
1136
- return a.score - b.score;
1137
- });
1138
- return (_ref = (_scoredFiles_ = scoredFiles[0]) === null || _scoredFiles_ === void 0 ? void 0 : _scoredFiles_.file) !== null && _ref !== void 0 ? _ref : firstFile;
1139
- }
1140
- function isHlsMediaFile(file) {
1141
- return file.type === "application/x-mpegURL" || file.type.includes("m3u8");
1142
- }
1143
- function createAdVideoElement() {
1144
- var video = document.createElement("video");
1145
- video.style.position = "absolute";
1146
- video.style.left = "0";
1147
- video.style.top = "0";
1148
- video.style.width = "100%";
1149
- video.style.height = "100%";
1150
- video.style.objectFit = "cover";
1151
- video.style.backgroundColor = "#000";
1152
- video.playsInline = true;
1153
- video.muted = false;
1154
- video.volume = 1;
1155
- return video;
1156
- }
1157
- function clearAdStallTimer() {
1158
- if (adStallTimerId != null) {
1159
- clearTimeout(adStallTimerId);
1160
- adStallTimerId = void 0;
1161
- }
1162
- }
1163
- function removeAdEventListeners() {
1164
- clearAdStallTimer();
1165
- if (!currentAdEventHandlers || !adVideoElement) return;
1166
- var el = adVideoElement;
1167
- el.removeEventListener("timeupdate", currentAdEventHandlers.timeupdate);
1168
- el.removeEventListener("playing", currentAdEventHandlers.playing);
1169
- el.removeEventListener("ended", currentAdEventHandlers.ended);
1170
- el.removeEventListener("error", currentAdEventHandlers.error);
1171
- el.removeEventListener("volumechange", currentAdEventHandlers.volumechange);
1172
- el.removeEventListener("pause", currentAdEventHandlers.pause);
1173
- el.removeEventListener("play", currentAdEventHandlers.play);
1174
- el.removeEventListener("waiting", currentAdEventHandlers.waiting);
1175
- currentAdEventHandlers = void 0;
1176
- }
1177
- function setupAdEventListeners() {
1178
- if (!adVideoElement) return;
1179
- removeAdEventListeners();
1180
- var handlers = {
1181
- timeupdate: function timeupdate() {
1182
- var ad = currentAd;
1183
- if (!ad || !adVideoElement) return;
1184
- var progress = adVideoElement.currentTime / ad.duration;
1185
- if (progress >= 0.25 && !trackingFired.firstQuartile) {
1186
- trackingFired.firstQuartile = true;
1187
- fireTrackingPixels2(ad.trackingUrls.firstQuartile);
1188
- }
1189
- if (progress >= 0.5 && !trackingFired.midpoint) {
1190
- trackingFired.midpoint = true;
1191
- fireTrackingPixels2(ad.trackingUrls.midpoint);
1192
- }
1193
- if (progress >= 0.75 && !trackingFired.thirdQuartile) {
1194
- trackingFired.thirdQuartile = true;
1195
- fireTrackingPixels2(ad.trackingUrls.thirdQuartile);
1196
- }
1197
- },
1198
- playing: function playing() {
1199
- clearAdStallTimer();
1200
- var ad = currentAd;
1201
- if (!ad || trackingFired.start) return;
1202
- trackingFired.start = true;
1203
- fireTrackingPixels2(ad.trackingUrls.start);
1204
- if (debug) console.log("".concat(LOG, " Ad started playing"));
1205
- },
1206
- ended: function ended() {
1207
- if (tornDown || !currentAd || trackingFired.complete) return;
1208
- trackingFired.complete = true;
1209
- fireTrackingPixels2(currentAd.trackingUrls.complete);
1210
- if (debug) console.log("".concat(LOG, " Ad completed"));
1211
- handleAdComplete();
1212
- },
1213
- error: function error(e) {
1214
- if (tornDown) return;
1215
- console.error("".concat(LOG, " Ad video error:"), e);
1216
- if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);
1217
- handleAdError();
1218
- },
1219
- volumechange: function volumechange() {
1220
- if (!currentAd || !adVideoElement) return;
1221
- if (adVideoElement.muted) {
1222
- fireTrackingPixels2(currentAd.trackingUrls.mute);
1223
- } else {
1224
- fireTrackingPixels2(currentAd.trackingUrls.unmute);
1225
- }
1226
- },
1227
- pause: function pause() {
1228
- if (currentAd && adVideoElement && !adVideoElement.ended) {
1229
- fireTrackingPixels2(currentAd.trackingUrls.pause);
1230
- }
1231
- },
1232
- play: function play() {
1233
- if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1234
- fireTrackingPixels2(currentAd.trackingUrls.resume);
1235
- }
1236
- },
1237
- waiting: function waiting() {
1238
- clearAdStallTimer();
1239
- adStallTimerId = setTimeout(function() {
1240
- adStallTimerId = void 0;
1241
- if (adPlaying) {
1242
- if (debug) console.warn("".concat(LOG, " Ad video stalled for too long, treating as error"));
1243
- handleAdError();
1244
- }
1245
- }, 8e3);
1246
- }
1247
- };
1248
- adVideoElement.addEventListener("timeupdate", handlers.timeupdate);
1249
- adVideoElement.addEventListener("playing", handlers.playing);
1250
- adVideoElement.addEventListener("ended", handlers.ended);
1251
- adVideoElement.addEventListener("error", handlers.error);
1252
- adVideoElement.addEventListener("volumechange", handlers.volumechange);
1253
- adVideoElement.addEventListener("pause", handlers.pause);
1254
- adVideoElement.addEventListener("play", handlers.play);
1255
- adVideoElement.addEventListener("waiting", handlers.waiting);
1256
- currentAdEventHandlers = handlers;
1257
- }
1258
- function setAdPlayingFlag(isPlaying) {
1259
- if (isPlaying) {
1260
- contentVideo.dataset.stormcloudAdPlaying = "true";
1261
- } else {
1262
- delete contentVideo.dataset.stormcloudAdPlaying;
1263
- }
1264
- }
1265
- function applyContentVideoAdCoverStyles() {
1266
- if (!singleElementMode) return;
1267
- savedContentVideoStyles = {
1268
- objectFit: contentVideo.style.objectFit,
1269
- width: contentVideo.style.width,
1270
- height: contentVideo.style.height
1271
- };
1272
- contentVideo.style.objectFit = "cover";
1273
- contentVideo.style.width = "100%";
1274
- contentVideo.style.height = "100%";
1275
- }
1276
- function restoreContentVideoStyles() {
1277
- if (!singleElementMode || !savedContentVideoStyles) return;
1278
- contentVideo.style.objectFit = savedContentVideoStyles.objectFit;
1279
- contentVideo.style.width = savedContentVideoStyles.width;
1280
- contentVideo.style.height = savedContentVideoStyles.height;
1281
- savedContentVideoStyles = void 0;
1282
- }
1283
- function handleAdComplete() {
1284
- if (tornDown) return;
1285
- clearAdStallTimer();
1286
- if (debug) console.log("".concat(LOG, " Handling ad completion"));
1287
- adPlaying = false;
1288
- setAdPlayingFlag(false);
1289
- restoreContentVideoStyles();
1290
- if (adContainerEl) {
1291
- adContainerEl.style.display = "none";
1292
- adContainerEl.style.pointerEvents = "none";
1293
- }
1294
- emit("ad_impression");
1295
- emit("content_resume");
1296
- }
1297
- function handleAdError() {
1298
- if (tornDown) return;
1299
- if (!adPlaying) return;
1300
- clearAdStallTimer();
1301
- if (debug) console.log("".concat(LOG, " Handling ad error"));
1302
- adPlaying = false;
1303
- setAdPlayingFlag(false);
1304
- restoreContentVideoStyles();
1305
- if (adContainerEl) {
1306
- adContainerEl.style.display = "none";
1307
- adContainerEl.style.pointerEvents = "none";
1308
- }
1309
- emit("ad_error");
1310
- }
1311
- function teardownCurrentPlayback() {
1312
- removeAdEventListeners();
1313
- if (adHls) {
1314
- adHls.destroy();
1315
- adHls = void 0;
1316
- }
1317
- if (adVideoElement) {
1318
- if (singleElementMode && adVideoElement === contentVideo) {
1319
- contentVideo.pause();
1320
- } else {
1321
- adVideoElement.pause();
1322
- adVideoElement.removeAttribute("src");
1323
- adVideoElement.load();
1324
- }
1209
+ function getDurationSecondsFromContext(requestContext) {
1210
+ var _ctx_remainingBreakSec;
1211
+ if (!requestContext || (typeof requestContext === "undefined" ? "undefined" : _type_of(requestContext)) !== "object") {
1212
+ return 30;
1325
1213
  }
1326
- }
1327
- function startNativePlayback(mediaFile) {
1328
- if (!adVideoElement) return;
1329
- if (debug) console.log("".concat(LOG, " Starting native MP4 playback: ").concat(mediaFile.url));
1330
- adVideoElement.src = mediaFile.url;
1331
- adVideoElement.load();
1332
- adVideoElement.play().catch(function(error) {
1333
- console.error("".concat(LOG, " Error starting native ad playback:"), error);
1334
- handleAdError();
1335
- });
1336
- }
1337
- function startHlsPlayback(mediaFile) {
1338
- if (!adVideoElement) return;
1339
- if (debug) console.log("".concat(LOG, " Starting HLS playback: ").concat(mediaFile.url));
1340
- if (import_hls.default.isSupported()) {
1341
- if (adHls) {
1342
- adHls.destroy();
1343
- adHls = void 0;
1344
- }
1345
- adHls = new import_hls.default({
1346
- enableWorker: true,
1347
- lowLatencyMode: false
1348
- });
1349
- adHls.loadSource(mediaFile.url);
1350
- adHls.attachMedia(adVideoElement);
1351
- adHls.on(import_hls.default.Events.MANIFEST_PARSED, function() {
1352
- if (!adPlaying) return;
1353
- adVideoElement.play().catch(function(error) {
1354
- console.error("".concat(LOG, " Error starting HLS ad playback:"), error);
1355
- handleAdError();
1356
- });
1357
- });
1358
- var nonFatalNetworkErrors = 0;
1359
- adHls.on(import_hls.default.Events.ERROR, function(_event, data) {
1360
- if (data.fatal) {
1361
- handleAdError();
1362
- } else if (data.type === import_hls.default.ErrorTypes.NETWORK_ERROR) {
1363
- nonFatalNetworkErrors++;
1364
- if (nonFatalNetworkErrors >= 3) {
1365
- if (debug) console.warn("".concat(LOG, " Too many non-fatal HLS network errors (").concat(nonFatalNetworkErrors, "), treating as fatal"));
1366
- handleAdError();
1367
- }
1368
- }
1369
- });
1370
- } else if (adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
1371
- adVideoElement.src = mediaFile.url;
1372
- adVideoElement.play().catch(function(error) {
1373
- console.error("".concat(LOG, " Error starting native HLS ad playback:"), error);
1374
- handleAdError();
1375
- });
1376
- } else {
1377
- console.error("".concat(LOG, " HLS not supported on this platform"));
1378
- handleAdError();
1379
- }
1380
- }
1381
- function startPlayback(mediaFile) {
1382
- if (!adVideoElement) return;
1383
- if (singleElementMode && isHlsMediaFile(mediaFile)) {
1384
- var mp4Fallback = currentAd === null || currentAd === void 0 ? void 0 : currentAd.mediaFiles.find(function(f) {
1385
- return !isHlsMediaFile(f);
1386
- });
1387
- if (mp4Fallback) {
1388
- if (debug) console.log("".concat(LOG, " singleElementMode: HLS ad blocked, using MP4 fallback"));
1389
- startNativePlayback(mp4Fallback);
1390
- return;
1391
- }
1392
- }
1393
- if (isHlsMediaFile(mediaFile)) {
1394
- startHlsPlayback(mediaFile);
1395
- } else {
1396
- startNativePlayback(mediaFile);
1214
+ var ctx = requestContext;
1215
+ var value = (_ctx_remainingBreakSec = ctx.remainingBreakSec) !== null && _ctx_remainingBreakSec !== void 0 ? _ctx_remainingBreakSec : ctx.breakDurationSec;
1216
+ if (typeof value !== "number" || Number.isNaN(value)) {
1217
+ return 30;
1397
1218
  }
1219
+ return Math.max(1, Math.ceil(value));
1398
1220
  }
1399
- function playAd(bids) {
1221
+ function requestAdFromApi(requestContext) {
1400
1222
  return _async_to_generator(function() {
1401
- var winner, ad, contentVolume, adVolume2, mediaFile2, _contentVideo_parentElement, container, adVolume, mediaFile;
1223
+ var durationSeconds, ads;
1402
1224
  return _ts_generator(this, function(_state) {
1403
1225
  switch(_state.label){
1404
1226
  case 0:
1405
- if (destroyed) {
1406
- return [
1407
- 2,
1408
- Promise.reject(new Error("Layer has been destroyed"))
1409
- ];
1410
- }
1411
- if (bids.length === 0) {
1412
- return [
1413
- 2,
1414
- Promise.reject(new Error("No bids provided"))
1415
- ];
1416
- }
1417
- winner = bids[0];
1418
- if (debug) {
1419
- console.log("".concat(LOG, " Winning bid: ").concat(winner.bidder, " $").concat(winner.cpm.toFixed(2), " ").concat(winner.currency));
1420
- }
1227
+ durationSeconds = getDurationSecondsFromContext(requestContext);
1421
1228
  return [
1422
1229
  4,
1423
- resolveBidToVastAd(winner, LOG)
1230
+ fetchVast(durationSeconds)
1424
1231
  ];
1425
1232
  case 1:
1426
- ad = _state.sent();
1427
- if (!ad) {
1428
- if (debug) console.warn("".concat(LOG, " Winning bid has no VAST URL or XML"));
1429
- emit("ad_error");
1430
- return [
1431
- 2,
1432
- Promise.reject(new Error("No VAST from bid"))
1433
- ];
1434
- }
1435
- if (debug) {
1436
- console.log("".concat(LOG, " Ad parsed: ").concat(ad.title, ", duration: ").concat(ad.duration, "s, mediaFiles: ").concat(ad.mediaFiles.length));
1437
- }
1438
- sessionId = generateSessionId();
1439
- currentAd = ad;
1440
- trackingFired = _object_spread({}, createEmptyTrackingState());
1441
- fireTrackingPixels2(ad.trackingUrls.impression);
1442
- trackingFired.impression = true;
1443
- contentVolume = contentVideo.volume;
1444
- originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1445
- if (!singleElementMode) return [
1446
- 3,
1447
- 3
1448
- ];
1449
- mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.detachMedia();
1450
- teardownCurrentPlayback();
1451
- adVideoElement = contentVideo;
1452
- adHls = void 0;
1453
- adPlaying = true;
1454
- setAdPlayingFlag(true);
1455
- contentVideo.removeAttribute("src");
1456
- contentVideo.load();
1457
- if (!continueLiveStreamDuringAds) {
1458
- contentVideo.pause();
1459
- }
1460
- contentVideo.muted = true;
1461
- contentVideo.volume = 0;
1233
+ ads = _state.sent();
1462
1234
  return [
1463
- 4,
1464
- new Promise(function(resolve) {
1465
- return setTimeout(resolve, 200);
1466
- })
1467
- ];
1468
- case 2:
1469
- _state.sent();
1470
- if (destroyed || tornDown) return [
1471
- 2
1472
- ];
1473
- contentVideo.style.visibility = "visible";
1474
- contentVideo.style.opacity = "1";
1475
- applyContentVideoAdCoverStyles();
1476
- emit("content_pause");
1477
- setupAdEventListeners();
1478
- adVolume2 = originalMutedState ? 1 : originalVolume;
1479
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume2));
1480
- adVideoElement.muted = false;
1481
- mediaFile2 = selectBestMediaFile(ad.mediaFiles);
1482
- if (debug) console.log("".concat(LOG, " Loading ad from: ").concat(mediaFile2.url));
1483
- startPlayback(mediaFile2);
1484
- return [
1485
- 2
1486
- ];
1487
- case 3:
1488
- if (!adContainerEl) {
1489
- ;
1490
- container = document.createElement("div");
1491
- container.style.position = "absolute";
1492
- container.style.left = "0";
1493
- container.style.top = "0";
1494
- container.style.right = "0";
1495
- container.style.bottom = "0";
1496
- container.style.display = "none";
1497
- container.style.alignItems = "center";
1498
- container.style.justifyContent = "center";
1499
- container.style.pointerEvents = "none";
1500
- container.style.zIndex = "10";
1501
- container.style.backgroundColor = "#000";
1502
- (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1503
- adContainerEl = container;
1504
- }
1505
- if (!adVideoElement) {
1506
- adVideoElement = createAdVideoElement();
1507
- adContainerEl.appendChild(adVideoElement);
1508
- setupAdEventListeners();
1509
- } else {
1510
- teardownCurrentPlayback();
1511
- }
1512
- if (!continueLiveStreamDuringAds) {
1513
- contentVideo.pause();
1514
- }
1515
- contentVideo.muted = true;
1516
- contentVideo.volume = 0;
1517
- adPlaying = true;
1518
- setAdPlayingFlag(true);
1519
- adVolume = originalMutedState ? 1 : originalVolume;
1520
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
1521
- adVideoElement.muted = false;
1522
- if (adContainerEl) {
1523
- adContainerEl.style.display = "flex";
1524
- adContainerEl.style.pointerEvents = "auto";
1525
- }
1526
- emit("content_pause");
1527
- mediaFile = selectBestMediaFile(ad.mediaFiles);
1528
- if (debug) console.log("".concat(LOG, " Loading ad from: ").concat(mediaFile.url));
1529
- startPlayback(mediaFile);
1530
- return [
1531
- 2
1235
+ 2,
1236
+ ads[0] || null
1532
1237
  ];
1533
1238
  }
1534
1239
  });
1535
1240
  })();
1536
1241
  }
1537
- function ensureAdContainer() {
1538
- if (!adContainerEl) {
1539
- var _contentVideo_parentElement;
1540
- var container = document.createElement("div");
1541
- container.style.position = "absolute";
1542
- container.style.left = "0";
1543
- container.style.top = "0";
1544
- container.style.right = "0";
1545
- container.style.bottom = "0";
1546
- container.style.display = "none";
1547
- container.style.alignItems = "center";
1548
- container.style.justifyContent = "center";
1549
- container.style.pointerEvents = "none";
1550
- container.style.zIndex = "10";
1551
- container.style.backgroundColor = "#000";
1552
- (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1553
- adContainerEl = container;
1554
- }
1555
- return adContainerEl;
1242
+ function assignCurrentAd(ad) {
1243
+ currentAd = ad;
1244
+ sessionId = generateSessionId();
1245
+ trackingFired = {
1246
+ impression: false,
1247
+ start: false,
1248
+ firstQuartile: false,
1249
+ midpoint: false,
1250
+ thirdQuartile: false,
1251
+ complete: false
1252
+ };
1253
+ fireTrackingPixels2(currentAd.trackingUrls.impression);
1254
+ trackingFired.impression = true;
1255
+ emit("ad_impression");
1556
1256
  }
1557
- function preloadAd(bids, token) {
1558
- return _async_to_generator(function() {
1559
- var winner, ad, mediaFile, slot, videoEl, container, hls, slot1, slot2;
1560
- return _ts_generator(this, function(_state) {
1561
- switch(_state.label){
1562
- case 0:
1563
- if (destroyed) return [
1564
- 2
1565
- ];
1566
- winner = bids[0];
1567
- if (!winner) return [
1568
- 2
1569
- ];
1570
- if (debug) console.log("".concat(LOG, " [preload] Resolving VAST for token=").concat(token));
1571
- return [
1572
- 4,
1573
- resolveBidToVastAd(winner, LOG)
1574
- ];
1575
- case 1:
1576
- ad = _state.sent();
1577
- if (!ad || destroyed) return [
1578
- 2
1579
- ];
1580
- mediaFile = selectBestMediaFile(ad.mediaFiles);
1581
- if (!mediaFile) return [
1582
- 2
1583
- ];
1584
- if (smartTVMode || singleElementMode) {
1585
- slot = {
1586
- bids: bids,
1587
- ad: ad,
1588
- mediaFile: mediaFile,
1589
- videoEl: null,
1590
- ready: true
1591
- };
1592
- preloadSlots.set(token, slot);
1593
- if (debug) console.log("".concat(LOG, " [preload] Metadata-only preload (smartTV/singleElement), token=").concat(token, ", url=").concat(mediaFile.url));
1257
+ return {
1258
+ initialize: function initialize() {
1259
+ log("Initializing");
1260
+ if (!adContainerEl) {
1261
+ var _contentVideo_parentElement;
1262
+ var parent = contentVideo.parentElement;
1263
+ if (parent) {
1264
+ var computed = window.getComputedStyle(parent).position;
1265
+ if (computed === "static") {
1266
+ parent.style.position = "relative";
1267
+ parentPositionOverridden = true;
1268
+ }
1269
+ }
1270
+ var container = document.createElement("div");
1271
+ container.style.position = "absolute";
1272
+ container.style.left = "0";
1273
+ container.style.top = "0";
1274
+ container.style.right = "0";
1275
+ container.style.bottom = "0";
1276
+ container.style.display = "none";
1277
+ container.style.alignItems = "center";
1278
+ container.style.justifyContent = "center";
1279
+ container.style.pointerEvents = "none";
1280
+ container.style.zIndex = AD_LAYER_Z_INDEX;
1281
+ container.style.backgroundColor = "#000";
1282
+ container.style.transition = "opacity 0.3s ease-in-out";
1283
+ container.style.opacity = "0";
1284
+ container.style.isolation = "isolate";
1285
+ var countdown = document.createElement("div");
1286
+ countdown.style.position = "absolute";
1287
+ countdown.style.right = "12px";
1288
+ countdown.style.top = "12px";
1289
+ countdown.style.padding = "4px 8px";
1290
+ countdown.style.borderRadius = "4px";
1291
+ countdown.style.background = "rgba(0,0,0,0.75)";
1292
+ countdown.style.color = "#fff";
1293
+ countdown.style.fontFamily = "sans-serif";
1294
+ countdown.style.fontSize = "12px";
1295
+ countdown.style.lineHeight = "1.2";
1296
+ countdown.style.pointerEvents = "none";
1297
+ countdown.style.zIndex = COUNTDOWN_Z_INDEX;
1298
+ countdown.textContent = "Ad";
1299
+ container.appendChild(countdown);
1300
+ (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1301
+ adContainerEl = container;
1302
+ adCountdownEl = countdown;
1303
+ }
1304
+ },
1305
+ requestAds: function requestAds(duration) {
1306
+ return _async_to_generator(function() {
1307
+ var durationSeconds, parsed, ads, error;
1308
+ return _ts_generator(this, function(_state) {
1309
+ switch(_state.label){
1310
+ case 0:
1311
+ log("Requesting ads for duration:", duration);
1312
+ if (adPlaying) {
1313
+ return [
1314
+ 2,
1315
+ Promise.reject(new Error("Ad already playing"))
1316
+ ];
1317
+ }
1318
+ if (destroyed) {
1319
+ return [
1320
+ 2,
1321
+ Promise.reject(new Error("Player has been destroyed"))
1322
+ ];
1323
+ }
1324
+ _state.label = 1;
1325
+ case 1:
1326
+ _state.trys.push([
1327
+ 1,
1328
+ 3,
1329
+ ,
1330
+ 4
1331
+ ]);
1332
+ tornDown = false;
1333
+ durationSeconds = 30;
1334
+ parsed = parseInt(duration || "", 10);
1335
+ if (!isNaN(parsed) && parsed > 0) {
1336
+ durationSeconds = parsed;
1337
+ }
1594
1338
  return [
1595
- 2
1339
+ 4,
1340
+ fetchVast(durationSeconds)
1596
1341
  ];
1597
- }
1598
- videoEl = createAdVideoElement();
1599
- videoEl.style.visibility = "hidden";
1600
- videoEl.style.pointerEvents = "none";
1601
- videoEl.preload = "auto";
1602
- container = ensureAdContainer();
1603
- container.appendChild(videoEl);
1604
- if (isHlsMediaFile(mediaFile) && import_hls.default.isSupported()) {
1605
- hls = new import_hls.default({
1606
- enableWorker: true,
1607
- lowLatencyMode: false
1608
- });
1609
- hls.loadSource(mediaFile.url);
1610
- hls.attachMedia(videoEl);
1611
- slot1 = {
1612
- bids: bids,
1613
- ad: ad,
1614
- mediaFile: mediaFile,
1615
- videoEl: videoEl,
1616
- hlsInstance: hls,
1617
- ready: false
1618
- };
1619
- preloadSlots.set(token, slot1);
1620
- hls.on(import_hls.default.Events.MANIFEST_PARSED, function() {
1621
- var s = preloadSlots.get(token);
1622
- if (s) s.ready = true;
1623
- if (debug) console.log("".concat(LOG, " [preload] HLS manifest parsed, token=").concat(token));
1624
- });
1625
- hls.on(import_hls.default.Events.ERROR, function(_evt, data) {
1626
- if (!preloadSlots.has(token)) return;
1627
- if (data.fatal) {
1628
- if (debug) console.warn("".concat(LOG, " [preload] HLS error for token=").concat(token));
1629
- preloadSlots.delete(token);
1630
- hls.destroy();
1631
- videoEl.remove();
1632
- }
1633
- });
1634
- } else {
1635
- videoEl.src = mediaFile.url;
1636
- videoEl.load();
1637
- slot2 = {
1638
- bids: bids,
1639
- ad: ad,
1640
- mediaFile: mediaFile,
1641
- videoEl: videoEl,
1642
- ready: false
1643
- };
1644
- preloadSlots.set(token, slot2);
1645
- videoEl.addEventListener("canplay", function() {
1646
- var s = preloadSlots.get(token);
1647
- if (s) s.ready = true;
1648
- if (debug) console.log("".concat(LOG, " [preload] canplay fired, token=").concat(token));
1649
- }, {
1650
- once: true
1651
- });
1652
- }
1653
- if (debug) console.log("".concat(LOG, " [preload] Started buffering token=").concat(token, ", url=").concat(mediaFile.url));
1654
- return [
1655
- 2
1656
- ];
1657
- }
1658
- });
1659
- })();
1660
- }
1661
- function playPreloaded(token) {
1662
- return _async_to_generator(function() {
1663
- var slot, contentVolume, adVolume2, videoEl, container2, adVolume21, nonFatalNetworkErrors, adVolume, container;
1664
- return _ts_generator(this, function(_state) {
1665
- switch(_state.label){
1666
- case 0:
1667
- if (destroyed) return [
1668
- 2,
1669
- Promise.reject(new Error("Layer has been destroyed"))
1670
- ];
1671
- slot = preloadSlots.get(token);
1672
- if (!slot) {
1673
- if (debug) console.warn("".concat(LOG, " [preload] No slot found for token=").concat(token, ", nothing to play"));
1342
+ case 2:
1343
+ ads = _state.sent();
1344
+ if (ads.length === 0) {
1345
+ log("No ads available from VAST response");
1346
+ emit("ad_error");
1347
+ return [
1348
+ 2,
1349
+ Promise.resolve()
1350
+ ];
1351
+ }
1352
+ assignCurrentAd(ads[0]);
1353
+ log("Ad loaded: ".concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1354
+ return [
1355
+ 2,
1356
+ Promise.resolve()
1357
+ ];
1358
+ case 3:
1359
+ error = _state.sent();
1360
+ console.error("[AdStormPlayer] Error requesting ads:", error);
1361
+ emit("ad_error");
1362
+ return [
1363
+ 2,
1364
+ Promise.reject(error)
1365
+ ];
1366
+ case 4:
1674
1367
  return [
1675
1368
  2
1676
1369
  ];
1677
- }
1678
- preloadSlots.delete(token);
1679
- if (debug) console.log("".concat(LOG, " [preload] Playing preloaded ad, token=").concat(token, ", ready=").concat(slot.ready));
1680
- contentVolume = contentVideo.volume;
1681
- originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1682
- sessionId = generateSessionId();
1683
- currentAd = slot.ad;
1684
- trackingFired = _object_spread({}, createEmptyTrackingState());
1685
- fireTrackingPixels2(slot.ad.trackingUrls.impression);
1686
- trackingFired.impression = true;
1687
- if (!singleElementMode) return [
1688
- 3,
1689
- 2
1690
- ];
1691
- mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.detachMedia();
1692
- teardownCurrentPlayback();
1693
- adVideoElement = contentVideo;
1694
- adHls = void 0;
1695
- adPlaying = true;
1696
- setAdPlayingFlag(true);
1697
- contentVideo.removeAttribute("src");
1698
- contentVideo.load();
1699
- contentVideo.muted = true;
1700
- contentVideo.volume = 0;
1701
- return [
1702
- 4,
1703
- new Promise(function(resolve) {
1704
- return setTimeout(resolve, 200);
1705
- })
1706
- ];
1707
- case 1:
1708
- _state.sent();
1709
- if (destroyed || tornDown) return [
1710
- 2
1711
- ];
1712
- contentVideo.style.visibility = "visible";
1713
- contentVideo.style.opacity = "1";
1714
- applyContentVideoAdCoverStyles();
1715
- emit("content_pause");
1716
- setupAdEventListeners();
1717
- adVolume2 = originalMutedState ? 1 : originalVolume;
1718
- contentVideo.volume = Math.max(0, Math.min(1, adVolume2));
1719
- contentVideo.muted = false;
1720
- if (debug) console.log("".concat(LOG, " [preload] singleElementMode: attaching ad to contentVideo, url=").concat(slot.mediaFile.url));
1721
- startPlayback(slot.mediaFile);
1722
- return [
1723
- 2
1724
- ];
1725
- case 2:
1726
- if (smartTVMode && !slot.videoEl) {
1727
- teardownCurrentPlayback();
1728
- if (adVideoElement) {
1729
- adVideoElement.remove();
1730
- adVideoElement = void 0;
1370
+ }
1371
+ });
1372
+ })();
1373
+ },
1374
+ play: function play() {
1375
+ return _async_to_generator(function() {
1376
+ var mediaFile, error;
1377
+ return _ts_generator(this, function(_state) {
1378
+ switch(_state.label){
1379
+ case 0:
1380
+ if (!currentAd) {
1381
+ return [
1382
+ 2,
1383
+ Promise.reject(new Error("No ad loaded"))
1384
+ ];
1385
+ }
1386
+ if (destroyed) {
1387
+ return [
1388
+ 2,
1389
+ Promise.reject(new Error("Player has been destroyed"))
1390
+ ];
1391
+ }
1392
+ log("Starting ad playback");
1393
+ _state.label = 1;
1394
+ case 1:
1395
+ _state.trys.push([
1396
+ 1,
1397
+ 3,
1398
+ ,
1399
+ 4
1400
+ ]);
1401
+ tornDown = false;
1402
+ if (adHideTimerId) {
1403
+ clearTimeout(adHideTimerId);
1404
+ adHideTimerId = void 0;
1405
+ }
1406
+ if (!adVideoElement) {
1407
+ adVideoElement = createAdVideoElement();
1408
+ adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.appendChild(adVideoElement);
1409
+ } else {
1410
+ teardownCurrentPlayback();
1731
1411
  }
1732
- videoEl = createAdVideoElement();
1733
- videoEl.style.visibility = "visible";
1734
- videoEl.style.pointerEvents = "none";
1735
- container2 = ensureAdContainer();
1736
- container2.appendChild(videoEl);
1737
- adVideoElement = videoEl;
1738
1412
  setupAdEventListeners();
1413
+ trackingFired = {
1414
+ impression: trackingFired.impression,
1415
+ start: false,
1416
+ firstQuartile: false,
1417
+ midpoint: false,
1418
+ thirdQuartile: false,
1419
+ complete: false
1420
+ };
1421
+ contentVideo.style.transition = "opacity 0.3s ease-in-out";
1422
+ contentVideo.style.opacity = "0";
1423
+ setTimeout(function() {
1424
+ contentVideo.style.visibility = "hidden";
1425
+ }, 300);
1426
+ contentVideo.muted = true;
1427
+ contentVideo.volume = 0;
1739
1428
  if (!continueLiveStreamDuringAds) {
1740
1429
  contentVideo.pause();
1741
1430
  }
1742
- contentVideo.muted = true;
1743
- contentVideo.volume = 0;
1744
1431
  adPlaying = true;
1745
1432
  setAdPlayingFlag(true);
1746
- adVolume21 = originalMutedState ? 1 : originalVolume;
1747
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume21));
1748
- adVideoElement.muted = false;
1749
- container2.style.display = "flex";
1750
- container2.style.pointerEvents = "auto";
1433
+ if (adVideoElement) {
1434
+ adVideoElement.volume = originalMutedState ? 0 : originalVolume;
1435
+ adVideoElement.muted = originalMutedState;
1436
+ }
1437
+ if (adContainerEl) {
1438
+ adContainerEl.style.display = "flex";
1439
+ adContainerEl.style.pointerEvents = "auto";
1440
+ adContainerEl.offsetHeight;
1441
+ adContainerEl.style.opacity = "1";
1442
+ }
1751
1443
  emit("content_pause");
1752
- if (debug) console.log("".concat(LOG, " [preload] smartTVMode deferred: creating video element and loading, url=").concat(slot.mediaFile.url));
1753
- startPlayback(slot.mediaFile);
1444
+ mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1445
+ if (!mediaFile) {
1446
+ throw new Error("No media file available");
1447
+ }
1448
+ log("Playing media file:", mediaFile.url);
1449
+ adVideoElement.src = mediaFile.url;
1450
+ adVideoElement.load();
1754
1451
  return [
1755
- 2
1452
+ 4,
1453
+ adVideoElement.play()
1756
1454
  ];
1757
- }
1758
- teardownCurrentPlayback();
1759
- if (adVideoElement && adVideoElement !== slot.videoEl) {
1760
- adVideoElement.remove();
1761
- }
1762
- slot.videoEl.style.visibility = "visible";
1763
- slot.videoEl.style.pointerEvents = "none";
1764
- adVideoElement = slot.videoEl;
1765
- adHls = slot.hlsInstance;
1766
- if (adHls) {
1767
- nonFatalNetworkErrors = 0;
1768
- adHls.on(import_hls.default.Events.ERROR, function(_event, data) {
1769
- if (!adPlaying) return;
1770
- if (data.fatal) {
1771
- handleAdError();
1772
- } else if (data.type === import_hls.default.ErrorTypes.NETWORK_ERROR) {
1773
- nonFatalNetworkErrors++;
1774
- if (nonFatalNetworkErrors >= 3) {
1775
- if (debug) console.warn("".concat(LOG, " [preload] Too many non-fatal HLS network errors during playback, treating as fatal"));
1776
- handleAdError();
1777
- }
1778
- }
1779
- });
1780
- }
1781
- setupAdEventListeners();
1782
- if (!continueLiveStreamDuringAds) {
1783
- contentVideo.pause();
1784
- }
1785
- contentVideo.muted = true;
1786
- contentVideo.volume = 0;
1787
- adPlaying = true;
1788
- setAdPlayingFlag(true);
1789
- adVolume = originalMutedState ? 1 : originalVolume;
1790
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
1791
- adVideoElement.muted = false;
1792
- container = ensureAdContainer();
1793
- container.style.display = "flex";
1794
- container.style.pointerEvents = "auto";
1795
- emit("content_pause");
1796
- adVideoElement.play().catch(function(error) {
1797
- console.error("".concat(LOG, " [preload] Error playing preloaded ad:"), error);
1455
+ case 2:
1456
+ _state.sent();
1457
+ return [
1458
+ 2,
1459
+ Promise.resolve()
1460
+ ];
1461
+ case 3:
1462
+ error = _state.sent();
1463
+ console.error("[AdStormPlayer] Error playing ad:", error);
1798
1464
  handleAdError();
1799
- });
1800
- return [
1801
- 2
1802
- ];
1803
- }
1804
- });
1805
- })();
1806
- }
1807
- function cancelPreload(token) {
1808
- var slot = preloadSlots.get(token);
1809
- if (!slot) return;
1810
- preloadSlots.delete(token);
1811
- if (slot.hlsInstance) {
1812
- slot.hlsInstance.destroy();
1813
- }
1814
- if (slot.videoEl) {
1815
- slot.videoEl.pause();
1816
- slot.videoEl.removeAttribute("src");
1817
- slot.videoEl.load();
1818
- slot.videoEl.remove();
1819
- }
1820
- if (debug) console.log("".concat(LOG, " [preload] Cancelled and cleaned up token=").concat(token));
1821
- }
1822
- return {
1823
- initialize: function initialize() {
1824
- if (debug) console.log("".concat(LOG, " Initializing"));
1825
- },
1826
- updateOptions: function updateOptions(opts) {
1827
- if (opts.continueLiveStreamDuringAds !== void 0) {
1828
- continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;
1829
- }
1830
- if (opts.mainHlsInstance !== void 0) {
1831
- var _opts_mainHlsInstance;
1832
- mainHlsInstance = (_opts_mainHlsInstance = opts.mainHlsInstance) !== null && _opts_mainHlsInstance !== void 0 ? _opts_mainHlsInstance : void 0;
1833
- }
1834
- },
1835
- playAd: playAd,
1836
- preloadAd: preloadAd,
1837
- playPreloaded: playPreloaded,
1838
- hasPreloaded: function hasPreloaded(token) {
1839
- return preloadSlots.has(token);
1840
- },
1841
- cancelPreload: cancelPreload,
1842
- pause: function pause() {
1843
- if (!adPlaying || !adVideoElement) return;
1844
- try {
1845
- if (!adVideoElement.paused) adVideoElement.pause();
1846
- } catch (error) {
1847
- if (debug) console.warn("".concat(LOG, " Error pausing ad:"), error);
1848
- }
1849
- },
1850
- resume: function resume() {
1851
- if (!adPlaying || !adVideoElement) return;
1852
- try {
1853
- if (adVideoElement.paused) adVideoElement.play().catch(function() {});
1854
- } catch (error) {
1855
- if (debug) console.warn("".concat(LOG, " Error resuming ad:"), error);
1856
- }
1465
+ return [
1466
+ 2,
1467
+ Promise.reject(error)
1468
+ ];
1469
+ case 4:
1470
+ return [
1471
+ 2
1472
+ ];
1473
+ }
1474
+ });
1475
+ })();
1857
1476
  },
1858
1477
  stop: function stop() {
1859
1478
  return _async_to_generator(function() {
1860
1479
  return _ts_generator(this, function(_state) {
1480
+ log("Stopping ad");
1861
1481
  tornDown = true;
1862
- if (debug) console.log("".concat(LOG, " Stopping ad"));
1863
1482
  adPlaying = false;
1864
1483
  setAdPlayingFlag(false);
1865
- restoreContentVideoStyles();
1866
- contentVideo.muted = originalMutedState;
1867
- contentVideo.volume = originalMutedState ? 0 : originalVolume;
1484
+ clearAdStallTimer();
1485
+ clearAdCountdownTimer();
1486
+ if (adContainerEl) {
1487
+ adContainerEl.style.opacity = "0";
1488
+ adHideTimerId = setTimeout(function() {
1489
+ if (adContainerEl) {
1490
+ adContainerEl.style.display = "none";
1491
+ adContainerEl.style.pointerEvents = "none";
1492
+ }
1493
+ }, 300);
1494
+ }
1495
+ teardownCurrentPlayback();
1868
1496
  contentVideo.style.visibility = "visible";
1869
1497
  contentVideo.style.opacity = "1";
1870
- if (singleElementMode) {
1871
- teardownCurrentPlayback();
1872
- contentVideo.removeAttribute("src");
1873
- contentVideo.load();
1874
- adVideoElement = void 0;
1875
- } else {
1876
- if (adContainerEl) {
1877
- adContainerEl.style.display = "none";
1878
- adContainerEl.style.pointerEvents = "none";
1879
- }
1880
- if (continueLiveStreamDuringAds) {
1881
- contentVideo.play().catch(function() {});
1882
- }
1883
- teardownCurrentPlayback();
1884
- if (adVideoElement) {
1885
- adVideoElement.pause();
1886
- adVideoElement.removeAttribute("src");
1887
- adVideoElement.load();
1888
- }
1889
- }
1498
+ contentVideo.muted = originalMutedState;
1499
+ contentVideo.volume = originalVolume;
1890
1500
  currentAd = void 0;
1891
1501
  tornDown = false;
1892
1502
  return [
1893
- 2
1503
+ 2,
1504
+ Promise.resolve()
1894
1505
  ];
1895
1506
  });
1896
1507
  })();
1897
1508
  },
1509
+ pause: function pause() {
1510
+ if (!adPlaying || !adVideoElement) return;
1511
+ try {
1512
+ if (!adVideoElement.paused) adVideoElement.pause();
1513
+ } catch (error) {
1514
+ console.warn("[AdStormPlayer] Error pausing ad:", error);
1515
+ }
1516
+ },
1517
+ resume: function resume() {
1518
+ if (!adPlaying || !adVideoElement) return;
1519
+ try {
1520
+ if (adVideoElement.paused) adVideoElement.play().catch(function() {});
1521
+ } catch (error) {
1522
+ console.warn("[AdStormPlayer] Error resuming ad:", error);
1523
+ }
1524
+ },
1898
1525
  destroy: function destroy() {
1899
- tornDown = true;
1900
- if (debug) console.log("".concat(LOG, " Destroying"));
1526
+ log("Destroying");
1901
1527
  destroyed = true;
1528
+ tornDown = true;
1902
1529
  adPlaying = false;
1903
1530
  setAdPlayingFlag(false);
1904
- restoreContentVideoStyles();
1531
+ clearAdStallTimer();
1532
+ clearAdCountdownTimer();
1533
+ if (adHideTimerId) {
1534
+ clearTimeout(adHideTimerId);
1535
+ adHideTimerId = void 0;
1536
+ }
1905
1537
  contentVideo.muted = originalMutedState;
1906
1538
  contentVideo.volume = originalVolume;
1907
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1908
- try {
1909
- for(var _iterator = Array.from(preloadSlots.entries())[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1910
- var _step_value = _sliced_to_array(_step.value, 1), token = _step_value[0];
1911
- cancelPreload(token);
1912
- }
1913
- } catch (err) {
1914
- _didIteratorError = true;
1915
- _iteratorError = err;
1916
- } finally{
1917
- try {
1918
- if (!_iteratorNormalCompletion && _iterator.return != null) {
1919
- _iterator.return();
1920
- }
1921
- } finally{
1922
- if (_didIteratorError) {
1923
- throw _iteratorError;
1924
- }
1925
- }
1926
- }
1539
+ contentVideo.style.visibility = "visible";
1540
+ contentVideo.style.opacity = "1";
1927
1541
  teardownCurrentPlayback();
1928
- if (adVideoElement) {
1929
- if (singleElementMode && adVideoElement === contentVideo) {
1930
- contentVideo.removeAttribute("src");
1931
- contentVideo.load();
1932
- } else {
1933
- adVideoElement.pause();
1934
- adVideoElement.removeAttribute("src");
1935
- adVideoElement.remove();
1936
- }
1937
- adVideoElement = void 0;
1938
- }
1542
+ adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.remove();
1543
+ adVideoElement = void 0;
1939
1544
  if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
1940
1545
  adContainerEl.parentElement.removeChild(adContainerEl);
1941
1546
  }
1942
1547
  adContainerEl = void 0;
1548
+ adCountdownEl = void 0;
1943
1549
  currentAd = void 0;
1550
+ sessionId = void 0;
1551
+ preloadSlots.clear();
1944
1552
  listeners.clear();
1553
+ if (parentPositionOverridden && contentVideo.parentElement) {
1554
+ contentVideo.parentElement.style.position = "";
1555
+ parentPositionOverridden = false;
1556
+ }
1557
+ },
1558
+ updateOptions: function updateOptions(opts) {
1559
+ if (opts.continueLiveStreamDuringAds !== void 0) {
1560
+ continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;
1561
+ }
1562
+ },
1563
+ playAd: function playAd(requestContext) {
1564
+ return _async_to_generator(function() {
1565
+ var ad;
1566
+ return _ts_generator(this, function(_state) {
1567
+ switch(_state.label){
1568
+ case 0:
1569
+ if (destroyed) return [
1570
+ 2,
1571
+ Promise.reject(new Error("Player has been destroyed"))
1572
+ ];
1573
+ if (!!currentAd) return [
1574
+ 3,
1575
+ 2
1576
+ ];
1577
+ return [
1578
+ 4,
1579
+ requestAdFromApi(requestContext)
1580
+ ];
1581
+ case 1:
1582
+ ad = _state.sent();
1583
+ if (!ad) {
1584
+ emit("ad_error", {
1585
+ message: "No valid ad from AdStorm API"
1586
+ });
1587
+ return [
1588
+ 2,
1589
+ Promise.reject(new Error("No valid ad from AdStorm API"))
1590
+ ];
1591
+ }
1592
+ assignCurrentAd(ad);
1593
+ _state.label = 2;
1594
+ case 2:
1595
+ return [
1596
+ 2,
1597
+ this.play()
1598
+ ];
1599
+ }
1600
+ });
1601
+ }).call(this);
1602
+ },
1603
+ preloadAd: function preloadAd(arg1, arg2) {
1604
+ return _async_to_generator(function() {
1605
+ var token, requestContext, ad;
1606
+ return _ts_generator(this, function(_state) {
1607
+ switch(_state.label){
1608
+ case 0:
1609
+ if (destroyed) return [
1610
+ 2
1611
+ ];
1612
+ token = typeof arg1 === "string" ? arg1 : typeof arg2 === "string" ? arg2 : void 0;
1613
+ if (!token) return [
1614
+ 2
1615
+ ];
1616
+ requestContext = typeof arg1 === "string" ? arg2 : arg1;
1617
+ return [
1618
+ 4,
1619
+ requestAdFromApi(requestContext)
1620
+ ];
1621
+ case 1:
1622
+ ad = _state.sent();
1623
+ if (!ad) return [
1624
+ 2
1625
+ ];
1626
+ preloadSlots.set(token, {
1627
+ ad: ad
1628
+ });
1629
+ return [
1630
+ 2
1631
+ ];
1632
+ }
1633
+ });
1634
+ })();
1635
+ },
1636
+ playPreloaded: function playPreloaded(token) {
1637
+ return _async_to_generator(function() {
1638
+ var slot;
1639
+ return _ts_generator(this, function(_state) {
1640
+ if (destroyed) return [
1641
+ 2,
1642
+ Promise.reject(new Error("Player has been destroyed"))
1643
+ ];
1644
+ slot = preloadSlots.get(token);
1645
+ if (!slot) {
1646
+ return [
1647
+ 2,
1648
+ Promise.reject(new Error("No preloaded ad for token ".concat(token)))
1649
+ ];
1650
+ }
1651
+ preloadSlots.delete(token);
1652
+ assignCurrentAd(slot.ad);
1653
+ return [
1654
+ 2,
1655
+ this.play()
1656
+ ];
1657
+ });
1658
+ }).call(this);
1659
+ },
1660
+ hasPreloaded: function hasPreloaded(token) {
1661
+ return preloadSlots.has(token);
1662
+ },
1663
+ cancelPreload: function cancelPreload(token) {
1664
+ preloadSlots.delete(token);
1945
1665
  },
1946
1666
  isAdPlaying: function isAdPlaying() {
1947
1667
  return adPlaying;
1948
1668
  },
1949
1669
  resize: function resize(width, height) {
1670
+ log("Resizing to ".concat(width, "x").concat(height));
1950
1671
  if (adContainerEl) {
1951
1672
  adContainerEl.style.width = "".concat(width, "px");
1952
1673
  adContainerEl.style.height = "".concat(height, "px");
@@ -1966,6 +1687,7 @@ function createVastAdLayer(contentVideo, options) {
1966
1687
  },
1967
1688
  updateOriginalMutedState: function updateOriginalMutedState(muted, volume) {
1968
1689
  var nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
1690
+ log("updateOriginalMutedState: muted=".concat(muted, ", volume=").concat(nextVolume));
1969
1691
  originalMutedState = muted;
1970
1692
  originalVolume = nextVolume;
1971
1693
  },
@@ -1978,6 +1700,7 @@ function createVastAdLayer(contentVideo, options) {
1978
1700
  setAdVolume: function setAdVolume(volume) {
1979
1701
  if (adVideoElement && adPlaying) {
1980
1702
  adVideoElement.volume = Math.max(0, Math.min(1, volume));
1703
+ adVideoElement.muted = volume === 0;
1981
1704
  }
1982
1705
  },
1983
1706
  getAdVolume: function getAdVolume() {
@@ -1987,11 +1710,16 @@ function createVastAdLayer(contentVideo, options) {
1987
1710
  return 1;
1988
1711
  },
1989
1712
  showPlaceholder: function showPlaceholder() {
1990
- if (singleElementMode) return;
1991
- contentVideo.style.opacity = "0";
1992
- contentVideo.style.visibility = "hidden";
1993
1713
  if (!adContainerEl) {
1994
1714
  var _contentVideo_parentElement;
1715
+ var parent = contentVideo.parentElement;
1716
+ if (parent) {
1717
+ var computed = window.getComputedStyle(parent).position;
1718
+ if (computed === "static") {
1719
+ parent.style.position = "relative";
1720
+ parentPositionOverridden = true;
1721
+ }
1722
+ }
1995
1723
  var container = document.createElement("div");
1996
1724
  container.style.position = "absolute";
1997
1725
  container.style.left = "0";
@@ -2002,24 +1730,43 @@ function createVastAdLayer(contentVideo, options) {
2002
1730
  container.style.alignItems = "center";
2003
1731
  container.style.justifyContent = "center";
2004
1732
  container.style.pointerEvents = "none";
2005
- container.style.zIndex = "10";
1733
+ container.style.zIndex = AD_LAYER_Z_INDEX;
2006
1734
  container.style.backgroundColor = "#000";
1735
+ container.style.isolation = "isolate";
1736
+ var countdown = document.createElement("div");
1737
+ countdown.style.position = "absolute";
1738
+ countdown.style.right = "12px";
1739
+ countdown.style.top = "12px";
1740
+ countdown.style.padding = "4px 8px";
1741
+ countdown.style.borderRadius = "4px";
1742
+ countdown.style.background = "rgba(0,0,0,0.75)";
1743
+ countdown.style.color = "#fff";
1744
+ countdown.style.fontFamily = "sans-serif";
1745
+ countdown.style.fontSize = "12px";
1746
+ countdown.style.lineHeight = "1.2";
1747
+ countdown.style.pointerEvents = "none";
1748
+ countdown.style.zIndex = COUNTDOWN_Z_INDEX;
1749
+ countdown.textContent = "Ad";
1750
+ container.appendChild(countdown);
2007
1751
  (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
2008
1752
  adContainerEl = container;
1753
+ adCountdownEl = countdown;
2009
1754
  }
2010
1755
  if (adContainerEl) {
2011
1756
  adContainerEl.style.display = "flex";
1757
+ adContainerEl.style.opacity = "1";
2012
1758
  adContainerEl.style.pointerEvents = "auto";
2013
1759
  }
2014
1760
  },
2015
1761
  hidePlaceholder: function hidePlaceholder() {
2016
1762
  if (adContainerEl) {
2017
- adContainerEl.style.display = "none";
2018
- adContainerEl.style.pointerEvents = "none";
2019
- }
2020
- if (!adPlaying) {
2021
- contentVideo.style.visibility = "visible";
2022
- contentVideo.style.opacity = "1";
1763
+ adContainerEl.style.opacity = "0";
1764
+ setTimeout(function() {
1765
+ if (adContainerEl) {
1766
+ adContainerEl.style.display = "none";
1767
+ adContainerEl.style.pointerEvents = "none";
1768
+ }
1769
+ }, 300);
2023
1770
  }
2024
1771
  }
2025
1772
  };
@@ -3122,6 +2869,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3122
2869
  this.backoffBaseMs = 1e3;
3123
2870
  this.maxBackoffMs = 15e3;
3124
2871
  this.MIN_AD_REMAINING_MS = 15e3;
2872
+ this.adRequestTimeoutMs = 5e3;
2873
+ this.adRequestMaxRetries = 3;
2874
+ this.adRequestRetryBackoffMs = 1500;
3125
2875
  this.preloadedTokens = [];
3126
2876
  initializePolyfills();
3127
2877
  var browserOverrides = getBrowserConfigOverrides();
@@ -3129,24 +2879,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3129
2879
  this.video = config.videoElement;
3130
2880
  this.adTransitionGapMs = (_this_config_adTransitionGapMs = this.config.adTransitionGapMs) !== null && _this_config_adTransitionGapMs !== void 0 ? _this_config_adTransitionGapMs : 100;
3131
2881
  logBrowserInfo(config.debugAdTiming);
3132
- this.vastManager = createVastManager(config.debugAdTiming !== void 0 ? {
3133
- debug: !!config.debugAdTiming
3134
- } : {});
3135
2882
  var browserForAdLayer = detectBrowser();
3136
2883
  var isSinglePipeline = browserForAdLayer.isSmartTV || !!this.config.singlePipelineMode;
3137
- this.adLayer = createVastAdLayer(this.video, {
3138
- continueLiveStreamDuringAds: false,
3139
- smartTVMode: isSinglePipeline,
3140
- singleElementMode: isSinglePipeline,
3141
- forceMP4Ads: isSinglePipeline,
2884
+ this.adLayer = createAdStormPlayer(this.video, {
2885
+ licenseKey: this.config.licenseKey || "",
3142
2886
  debug: !!config.debugAdTiming
3143
2887
  });
2888
+ this.adLayer.updateOptions({
2889
+ continueLiveStreamDuringAds: !isSinglePipeline && this.shouldContinueLiveStreamDuringAds()
2890
+ });
3144
2891
  }
3145
2892
  _create_class(StormcloudVideoPlayer, [
3146
2893
  {
3147
2894
  key: "adRequest",
3148
2895
  value: function adRequest(context) {
3149
2896
  return _async_to_generator(function() {
2897
+ var _ref, _ref1, durationSeconds;
3150
2898
  return _ts_generator(this, function(_state) {
3151
2899
  switch(_state.label){
3152
2900
  case 0:
@@ -3154,15 +2902,28 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3154
2902
  2,
3155
2903
  []
3156
2904
  ];
2905
+ 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));
3157
2906
  return [
3158
2907
  4,
3159
- this.vastManager.initialize()
2908
+ this.adLayer.requestAds(String(durationSeconds))
3160
2909
  ];
3161
2910
  case 1:
3162
2911
  _state.sent();
3163
2912
  return [
3164
2913
  2,
3165
- this.vastManager.requestBidsUntilResponse(context)
2914
+ [
2915
+ {
2916
+ bidder: "adstorm-direct",
2917
+ cpm: 0,
2918
+ width: 0,
2919
+ height: 0,
2920
+ adId: "adstorm",
2921
+ impId: "",
2922
+ creativeId: "adstorm",
2923
+ currency: "USD",
2924
+ durationSec: durationSeconds
2925
+ }
2926
+ ]
3166
2927
  ];
3167
2928
  }
3168
2929
  });
@@ -3219,7 +2980,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3219
2980
  2
3220
2981
  ];
3221
2982
  case 3:
3222
- this.hls = new import_hls2.default(_object_spread_props(_object_spread({
2983
+ this.hls = new import_hls.default(_object_spread_props(_object_spread({
3223
2984
  enableWorker: true,
3224
2985
  backBufferLength: 30,
3225
2986
  liveDurationInfinity: true,
@@ -3237,11 +2998,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3237
2998
  nudgeMaxRetry: 3,
3238
2999
  startPosition: -1
3239
3000
  }));
3240
- this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, function() {
3001
+ this.hls.on(import_hls.default.Events.MEDIA_ATTACHED, function() {
3241
3002
  var _this_hls;
3242
3003
  (_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.loadSource(_this.config.src);
3243
3004
  });
3244
- this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, function(_, data) {
3005
+ this.hls.on(import_hls.default.Events.MANIFEST_PARSED, function(_, data) {
3245
3006
  return _async_to_generator(function() {
3246
3007
  var _this_config_minSegmentsBeforePlay, _ref, _this_hls_levels, _this_hls, adBehavior, _this_hls1, minSegments, _this_video_play;
3247
3008
  return _ts_generator(this, function(_state) {
@@ -3303,7 +3064,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3303
3064
  });
3304
3065
  }).call(_this);
3305
3066
  });
3306
- this.hls.on(import_hls2.default.Events.LEVEL_LOADED, function(_evt, data) {
3067
+ this.hls.on(import_hls.default.Events.LEVEL_LOADED, function(_evt, data) {
3307
3068
  if (_this.inAdBreak || _this.pendingAdBreak) {
3308
3069
  return;
3309
3070
  }
@@ -3376,7 +3137,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3376
3137
  }
3377
3138
  }
3378
3139
  });
3379
- this.hls.on(import_hls2.default.Events.FRAG_BUFFERED, function(_evt, data) {
3140
+ this.hls.on(import_hls.default.Events.FRAG_BUFFERED, function(_evt, data) {
3380
3141
  return _async_to_generator(function() {
3381
3142
  var _this, _this_config_minSegmentsBeforePlay, minSegments, _this_video_play;
3382
3143
  return _ts_generator(this, function(_state) {
@@ -3436,7 +3197,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3436
3197
  });
3437
3198
  }).call(_this);
3438
3199
  });
3439
- this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, function(_evt, data) {
3200
+ this.hls.on(import_hls.default.Events.FRAG_PARSING_METADATA, function(_evt, data) {
3440
3201
  var id3Tags = ((data === null || data === void 0 ? void 0 : data.samples) || []).map(function(s) {
3441
3202
  return {
3442
3203
  key: "ID3",
@@ -3448,7 +3209,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3448
3209
  return _this.onId3Tag(tag);
3449
3210
  });
3450
3211
  });
3451
- this.hls.on(import_hls2.default.Events.FRAG_CHANGED, function(_evt, data) {
3212
+ this.hls.on(import_hls.default.Events.FRAG_CHANGED, function(_evt, data) {
3452
3213
  var frag = data === null || data === void 0 ? void 0 : data.frag;
3453
3214
  var tagList = frag === null || frag === void 0 ? void 0 : frag.tagList;
3454
3215
  if (!Array.isArray(tagList)) return;
@@ -3557,14 +3318,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3557
3318
  }
3558
3319
  }
3559
3320
  });
3560
- this.hls.on(import_hls2.default.Events.ERROR, function(_evt, data) {
3321
+ this.hls.on(import_hls.default.Events.ERROR, function(_evt, data) {
3561
3322
  if (data === null || data === void 0 ? void 0 : data.fatal) {
3562
3323
  switch(data.type){
3563
- case import_hls2.default.ErrorTypes.NETWORK_ERROR:
3324
+ case import_hls.default.ErrorTypes.NETWORK_ERROR:
3564
3325
  var _this_hls;
3565
3326
  (_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.startLoad();
3566
3327
  break;
3567
- case import_hls2.default.ErrorTypes.MEDIA_ERROR:
3328
+ case import_hls.default.ErrorTypes.MEDIA_ERROR:
3568
3329
  var _this_hls1;
3569
3330
  (_this_hls1 = _this.hls) === null || _this_hls1 === void 0 ? void 0 : _this_hls1.recoverMediaError();
3570
3331
  break;
@@ -3656,7 +3417,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3656
3417
  }
3657
3418
  });
3658
3419
  this.adLayer.on("content_resume", function() {
3420
+ var _ref, _ref1;
3421
+ var _this_savedMutedStateBeforeScte, _this_savedMutedStateBeforeScte1;
3659
3422
  var remaining = _this.getRemainingAdMs();
3423
+ 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();
3424
+ 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();
3660
3425
  if (_this.config.debugAdTiming) {
3661
3426
  console.log("[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s, preloadedTokens=%d, pendingNext=%s", _this.inAdBreak, remaining, _this.preloadedTokens.length, !!_this.pendingNextAdBids);
3662
3427
  }
@@ -3671,7 +3436,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3671
3436
  return;
3672
3437
  }
3673
3438
  _this.consecutiveFailures = 0;
3674
- if (!_this.video.muted) {
3439
+ if (!_this.config.disableFiller && !_this.video.muted) {
3675
3440
  _this.video.muted = true;
3676
3441
  _this.video.volume = 0;
3677
3442
  }
@@ -3738,6 +3503,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3738
3503
  if (!_this.config.disableFiller) {
3739
3504
  _this.showPlaceholderLayer();
3740
3505
  _this.adLayer.showPlaceholder();
3506
+ } else {
3507
+ _this.adLayer.hidePlaceholder();
3508
+ if (_this.video.muted !== breakMuted) {
3509
+ _this.video.muted = breakMuted;
3510
+ }
3511
+ if (Math.abs(_this.video.volume - breakVolume) > 0.01) {
3512
+ _this.video.volume = breakVolume;
3513
+ }
3514
+ if (_this.video.paused) {
3515
+ var _this_video_play;
3516
+ (_this_video_play = _this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
3517
+ }
3741
3518
  }
3742
3519
  _this.stopContinuousFetching();
3743
3520
  return;
@@ -4465,6 +4242,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4465
4242
  return this.totalAdsInBreak;
4466
4243
  }
4467
4244
  },
4245
+ {
4246
+ key: "getRemainingAdSeconds",
4247
+ value: function getRemainingAdSeconds() {
4248
+ var remainingMs = this.getRemainingAdMs();
4249
+ if (!Number.isFinite(remainingMs) || remainingMs <= 0 || remainingMs === Number.MAX_SAFE_INTEGER) {
4250
+ return 0;
4251
+ }
4252
+ return Math.ceil(remainingMs / 1e3);
4253
+ }
4254
+ },
4468
4255
  {
4469
4256
  key: "isAdPlaying",
4470
4257
  value: function isAdPlaying() {
@@ -5694,7 +5481,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5694
5481
  });
5695
5482
  };
5696
5483
  var onManifestParsedRestore = function onManifestParsedRestore1() {
5697
- hlsRef.off(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5484
+ hlsRef.off(import_hls.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5698
5485
  if (!_this.inAdBreak && !_this.adLayer.isAdPlaying()) {
5699
5486
  if (videoRef.muted !== savedMuted) videoRef.muted = savedMuted;
5700
5487
  if (Math.abs(videoRef.volume - savedVolume) > 0.01) videoRef.volume = savedVolume;
@@ -5707,7 +5494,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5707
5494
  }
5708
5495
  }
5709
5496
  };
5710
- hlsRef.on(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5497
+ hlsRef.on(import_hls.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5711
5498
  var pipelineDelayMs = 300;
5712
5499
  if (debugEnabled) {
5713
5500
  console.log("[StormcloudVideoPlayer] Smart TV: waiting ".concat(pipelineDelayMs, "ms for hardware pipeline release before re-attach"));