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.
@@ -399,185 +399,8 @@ __export(HlsPlayer_exports, {
399
399
  module.exports = __toCommonJS(HlsPlayer_exports);
400
400
  var import_react = require("react");
401
401
  // src/player/StormcloudVideoPlayer.ts
402
- var import_hls2 = __toESM(require("hls.js"), 1);
402
+ var import_hls = __toESM(require("hls.js"), 1);
403
403
  // src/sdk/vastParser.ts
404
- function isHlsType(type) {
405
- return type === "application/x-mpegURL" || type.includes("m3u8");
406
- }
407
- function isMp4Type(type) {
408
- return type === "video/mp4" || type.includes("mp4");
409
- }
410
- function parseVastXml(xmlString) {
411
- var filter = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "all", logPrefix = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "[VastParser]";
412
- try {
413
- var _xmlDoc_querySelector, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector2;
414
- var parser = new DOMParser();
415
- var xmlDoc = parser.parseFromString(xmlString, "text/xml");
416
- var parserError = xmlDoc.querySelector("parsererror");
417
- if (parserError) {
418
- console.error("".concat(logPrefix, " XML parsing error (malformed VAST XML):"), parserError.textContent);
419
- return null;
420
- }
421
- var adElement = xmlDoc.querySelector("Ad");
422
- if (!adElement) {
423
- console.warn("".concat(logPrefix, " No Ad element found in VAST XML"));
424
- return null;
425
- }
426
- var adId = adElement.getAttribute("id") || "unknown";
427
- var title = ((_xmlDoc_querySelector = xmlDoc.querySelector("AdTitle")) === null || _xmlDoc_querySelector === void 0 ? void 0 : _xmlDoc_querySelector.textContent) || "Ad";
428
- var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
429
- var durationText = ((_xmlDoc_querySelector1 = xmlDoc.querySelector("Duration")) === null || _xmlDoc_querySelector1 === void 0 ? void 0 : _xmlDoc_querySelector1.textContent) || "00:00:30";
430
- var durationParts = durationText.split(":");
431
- var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + Math.round(parseFloat(durationParts[2] || "0"));
432
- var mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
433
- var mediaFiles = [];
434
- console.log("".concat(logPrefix, " Found ").concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
435
- mediaFileElements.forEach(function(mf, index) {
436
- var _mf_textContent;
437
- var type = mf.getAttribute("type") || "";
438
- var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
439
- var width = mf.getAttribute("width") || "";
440
- var height = mf.getAttribute("height") || "";
441
- console.log("".concat(logPrefix, " MediaFile ").concat(index, ': type="').concat(type, '", url="').concat(url.substring(0, 80), '...", width="').concat(width, '", height="').concat(height, '"'));
442
- if (!url) {
443
- console.warn("".concat(logPrefix, " MediaFile ").concat(index, " has empty URL"));
444
- return;
445
- }
446
- var isHls = isHlsType(type);
447
- var isMp4 = isMp4Type(type);
448
- var accepted = false;
449
- if (filter === "hls-only") {
450
- accepted = isHls;
451
- } else if (filter === "mp4-first") {
452
- accepted = isMp4 || isHls;
453
- } else {
454
- accepted = true;
455
- }
456
- if (!accepted) {
457
- console.log("".concat(logPrefix, " MediaFile ").concat(index, ' ignored (type="').concat(type, '" not accepted by filter "').concat(filter, '")'));
458
- return;
459
- }
460
- var bitrateAttr = mf.getAttribute("bitrate");
461
- var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
462
- mediaFiles.push({
463
- url: url,
464
- type: type,
465
- width: parseInt(width || "1920", 10),
466
- height: parseInt(height || "1080", 10),
467
- bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
468
- });
469
- console.log("".concat(logPrefix, ' Added MediaFile: type="').concat(type, '" url="').concat(url.substring(0, 80), '..."'));
470
- });
471
- if (filter === "mp4-first" && mediaFiles.length > 1) {
472
- mediaFiles.sort(function(a, b) {
473
- var aIsMp4 = isMp4Type(a.type) ? 0 : 1;
474
- var bIsMp4 = isMp4Type(b.type) ? 0 : 1;
475
- return aIsMp4 - bIsMp4;
476
- });
477
- }
478
- if (mediaFiles.length === 0) {
479
- if (isNoAdAvailable) {
480
- console.warn("".concat(logPrefix, " No ads available (VAST response indicates no ads)"));
481
- } else {
482
- console.warn("".concat(logPrefix, " No compatible media files found in VAST XML"));
483
- }
484
- return null;
485
- }
486
- var trackingUrls = {
487
- impression: [],
488
- start: [],
489
- firstQuartile: [],
490
- midpoint: [],
491
- thirdQuartile: [],
492
- complete: [],
493
- mute: [],
494
- unmute: [],
495
- pause: [],
496
- resume: [],
497
- fullscreen: [],
498
- exitFullscreen: [],
499
- skip: [],
500
- error: []
501
- };
502
- xmlDoc.querySelectorAll("Impression").forEach(function(el) {
503
- var _el_textContent;
504
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
505
- if (url) trackingUrls.impression.push(url);
506
- });
507
- xmlDoc.querySelectorAll("Tracking").forEach(function(el) {
508
- var _el_textContent;
509
- var event = el.getAttribute("event");
510
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
511
- if (event && url) {
512
- var eventKey = event;
513
- if (trackingUrls[eventKey]) {
514
- trackingUrls[eventKey].push(url);
515
- }
516
- }
517
- });
518
- 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();
519
- return {
520
- id: adId,
521
- title: title,
522
- duration: duration,
523
- mediaFiles: mediaFiles,
524
- trackingUrls: trackingUrls,
525
- clickThrough: clickThrough
526
- };
527
- } catch (error) {
528
- console.error("".concat(logPrefix, " Error parsing VAST XML:"), error);
529
- return null;
530
- }
531
- }
532
- function fetchAndParseVastAd(vastTagUrl) {
533
- var filter = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "all", logPrefix = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "[VastParser]";
534
- return _async_to_generator(function() {
535
- var response, vastXml;
536
- return _ts_generator(this, function(_state) {
537
- switch(_state.label){
538
- case 0:
539
- return [
540
- 4,
541
- fetch(vastTagUrl, {
542
- mode: "cors",
543
- credentials: "include",
544
- headers: {
545
- Accept: "application/xml, text/xml, */*"
546
- },
547
- referrerPolicy: "no-referrer-when-downgrade"
548
- })
549
- ];
550
- case 1:
551
- response = _state.sent();
552
- if (!response.ok) {
553
- throw new Error("Failed to fetch VAST: ".concat(response.statusText));
554
- }
555
- return [
556
- 4,
557
- response.text()
558
- ];
559
- case 2:
560
- vastXml = _state.sent();
561
- console.log("".concat(logPrefix, " VAST XML received"));
562
- console.log("".concat(logPrefix, " VAST XML content (first 2000 chars):"), vastXml.substring(0, 2e3));
563
- return [
564
- 2,
565
- parseVastXml(vastXml, filter, logPrefix)
566
- ];
567
- }
568
- });
569
- })();
570
- }
571
- function createEmptyTrackingState() {
572
- return {
573
- impression: false,
574
- start: false,
575
- firstQuartile: false,
576
- midpoint: false,
577
- thirdQuartile: false,
578
- complete: false
579
- };
580
- }
581
404
  function firePixelWithRetry(url) {
582
405
  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]";
583
406
  return _async_to_generator(function() {
@@ -700,16 +523,164 @@ function fireTrackingPixels(urls, sessionId) {
700
523
  }
701
524
  });
702
525
  }
703
- // src/sdk/vastManager.ts
704
- 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";
705
- var DEFAULT_TIMEOUT_MS = 5e3;
706
- var MAX_RETRIES = 3;
707
- var RETRY_BACKOFF_MS = 1500;
708
- function createVastManager() {
709
- var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
710
- var _options_debug;
711
- var initialized = false;
712
- var debug = (_options_debug = options.debug) !== null && _options_debug !== void 0 ? _options_debug : false;
526
+ // src/sdk/adstormPlayer.ts
527
+ var SUPPORTED_VIDEO_EXTENSIONS = [
528
+ ".mp4",
529
+ ".webm",
530
+ ".ogg",
531
+ ".m3u8",
532
+ ".ts"
533
+ ];
534
+ var UNSUPPORTED_VIDEO_EXTENSIONS = [
535
+ ".flv",
536
+ ".f4v",
537
+ ".swf",
538
+ ".wmv",
539
+ ".avi",
540
+ ".mov",
541
+ ".mkv"
542
+ ];
543
+ var REQUEST_TIMEOUT_MS = 5e3;
544
+ var REQUEST_MAX_RETRIES = 3;
545
+ var REQUEST_RETRY_BACKOFF_MS = 1500;
546
+ var AD_LAYER_Z_INDEX = "2147483646";
547
+ var COUNTDOWN_Z_INDEX = "2147483647";
548
+ var STALL_TIMEOUT_MS = 8e3;
549
+ function getFileExtension(url) {
550
+ try {
551
+ var pathname = new URL(url, "http://dummy").pathname;
552
+ var lastDot = pathname.lastIndexOf(".");
553
+ if (lastDot === -1) return "";
554
+ return pathname.slice(lastDot).toLowerCase();
555
+ } catch (unused) {
556
+ var lastDot1 = url.lastIndexOf(".");
557
+ if (lastDot1 === -1) return "";
558
+ var ext = url.slice(lastDot1).split(/[?#]/)[0];
559
+ return (ext || "").toLowerCase();
560
+ }
561
+ }
562
+ function isUnsupportedFormat(url) {
563
+ var ext = getFileExtension(url);
564
+ return UNSUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1;
565
+ }
566
+ function replaceFlvExtension(url) {
567
+ var ext = getFileExtension(url);
568
+ if (ext === ".flv") {
569
+ return url.replace(/\.flv(\?|$)/i, ".mp4$1");
570
+ }
571
+ return url;
572
+ }
573
+ function isSupportedFormat(url, mimeType) {
574
+ if (isUnsupportedFormat(url)) {
575
+ return false;
576
+ }
577
+ var ext = getFileExtension(url);
578
+ if (SUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1) {
579
+ return true;
580
+ }
581
+ if (ext === "" || ext === ".") {
582
+ return mimeType.includes("video/mp4") || mimeType.includes("video/webm") || mimeType.includes("m3u8") || mimeType.includes("application/x-mpegurl");
583
+ }
584
+ return false;
585
+ }
586
+ function createAdStormPlayer(contentVideo, options) {
587
+ var licenseKey = options.licenseKey, _options_debug = options.debug, debug = _options_debug === void 0 ? false : _options_debug;
588
+ var adPlaying = false;
589
+ var originalMutedState = false;
590
+ var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
591
+ var listeners = /* @__PURE__ */ new Map();
592
+ var adVideoElement;
593
+ var adContainerEl;
594
+ var adCountdownEl;
595
+ var currentAd;
596
+ var destroyed = false;
597
+ var tornDown = false;
598
+ var continueLiveStreamDuringAds = false;
599
+ var sessionId;
600
+ var adStallTimerId;
601
+ var adCountdownTimerId;
602
+ var adHideTimerId;
603
+ var lastCountdownSecond = -1;
604
+ var adListenersBound = false;
605
+ var parentPositionOverridden = false;
606
+ var adHandlers = {
607
+ timeupdate: function timeupdate() {
608
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
609
+ var progress = adVideoElement.currentTime / currentAd.duration;
610
+ if (progress >= 0.25 && !trackingFired.firstQuartile) {
611
+ trackingFired.firstQuartile = true;
612
+ fireTrackingPixels2(currentAd.trackingUrls.firstQuartile);
613
+ }
614
+ if (progress >= 0.5 && !trackingFired.midpoint) {
615
+ trackingFired.midpoint = true;
616
+ fireTrackingPixels2(currentAd.trackingUrls.midpoint);
617
+ }
618
+ if (progress >= 0.75 && !trackingFired.thirdQuartile) {
619
+ trackingFired.thirdQuartile = true;
620
+ fireTrackingPixels2(currentAd.trackingUrls.thirdQuartile);
621
+ }
622
+ updateAdCountdown();
623
+ },
624
+ playing: function playing() {
625
+ clearAdStallTimer();
626
+ if (!currentAd || trackingFired.start || destroyed || tornDown) return;
627
+ trackingFired.start = true;
628
+ fireTrackingPixels2(currentAd.trackingUrls.start);
629
+ startAdCountdown();
630
+ log("Ad started playing");
631
+ },
632
+ ended: function ended() {
633
+ if (!currentAd || trackingFired.complete || destroyed || tornDown) return;
634
+ trackingFired.complete = true;
635
+ fireTrackingPixels2(currentAd.trackingUrls.complete);
636
+ log("Ad completed");
637
+ handleAdComplete();
638
+ },
639
+ error: function error(e) {
640
+ if (destroyed || tornDown) return;
641
+ console.error("[AdStormPlayer] Ad video error:", e);
642
+ if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);
643
+ handleAdError();
644
+ },
645
+ waiting: function waiting() {
646
+ clearAdStallTimer();
647
+ adStallTimerId = setTimeout(function() {
648
+ adStallTimerId = void 0;
649
+ if (!adPlaying || destroyed || tornDown) return;
650
+ console.warn("[AdStormPlayer] Ad playback stalled too long");
651
+ handleAdError();
652
+ }, STALL_TIMEOUT_MS);
653
+ },
654
+ volumechange: function volumechange() {
655
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
656
+ if (adVideoElement.muted || adVideoElement.volume <= 0) {
657
+ fireTrackingPixels2(currentAd.trackingUrls.mute);
658
+ } else {
659
+ fireTrackingPixels2(currentAd.trackingUrls.unmute);
660
+ }
661
+ },
662
+ pause: function pause() {
663
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
664
+ if (!adVideoElement.ended) {
665
+ fireTrackingPixels2(currentAd.trackingUrls.pause);
666
+ }
667
+ },
668
+ play: function play() {
669
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
670
+ if (adVideoElement.currentTime > 0) {
671
+ fireTrackingPixels2(currentAd.trackingUrls.resume);
672
+ }
673
+ }
674
+ };
675
+ var trackingFired = {
676
+ impression: false,
677
+ start: false,
678
+ firstQuartile: false,
679
+ midpoint: false,
680
+ thirdQuartile: false,
681
+ complete: false
682
+ };
683
+ var preloadSlots = /* @__PURE__ */ new Map();
713
684
  function log() {
714
685
  for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
715
686
  args[_key] = arguments[_key];
@@ -717,58 +688,340 @@ function createVastManager() {
717
688
  if (debug) {
718
689
  var _console;
719
690
  (_console = console).log.apply(_console, [
720
- "[VastManager]"
691
+ "[AdStormPlayer]"
721
692
  ].concat(_to_consumable_array(args)));
722
693
  }
723
694
  }
724
- function warn() {
725
- for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
726
- args[_key] = arguments[_key];
695
+ function emit(event, payload) {
696
+ var set = listeners.get(event);
697
+ if (!set) return;
698
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
699
+ try {
700
+ for(var _iterator = Array.from(set)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
701
+ var fn = _step.value;
702
+ try {
703
+ fn(payload);
704
+ } catch (error) {
705
+ console.warn("[AdStormPlayer] Error in event listener for ".concat(event, ":"), error);
706
+ }
707
+ }
708
+ } catch (err) {
709
+ _didIteratorError = true;
710
+ _iteratorError = err;
711
+ } finally{
712
+ try {
713
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
714
+ _iterator.return();
715
+ }
716
+ } finally{
717
+ if (_didIteratorError) {
718
+ throw _iteratorError;
719
+ }
720
+ }
727
721
  }
728
- var _console;
729
- (_console = console).warn.apply(_console, [
730
- "[VastManager]"
731
- ].concat(_to_consumable_array(args)));
732
722
  }
733
- function initialize() {
734
- return _async_to_generator(function() {
735
- return _ts_generator(this, function(_state) {
736
- if (initialized) return [
737
- 2
738
- ];
739
- initialized = true;
740
- log("Initialized, VAST tag URL:", VAST_TAG_URL.split("?")[0]);
741
- return [
742
- 2
743
- ];
723
+ function fireTrackingPixels2(urls) {
724
+ fireTrackingPixels(urls, sessionId, "[AdStormPlayer]");
725
+ }
726
+ function clearAdStallTimer() {
727
+ if (adStallTimerId) {
728
+ clearTimeout(adStallTimerId);
729
+ adStallTimerId = void 0;
730
+ }
731
+ }
732
+ function clearAdCountdownTimer() {
733
+ if (adCountdownTimerId) {
734
+ clearInterval(adCountdownTimerId);
735
+ adCountdownTimerId = void 0;
736
+ }
737
+ lastCountdownSecond = -1;
738
+ }
739
+ function updateAdCountdown() {
740
+ if (!adCountdownEl || !adVideoElement || !currentAd || !adPlaying) return;
741
+ var remainingSec = Math.max(0, Math.ceil((currentAd.duration || 0) - adVideoElement.currentTime));
742
+ if (remainingSec === lastCountdownSecond) return;
743
+ lastCountdownSecond = remainingSec;
744
+ adCountdownEl.textContent = "Ad ".concat(remainingSec, "s");
745
+ emit("ad_countdown", {
746
+ remainingSec: remainingSec,
747
+ durationSec: currentAd.duration,
748
+ currentTimeSec: adVideoElement.currentTime
749
+ });
750
+ }
751
+ function startAdCountdown() {
752
+ clearAdCountdownTimer();
753
+ updateAdCountdown();
754
+ adCountdownTimerId = setInterval(updateAdCountdown, 250);
755
+ }
756
+ function generateSessionId() {
757
+ return "adstorm-".concat(Date.now(), "-").concat(Math.random().toString(36).slice(2, 10));
758
+ }
759
+ function bindAdEventListeners() {
760
+ if (!adVideoElement || adListenersBound) return;
761
+ adVideoElement.addEventListener("timeupdate", adHandlers.timeupdate);
762
+ adVideoElement.addEventListener("playing", adHandlers.playing);
763
+ adVideoElement.addEventListener("ended", adHandlers.ended);
764
+ adVideoElement.addEventListener("error", adHandlers.error);
765
+ adVideoElement.addEventListener("waiting", adHandlers.waiting);
766
+ adVideoElement.addEventListener("volumechange", adHandlers.volumechange);
767
+ adVideoElement.addEventListener("pause", adHandlers.pause);
768
+ adVideoElement.addEventListener("play", adHandlers.play);
769
+ adListenersBound = true;
770
+ }
771
+ function unbindAdEventListeners() {
772
+ if (!adVideoElement || !adListenersBound) return;
773
+ adVideoElement.removeEventListener("timeupdate", adHandlers.timeupdate);
774
+ adVideoElement.removeEventListener("playing", adHandlers.playing);
775
+ adVideoElement.removeEventListener("ended", adHandlers.ended);
776
+ adVideoElement.removeEventListener("error", adHandlers.error);
777
+ adVideoElement.removeEventListener("waiting", adHandlers.waiting);
778
+ adVideoElement.removeEventListener("volumechange", adHandlers.volumechange);
779
+ adVideoElement.removeEventListener("pause", adHandlers.pause);
780
+ adVideoElement.removeEventListener("play", adHandlers.play);
781
+ adListenersBound = false;
782
+ }
783
+ function teardownCurrentPlayback() {
784
+ unbindAdEventListeners();
785
+ clearAdStallTimer();
786
+ clearAdCountdownTimer();
787
+ if (!adVideoElement) return;
788
+ adVideoElement.pause();
789
+ adVideoElement.removeAttribute("src");
790
+ adVideoElement.load();
791
+ }
792
+ function buildVastUrl(durationSeconds, metadata) {
793
+ var baseUrl = "https://adstorm.co/api-adstorm-dev/adstorm/vast/".concat(licenseKey, "/pod");
794
+ var defaultMetadata = {
795
+ video: {
796
+ codec: "h264",
797
+ width: contentVideo.videoWidth || 1280,
798
+ height: contentVideo.videoHeight || 720,
799
+ fps: 29.97,
800
+ bitrate: 5e3,
801
+ profile: "high",
802
+ pix_fmt: "yuv420p",
803
+ has_b_frames: 0
804
+ },
805
+ audio: {
806
+ codec: "aac",
807
+ sample_rate: 48e3,
808
+ bitrate: 128
809
+ }
810
+ };
811
+ var finalMetadata = metadata || defaultMetadata;
812
+ var metadataStr = encodeURIComponent(JSON.stringify(finalMetadata));
813
+ return "".concat(baseUrl, "?duration=").concat(Math.ceil(durationSeconds), "&metadata=").concat(metadataStr);
814
+ }
815
+ function parseVastXml(xmlString) {
816
+ var ads = [];
817
+ try {
818
+ var parser = new DOMParser();
819
+ var xmlDoc = parser.parseFromString(xmlString, "text/xml");
820
+ var parserError = xmlDoc.querySelector("parsererror");
821
+ if (parserError) {
822
+ console.error("[AdStormPlayer] XML parsing error:", parserError.textContent);
823
+ return [];
824
+ }
825
+ var adElements = xmlDoc.querySelectorAll("Ad");
826
+ adElements.forEach(function(adElement) {
827
+ var _adElement_querySelector, _adElement_querySelector1, _adElement_querySelector_textContent, _adElement_querySelector2;
828
+ var adId = adElement.getAttribute("id") || "unknown";
829
+ var title = ((_adElement_querySelector = adElement.querySelector("AdTitle")) === null || _adElement_querySelector === void 0 ? void 0 : _adElement_querySelector.textContent) || "Ad";
830
+ var durationText = ((_adElement_querySelector1 = adElement.querySelector("Duration")) === null || _adElement_querySelector1 === void 0 ? void 0 : _adElement_querySelector1.textContent) || "00:00:30";
831
+ var durationParts = durationText.split(":");
832
+ var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseFloat(durationParts[2] || "0");
833
+ var mediaFileElements = adElement.querySelectorAll("MediaFile");
834
+ var mediaFiles = [];
835
+ mediaFileElements.forEach(function(mf) {
836
+ var _mf_textContent;
837
+ var type = mf.getAttribute("type") || "";
838
+ var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
839
+ var width = parseInt(mf.getAttribute("width") || "1920", 10);
840
+ var height = parseInt(mf.getAttribute("height") || "1080", 10);
841
+ var bitrate = mf.getAttribute("bitrate") ? parseInt(mf.getAttribute("bitrate"), 10) : void 0;
842
+ if (!url) {
843
+ log("Skipping empty MediaFile URL");
844
+ return;
845
+ }
846
+ var originalUrl = url;
847
+ url = replaceFlvExtension(url);
848
+ if (url !== originalUrl) {
849
+ log("Converted FLV to MP4: ".concat(originalUrl, " -> ").concat(url));
850
+ }
851
+ if (isUnsupportedFormat(url)) {
852
+ var ext = getFileExtension(url);
853
+ log("Skipping unsupported format: ".concat(url, " (extension: ").concat(ext, ", declared type: ").concat(type, ")"));
854
+ return;
855
+ }
856
+ if (isSupportedFormat(url, type)) {
857
+ mediaFiles.push({
858
+ url: url,
859
+ type: type,
860
+ width: width,
861
+ height: height,
862
+ bitrate: bitrate
863
+ });
864
+ log("Found media file: ".concat(url, " (").concat(type, ", ").concat(width, "x").concat(height, ")"));
865
+ } else {
866
+ log("Skipping incompatible media file: ".concat(url, " (type: ").concat(type, ")"));
867
+ }
868
+ });
869
+ if (mediaFiles.length === 0) {
870
+ log("No valid media files found in ad:", adId);
871
+ return;
872
+ }
873
+ var trackingUrls = {
874
+ impression: [],
875
+ start: [],
876
+ firstQuartile: [],
877
+ midpoint: [],
878
+ thirdQuartile: [],
879
+ complete: [],
880
+ mute: [],
881
+ unmute: [],
882
+ pause: [],
883
+ resume: [],
884
+ error: []
885
+ };
886
+ adElement.querySelectorAll("Impression").forEach(function(el) {
887
+ var _el_textContent;
888
+ var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
889
+ if (url) trackingUrls.impression.push(url);
890
+ });
891
+ adElement.querySelectorAll("Tracking").forEach(function(el) {
892
+ var _el_textContent;
893
+ var event = el.getAttribute("event");
894
+ var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
895
+ if (event && url) {
896
+ var eventKey = event;
897
+ if (trackingUrls[eventKey]) {
898
+ trackingUrls[eventKey].push(url);
899
+ }
900
+ }
901
+ });
902
+ 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();
903
+ ads.push({
904
+ id: adId,
905
+ title: title,
906
+ duration: duration,
907
+ mediaFiles: mediaFiles,
908
+ trackingUrls: trackingUrls,
909
+ clickThrough: clickThrough
910
+ });
911
+ log("Parsed ad: ".concat(title, ", duration: ").concat(duration, "s, media files: ").concat(mediaFiles.length));
744
912
  });
745
- })();
913
+ } catch (error) {
914
+ console.error("[AdStormPlayer] Error parsing VAST XML:", error);
915
+ }
916
+ return ads;
917
+ }
918
+ function selectBestMediaFile(mediaFiles) {
919
+ if (mediaFiles.length === 0) return null;
920
+ if (mediaFiles.length === 1) return mediaFiles[0];
921
+ var mp4Files = mediaFiles.filter(function(mf) {
922
+ return mf.type.includes("video/mp4");
923
+ });
924
+ var candidates = mp4Files.length > 0 ? mp4Files : mediaFiles;
925
+ var targetWidth = contentVideo.videoWidth || 1280;
926
+ var targetHeight = contentVideo.videoHeight || 720;
927
+ candidates.sort(function(a, b) {
928
+ var diffA = Math.abs(a.width - targetWidth) + Math.abs(a.height - targetHeight);
929
+ var diffB = Math.abs(b.width - targetWidth) + Math.abs(b.height - targetHeight);
930
+ return diffA - diffB;
931
+ });
932
+ return candidates[0] || null;
933
+ }
934
+ function createAdVideoElement() {
935
+ var video = document.createElement("video");
936
+ video.style.position = "absolute";
937
+ video.style.left = "0";
938
+ video.style.top = "0";
939
+ video.style.width = "100%";
940
+ video.style.height = "100%";
941
+ video.style.objectFit = "contain";
942
+ video.style.backgroundColor = "#000";
943
+ video.style.zIndex = "1";
944
+ video.playsInline = true;
945
+ video.preload = "auto";
946
+ video.muted = originalMutedState;
947
+ video.volume = originalMutedState ? 0 : originalVolume;
948
+ return video;
949
+ }
950
+ function setAdPlayingFlag(isPlaying) {
951
+ if (isPlaying) {
952
+ contentVideo.dataset.stormcloudAdPlaying = "true";
953
+ } else {
954
+ delete contentVideo.dataset.stormcloudAdPlaying;
955
+ }
956
+ }
957
+ function setupAdEventListeners() {
958
+ bindAdEventListeners();
959
+ }
960
+ function handleAdComplete() {
961
+ if (destroyed || tornDown) return;
962
+ log("Handling ad completion");
963
+ adPlaying = false;
964
+ setAdPlayingFlag(false);
965
+ clearAdStallTimer();
966
+ clearAdCountdownTimer();
967
+ if (adContainerEl) {
968
+ adContainerEl.style.opacity = "0";
969
+ adHideTimerId = setTimeout(function() {
970
+ if (adContainerEl) {
971
+ adContainerEl.style.display = "none";
972
+ adContainerEl.style.pointerEvents = "none";
973
+ }
974
+ }, 300);
975
+ }
976
+ contentVideo.style.visibility = "visible";
977
+ contentVideo.style.opacity = "1";
978
+ contentVideo.muted = originalMutedState;
979
+ contentVideo.volume = originalVolume;
980
+ currentAd = void 0;
981
+ emit("content_resume");
982
+ emit("all_ads_completed");
983
+ }
984
+ function handleAdError() {
985
+ if (destroyed || tornDown) return;
986
+ log("Handling ad error");
987
+ if (!adPlaying) return;
988
+ adPlaying = false;
989
+ setAdPlayingFlag(false);
990
+ clearAdStallTimer();
991
+ clearAdCountdownTimer();
992
+ contentVideo.muted = originalMutedState;
993
+ contentVideo.volume = originalVolume;
994
+ contentVideo.style.visibility = "visible";
995
+ contentVideo.style.opacity = "1";
996
+ if (adContainerEl) {
997
+ adContainerEl.style.display = "none";
998
+ adContainerEl.style.pointerEvents = "none";
999
+ }
1000
+ currentAd = void 0;
1001
+ emit("ad_error");
1002
+ emit("content_resume");
746
1003
  }
747
- function requestBids(_context) {
1004
+ function fetchVastOnce(durationSeconds) {
748
1005
  return _async_to_generator(function() {
749
- var correlator, url, controller, timeoutId, _ref, _ref1, _vastAd_mediaFiles_, _vastAd_mediaFiles_1, fetchOptions, response, vastXml, vastAd, bid, error;
1006
+ var vastUrl, controller, timeoutId, requestInit, response, xmlText;
750
1007
  return _ts_generator(this, function(_state) {
751
1008
  switch(_state.label){
752
1009
  case 0:
753
- if (!initialized) {
754
- throw new Error("VastManager not initialized. Call initialize() first.");
755
- }
756
- correlator = Math.floor(Math.random() * 1e12).toString();
757
- url = VAST_TAG_URL.replace("[placeholder]", correlator);
758
- log("Fetching VAST tag, correlator:", correlator);
1010
+ vastUrl = buildVastUrl(durationSeconds);
1011
+ log("Fetching VAST from:", vastUrl);
759
1012
  controller = typeof AbortController !== "undefined" ? new AbortController() : null;
760
1013
  timeoutId = setTimeout(function() {
761
1014
  return controller === null || controller === void 0 ? void 0 : controller.abort();
762
- }, DEFAULT_TIMEOUT_MS);
1015
+ }, REQUEST_TIMEOUT_MS);
763
1016
  _state.label = 1;
764
1017
  case 1:
765
1018
  _state.trys.push([
766
1019
  1,
767
- 4,
768
1020
  ,
1021
+ 4,
769
1022
  5
770
1023
  ]);
771
- fetchOptions = {
1024
+ requestInit = {
772
1025
  method: "GET",
773
1026
  mode: "cors",
774
1027
  credentials: "omit",
@@ -777,62 +1030,34 @@ function createVastManager() {
777
1030
  },
778
1031
  referrerPolicy: "no-referrer-when-downgrade"
779
1032
  };
780
- if (controller) fetchOptions.signal = controller.signal;
1033
+ if (controller) {
1034
+ requestInit.signal = controller.signal;
1035
+ }
781
1036
  return [
782
1037
  4,
783
- fetch(url, fetchOptions)
1038
+ fetch(vastUrl, requestInit)
784
1039
  ];
785
1040
  case 2:
786
1041
  response = _state.sent();
787
- clearTimeout(timeoutId);
788
1042
  if (!response.ok) {
789
- throw new Error("VAST request returned HTTP ".concat(response.status));
1043
+ throw new Error("Failed to fetch VAST: ".concat(response.status, " ").concat(response.statusText));
790
1044
  }
791
1045
  return [
792
1046
  4,
793
1047
  response.text()
794
1048
  ];
795
1049
  case 3:
796
- vastXml = _state.sent();
797
- log("VAST XML received, length:", vastXml.length);
798
- vastAd = parseVastXml(vastXml, "mp4-first", "[VastManager]");
799
- if (!vastAd) {
800
- log("VAST parsed but no usable ad found");
801
- return [
802
- 2,
803
- []
804
- ];
805
- }
806
- log("Ad parsed: id=".concat(vastAd.id, ", duration=").concat(vastAd.duration, "s, mediaFiles=").concat(vastAd.mediaFiles.length));
807
- bid = {
808
- bidder: "vast-direct",
809
- cpm: 0,
810
- vastXml: vastXml,
811
- width: (_ref = (_vastAd_mediaFiles_ = vastAd.mediaFiles[0]) === null || _vastAd_mediaFiles_ === void 0 ? void 0 : _vastAd_mediaFiles_.width) !== null && _ref !== void 0 ? _ref : 0,
812
- 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,
813
- adId: vastAd.id,
814
- impId: correlator,
815
- creativeId: vastAd.id,
816
- currency: "USD",
817
- durationSec: vastAd.duration
818
- };
1050
+ xmlText = _state.sent();
1051
+ log("VAST response received, length:", xmlText.length);
819
1052
  return [
820
1053
  2,
821
- [
822
- bid
823
- ]
1054
+ parseVastXml(xmlText)
824
1055
  ];
825
1056
  case 4:
826
- error = _state.sent();
827
1057
  clearTimeout(timeoutId);
828
- if ((error === null || error === void 0 ? void 0 : error.name) === "AbortError") {
829
- warn("VAST request timed out after ".concat(DEFAULT_TIMEOUT_MS, "ms"));
830
- return [
831
- 2,
832
- []
833
- ];
834
- }
835
- throw error;
1058
+ return [
1059
+ 7
1060
+ ];
836
1061
  case 5:
837
1062
  return [
838
1063
  2
@@ -841,14 +1066,14 @@ function createVastManager() {
841
1066
  });
842
1067
  })();
843
1068
  }
844
- function requestBidsUntilResponse(context) {
1069
+ function fetchVast(durationSeconds) {
845
1070
  return _async_to_generator(function() {
846
1071
  var _loop, lastError, attempt, _ret;
847
1072
  return _ts_generator(this, function(_state) {
848
1073
  switch(_state.label){
849
1074
  case 0:
850
1075
  _loop = function(attempt) {
851
- var bids, err, delay;
1076
+ var ads, error, delay;
852
1077
  return _ts_generator(this, function(_state) {
853
1078
  switch(_state.label){
854
1079
  case 0:
@@ -860,39 +1085,39 @@ function createVastManager() {
860
1085
  ]);
861
1086
  return [
862
1087
  4,
863
- requestBids(context)
1088
+ fetchVastOnce(durationSeconds)
864
1089
  ];
865
1090
  case 1:
866
- bids = _state.sent();
867
- if (bids.length > 0) {
868
- log("requestBidsUntilResponse: got ".concat(bids.length, " ad(s) on attempt ").concat(attempt));
869
- return [
870
- 2,
871
- {
872
- v: bids
873
- }
874
- ];
875
- }
876
- log("requestBidsUntilResponse: no ads on attempt ".concat(attempt, "/").concat(MAX_RETRIES));
1091
+ ads = _state.sent();
1092
+ if (ads.length > 0) return [
1093
+ 2,
1094
+ {
1095
+ v: ads
1096
+ }
1097
+ ];
1098
+ log("No ad returned from VAST on attempt ".concat(attempt, "/").concat(REQUEST_MAX_RETRIES));
877
1099
  return [
878
1100
  3,
879
1101
  3
880
1102
  ];
881
1103
  case 2:
882
- err = _state.sent();
883
- lastError = err;
884
- warn("requestBidsUntilResponse: attempt ".concat(attempt, "/").concat(MAX_RETRIES, " failed:"), err);
1104
+ error = _state.sent();
1105
+ lastError = error;
1106
+ if ((error === null || error === void 0 ? void 0 : error.name) === "AbortError") {
1107
+ console.warn("[AdStormPlayer] VAST request timed out (".concat(REQUEST_TIMEOUT_MS, "ms), attempt ").concat(attempt, "/").concat(REQUEST_MAX_RETRIES));
1108
+ } else {
1109
+ console.warn("[AdStormPlayer] VAST request failed on attempt ".concat(attempt, "/").concat(REQUEST_MAX_RETRIES, ":"), error);
1110
+ }
885
1111
  return [
886
1112
  3,
887
1113
  3
888
1114
  ];
889
1115
  case 3:
890
- if (!(attempt < MAX_RETRIES)) return [
1116
+ if (!(attempt < REQUEST_MAX_RETRIES)) return [
891
1117
  3,
892
1118
  5
893
1119
  ];
894
- delay = RETRY_BACKOFF_MS * attempt;
895
- log("requestBidsUntilResponse: waiting ".concat(delay, "ms before retry"));
1120
+ delay = REQUEST_RETRY_BACKOFF_MS * attempt;
896
1121
  return [
897
1122
  4,
898
1123
  new Promise(function(resolve) {
@@ -909,13 +1134,10 @@ function createVastManager() {
909
1134
  }
910
1135
  });
911
1136
  };
912
- if (!initialized) {
913
- throw new Error("VastManager not initialized. Call initialize() first.");
914
- }
915
1137
  attempt = 1;
916
1138
  _state.label = 1;
917
1139
  case 1:
918
- if (!(attempt <= MAX_RETRIES)) return [
1140
+ if (!(attempt <= REQUEST_MAX_RETRIES)) return [
919
1141
  3,
920
1142
  4
921
1143
  ];
@@ -937,7 +1159,9 @@ function createVastManager() {
937
1159
  1
938
1160
  ];
939
1161
  case 4:
940
- if (_instanceof(lastError, Error)) throw lastError;
1162
+ if (_instanceof(lastError, Error)) {
1163
+ throw lastError;
1164
+ }
941
1165
  return [
942
1166
  2,
943
1167
  []
@@ -946,971 +1170,468 @@ function createVastManager() {
946
1170
  });
947
1171
  })();
948
1172
  }
949
- function destroy() {
950
- initialized = false;
951
- log("Destroyed");
952
- }
953
- return {
954
- initialize: initialize,
955
- requestBids: requestBids,
956
- requestBidsUntilResponse: requestBidsUntilResponse,
957
- destroy: destroy,
958
- get isInitialized () {
959
- return initialized;
1173
+ function getDurationSecondsFromContext(requestContext) {
1174
+ var _ctx_remainingBreakSec;
1175
+ if (!requestContext || (typeof requestContext === "undefined" ? "undefined" : _type_of(requestContext)) !== "object") {
1176
+ return 30;
960
1177
  }
961
- };
962
- }
963
- // src/sdk/vastAdLayer.ts
964
- var import_hls = __toESM(require("hls.js"), 1);
965
- var LOG = "[VastAdLayer]";
966
- function resolveBidToVastAd(winner, logPrefix) {
967
- if (winner.vastXml) {
968
- var ad = parseVastXml(winner.vastXml, "mp4-first", logPrefix);
969
- return Promise.resolve(ad);
970
- }
971
- if (winner.vastUrl) {
972
- return fetchAndParseVastAd(winner.vastUrl, "mp4-first", logPrefix);
973
- }
974
- return Promise.resolve(null);
975
- }
976
- function createVastAdLayer(contentVideo, options) {
977
- var _ref, _ref1, _ref2, _ref3, _ref4;
978
- var adPlaying = false;
979
- var originalMutedState = false;
980
- var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
981
- var listeners = /* @__PURE__ */ new Map();
982
- var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
983
- var continueLiveStreamDuringAds = (_ref = options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) !== null && _ref !== void 0 ? _ref : false;
984
- var smartTVMode = (_ref1 = options === null || options === void 0 ? void 0 : options.smartTVMode) !== null && _ref1 !== void 0 ? _ref1 : false;
985
- var singleElementMode = (_ref2 = options === null || options === void 0 ? void 0 : options.singleElementMode) !== null && _ref2 !== void 0 ? _ref2 : false;
986
- var forceMP4Ads = (_ref3 = options === null || options === void 0 ? void 0 : options.forceMP4Ads) !== null && _ref3 !== void 0 ? _ref3 : smartTVMode || singleElementMode;
987
- var debug = (_ref4 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref4 !== void 0 ? _ref4 : false;
988
- var adVideoElement;
989
- var adHls;
990
- var adContainerEl;
991
- var currentAd;
992
- var sessionId;
993
- var destroyed = false;
994
- var tornDown = false;
995
- var trackingFired = createEmptyTrackingState();
996
- var adStallTimerId;
997
- var savedContentVideoStyles;
998
- var currentAdEventHandlers;
999
- var preloadSlots = /* @__PURE__ */ new Map();
1000
- function emit(event, payload) {
1001
- var set = listeners.get(event);
1002
- if (!set) return;
1003
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1004
- try {
1005
- for(var _iterator = Array.from(set)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1006
- var fn = _step.value;
1007
- try {
1008
- fn(payload);
1009
- } catch (error) {
1010
- console.warn("".concat(LOG, " Error in event listener for ").concat(event, ":"), error);
1011
- }
1012
- }
1013
- } catch (err) {
1014
- _didIteratorError = true;
1015
- _iteratorError = err;
1016
- } finally{
1017
- try {
1018
- if (!_iteratorNormalCompletion && _iterator.return != null) {
1019
- _iterator.return();
1020
- }
1021
- } finally{
1022
- if (_didIteratorError) {
1023
- throw _iteratorError;
1024
- }
1025
- }
1026
- }
1027
- }
1028
- function generateSessionId() {
1029
- return "session-".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
1030
- }
1031
- function fireTrackingPixels2(urls) {
1032
- fireTrackingPixels(urls, sessionId, LOG);
1033
- }
1034
- function getMainStreamQuality() {
1035
- if (!(mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.levels)) return null;
1036
- var currentLevel = mainHlsInstance.currentLevel;
1037
- if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {
1038
- var autoLevel = mainHlsInstance.loadLevel;
1039
- if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {
1040
- var level2 = mainHlsInstance.levels[autoLevel];
1041
- return {
1042
- width: level2.width || 1920,
1043
- height: level2.height || 1080,
1044
- bitrate: level2.bitrate || 5e6
1045
- };
1046
- }
1047
- return null;
1048
- }
1049
- var level = mainHlsInstance.levels[currentLevel];
1050
- return {
1051
- width: level.width || 1920,
1052
- height: level.height || 1080,
1053
- bitrate: level.bitrate || 5e6
1054
- };
1055
- }
1056
- function selectBestMediaFile(mediaFiles) {
1057
- var _ref;
1058
- var _scoredFiles_;
1059
- if (mediaFiles.length === 0) throw new Error("No media files available");
1060
- var candidates = mediaFiles;
1061
- if (forceMP4Ads) {
1062
- var mp4Only = candidates.filter(function(f) {
1063
- return !isHlsMediaFile(f);
1064
- });
1065
- if (mp4Only.length > 0) {
1066
- candidates = mp4Only;
1067
- if (debug) console.log("".concat(LOG, " forceMP4Ads: filtered to ").concat(mp4Only.length, " MP4-only file(s)"));
1068
- } else if (debug) {
1069
- console.warn("".concat(LOG, " forceMP4Ads: no MP4 files available, falling back to all media files"));
1070
- }
1071
- } else {
1072
- var mp4Only1 = candidates.filter(function(f) {
1073
- return !isHlsMediaFile(f);
1074
- });
1075
- if (mp4Only1.length > 0) {
1076
- candidates = mp4Only1;
1077
- if (debug) console.log("".concat(LOG, " Preferring ").concat(mp4Only1.length, " MP4 file(s) over HLS (mp4-first)"));
1078
- }
1079
- }
1080
- var firstFile = candidates[0];
1081
- if (candidates.length === 1) return firstFile;
1082
- var mainQuality = getMainStreamQuality();
1083
- if (!mainQuality) {
1084
- if (debug) console.log("".concat(LOG, " No main stream quality info, using first media file"));
1085
- return firstFile;
1086
- }
1087
- var scoredFiles = candidates.map(function(file) {
1088
- var widthDiff = Math.abs(file.width - mainQuality.width);
1089
- var heightDiff = Math.abs(file.height - mainQuality.height);
1090
- var resolutionDiff = widthDiff + heightDiff;
1091
- var fileBitrate = (file.bitrate || 5e3) * 1e3;
1092
- var bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);
1093
- var score = resolutionDiff * 2 + bitrateDiff / 1e3;
1094
- return {
1095
- file: file,
1096
- score: score
1097
- };
1098
- });
1099
- scoredFiles.sort(function(a, b) {
1100
- return a.score - b.score;
1101
- });
1102
- return (_ref = (_scoredFiles_ = scoredFiles[0]) === null || _scoredFiles_ === void 0 ? void 0 : _scoredFiles_.file) !== null && _ref !== void 0 ? _ref : firstFile;
1103
- }
1104
- function isHlsMediaFile(file) {
1105
- return file.type === "application/x-mpegURL" || file.type.includes("m3u8");
1106
- }
1107
- function createAdVideoElement() {
1108
- var video = document.createElement("video");
1109
- video.style.position = "absolute";
1110
- video.style.left = "0";
1111
- video.style.top = "0";
1112
- video.style.width = "100%";
1113
- video.style.height = "100%";
1114
- video.style.objectFit = "cover";
1115
- video.style.backgroundColor = "#000";
1116
- video.playsInline = true;
1117
- video.muted = false;
1118
- video.volume = 1;
1119
- return video;
1120
- }
1121
- function clearAdStallTimer() {
1122
- if (adStallTimerId != null) {
1123
- clearTimeout(adStallTimerId);
1124
- adStallTimerId = void 0;
1125
- }
1126
- }
1127
- function removeAdEventListeners() {
1128
- clearAdStallTimer();
1129
- if (!currentAdEventHandlers || !adVideoElement) return;
1130
- var el = adVideoElement;
1131
- el.removeEventListener("timeupdate", currentAdEventHandlers.timeupdate);
1132
- el.removeEventListener("playing", currentAdEventHandlers.playing);
1133
- el.removeEventListener("ended", currentAdEventHandlers.ended);
1134
- el.removeEventListener("error", currentAdEventHandlers.error);
1135
- el.removeEventListener("volumechange", currentAdEventHandlers.volumechange);
1136
- el.removeEventListener("pause", currentAdEventHandlers.pause);
1137
- el.removeEventListener("play", currentAdEventHandlers.play);
1138
- el.removeEventListener("waiting", currentAdEventHandlers.waiting);
1139
- currentAdEventHandlers = void 0;
1140
- }
1141
- function setupAdEventListeners() {
1142
- if (!adVideoElement) return;
1143
- removeAdEventListeners();
1144
- var handlers = {
1145
- timeupdate: function timeupdate() {
1146
- var ad = currentAd;
1147
- if (!ad || !adVideoElement) return;
1148
- var progress = adVideoElement.currentTime / ad.duration;
1149
- if (progress >= 0.25 && !trackingFired.firstQuartile) {
1150
- trackingFired.firstQuartile = true;
1151
- fireTrackingPixels2(ad.trackingUrls.firstQuartile);
1152
- }
1153
- if (progress >= 0.5 && !trackingFired.midpoint) {
1154
- trackingFired.midpoint = true;
1155
- fireTrackingPixels2(ad.trackingUrls.midpoint);
1156
- }
1157
- if (progress >= 0.75 && !trackingFired.thirdQuartile) {
1158
- trackingFired.thirdQuartile = true;
1159
- fireTrackingPixels2(ad.trackingUrls.thirdQuartile);
1160
- }
1161
- },
1162
- playing: function playing() {
1163
- clearAdStallTimer();
1164
- var ad = currentAd;
1165
- if (!ad || trackingFired.start) return;
1166
- trackingFired.start = true;
1167
- fireTrackingPixels2(ad.trackingUrls.start);
1168
- if (debug) console.log("".concat(LOG, " Ad started playing"));
1169
- },
1170
- ended: function ended() {
1171
- if (tornDown || !currentAd || trackingFired.complete) return;
1172
- trackingFired.complete = true;
1173
- fireTrackingPixels2(currentAd.trackingUrls.complete);
1174
- if (debug) console.log("".concat(LOG, " Ad completed"));
1175
- handleAdComplete();
1176
- },
1177
- error: function error(e) {
1178
- if (tornDown) return;
1179
- console.error("".concat(LOG, " Ad video error:"), e);
1180
- if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);
1181
- handleAdError();
1182
- },
1183
- volumechange: function volumechange() {
1184
- if (!currentAd || !adVideoElement) return;
1185
- if (adVideoElement.muted) {
1186
- fireTrackingPixels2(currentAd.trackingUrls.mute);
1187
- } else {
1188
- fireTrackingPixels2(currentAd.trackingUrls.unmute);
1189
- }
1190
- },
1191
- pause: function pause() {
1192
- if (currentAd && adVideoElement && !adVideoElement.ended) {
1193
- fireTrackingPixels2(currentAd.trackingUrls.pause);
1194
- }
1195
- },
1196
- play: function play() {
1197
- if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1198
- fireTrackingPixels2(currentAd.trackingUrls.resume);
1199
- }
1200
- },
1201
- waiting: function waiting() {
1202
- clearAdStallTimer();
1203
- adStallTimerId = setTimeout(function() {
1204
- adStallTimerId = void 0;
1205
- if (adPlaying) {
1206
- if (debug) console.warn("".concat(LOG, " Ad video stalled for too long, treating as error"));
1207
- handleAdError();
1208
- }
1209
- }, 8e3);
1210
- }
1211
- };
1212
- adVideoElement.addEventListener("timeupdate", handlers.timeupdate);
1213
- adVideoElement.addEventListener("playing", handlers.playing);
1214
- adVideoElement.addEventListener("ended", handlers.ended);
1215
- adVideoElement.addEventListener("error", handlers.error);
1216
- adVideoElement.addEventListener("volumechange", handlers.volumechange);
1217
- adVideoElement.addEventListener("pause", handlers.pause);
1218
- adVideoElement.addEventListener("play", handlers.play);
1219
- adVideoElement.addEventListener("waiting", handlers.waiting);
1220
- currentAdEventHandlers = handlers;
1221
- }
1222
- function setAdPlayingFlag(isPlaying) {
1223
- if (isPlaying) {
1224
- contentVideo.dataset.stormcloudAdPlaying = "true";
1225
- } else {
1226
- delete contentVideo.dataset.stormcloudAdPlaying;
1227
- }
1228
- }
1229
- function applyContentVideoAdCoverStyles() {
1230
- if (!singleElementMode) return;
1231
- savedContentVideoStyles = {
1232
- objectFit: contentVideo.style.objectFit,
1233
- width: contentVideo.style.width,
1234
- height: contentVideo.style.height
1235
- };
1236
- contentVideo.style.objectFit = "cover";
1237
- contentVideo.style.width = "100%";
1238
- contentVideo.style.height = "100%";
1239
- }
1240
- function restoreContentVideoStyles() {
1241
- if (!singleElementMode || !savedContentVideoStyles) return;
1242
- contentVideo.style.objectFit = savedContentVideoStyles.objectFit;
1243
- contentVideo.style.width = savedContentVideoStyles.width;
1244
- contentVideo.style.height = savedContentVideoStyles.height;
1245
- savedContentVideoStyles = void 0;
1246
- }
1247
- function handleAdComplete() {
1248
- if (tornDown) return;
1249
- clearAdStallTimer();
1250
- if (debug) console.log("".concat(LOG, " Handling ad completion"));
1251
- adPlaying = false;
1252
- setAdPlayingFlag(false);
1253
- restoreContentVideoStyles();
1254
- if (adContainerEl) {
1255
- adContainerEl.style.display = "none";
1256
- adContainerEl.style.pointerEvents = "none";
1257
- }
1258
- emit("ad_impression");
1259
- emit("content_resume");
1260
- }
1261
- function handleAdError() {
1262
- if (tornDown) return;
1263
- if (!adPlaying) return;
1264
- clearAdStallTimer();
1265
- if (debug) console.log("".concat(LOG, " Handling ad error"));
1266
- adPlaying = false;
1267
- setAdPlayingFlag(false);
1268
- restoreContentVideoStyles();
1269
- if (adContainerEl) {
1270
- adContainerEl.style.display = "none";
1271
- adContainerEl.style.pointerEvents = "none";
1272
- }
1273
- emit("ad_error");
1274
- }
1275
- function teardownCurrentPlayback() {
1276
- removeAdEventListeners();
1277
- if (adHls) {
1278
- adHls.destroy();
1279
- adHls = void 0;
1280
- }
1281
- if (adVideoElement) {
1282
- if (singleElementMode && adVideoElement === contentVideo) {
1283
- contentVideo.pause();
1284
- } else {
1285
- adVideoElement.pause();
1286
- adVideoElement.removeAttribute("src");
1287
- adVideoElement.load();
1288
- }
1289
- }
1290
- }
1291
- function startNativePlayback(mediaFile) {
1292
- if (!adVideoElement) return;
1293
- if (debug) console.log("".concat(LOG, " Starting native MP4 playback: ").concat(mediaFile.url));
1294
- adVideoElement.src = mediaFile.url;
1295
- adVideoElement.load();
1296
- adVideoElement.play().catch(function(error) {
1297
- console.error("".concat(LOG, " Error starting native ad playback:"), error);
1298
- handleAdError();
1299
- });
1300
- }
1301
- function startHlsPlayback(mediaFile) {
1302
- if (!adVideoElement) return;
1303
- if (debug) console.log("".concat(LOG, " Starting HLS playback: ").concat(mediaFile.url));
1304
- if (import_hls.default.isSupported()) {
1305
- if (adHls) {
1306
- adHls.destroy();
1307
- adHls = void 0;
1308
- }
1309
- adHls = new import_hls.default({
1310
- enableWorker: true,
1311
- lowLatencyMode: false
1312
- });
1313
- adHls.loadSource(mediaFile.url);
1314
- adHls.attachMedia(adVideoElement);
1315
- adHls.on(import_hls.default.Events.MANIFEST_PARSED, function() {
1316
- if (!adPlaying) return;
1317
- adVideoElement.play().catch(function(error) {
1318
- console.error("".concat(LOG, " Error starting HLS ad playback:"), error);
1319
- handleAdError();
1320
- });
1321
- });
1322
- var nonFatalNetworkErrors = 0;
1323
- adHls.on(import_hls.default.Events.ERROR, function(_event, data) {
1324
- if (data.fatal) {
1325
- handleAdError();
1326
- } else if (data.type === import_hls.default.ErrorTypes.NETWORK_ERROR) {
1327
- nonFatalNetworkErrors++;
1328
- if (nonFatalNetworkErrors >= 3) {
1329
- if (debug) console.warn("".concat(LOG, " Too many non-fatal HLS network errors (").concat(nonFatalNetworkErrors, "), treating as fatal"));
1330
- handleAdError();
1331
- }
1332
- }
1333
- });
1334
- } else if (adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
1335
- adVideoElement.src = mediaFile.url;
1336
- adVideoElement.play().catch(function(error) {
1337
- console.error("".concat(LOG, " Error starting native HLS ad playback:"), error);
1338
- handleAdError();
1339
- });
1340
- } else {
1341
- console.error("".concat(LOG, " HLS not supported on this platform"));
1342
- handleAdError();
1178
+ var ctx = requestContext;
1179
+ var value = (_ctx_remainingBreakSec = ctx.remainingBreakSec) !== null && _ctx_remainingBreakSec !== void 0 ? _ctx_remainingBreakSec : ctx.breakDurationSec;
1180
+ if (typeof value !== "number" || Number.isNaN(value)) {
1181
+ return 30;
1343
1182
  }
1183
+ return Math.max(1, Math.ceil(value));
1344
1184
  }
1345
- function startPlayback(mediaFile) {
1346
- if (!adVideoElement) return;
1347
- if (singleElementMode && isHlsMediaFile(mediaFile)) {
1348
- var mp4Fallback = currentAd === null || currentAd === void 0 ? void 0 : currentAd.mediaFiles.find(function(f) {
1349
- return !isHlsMediaFile(f);
1350
- });
1351
- if (mp4Fallback) {
1352
- if (debug) console.log("".concat(LOG, " singleElementMode: HLS ad blocked, using MP4 fallback"));
1353
- startNativePlayback(mp4Fallback);
1354
- return;
1355
- }
1356
- }
1357
- if (isHlsMediaFile(mediaFile)) {
1358
- startHlsPlayback(mediaFile);
1359
- } else {
1360
- startNativePlayback(mediaFile);
1361
- }
1362
- }
1363
- function playAd(bids) {
1185
+ function requestAdFromApi(requestContext) {
1364
1186
  return _async_to_generator(function() {
1365
- var winner, ad, contentVolume, adVolume2, mediaFile2, _contentVideo_parentElement, container, adVolume, mediaFile;
1187
+ var durationSeconds, ads;
1366
1188
  return _ts_generator(this, function(_state) {
1367
1189
  switch(_state.label){
1368
1190
  case 0:
1369
- if (destroyed) {
1370
- return [
1371
- 2,
1372
- Promise.reject(new Error("Layer has been destroyed"))
1373
- ];
1374
- }
1375
- if (bids.length === 0) {
1376
- return [
1377
- 2,
1378
- Promise.reject(new Error("No bids provided"))
1379
- ];
1380
- }
1381
- winner = bids[0];
1382
- if (debug) {
1383
- console.log("".concat(LOG, " Winning bid: ").concat(winner.bidder, " $").concat(winner.cpm.toFixed(2), " ").concat(winner.currency));
1384
- }
1191
+ durationSeconds = getDurationSecondsFromContext(requestContext);
1385
1192
  return [
1386
1193
  4,
1387
- resolveBidToVastAd(winner, LOG)
1194
+ fetchVast(durationSeconds)
1388
1195
  ];
1389
1196
  case 1:
1390
- ad = _state.sent();
1391
- if (!ad) {
1392
- if (debug) console.warn("".concat(LOG, " Winning bid has no VAST URL or XML"));
1393
- emit("ad_error");
1394
- return [
1395
- 2,
1396
- Promise.reject(new Error("No VAST from bid"))
1397
- ];
1398
- }
1399
- if (debug) {
1400
- console.log("".concat(LOG, " Ad parsed: ").concat(ad.title, ", duration: ").concat(ad.duration, "s, mediaFiles: ").concat(ad.mediaFiles.length));
1401
- }
1402
- sessionId = generateSessionId();
1403
- currentAd = ad;
1404
- trackingFired = _object_spread({}, createEmptyTrackingState());
1405
- fireTrackingPixels2(ad.trackingUrls.impression);
1406
- trackingFired.impression = true;
1407
- contentVolume = contentVideo.volume;
1408
- originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1409
- if (!singleElementMode) return [
1410
- 3,
1411
- 3
1412
- ];
1413
- mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.detachMedia();
1414
- teardownCurrentPlayback();
1415
- adVideoElement = contentVideo;
1416
- adHls = void 0;
1417
- adPlaying = true;
1418
- setAdPlayingFlag(true);
1419
- contentVideo.removeAttribute("src");
1420
- contentVideo.load();
1421
- if (!continueLiveStreamDuringAds) {
1422
- contentVideo.pause();
1423
- }
1424
- contentVideo.muted = true;
1425
- contentVideo.volume = 0;
1197
+ ads = _state.sent();
1426
1198
  return [
1427
- 4,
1428
- new Promise(function(resolve) {
1429
- return setTimeout(resolve, 200);
1430
- })
1431
- ];
1432
- case 2:
1433
- _state.sent();
1434
- if (destroyed || tornDown) return [
1435
- 2
1436
- ];
1437
- contentVideo.style.visibility = "visible";
1438
- contentVideo.style.opacity = "1";
1439
- applyContentVideoAdCoverStyles();
1440
- emit("content_pause");
1441
- setupAdEventListeners();
1442
- adVolume2 = originalMutedState ? 1 : originalVolume;
1443
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume2));
1444
- adVideoElement.muted = false;
1445
- mediaFile2 = selectBestMediaFile(ad.mediaFiles);
1446
- if (debug) console.log("".concat(LOG, " Loading ad from: ").concat(mediaFile2.url));
1447
- startPlayback(mediaFile2);
1448
- return [
1449
- 2
1450
- ];
1451
- case 3:
1452
- if (!adContainerEl) {
1453
- ;
1454
- container = document.createElement("div");
1455
- container.style.position = "absolute";
1456
- container.style.left = "0";
1457
- container.style.top = "0";
1458
- container.style.right = "0";
1459
- container.style.bottom = "0";
1460
- container.style.display = "none";
1461
- container.style.alignItems = "center";
1462
- container.style.justifyContent = "center";
1463
- container.style.pointerEvents = "none";
1464
- container.style.zIndex = "10";
1465
- container.style.backgroundColor = "#000";
1466
- (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1467
- adContainerEl = container;
1468
- }
1469
- if (!adVideoElement) {
1470
- adVideoElement = createAdVideoElement();
1471
- adContainerEl.appendChild(adVideoElement);
1472
- setupAdEventListeners();
1473
- } else {
1474
- teardownCurrentPlayback();
1475
- }
1476
- if (!continueLiveStreamDuringAds) {
1477
- contentVideo.pause();
1478
- }
1479
- contentVideo.muted = true;
1480
- contentVideo.volume = 0;
1481
- adPlaying = true;
1482
- setAdPlayingFlag(true);
1483
- adVolume = originalMutedState ? 1 : originalVolume;
1484
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
1485
- adVideoElement.muted = false;
1486
- if (adContainerEl) {
1487
- adContainerEl.style.display = "flex";
1488
- adContainerEl.style.pointerEvents = "auto";
1489
- }
1490
- emit("content_pause");
1491
- mediaFile = selectBestMediaFile(ad.mediaFiles);
1492
- if (debug) console.log("".concat(LOG, " Loading ad from: ").concat(mediaFile.url));
1493
- startPlayback(mediaFile);
1494
- return [
1495
- 2
1199
+ 2,
1200
+ ads[0] || null
1496
1201
  ];
1497
1202
  }
1498
1203
  });
1499
1204
  })();
1500
1205
  }
1501
- function ensureAdContainer() {
1502
- if (!adContainerEl) {
1503
- var _contentVideo_parentElement;
1504
- var container = document.createElement("div");
1505
- container.style.position = "absolute";
1506
- container.style.left = "0";
1507
- container.style.top = "0";
1508
- container.style.right = "0";
1509
- container.style.bottom = "0";
1510
- container.style.display = "none";
1511
- container.style.alignItems = "center";
1512
- container.style.justifyContent = "center";
1513
- container.style.pointerEvents = "none";
1514
- container.style.zIndex = "10";
1515
- container.style.backgroundColor = "#000";
1516
- (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1517
- adContainerEl = container;
1518
- }
1519
- return adContainerEl;
1206
+ function assignCurrentAd(ad) {
1207
+ currentAd = ad;
1208
+ sessionId = generateSessionId();
1209
+ trackingFired = {
1210
+ impression: false,
1211
+ start: false,
1212
+ firstQuartile: false,
1213
+ midpoint: false,
1214
+ thirdQuartile: false,
1215
+ complete: false
1216
+ };
1217
+ fireTrackingPixels2(currentAd.trackingUrls.impression);
1218
+ trackingFired.impression = true;
1219
+ emit("ad_impression");
1520
1220
  }
1521
- function preloadAd(bids, token) {
1522
- return _async_to_generator(function() {
1523
- var winner, ad, mediaFile, slot, videoEl, container, hls, slot1, slot2;
1524
- return _ts_generator(this, function(_state) {
1525
- switch(_state.label){
1526
- case 0:
1527
- if (destroyed) return [
1528
- 2
1529
- ];
1530
- winner = bids[0];
1531
- if (!winner) return [
1532
- 2
1533
- ];
1534
- if (debug) console.log("".concat(LOG, " [preload] Resolving VAST for token=").concat(token));
1535
- return [
1536
- 4,
1537
- resolveBidToVastAd(winner, LOG)
1538
- ];
1539
- case 1:
1540
- ad = _state.sent();
1541
- if (!ad || destroyed) return [
1542
- 2
1543
- ];
1544
- mediaFile = selectBestMediaFile(ad.mediaFiles);
1545
- if (!mediaFile) return [
1546
- 2
1547
- ];
1548
- if (smartTVMode || singleElementMode) {
1549
- slot = {
1550
- bids: bids,
1551
- ad: ad,
1552
- mediaFile: mediaFile,
1553
- videoEl: null,
1554
- ready: true
1555
- };
1556
- preloadSlots.set(token, slot);
1557
- if (debug) console.log("".concat(LOG, " [preload] Metadata-only preload (smartTV/singleElement), token=").concat(token, ", url=").concat(mediaFile.url));
1221
+ return {
1222
+ initialize: function initialize() {
1223
+ log("Initializing");
1224
+ if (!adContainerEl) {
1225
+ var _contentVideo_parentElement;
1226
+ var parent = contentVideo.parentElement;
1227
+ if (parent) {
1228
+ var computed = window.getComputedStyle(parent).position;
1229
+ if (computed === "static") {
1230
+ parent.style.position = "relative";
1231
+ parentPositionOverridden = true;
1232
+ }
1233
+ }
1234
+ var container = document.createElement("div");
1235
+ container.style.position = "absolute";
1236
+ container.style.left = "0";
1237
+ container.style.top = "0";
1238
+ container.style.right = "0";
1239
+ container.style.bottom = "0";
1240
+ container.style.display = "none";
1241
+ container.style.alignItems = "center";
1242
+ container.style.justifyContent = "center";
1243
+ container.style.pointerEvents = "none";
1244
+ container.style.zIndex = AD_LAYER_Z_INDEX;
1245
+ container.style.backgroundColor = "#000";
1246
+ container.style.transition = "opacity 0.3s ease-in-out";
1247
+ container.style.opacity = "0";
1248
+ container.style.isolation = "isolate";
1249
+ var countdown = document.createElement("div");
1250
+ countdown.style.position = "absolute";
1251
+ countdown.style.right = "12px";
1252
+ countdown.style.top = "12px";
1253
+ countdown.style.padding = "4px 8px";
1254
+ countdown.style.borderRadius = "4px";
1255
+ countdown.style.background = "rgba(0,0,0,0.75)";
1256
+ countdown.style.color = "#fff";
1257
+ countdown.style.fontFamily = "sans-serif";
1258
+ countdown.style.fontSize = "12px";
1259
+ countdown.style.lineHeight = "1.2";
1260
+ countdown.style.pointerEvents = "none";
1261
+ countdown.style.zIndex = COUNTDOWN_Z_INDEX;
1262
+ countdown.textContent = "Ad";
1263
+ container.appendChild(countdown);
1264
+ (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1265
+ adContainerEl = container;
1266
+ adCountdownEl = countdown;
1267
+ }
1268
+ },
1269
+ requestAds: function requestAds(duration) {
1270
+ return _async_to_generator(function() {
1271
+ var durationSeconds, parsed, ads, error;
1272
+ return _ts_generator(this, function(_state) {
1273
+ switch(_state.label){
1274
+ case 0:
1275
+ log("Requesting ads for duration:", duration);
1276
+ if (adPlaying) {
1277
+ return [
1278
+ 2,
1279
+ Promise.reject(new Error("Ad already playing"))
1280
+ ];
1281
+ }
1282
+ if (destroyed) {
1283
+ return [
1284
+ 2,
1285
+ Promise.reject(new Error("Player has been destroyed"))
1286
+ ];
1287
+ }
1288
+ _state.label = 1;
1289
+ case 1:
1290
+ _state.trys.push([
1291
+ 1,
1292
+ 3,
1293
+ ,
1294
+ 4
1295
+ ]);
1296
+ tornDown = false;
1297
+ durationSeconds = 30;
1298
+ parsed = parseInt(duration || "", 10);
1299
+ if (!isNaN(parsed) && parsed > 0) {
1300
+ durationSeconds = parsed;
1301
+ }
1558
1302
  return [
1559
- 2
1303
+ 4,
1304
+ fetchVast(durationSeconds)
1560
1305
  ];
1561
- }
1562
- videoEl = createAdVideoElement();
1563
- videoEl.style.visibility = "hidden";
1564
- videoEl.style.pointerEvents = "none";
1565
- videoEl.preload = "auto";
1566
- container = ensureAdContainer();
1567
- container.appendChild(videoEl);
1568
- if (isHlsMediaFile(mediaFile) && import_hls.default.isSupported()) {
1569
- hls = new import_hls.default({
1570
- enableWorker: true,
1571
- lowLatencyMode: false
1572
- });
1573
- hls.loadSource(mediaFile.url);
1574
- hls.attachMedia(videoEl);
1575
- slot1 = {
1576
- bids: bids,
1577
- ad: ad,
1578
- mediaFile: mediaFile,
1579
- videoEl: videoEl,
1580
- hlsInstance: hls,
1581
- ready: false
1582
- };
1583
- preloadSlots.set(token, slot1);
1584
- hls.on(import_hls.default.Events.MANIFEST_PARSED, function() {
1585
- var s = preloadSlots.get(token);
1586
- if (s) s.ready = true;
1587
- if (debug) console.log("".concat(LOG, " [preload] HLS manifest parsed, token=").concat(token));
1588
- });
1589
- hls.on(import_hls.default.Events.ERROR, function(_evt, data) {
1590
- if (!preloadSlots.has(token)) return;
1591
- if (data.fatal) {
1592
- if (debug) console.warn("".concat(LOG, " [preload] HLS error for token=").concat(token));
1593
- preloadSlots.delete(token);
1594
- hls.destroy();
1595
- videoEl.remove();
1596
- }
1597
- });
1598
- } else {
1599
- videoEl.src = mediaFile.url;
1600
- videoEl.load();
1601
- slot2 = {
1602
- bids: bids,
1603
- ad: ad,
1604
- mediaFile: mediaFile,
1605
- videoEl: videoEl,
1606
- ready: false
1607
- };
1608
- preloadSlots.set(token, slot2);
1609
- videoEl.addEventListener("canplay", function() {
1610
- var s = preloadSlots.get(token);
1611
- if (s) s.ready = true;
1612
- if (debug) console.log("".concat(LOG, " [preload] canplay fired, token=").concat(token));
1613
- }, {
1614
- once: true
1615
- });
1616
- }
1617
- if (debug) console.log("".concat(LOG, " [preload] Started buffering token=").concat(token, ", url=").concat(mediaFile.url));
1618
- return [
1619
- 2
1620
- ];
1621
- }
1622
- });
1623
- })();
1624
- }
1625
- function playPreloaded(token) {
1626
- return _async_to_generator(function() {
1627
- var slot, contentVolume, adVolume2, videoEl, container2, adVolume21, nonFatalNetworkErrors, adVolume, container;
1628
- return _ts_generator(this, function(_state) {
1629
- switch(_state.label){
1630
- case 0:
1631
- if (destroyed) return [
1632
- 2,
1633
- Promise.reject(new Error("Layer has been destroyed"))
1634
- ];
1635
- slot = preloadSlots.get(token);
1636
- if (!slot) {
1637
- if (debug) console.warn("".concat(LOG, " [preload] No slot found for token=").concat(token, ", nothing to play"));
1306
+ case 2:
1307
+ ads = _state.sent();
1308
+ if (ads.length === 0) {
1309
+ log("No ads available from VAST response");
1310
+ emit("ad_error");
1311
+ return [
1312
+ 2,
1313
+ Promise.resolve()
1314
+ ];
1315
+ }
1316
+ assignCurrentAd(ads[0]);
1317
+ log("Ad loaded: ".concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1318
+ return [
1319
+ 2,
1320
+ Promise.resolve()
1321
+ ];
1322
+ case 3:
1323
+ error = _state.sent();
1324
+ console.error("[AdStormPlayer] Error requesting ads:", error);
1325
+ emit("ad_error");
1326
+ return [
1327
+ 2,
1328
+ Promise.reject(error)
1329
+ ];
1330
+ case 4:
1638
1331
  return [
1639
1332
  2
1640
1333
  ];
1641
- }
1642
- preloadSlots.delete(token);
1643
- if (debug) console.log("".concat(LOG, " [preload] Playing preloaded ad, token=").concat(token, ", ready=").concat(slot.ready));
1644
- contentVolume = contentVideo.volume;
1645
- originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1646
- sessionId = generateSessionId();
1647
- currentAd = slot.ad;
1648
- trackingFired = _object_spread({}, createEmptyTrackingState());
1649
- fireTrackingPixels2(slot.ad.trackingUrls.impression);
1650
- trackingFired.impression = true;
1651
- if (!singleElementMode) return [
1652
- 3,
1653
- 2
1654
- ];
1655
- mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.detachMedia();
1656
- teardownCurrentPlayback();
1657
- adVideoElement = contentVideo;
1658
- adHls = void 0;
1659
- adPlaying = true;
1660
- setAdPlayingFlag(true);
1661
- contentVideo.removeAttribute("src");
1662
- contentVideo.load();
1663
- contentVideo.muted = true;
1664
- contentVideo.volume = 0;
1665
- return [
1666
- 4,
1667
- new Promise(function(resolve) {
1668
- return setTimeout(resolve, 200);
1669
- })
1670
- ];
1671
- case 1:
1672
- _state.sent();
1673
- if (destroyed || tornDown) return [
1674
- 2
1675
- ];
1676
- contentVideo.style.visibility = "visible";
1677
- contentVideo.style.opacity = "1";
1678
- applyContentVideoAdCoverStyles();
1679
- emit("content_pause");
1680
- setupAdEventListeners();
1681
- adVolume2 = originalMutedState ? 1 : originalVolume;
1682
- contentVideo.volume = Math.max(0, Math.min(1, adVolume2));
1683
- contentVideo.muted = false;
1684
- if (debug) console.log("".concat(LOG, " [preload] singleElementMode: attaching ad to contentVideo, url=").concat(slot.mediaFile.url));
1685
- startPlayback(slot.mediaFile);
1686
- return [
1687
- 2
1688
- ];
1689
- case 2:
1690
- if (smartTVMode && !slot.videoEl) {
1691
- teardownCurrentPlayback();
1692
- if (adVideoElement) {
1693
- adVideoElement.remove();
1694
- adVideoElement = void 0;
1334
+ }
1335
+ });
1336
+ })();
1337
+ },
1338
+ play: function play() {
1339
+ return _async_to_generator(function() {
1340
+ var mediaFile, error;
1341
+ return _ts_generator(this, function(_state) {
1342
+ switch(_state.label){
1343
+ case 0:
1344
+ if (!currentAd) {
1345
+ return [
1346
+ 2,
1347
+ Promise.reject(new Error("No ad loaded"))
1348
+ ];
1349
+ }
1350
+ if (destroyed) {
1351
+ return [
1352
+ 2,
1353
+ Promise.reject(new Error("Player has been destroyed"))
1354
+ ];
1355
+ }
1356
+ log("Starting ad playback");
1357
+ _state.label = 1;
1358
+ case 1:
1359
+ _state.trys.push([
1360
+ 1,
1361
+ 3,
1362
+ ,
1363
+ 4
1364
+ ]);
1365
+ tornDown = false;
1366
+ if (adHideTimerId) {
1367
+ clearTimeout(adHideTimerId);
1368
+ adHideTimerId = void 0;
1369
+ }
1370
+ if (!adVideoElement) {
1371
+ adVideoElement = createAdVideoElement();
1372
+ adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.appendChild(adVideoElement);
1373
+ } else {
1374
+ teardownCurrentPlayback();
1695
1375
  }
1696
- videoEl = createAdVideoElement();
1697
- videoEl.style.visibility = "visible";
1698
- videoEl.style.pointerEvents = "none";
1699
- container2 = ensureAdContainer();
1700
- container2.appendChild(videoEl);
1701
- adVideoElement = videoEl;
1702
1376
  setupAdEventListeners();
1377
+ trackingFired = {
1378
+ impression: trackingFired.impression,
1379
+ start: false,
1380
+ firstQuartile: false,
1381
+ midpoint: false,
1382
+ thirdQuartile: false,
1383
+ complete: false
1384
+ };
1385
+ contentVideo.style.transition = "opacity 0.3s ease-in-out";
1386
+ contentVideo.style.opacity = "0";
1387
+ setTimeout(function() {
1388
+ contentVideo.style.visibility = "hidden";
1389
+ }, 300);
1390
+ contentVideo.muted = true;
1391
+ contentVideo.volume = 0;
1703
1392
  if (!continueLiveStreamDuringAds) {
1704
1393
  contentVideo.pause();
1705
1394
  }
1706
- contentVideo.muted = true;
1707
- contentVideo.volume = 0;
1708
1395
  adPlaying = true;
1709
1396
  setAdPlayingFlag(true);
1710
- adVolume21 = originalMutedState ? 1 : originalVolume;
1711
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume21));
1712
- adVideoElement.muted = false;
1713
- container2.style.display = "flex";
1714
- container2.style.pointerEvents = "auto";
1397
+ if (adVideoElement) {
1398
+ adVideoElement.volume = originalMutedState ? 0 : originalVolume;
1399
+ adVideoElement.muted = originalMutedState;
1400
+ }
1401
+ if (adContainerEl) {
1402
+ adContainerEl.style.display = "flex";
1403
+ adContainerEl.style.pointerEvents = "auto";
1404
+ adContainerEl.offsetHeight;
1405
+ adContainerEl.style.opacity = "1";
1406
+ }
1715
1407
  emit("content_pause");
1716
- if (debug) console.log("".concat(LOG, " [preload] smartTVMode deferred: creating video element and loading, url=").concat(slot.mediaFile.url));
1717
- startPlayback(slot.mediaFile);
1408
+ mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1409
+ if (!mediaFile) {
1410
+ throw new Error("No media file available");
1411
+ }
1412
+ log("Playing media file:", mediaFile.url);
1413
+ adVideoElement.src = mediaFile.url;
1414
+ adVideoElement.load();
1718
1415
  return [
1719
- 2
1416
+ 4,
1417
+ adVideoElement.play()
1720
1418
  ];
1721
- }
1722
- teardownCurrentPlayback();
1723
- if (adVideoElement && adVideoElement !== slot.videoEl) {
1724
- adVideoElement.remove();
1725
- }
1726
- slot.videoEl.style.visibility = "visible";
1727
- slot.videoEl.style.pointerEvents = "none";
1728
- adVideoElement = slot.videoEl;
1729
- adHls = slot.hlsInstance;
1730
- if (adHls) {
1731
- nonFatalNetworkErrors = 0;
1732
- adHls.on(import_hls.default.Events.ERROR, function(_event, data) {
1733
- if (!adPlaying) return;
1734
- if (data.fatal) {
1735
- handleAdError();
1736
- } else if (data.type === import_hls.default.ErrorTypes.NETWORK_ERROR) {
1737
- nonFatalNetworkErrors++;
1738
- if (nonFatalNetworkErrors >= 3) {
1739
- if (debug) console.warn("".concat(LOG, " [preload] Too many non-fatal HLS network errors during playback, treating as fatal"));
1740
- handleAdError();
1741
- }
1742
- }
1743
- });
1744
- }
1745
- setupAdEventListeners();
1746
- if (!continueLiveStreamDuringAds) {
1747
- contentVideo.pause();
1748
- }
1749
- contentVideo.muted = true;
1750
- contentVideo.volume = 0;
1751
- adPlaying = true;
1752
- setAdPlayingFlag(true);
1753
- adVolume = originalMutedState ? 1 : originalVolume;
1754
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
1755
- adVideoElement.muted = false;
1756
- container = ensureAdContainer();
1757
- container.style.display = "flex";
1758
- container.style.pointerEvents = "auto";
1759
- emit("content_pause");
1760
- adVideoElement.play().catch(function(error) {
1761
- console.error("".concat(LOG, " [preload] Error playing preloaded ad:"), error);
1419
+ case 2:
1420
+ _state.sent();
1421
+ return [
1422
+ 2,
1423
+ Promise.resolve()
1424
+ ];
1425
+ case 3:
1426
+ error = _state.sent();
1427
+ console.error("[AdStormPlayer] Error playing ad:", error);
1762
1428
  handleAdError();
1763
- });
1764
- return [
1765
- 2
1766
- ];
1767
- }
1768
- });
1769
- })();
1770
- }
1771
- function cancelPreload(token) {
1772
- var slot = preloadSlots.get(token);
1773
- if (!slot) return;
1774
- preloadSlots.delete(token);
1775
- if (slot.hlsInstance) {
1776
- slot.hlsInstance.destroy();
1777
- }
1778
- if (slot.videoEl) {
1779
- slot.videoEl.pause();
1780
- slot.videoEl.removeAttribute("src");
1781
- slot.videoEl.load();
1782
- slot.videoEl.remove();
1783
- }
1784
- if (debug) console.log("".concat(LOG, " [preload] Cancelled and cleaned up token=").concat(token));
1785
- }
1786
- return {
1787
- initialize: function initialize() {
1788
- if (debug) console.log("".concat(LOG, " Initializing"));
1789
- },
1790
- updateOptions: function updateOptions(opts) {
1791
- if (opts.continueLiveStreamDuringAds !== void 0) {
1792
- continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;
1793
- }
1794
- if (opts.mainHlsInstance !== void 0) {
1795
- var _opts_mainHlsInstance;
1796
- mainHlsInstance = (_opts_mainHlsInstance = opts.mainHlsInstance) !== null && _opts_mainHlsInstance !== void 0 ? _opts_mainHlsInstance : void 0;
1797
- }
1798
- },
1799
- playAd: playAd,
1800
- preloadAd: preloadAd,
1801
- playPreloaded: playPreloaded,
1802
- hasPreloaded: function hasPreloaded(token) {
1803
- return preloadSlots.has(token);
1804
- },
1805
- cancelPreload: cancelPreload,
1806
- pause: function pause() {
1807
- if (!adPlaying || !adVideoElement) return;
1808
- try {
1809
- if (!adVideoElement.paused) adVideoElement.pause();
1810
- } catch (error) {
1811
- if (debug) console.warn("".concat(LOG, " Error pausing ad:"), error);
1812
- }
1813
- },
1814
- resume: function resume() {
1815
- if (!adPlaying || !adVideoElement) return;
1816
- try {
1817
- if (adVideoElement.paused) adVideoElement.play().catch(function() {});
1818
- } catch (error) {
1819
- if (debug) console.warn("".concat(LOG, " Error resuming ad:"), error);
1820
- }
1429
+ return [
1430
+ 2,
1431
+ Promise.reject(error)
1432
+ ];
1433
+ case 4:
1434
+ return [
1435
+ 2
1436
+ ];
1437
+ }
1438
+ });
1439
+ })();
1821
1440
  },
1822
1441
  stop: function stop() {
1823
1442
  return _async_to_generator(function() {
1824
1443
  return _ts_generator(this, function(_state) {
1444
+ log("Stopping ad");
1825
1445
  tornDown = true;
1826
- if (debug) console.log("".concat(LOG, " Stopping ad"));
1827
1446
  adPlaying = false;
1828
1447
  setAdPlayingFlag(false);
1829
- restoreContentVideoStyles();
1830
- contentVideo.muted = originalMutedState;
1831
- contentVideo.volume = originalMutedState ? 0 : originalVolume;
1448
+ clearAdStallTimer();
1449
+ clearAdCountdownTimer();
1450
+ if (adContainerEl) {
1451
+ adContainerEl.style.opacity = "0";
1452
+ adHideTimerId = setTimeout(function() {
1453
+ if (adContainerEl) {
1454
+ adContainerEl.style.display = "none";
1455
+ adContainerEl.style.pointerEvents = "none";
1456
+ }
1457
+ }, 300);
1458
+ }
1459
+ teardownCurrentPlayback();
1832
1460
  contentVideo.style.visibility = "visible";
1833
1461
  contentVideo.style.opacity = "1";
1834
- if (singleElementMode) {
1835
- teardownCurrentPlayback();
1836
- contentVideo.removeAttribute("src");
1837
- contentVideo.load();
1838
- adVideoElement = void 0;
1839
- } else {
1840
- if (adContainerEl) {
1841
- adContainerEl.style.display = "none";
1842
- adContainerEl.style.pointerEvents = "none";
1843
- }
1844
- if (continueLiveStreamDuringAds) {
1845
- contentVideo.play().catch(function() {});
1846
- }
1847
- teardownCurrentPlayback();
1848
- if (adVideoElement) {
1849
- adVideoElement.pause();
1850
- adVideoElement.removeAttribute("src");
1851
- adVideoElement.load();
1852
- }
1853
- }
1462
+ contentVideo.muted = originalMutedState;
1463
+ contentVideo.volume = originalVolume;
1854
1464
  currentAd = void 0;
1855
1465
  tornDown = false;
1856
1466
  return [
1857
- 2
1467
+ 2,
1468
+ Promise.resolve()
1858
1469
  ];
1859
1470
  });
1860
1471
  })();
1861
1472
  },
1473
+ pause: function pause() {
1474
+ if (!adPlaying || !adVideoElement) return;
1475
+ try {
1476
+ if (!adVideoElement.paused) adVideoElement.pause();
1477
+ } catch (error) {
1478
+ console.warn("[AdStormPlayer] Error pausing ad:", error);
1479
+ }
1480
+ },
1481
+ resume: function resume() {
1482
+ if (!adPlaying || !adVideoElement) return;
1483
+ try {
1484
+ if (adVideoElement.paused) adVideoElement.play().catch(function() {});
1485
+ } catch (error) {
1486
+ console.warn("[AdStormPlayer] Error resuming ad:", error);
1487
+ }
1488
+ },
1862
1489
  destroy: function destroy() {
1863
- tornDown = true;
1864
- if (debug) console.log("".concat(LOG, " Destroying"));
1490
+ log("Destroying");
1865
1491
  destroyed = true;
1492
+ tornDown = true;
1866
1493
  adPlaying = false;
1867
1494
  setAdPlayingFlag(false);
1868
- restoreContentVideoStyles();
1495
+ clearAdStallTimer();
1496
+ clearAdCountdownTimer();
1497
+ if (adHideTimerId) {
1498
+ clearTimeout(adHideTimerId);
1499
+ adHideTimerId = void 0;
1500
+ }
1869
1501
  contentVideo.muted = originalMutedState;
1870
1502
  contentVideo.volume = originalVolume;
1871
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1872
- try {
1873
- for(var _iterator = Array.from(preloadSlots.entries())[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1874
- var _step_value = _sliced_to_array(_step.value, 1), token = _step_value[0];
1875
- cancelPreload(token);
1876
- }
1877
- } catch (err) {
1878
- _didIteratorError = true;
1879
- _iteratorError = err;
1880
- } finally{
1881
- try {
1882
- if (!_iteratorNormalCompletion && _iterator.return != null) {
1883
- _iterator.return();
1884
- }
1885
- } finally{
1886
- if (_didIteratorError) {
1887
- throw _iteratorError;
1888
- }
1889
- }
1890
- }
1503
+ contentVideo.style.visibility = "visible";
1504
+ contentVideo.style.opacity = "1";
1891
1505
  teardownCurrentPlayback();
1892
- if (adVideoElement) {
1893
- if (singleElementMode && adVideoElement === contentVideo) {
1894
- contentVideo.removeAttribute("src");
1895
- contentVideo.load();
1896
- } else {
1897
- adVideoElement.pause();
1898
- adVideoElement.removeAttribute("src");
1899
- adVideoElement.remove();
1900
- }
1901
- adVideoElement = void 0;
1902
- }
1506
+ adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.remove();
1507
+ adVideoElement = void 0;
1903
1508
  if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
1904
1509
  adContainerEl.parentElement.removeChild(adContainerEl);
1905
1510
  }
1906
1511
  adContainerEl = void 0;
1512
+ adCountdownEl = void 0;
1907
1513
  currentAd = void 0;
1514
+ sessionId = void 0;
1515
+ preloadSlots.clear();
1908
1516
  listeners.clear();
1517
+ if (parentPositionOverridden && contentVideo.parentElement) {
1518
+ contentVideo.parentElement.style.position = "";
1519
+ parentPositionOverridden = false;
1520
+ }
1521
+ },
1522
+ updateOptions: function updateOptions(opts) {
1523
+ if (opts.continueLiveStreamDuringAds !== void 0) {
1524
+ continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;
1525
+ }
1526
+ },
1527
+ playAd: function playAd(requestContext) {
1528
+ return _async_to_generator(function() {
1529
+ var ad;
1530
+ return _ts_generator(this, function(_state) {
1531
+ switch(_state.label){
1532
+ case 0:
1533
+ if (destroyed) return [
1534
+ 2,
1535
+ Promise.reject(new Error("Player has been destroyed"))
1536
+ ];
1537
+ if (!!currentAd) return [
1538
+ 3,
1539
+ 2
1540
+ ];
1541
+ return [
1542
+ 4,
1543
+ requestAdFromApi(requestContext)
1544
+ ];
1545
+ case 1:
1546
+ ad = _state.sent();
1547
+ if (!ad) {
1548
+ emit("ad_error", {
1549
+ message: "No valid ad from AdStorm API"
1550
+ });
1551
+ return [
1552
+ 2,
1553
+ Promise.reject(new Error("No valid ad from AdStorm API"))
1554
+ ];
1555
+ }
1556
+ assignCurrentAd(ad);
1557
+ _state.label = 2;
1558
+ case 2:
1559
+ return [
1560
+ 2,
1561
+ this.play()
1562
+ ];
1563
+ }
1564
+ });
1565
+ }).call(this);
1566
+ },
1567
+ preloadAd: function preloadAd(arg1, arg2) {
1568
+ return _async_to_generator(function() {
1569
+ var token, requestContext, ad;
1570
+ return _ts_generator(this, function(_state) {
1571
+ switch(_state.label){
1572
+ case 0:
1573
+ if (destroyed) return [
1574
+ 2
1575
+ ];
1576
+ token = typeof arg1 === "string" ? arg1 : typeof arg2 === "string" ? arg2 : void 0;
1577
+ if (!token) return [
1578
+ 2
1579
+ ];
1580
+ requestContext = typeof arg1 === "string" ? arg2 : arg1;
1581
+ return [
1582
+ 4,
1583
+ requestAdFromApi(requestContext)
1584
+ ];
1585
+ case 1:
1586
+ ad = _state.sent();
1587
+ if (!ad) return [
1588
+ 2
1589
+ ];
1590
+ preloadSlots.set(token, {
1591
+ ad: ad
1592
+ });
1593
+ return [
1594
+ 2
1595
+ ];
1596
+ }
1597
+ });
1598
+ })();
1599
+ },
1600
+ playPreloaded: function playPreloaded(token) {
1601
+ return _async_to_generator(function() {
1602
+ var slot;
1603
+ return _ts_generator(this, function(_state) {
1604
+ if (destroyed) return [
1605
+ 2,
1606
+ Promise.reject(new Error("Player has been destroyed"))
1607
+ ];
1608
+ slot = preloadSlots.get(token);
1609
+ if (!slot) {
1610
+ return [
1611
+ 2,
1612
+ Promise.reject(new Error("No preloaded ad for token ".concat(token)))
1613
+ ];
1614
+ }
1615
+ preloadSlots.delete(token);
1616
+ assignCurrentAd(slot.ad);
1617
+ return [
1618
+ 2,
1619
+ this.play()
1620
+ ];
1621
+ });
1622
+ }).call(this);
1623
+ },
1624
+ hasPreloaded: function hasPreloaded(token) {
1625
+ return preloadSlots.has(token);
1626
+ },
1627
+ cancelPreload: function cancelPreload(token) {
1628
+ preloadSlots.delete(token);
1909
1629
  },
1910
1630
  isAdPlaying: function isAdPlaying() {
1911
1631
  return adPlaying;
1912
1632
  },
1913
1633
  resize: function resize(width, height) {
1634
+ log("Resizing to ".concat(width, "x").concat(height));
1914
1635
  if (adContainerEl) {
1915
1636
  adContainerEl.style.width = "".concat(width, "px");
1916
1637
  adContainerEl.style.height = "".concat(height, "px");
@@ -1930,6 +1651,7 @@ function createVastAdLayer(contentVideo, options) {
1930
1651
  },
1931
1652
  updateOriginalMutedState: function updateOriginalMutedState(muted, volume) {
1932
1653
  var nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
1654
+ log("updateOriginalMutedState: muted=".concat(muted, ", volume=").concat(nextVolume));
1933
1655
  originalMutedState = muted;
1934
1656
  originalVolume = nextVolume;
1935
1657
  },
@@ -1942,6 +1664,7 @@ function createVastAdLayer(contentVideo, options) {
1942
1664
  setAdVolume: function setAdVolume(volume) {
1943
1665
  if (adVideoElement && adPlaying) {
1944
1666
  adVideoElement.volume = Math.max(0, Math.min(1, volume));
1667
+ adVideoElement.muted = volume === 0;
1945
1668
  }
1946
1669
  },
1947
1670
  getAdVolume: function getAdVolume() {
@@ -1951,11 +1674,16 @@ function createVastAdLayer(contentVideo, options) {
1951
1674
  return 1;
1952
1675
  },
1953
1676
  showPlaceholder: function showPlaceholder() {
1954
- if (singleElementMode) return;
1955
- contentVideo.style.opacity = "0";
1956
- contentVideo.style.visibility = "hidden";
1957
1677
  if (!adContainerEl) {
1958
1678
  var _contentVideo_parentElement;
1679
+ var parent = contentVideo.parentElement;
1680
+ if (parent) {
1681
+ var computed = window.getComputedStyle(parent).position;
1682
+ if (computed === "static") {
1683
+ parent.style.position = "relative";
1684
+ parentPositionOverridden = true;
1685
+ }
1686
+ }
1959
1687
  var container = document.createElement("div");
1960
1688
  container.style.position = "absolute";
1961
1689
  container.style.left = "0";
@@ -1966,24 +1694,43 @@ function createVastAdLayer(contentVideo, options) {
1966
1694
  container.style.alignItems = "center";
1967
1695
  container.style.justifyContent = "center";
1968
1696
  container.style.pointerEvents = "none";
1969
- container.style.zIndex = "10";
1697
+ container.style.zIndex = AD_LAYER_Z_INDEX;
1970
1698
  container.style.backgroundColor = "#000";
1699
+ container.style.isolation = "isolate";
1700
+ var countdown = document.createElement("div");
1701
+ countdown.style.position = "absolute";
1702
+ countdown.style.right = "12px";
1703
+ countdown.style.top = "12px";
1704
+ countdown.style.padding = "4px 8px";
1705
+ countdown.style.borderRadius = "4px";
1706
+ countdown.style.background = "rgba(0,0,0,0.75)";
1707
+ countdown.style.color = "#fff";
1708
+ countdown.style.fontFamily = "sans-serif";
1709
+ countdown.style.fontSize = "12px";
1710
+ countdown.style.lineHeight = "1.2";
1711
+ countdown.style.pointerEvents = "none";
1712
+ countdown.style.zIndex = COUNTDOWN_Z_INDEX;
1713
+ countdown.textContent = "Ad";
1714
+ container.appendChild(countdown);
1971
1715
  (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1972
1716
  adContainerEl = container;
1717
+ adCountdownEl = countdown;
1973
1718
  }
1974
1719
  if (adContainerEl) {
1975
1720
  adContainerEl.style.display = "flex";
1721
+ adContainerEl.style.opacity = "1";
1976
1722
  adContainerEl.style.pointerEvents = "auto";
1977
1723
  }
1978
1724
  },
1979
1725
  hidePlaceholder: function hidePlaceholder() {
1980
1726
  if (adContainerEl) {
1981
- adContainerEl.style.display = "none";
1982
- adContainerEl.style.pointerEvents = "none";
1983
- }
1984
- if (!adPlaying) {
1985
- contentVideo.style.visibility = "visible";
1986
- contentVideo.style.opacity = "1";
1727
+ adContainerEl.style.opacity = "0";
1728
+ setTimeout(function() {
1729
+ if (adContainerEl) {
1730
+ adContainerEl.style.display = "none";
1731
+ adContainerEl.style.pointerEvents = "none";
1732
+ }
1733
+ }, 300);
1987
1734
  }
1988
1735
  }
1989
1736
  };
@@ -3086,6 +2833,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3086
2833
  this.backoffBaseMs = 1e3;
3087
2834
  this.maxBackoffMs = 15e3;
3088
2835
  this.MIN_AD_REMAINING_MS = 15e3;
2836
+ this.adRequestTimeoutMs = 5e3;
2837
+ this.adRequestMaxRetries = 3;
2838
+ this.adRequestRetryBackoffMs = 1500;
3089
2839
  this.preloadedTokens = [];
3090
2840
  initializePolyfills();
3091
2841
  var browserOverrides = getBrowserConfigOverrides();
@@ -3093,24 +2843,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3093
2843
  this.video = config.videoElement;
3094
2844
  this.adTransitionGapMs = (_this_config_adTransitionGapMs = this.config.adTransitionGapMs) !== null && _this_config_adTransitionGapMs !== void 0 ? _this_config_adTransitionGapMs : 100;
3095
2845
  logBrowserInfo(config.debugAdTiming);
3096
- this.vastManager = createVastManager(config.debugAdTiming !== void 0 ? {
3097
- debug: !!config.debugAdTiming
3098
- } : {});
3099
2846
  var browserForAdLayer = detectBrowser();
3100
2847
  var isSinglePipeline = browserForAdLayer.isSmartTV || !!this.config.singlePipelineMode;
3101
- this.adLayer = createVastAdLayer(this.video, {
3102
- continueLiveStreamDuringAds: false,
3103
- smartTVMode: isSinglePipeline,
3104
- singleElementMode: isSinglePipeline,
3105
- forceMP4Ads: isSinglePipeline,
2848
+ this.adLayer = createAdStormPlayer(this.video, {
2849
+ licenseKey: this.config.licenseKey || "",
3106
2850
  debug: !!config.debugAdTiming
3107
2851
  });
2852
+ this.adLayer.updateOptions({
2853
+ continueLiveStreamDuringAds: !isSinglePipeline && this.shouldContinueLiveStreamDuringAds()
2854
+ });
3108
2855
  }
3109
2856
  _create_class(StormcloudVideoPlayer, [
3110
2857
  {
3111
2858
  key: "adRequest",
3112
2859
  value: function adRequest(context) {
3113
2860
  return _async_to_generator(function() {
2861
+ var _ref, _ref1, durationSeconds;
3114
2862
  return _ts_generator(this, function(_state) {
3115
2863
  switch(_state.label){
3116
2864
  case 0:
@@ -3118,15 +2866,28 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3118
2866
  2,
3119
2867
  []
3120
2868
  ];
2869
+ 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));
3121
2870
  return [
3122
2871
  4,
3123
- this.vastManager.initialize()
2872
+ this.adLayer.requestAds(String(durationSeconds))
3124
2873
  ];
3125
2874
  case 1:
3126
2875
  _state.sent();
3127
2876
  return [
3128
2877
  2,
3129
- this.vastManager.requestBidsUntilResponse(context)
2878
+ [
2879
+ {
2880
+ bidder: "adstorm-direct",
2881
+ cpm: 0,
2882
+ width: 0,
2883
+ height: 0,
2884
+ adId: "adstorm",
2885
+ impId: "",
2886
+ creativeId: "adstorm",
2887
+ currency: "USD",
2888
+ durationSec: durationSeconds
2889
+ }
2890
+ ]
3130
2891
  ];
3131
2892
  }
3132
2893
  });
@@ -3183,7 +2944,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3183
2944
  2
3184
2945
  ];
3185
2946
  case 3:
3186
- this.hls = new import_hls2.default(_object_spread_props(_object_spread({
2947
+ this.hls = new import_hls.default(_object_spread_props(_object_spread({
3187
2948
  enableWorker: true,
3188
2949
  backBufferLength: 30,
3189
2950
  liveDurationInfinity: true,
@@ -3201,11 +2962,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3201
2962
  nudgeMaxRetry: 3,
3202
2963
  startPosition: -1
3203
2964
  }));
3204
- this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, function() {
2965
+ this.hls.on(import_hls.default.Events.MEDIA_ATTACHED, function() {
3205
2966
  var _this_hls;
3206
2967
  (_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.loadSource(_this.config.src);
3207
2968
  });
3208
- this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, function(_, data) {
2969
+ this.hls.on(import_hls.default.Events.MANIFEST_PARSED, function(_, data) {
3209
2970
  return _async_to_generator(function() {
3210
2971
  var _this_config_minSegmentsBeforePlay, _ref, _this_hls_levels, _this_hls, adBehavior, _this_hls1, minSegments, _this_video_play;
3211
2972
  return _ts_generator(this, function(_state) {
@@ -3267,7 +3028,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3267
3028
  });
3268
3029
  }).call(_this);
3269
3030
  });
3270
- this.hls.on(import_hls2.default.Events.LEVEL_LOADED, function(_evt, data) {
3031
+ this.hls.on(import_hls.default.Events.LEVEL_LOADED, function(_evt, data) {
3271
3032
  if (_this.inAdBreak || _this.pendingAdBreak) {
3272
3033
  return;
3273
3034
  }
@@ -3340,7 +3101,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3340
3101
  }
3341
3102
  }
3342
3103
  });
3343
- this.hls.on(import_hls2.default.Events.FRAG_BUFFERED, function(_evt, data) {
3104
+ this.hls.on(import_hls.default.Events.FRAG_BUFFERED, function(_evt, data) {
3344
3105
  return _async_to_generator(function() {
3345
3106
  var _this, _this_config_minSegmentsBeforePlay, minSegments, _this_video_play;
3346
3107
  return _ts_generator(this, function(_state) {
@@ -3400,7 +3161,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3400
3161
  });
3401
3162
  }).call(_this);
3402
3163
  });
3403
- this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, function(_evt, data) {
3164
+ this.hls.on(import_hls.default.Events.FRAG_PARSING_METADATA, function(_evt, data) {
3404
3165
  var id3Tags = ((data === null || data === void 0 ? void 0 : data.samples) || []).map(function(s) {
3405
3166
  return {
3406
3167
  key: "ID3",
@@ -3412,7 +3173,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3412
3173
  return _this.onId3Tag(tag);
3413
3174
  });
3414
3175
  });
3415
- this.hls.on(import_hls2.default.Events.FRAG_CHANGED, function(_evt, data) {
3176
+ this.hls.on(import_hls.default.Events.FRAG_CHANGED, function(_evt, data) {
3416
3177
  var frag = data === null || data === void 0 ? void 0 : data.frag;
3417
3178
  var tagList = frag === null || frag === void 0 ? void 0 : frag.tagList;
3418
3179
  if (!Array.isArray(tagList)) return;
@@ -3521,14 +3282,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3521
3282
  }
3522
3283
  }
3523
3284
  });
3524
- this.hls.on(import_hls2.default.Events.ERROR, function(_evt, data) {
3285
+ this.hls.on(import_hls.default.Events.ERROR, function(_evt, data) {
3525
3286
  if (data === null || data === void 0 ? void 0 : data.fatal) {
3526
3287
  switch(data.type){
3527
- case import_hls2.default.ErrorTypes.NETWORK_ERROR:
3288
+ case import_hls.default.ErrorTypes.NETWORK_ERROR:
3528
3289
  var _this_hls;
3529
3290
  (_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.startLoad();
3530
3291
  break;
3531
- case import_hls2.default.ErrorTypes.MEDIA_ERROR:
3292
+ case import_hls.default.ErrorTypes.MEDIA_ERROR:
3532
3293
  var _this_hls1;
3533
3294
  (_this_hls1 = _this.hls) === null || _this_hls1 === void 0 ? void 0 : _this_hls1.recoverMediaError();
3534
3295
  break;
@@ -3620,7 +3381,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3620
3381
  }
3621
3382
  });
3622
3383
  this.adLayer.on("content_resume", function() {
3384
+ var _ref, _ref1;
3385
+ var _this_savedMutedStateBeforeScte, _this_savedMutedStateBeforeScte1;
3623
3386
  var remaining = _this.getRemainingAdMs();
3387
+ 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();
3388
+ 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();
3624
3389
  if (_this.config.debugAdTiming) {
3625
3390
  console.log("[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s, preloadedTokens=%d, pendingNext=%s", _this.inAdBreak, remaining, _this.preloadedTokens.length, !!_this.pendingNextAdBids);
3626
3391
  }
@@ -3635,7 +3400,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3635
3400
  return;
3636
3401
  }
3637
3402
  _this.consecutiveFailures = 0;
3638
- if (!_this.video.muted) {
3403
+ if (!_this.config.disableFiller && !_this.video.muted) {
3639
3404
  _this.video.muted = true;
3640
3405
  _this.video.volume = 0;
3641
3406
  }
@@ -3702,6 +3467,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3702
3467
  if (!_this.config.disableFiller) {
3703
3468
  _this.showPlaceholderLayer();
3704
3469
  _this.adLayer.showPlaceholder();
3470
+ } else {
3471
+ _this.adLayer.hidePlaceholder();
3472
+ if (_this.video.muted !== breakMuted) {
3473
+ _this.video.muted = breakMuted;
3474
+ }
3475
+ if (Math.abs(_this.video.volume - breakVolume) > 0.01) {
3476
+ _this.video.volume = breakVolume;
3477
+ }
3478
+ if (_this.video.paused) {
3479
+ var _this_video_play;
3480
+ (_this_video_play = _this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
3481
+ }
3705
3482
  }
3706
3483
  _this.stopContinuousFetching();
3707
3484
  return;
@@ -4429,6 +4206,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4429
4206
  return this.totalAdsInBreak;
4430
4207
  }
4431
4208
  },
4209
+ {
4210
+ key: "getRemainingAdSeconds",
4211
+ value: function getRemainingAdSeconds() {
4212
+ var remainingMs = this.getRemainingAdMs();
4213
+ if (!Number.isFinite(remainingMs) || remainingMs <= 0 || remainingMs === Number.MAX_SAFE_INTEGER) {
4214
+ return 0;
4215
+ }
4216
+ return Math.ceil(remainingMs / 1e3);
4217
+ }
4218
+ },
4432
4219
  {
4433
4220
  key: "isAdPlaying",
4434
4221
  value: function isAdPlaying() {
@@ -5658,7 +5445,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5658
5445
  });
5659
5446
  };
5660
5447
  var onManifestParsedRestore = function onManifestParsedRestore1() {
5661
- hlsRef.off(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5448
+ hlsRef.off(import_hls.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5662
5449
  if (!_this.inAdBreak && !_this.adLayer.isAdPlaying()) {
5663
5450
  if (videoRef.muted !== savedMuted) videoRef.muted = savedMuted;
5664
5451
  if (Math.abs(videoRef.volume - savedVolume) > 0.01) videoRef.volume = savedVolume;
@@ -5671,7 +5458,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5671
5458
  }
5672
5459
  }
5673
5460
  };
5674
- hlsRef.on(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5461
+ hlsRef.on(import_hls.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5675
5462
  var pipelineDelayMs = 300;
5676
5463
  if (debugEnabled) {
5677
5464
  console.log("[StormcloudVideoPlayer] Smart TV: waiting ".concat(pipelineDelayMs, "ms for hardware pipeline release before re-attach"));