stormcloud-video-player 0.7.3 → 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.
@@ -385,185 +385,8 @@ __export(StormcloudVideoPlayer_exports, {
385
385
  module.exports = __toCommonJS(StormcloudVideoPlayer_exports);
386
386
  var import_react2 = __toESM(require("react"), 1);
387
387
  // src/player/StormcloudVideoPlayer.ts
388
- var import_hls2 = __toESM(require("hls.js"), 1);
388
+ var import_hls = __toESM(require("hls.js"), 1);
389
389
  // src/sdk/vastParser.ts
390
- function isHlsType(type) {
391
- return type === "application/x-mpegURL" || type.includes("m3u8");
392
- }
393
- function isMp4Type(type) {
394
- return type === "video/mp4" || type.includes("mp4");
395
- }
396
- function parseVastXml(xmlString) {
397
- var filter = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "all", logPrefix = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "[VastParser]";
398
- try {
399
- var _xmlDoc_querySelector, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector2;
400
- var parser = new DOMParser();
401
- var xmlDoc = parser.parseFromString(xmlString, "text/xml");
402
- var parserError = xmlDoc.querySelector("parsererror");
403
- if (parserError) {
404
- console.error("".concat(logPrefix, " XML parsing error (malformed VAST XML):"), parserError.textContent);
405
- return null;
406
- }
407
- var adElement = xmlDoc.querySelector("Ad");
408
- if (!adElement) {
409
- console.warn("".concat(logPrefix, " No Ad element found in VAST XML"));
410
- return null;
411
- }
412
- var adId = adElement.getAttribute("id") || "unknown";
413
- var title = ((_xmlDoc_querySelector = xmlDoc.querySelector("AdTitle")) === null || _xmlDoc_querySelector === void 0 ? void 0 : _xmlDoc_querySelector.textContent) || "Ad";
414
- var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
415
- var durationText = ((_xmlDoc_querySelector1 = xmlDoc.querySelector("Duration")) === null || _xmlDoc_querySelector1 === void 0 ? void 0 : _xmlDoc_querySelector1.textContent) || "00:00:30";
416
- var durationParts = durationText.split(":");
417
- var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + Math.round(parseFloat(durationParts[2] || "0"));
418
- var mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
419
- var mediaFiles = [];
420
- console.log("".concat(logPrefix, " Found ").concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
421
- mediaFileElements.forEach(function(mf, index) {
422
- var _mf_textContent;
423
- var type = mf.getAttribute("type") || "";
424
- var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
425
- var width = mf.getAttribute("width") || "";
426
- var height = mf.getAttribute("height") || "";
427
- console.log("".concat(logPrefix, " MediaFile ").concat(index, ': type="').concat(type, '", url="').concat(url.substring(0, 80), '...", width="').concat(width, '", height="').concat(height, '"'));
428
- if (!url) {
429
- console.warn("".concat(logPrefix, " MediaFile ").concat(index, " has empty URL"));
430
- return;
431
- }
432
- var isHls = isHlsType(type);
433
- var isMp4 = isMp4Type(type);
434
- var accepted = false;
435
- if (filter === "hls-only") {
436
- accepted = isHls;
437
- } else if (filter === "mp4-first") {
438
- accepted = isMp4 || isHls;
439
- } else {
440
- accepted = true;
441
- }
442
- if (!accepted) {
443
- console.log("".concat(logPrefix, " MediaFile ").concat(index, ' ignored (type="').concat(type, '" not accepted by filter "').concat(filter, '")'));
444
- return;
445
- }
446
- var bitrateAttr = mf.getAttribute("bitrate");
447
- var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
448
- mediaFiles.push({
449
- url: url,
450
- type: type,
451
- width: parseInt(width || "1920", 10),
452
- height: parseInt(height || "1080", 10),
453
- bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
454
- });
455
- console.log("".concat(logPrefix, ' Added MediaFile: type="').concat(type, '" url="').concat(url.substring(0, 80), '..."'));
456
- });
457
- if (filter === "mp4-first" && mediaFiles.length > 1) {
458
- mediaFiles.sort(function(a, b) {
459
- var aIsMp4 = isMp4Type(a.type) ? 0 : 1;
460
- var bIsMp4 = isMp4Type(b.type) ? 0 : 1;
461
- return aIsMp4 - bIsMp4;
462
- });
463
- }
464
- if (mediaFiles.length === 0) {
465
- if (isNoAdAvailable) {
466
- console.warn("".concat(logPrefix, " No ads available (VAST response indicates no ads)"));
467
- } else {
468
- console.warn("".concat(logPrefix, " No compatible media files found in VAST XML"));
469
- }
470
- return null;
471
- }
472
- var trackingUrls = {
473
- impression: [],
474
- start: [],
475
- firstQuartile: [],
476
- midpoint: [],
477
- thirdQuartile: [],
478
- complete: [],
479
- mute: [],
480
- unmute: [],
481
- pause: [],
482
- resume: [],
483
- fullscreen: [],
484
- exitFullscreen: [],
485
- skip: [],
486
- error: []
487
- };
488
- xmlDoc.querySelectorAll("Impression").forEach(function(el) {
489
- var _el_textContent;
490
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
491
- if (url) trackingUrls.impression.push(url);
492
- });
493
- xmlDoc.querySelectorAll("Tracking").forEach(function(el) {
494
- var _el_textContent;
495
- var event = el.getAttribute("event");
496
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
497
- if (event && url) {
498
- var eventKey = event;
499
- if (trackingUrls[eventKey]) {
500
- trackingUrls[eventKey].push(url);
501
- }
502
- }
503
- });
504
- 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();
505
- return {
506
- id: adId,
507
- title: title,
508
- duration: duration,
509
- mediaFiles: mediaFiles,
510
- trackingUrls: trackingUrls,
511
- clickThrough: clickThrough
512
- };
513
- } catch (error) {
514
- console.error("".concat(logPrefix, " Error parsing VAST XML:"), error);
515
- return null;
516
- }
517
- }
518
- function fetchAndParseVastAd(vastTagUrl) {
519
- var filter = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "all", logPrefix = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "[VastParser]";
520
- return _async_to_generator(function() {
521
- var response, vastXml;
522
- return _ts_generator(this, function(_state) {
523
- switch(_state.label){
524
- case 0:
525
- return [
526
- 4,
527
- fetch(vastTagUrl, {
528
- mode: "cors",
529
- credentials: "include",
530
- headers: {
531
- Accept: "application/xml, text/xml, */*"
532
- },
533
- referrerPolicy: "no-referrer-when-downgrade"
534
- })
535
- ];
536
- case 1:
537
- response = _state.sent();
538
- if (!response.ok) {
539
- throw new Error("Failed to fetch VAST: ".concat(response.statusText));
540
- }
541
- return [
542
- 4,
543
- response.text()
544
- ];
545
- case 2:
546
- vastXml = _state.sent();
547
- console.log("".concat(logPrefix, " VAST XML received"));
548
- console.log("".concat(logPrefix, " VAST XML content (first 2000 chars):"), vastXml.substring(0, 2e3));
549
- return [
550
- 2,
551
- parseVastXml(vastXml, filter, logPrefix)
552
- ];
553
- }
554
- });
555
- })();
556
- }
557
- function createEmptyTrackingState() {
558
- return {
559
- impression: false,
560
- start: false,
561
- firstQuartile: false,
562
- midpoint: false,
563
- thirdQuartile: false,
564
- complete: false
565
- };
566
- }
567
390
  function firePixelWithRetry(url) {
568
391
  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]";
569
392
  return _async_to_generator(function() {
@@ -686,16 +509,164 @@ function fireTrackingPixels(urls, sessionId) {
686
509
  }
687
510
  });
688
511
  }
689
- // src/sdk/vastManager.ts
690
- 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";
691
- var DEFAULT_TIMEOUT_MS = 5e3;
692
- var MAX_RETRIES = 3;
693
- var RETRY_BACKOFF_MS = 1500;
694
- function createVastManager() {
695
- var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
696
- var _options_debug;
697
- var initialized = false;
698
- var debug = (_options_debug = options.debug) !== null && _options_debug !== void 0 ? _options_debug : false;
512
+ // src/sdk/adstormPlayer.ts
513
+ var SUPPORTED_VIDEO_EXTENSIONS = [
514
+ ".mp4",
515
+ ".webm",
516
+ ".ogg",
517
+ ".m3u8",
518
+ ".ts"
519
+ ];
520
+ var UNSUPPORTED_VIDEO_EXTENSIONS = [
521
+ ".flv",
522
+ ".f4v",
523
+ ".swf",
524
+ ".wmv",
525
+ ".avi",
526
+ ".mov",
527
+ ".mkv"
528
+ ];
529
+ var REQUEST_TIMEOUT_MS = 5e3;
530
+ var REQUEST_MAX_RETRIES = 3;
531
+ var REQUEST_RETRY_BACKOFF_MS = 1500;
532
+ var AD_LAYER_Z_INDEX = "2147483646";
533
+ var COUNTDOWN_Z_INDEX = "2147483647";
534
+ var STALL_TIMEOUT_MS = 8e3;
535
+ function getFileExtension(url) {
536
+ try {
537
+ var pathname = new URL(url, "http://dummy").pathname;
538
+ var lastDot = pathname.lastIndexOf(".");
539
+ if (lastDot === -1) return "";
540
+ return pathname.slice(lastDot).toLowerCase();
541
+ } catch (unused) {
542
+ var lastDot1 = url.lastIndexOf(".");
543
+ if (lastDot1 === -1) return "";
544
+ var ext = url.slice(lastDot1).split(/[?#]/)[0];
545
+ return (ext || "").toLowerCase();
546
+ }
547
+ }
548
+ function isUnsupportedFormat(url) {
549
+ var ext = getFileExtension(url);
550
+ return UNSUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1;
551
+ }
552
+ function replaceFlvExtension(url) {
553
+ var ext = getFileExtension(url);
554
+ if (ext === ".flv") {
555
+ return url.replace(/\.flv(\?|$)/i, ".mp4$1");
556
+ }
557
+ return url;
558
+ }
559
+ function isSupportedFormat(url, mimeType) {
560
+ if (isUnsupportedFormat(url)) {
561
+ return false;
562
+ }
563
+ var ext = getFileExtension(url);
564
+ if (SUPPORTED_VIDEO_EXTENSIONS.indexOf(ext) !== -1) {
565
+ return true;
566
+ }
567
+ if (ext === "" || ext === ".") {
568
+ return mimeType.includes("video/mp4") || mimeType.includes("video/webm") || mimeType.includes("m3u8") || mimeType.includes("application/x-mpegurl");
569
+ }
570
+ return false;
571
+ }
572
+ function createAdStormPlayer(contentVideo, options) {
573
+ var licenseKey = options.licenseKey, _options_debug = options.debug, debug = _options_debug === void 0 ? false : _options_debug;
574
+ var adPlaying = false;
575
+ var originalMutedState = false;
576
+ var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
577
+ var listeners = /* @__PURE__ */ new Map();
578
+ var adVideoElement;
579
+ var adContainerEl;
580
+ var adCountdownEl;
581
+ var currentAd;
582
+ var destroyed = false;
583
+ var tornDown = false;
584
+ var continueLiveStreamDuringAds = false;
585
+ var sessionId;
586
+ var adStallTimerId;
587
+ var adCountdownTimerId;
588
+ var adHideTimerId;
589
+ var lastCountdownSecond = -1;
590
+ var adListenersBound = false;
591
+ var parentPositionOverridden = false;
592
+ var adHandlers = {
593
+ timeupdate: function timeupdate() {
594
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
595
+ var progress = adVideoElement.currentTime / currentAd.duration;
596
+ if (progress >= 0.25 && !trackingFired.firstQuartile) {
597
+ trackingFired.firstQuartile = true;
598
+ fireTrackingPixels2(currentAd.trackingUrls.firstQuartile);
599
+ }
600
+ if (progress >= 0.5 && !trackingFired.midpoint) {
601
+ trackingFired.midpoint = true;
602
+ fireTrackingPixels2(currentAd.trackingUrls.midpoint);
603
+ }
604
+ if (progress >= 0.75 && !trackingFired.thirdQuartile) {
605
+ trackingFired.thirdQuartile = true;
606
+ fireTrackingPixels2(currentAd.trackingUrls.thirdQuartile);
607
+ }
608
+ updateAdCountdown();
609
+ },
610
+ playing: function playing() {
611
+ clearAdStallTimer();
612
+ if (!currentAd || trackingFired.start || destroyed || tornDown) return;
613
+ trackingFired.start = true;
614
+ fireTrackingPixels2(currentAd.trackingUrls.start);
615
+ startAdCountdown();
616
+ log("Ad started playing");
617
+ },
618
+ ended: function ended() {
619
+ if (!currentAd || trackingFired.complete || destroyed || tornDown) return;
620
+ trackingFired.complete = true;
621
+ fireTrackingPixels2(currentAd.trackingUrls.complete);
622
+ log("Ad completed");
623
+ handleAdComplete();
624
+ },
625
+ error: function error(e) {
626
+ if (destroyed || tornDown) return;
627
+ console.error("[AdStormPlayer] Ad video error:", e);
628
+ if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);
629
+ handleAdError();
630
+ },
631
+ waiting: function waiting() {
632
+ clearAdStallTimer();
633
+ adStallTimerId = setTimeout(function() {
634
+ adStallTimerId = void 0;
635
+ if (!adPlaying || destroyed || tornDown) return;
636
+ console.warn("[AdStormPlayer] Ad playback stalled too long");
637
+ handleAdError();
638
+ }, STALL_TIMEOUT_MS);
639
+ },
640
+ volumechange: function volumechange() {
641
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
642
+ if (adVideoElement.muted || adVideoElement.volume <= 0) {
643
+ fireTrackingPixels2(currentAd.trackingUrls.mute);
644
+ } else {
645
+ fireTrackingPixels2(currentAd.trackingUrls.unmute);
646
+ }
647
+ },
648
+ pause: function pause() {
649
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
650
+ if (!adVideoElement.ended) {
651
+ fireTrackingPixels2(currentAd.trackingUrls.pause);
652
+ }
653
+ },
654
+ play: function play() {
655
+ if (!currentAd || !adVideoElement || destroyed || tornDown) return;
656
+ if (adVideoElement.currentTime > 0) {
657
+ fireTrackingPixels2(currentAd.trackingUrls.resume);
658
+ }
659
+ }
660
+ };
661
+ var trackingFired = {
662
+ impression: false,
663
+ start: false,
664
+ firstQuartile: false,
665
+ midpoint: false,
666
+ thirdQuartile: false,
667
+ complete: false
668
+ };
669
+ var preloadSlots = /* @__PURE__ */ new Map();
699
670
  function log() {
700
671
  for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
701
672
  args[_key] = arguments[_key];
@@ -703,58 +674,340 @@ function createVastManager() {
703
674
  if (debug) {
704
675
  var _console;
705
676
  (_console = console).log.apply(_console, [
706
- "[VastManager]"
677
+ "[AdStormPlayer]"
707
678
  ].concat(_to_consumable_array(args)));
708
679
  }
709
680
  }
710
- function warn() {
711
- for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
712
- args[_key] = arguments[_key];
681
+ function emit(event, payload) {
682
+ var set = listeners.get(event);
683
+ if (!set) return;
684
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
685
+ try {
686
+ for(var _iterator = Array.from(set)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
687
+ var fn = _step.value;
688
+ try {
689
+ fn(payload);
690
+ } catch (error) {
691
+ console.warn("[AdStormPlayer] Error in event listener for ".concat(event, ":"), error);
692
+ }
693
+ }
694
+ } catch (err) {
695
+ _didIteratorError = true;
696
+ _iteratorError = err;
697
+ } finally{
698
+ try {
699
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
700
+ _iterator.return();
701
+ }
702
+ } finally{
703
+ if (_didIteratorError) {
704
+ throw _iteratorError;
705
+ }
706
+ }
713
707
  }
714
- var _console;
715
- (_console = console).warn.apply(_console, [
716
- "[VastManager]"
717
- ].concat(_to_consumable_array(args)));
718
708
  }
719
- function initialize() {
720
- return _async_to_generator(function() {
721
- return _ts_generator(this, function(_state) {
722
- if (initialized) return [
723
- 2
724
- ];
725
- initialized = true;
726
- log("Initialized, VAST tag URL:", VAST_TAG_URL.split("?")[0]);
727
- return [
728
- 2
729
- ];
709
+ function fireTrackingPixels2(urls) {
710
+ fireTrackingPixels(urls, sessionId, "[AdStormPlayer]");
711
+ }
712
+ function clearAdStallTimer() {
713
+ if (adStallTimerId) {
714
+ clearTimeout(adStallTimerId);
715
+ adStallTimerId = void 0;
716
+ }
717
+ }
718
+ function clearAdCountdownTimer() {
719
+ if (adCountdownTimerId) {
720
+ clearInterval(adCountdownTimerId);
721
+ adCountdownTimerId = void 0;
722
+ }
723
+ lastCountdownSecond = -1;
724
+ }
725
+ function updateAdCountdown() {
726
+ if (!adCountdownEl || !adVideoElement || !currentAd || !adPlaying) return;
727
+ var remainingSec = Math.max(0, Math.ceil((currentAd.duration || 0) - adVideoElement.currentTime));
728
+ if (remainingSec === lastCountdownSecond) return;
729
+ lastCountdownSecond = remainingSec;
730
+ adCountdownEl.textContent = "Ad ".concat(remainingSec, "s");
731
+ emit("ad_countdown", {
732
+ remainingSec: remainingSec,
733
+ durationSec: currentAd.duration,
734
+ currentTimeSec: adVideoElement.currentTime
735
+ });
736
+ }
737
+ function startAdCountdown() {
738
+ clearAdCountdownTimer();
739
+ updateAdCountdown();
740
+ adCountdownTimerId = setInterval(updateAdCountdown, 250);
741
+ }
742
+ function generateSessionId() {
743
+ return "adstorm-".concat(Date.now(), "-").concat(Math.random().toString(36).slice(2, 10));
744
+ }
745
+ function bindAdEventListeners() {
746
+ if (!adVideoElement || adListenersBound) return;
747
+ adVideoElement.addEventListener("timeupdate", adHandlers.timeupdate);
748
+ adVideoElement.addEventListener("playing", adHandlers.playing);
749
+ adVideoElement.addEventListener("ended", adHandlers.ended);
750
+ adVideoElement.addEventListener("error", adHandlers.error);
751
+ adVideoElement.addEventListener("waiting", adHandlers.waiting);
752
+ adVideoElement.addEventListener("volumechange", adHandlers.volumechange);
753
+ adVideoElement.addEventListener("pause", adHandlers.pause);
754
+ adVideoElement.addEventListener("play", adHandlers.play);
755
+ adListenersBound = true;
756
+ }
757
+ function unbindAdEventListeners() {
758
+ if (!adVideoElement || !adListenersBound) return;
759
+ adVideoElement.removeEventListener("timeupdate", adHandlers.timeupdate);
760
+ adVideoElement.removeEventListener("playing", adHandlers.playing);
761
+ adVideoElement.removeEventListener("ended", adHandlers.ended);
762
+ adVideoElement.removeEventListener("error", adHandlers.error);
763
+ adVideoElement.removeEventListener("waiting", adHandlers.waiting);
764
+ adVideoElement.removeEventListener("volumechange", adHandlers.volumechange);
765
+ adVideoElement.removeEventListener("pause", adHandlers.pause);
766
+ adVideoElement.removeEventListener("play", adHandlers.play);
767
+ adListenersBound = false;
768
+ }
769
+ function teardownCurrentPlayback() {
770
+ unbindAdEventListeners();
771
+ clearAdStallTimer();
772
+ clearAdCountdownTimer();
773
+ if (!adVideoElement) return;
774
+ adVideoElement.pause();
775
+ adVideoElement.removeAttribute("src");
776
+ adVideoElement.load();
777
+ }
778
+ function buildVastUrl(durationSeconds, metadata) {
779
+ var baseUrl = "https://adstorm.co/api-adstorm-dev/adstorm/vast/".concat(licenseKey, "/pod");
780
+ var defaultMetadata = {
781
+ video: {
782
+ codec: "h264",
783
+ width: contentVideo.videoWidth || 1280,
784
+ height: contentVideo.videoHeight || 720,
785
+ fps: 29.97,
786
+ bitrate: 5e3,
787
+ profile: "high",
788
+ pix_fmt: "yuv420p",
789
+ has_b_frames: 0
790
+ },
791
+ audio: {
792
+ codec: "aac",
793
+ sample_rate: 48e3,
794
+ bitrate: 128
795
+ }
796
+ };
797
+ var finalMetadata = metadata || defaultMetadata;
798
+ var metadataStr = encodeURIComponent(JSON.stringify(finalMetadata));
799
+ return "".concat(baseUrl, "?duration=").concat(Math.ceil(durationSeconds), "&metadata=").concat(metadataStr);
800
+ }
801
+ function parseVastXml(xmlString) {
802
+ var ads = [];
803
+ try {
804
+ var parser = new DOMParser();
805
+ var xmlDoc = parser.parseFromString(xmlString, "text/xml");
806
+ var parserError = xmlDoc.querySelector("parsererror");
807
+ if (parserError) {
808
+ console.error("[AdStormPlayer] XML parsing error:", parserError.textContent);
809
+ return [];
810
+ }
811
+ var adElements = xmlDoc.querySelectorAll("Ad");
812
+ adElements.forEach(function(adElement) {
813
+ var _adElement_querySelector, _adElement_querySelector1, _adElement_querySelector_textContent, _adElement_querySelector2;
814
+ var adId = adElement.getAttribute("id") || "unknown";
815
+ var title = ((_adElement_querySelector = adElement.querySelector("AdTitle")) === null || _adElement_querySelector === void 0 ? void 0 : _adElement_querySelector.textContent) || "Ad";
816
+ var durationText = ((_adElement_querySelector1 = adElement.querySelector("Duration")) === null || _adElement_querySelector1 === void 0 ? void 0 : _adElement_querySelector1.textContent) || "00:00:30";
817
+ var durationParts = durationText.split(":");
818
+ var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseFloat(durationParts[2] || "0");
819
+ var mediaFileElements = adElement.querySelectorAll("MediaFile");
820
+ var mediaFiles = [];
821
+ mediaFileElements.forEach(function(mf) {
822
+ var _mf_textContent;
823
+ var type = mf.getAttribute("type") || "";
824
+ var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
825
+ var width = parseInt(mf.getAttribute("width") || "1920", 10);
826
+ var height = parseInt(mf.getAttribute("height") || "1080", 10);
827
+ var bitrate = mf.getAttribute("bitrate") ? parseInt(mf.getAttribute("bitrate"), 10) : void 0;
828
+ if (!url) {
829
+ log("Skipping empty MediaFile URL");
830
+ return;
831
+ }
832
+ var originalUrl = url;
833
+ url = replaceFlvExtension(url);
834
+ if (url !== originalUrl) {
835
+ log("Converted FLV to MP4: ".concat(originalUrl, " -> ").concat(url));
836
+ }
837
+ if (isUnsupportedFormat(url)) {
838
+ var ext = getFileExtension(url);
839
+ log("Skipping unsupported format: ".concat(url, " (extension: ").concat(ext, ", declared type: ").concat(type, ")"));
840
+ return;
841
+ }
842
+ if (isSupportedFormat(url, type)) {
843
+ mediaFiles.push({
844
+ url: url,
845
+ type: type,
846
+ width: width,
847
+ height: height,
848
+ bitrate: bitrate
849
+ });
850
+ log("Found media file: ".concat(url, " (").concat(type, ", ").concat(width, "x").concat(height, ")"));
851
+ } else {
852
+ log("Skipping incompatible media file: ".concat(url, " (type: ").concat(type, ")"));
853
+ }
854
+ });
855
+ if (mediaFiles.length === 0) {
856
+ log("No valid media files found in ad:", adId);
857
+ return;
858
+ }
859
+ var trackingUrls = {
860
+ impression: [],
861
+ start: [],
862
+ firstQuartile: [],
863
+ midpoint: [],
864
+ thirdQuartile: [],
865
+ complete: [],
866
+ mute: [],
867
+ unmute: [],
868
+ pause: [],
869
+ resume: [],
870
+ error: []
871
+ };
872
+ adElement.querySelectorAll("Impression").forEach(function(el) {
873
+ var _el_textContent;
874
+ var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
875
+ if (url) trackingUrls.impression.push(url);
876
+ });
877
+ adElement.querySelectorAll("Tracking").forEach(function(el) {
878
+ var _el_textContent;
879
+ var event = el.getAttribute("event");
880
+ var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
881
+ if (event && url) {
882
+ var eventKey = event;
883
+ if (trackingUrls[eventKey]) {
884
+ trackingUrls[eventKey].push(url);
885
+ }
886
+ }
887
+ });
888
+ 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();
889
+ ads.push({
890
+ id: adId,
891
+ title: title,
892
+ duration: duration,
893
+ mediaFiles: mediaFiles,
894
+ trackingUrls: trackingUrls,
895
+ clickThrough: clickThrough
896
+ });
897
+ log("Parsed ad: ".concat(title, ", duration: ").concat(duration, "s, media files: ").concat(mediaFiles.length));
730
898
  });
731
- })();
899
+ } catch (error) {
900
+ console.error("[AdStormPlayer] Error parsing VAST XML:", error);
901
+ }
902
+ return ads;
903
+ }
904
+ function selectBestMediaFile(mediaFiles) {
905
+ if (mediaFiles.length === 0) return null;
906
+ if (mediaFiles.length === 1) return mediaFiles[0];
907
+ var mp4Files = mediaFiles.filter(function(mf) {
908
+ return mf.type.includes("video/mp4");
909
+ });
910
+ var candidates = mp4Files.length > 0 ? mp4Files : mediaFiles;
911
+ var targetWidth = contentVideo.videoWidth || 1280;
912
+ var targetHeight = contentVideo.videoHeight || 720;
913
+ candidates.sort(function(a, b) {
914
+ var diffA = Math.abs(a.width - targetWidth) + Math.abs(a.height - targetHeight);
915
+ var diffB = Math.abs(b.width - targetWidth) + Math.abs(b.height - targetHeight);
916
+ return diffA - diffB;
917
+ });
918
+ return candidates[0] || null;
919
+ }
920
+ function createAdVideoElement() {
921
+ var video = document.createElement("video");
922
+ video.style.position = "absolute";
923
+ video.style.left = "0";
924
+ video.style.top = "0";
925
+ video.style.width = "100%";
926
+ video.style.height = "100%";
927
+ video.style.objectFit = "contain";
928
+ video.style.backgroundColor = "#000";
929
+ video.style.zIndex = "1";
930
+ video.playsInline = true;
931
+ video.preload = "auto";
932
+ video.muted = originalMutedState;
933
+ video.volume = originalMutedState ? 0 : originalVolume;
934
+ return video;
935
+ }
936
+ function setAdPlayingFlag(isPlaying) {
937
+ if (isPlaying) {
938
+ contentVideo.dataset.stormcloudAdPlaying = "true";
939
+ } else {
940
+ delete contentVideo.dataset.stormcloudAdPlaying;
941
+ }
942
+ }
943
+ function setupAdEventListeners() {
944
+ bindAdEventListeners();
945
+ }
946
+ function handleAdComplete() {
947
+ if (destroyed || tornDown) return;
948
+ log("Handling ad completion");
949
+ adPlaying = false;
950
+ setAdPlayingFlag(false);
951
+ clearAdStallTimer();
952
+ clearAdCountdownTimer();
953
+ if (adContainerEl) {
954
+ adContainerEl.style.opacity = "0";
955
+ adHideTimerId = setTimeout(function() {
956
+ if (adContainerEl) {
957
+ adContainerEl.style.display = "none";
958
+ adContainerEl.style.pointerEvents = "none";
959
+ }
960
+ }, 300);
961
+ }
962
+ contentVideo.style.visibility = "visible";
963
+ contentVideo.style.opacity = "1";
964
+ contentVideo.muted = originalMutedState;
965
+ contentVideo.volume = originalVolume;
966
+ currentAd = void 0;
967
+ emit("content_resume");
968
+ emit("all_ads_completed");
969
+ }
970
+ function handleAdError() {
971
+ if (destroyed || tornDown) return;
972
+ log("Handling ad error");
973
+ if (!adPlaying) return;
974
+ adPlaying = false;
975
+ setAdPlayingFlag(false);
976
+ clearAdStallTimer();
977
+ clearAdCountdownTimer();
978
+ contentVideo.muted = originalMutedState;
979
+ contentVideo.volume = originalVolume;
980
+ contentVideo.style.visibility = "visible";
981
+ contentVideo.style.opacity = "1";
982
+ if (adContainerEl) {
983
+ adContainerEl.style.display = "none";
984
+ adContainerEl.style.pointerEvents = "none";
985
+ }
986
+ currentAd = void 0;
987
+ emit("ad_error");
988
+ emit("content_resume");
732
989
  }
733
- function requestBids(_context) {
990
+ function fetchVastOnce(durationSeconds) {
734
991
  return _async_to_generator(function() {
735
- var correlator, url, controller, timeoutId, _ref, _ref1, _vastAd_mediaFiles_, _vastAd_mediaFiles_1, fetchOptions, response, vastXml, vastAd, bid, error;
992
+ var vastUrl, controller, timeoutId, requestInit, response, xmlText;
736
993
  return _ts_generator(this, function(_state) {
737
994
  switch(_state.label){
738
995
  case 0:
739
- if (!initialized) {
740
- throw new Error("VastManager not initialized. Call initialize() first.");
741
- }
742
- correlator = Math.floor(Math.random() * 1e12).toString();
743
- url = VAST_TAG_URL.replace("[placeholder]", correlator);
744
- log("Fetching VAST tag, correlator:", correlator);
996
+ vastUrl = buildVastUrl(durationSeconds);
997
+ log("Fetching VAST from:", vastUrl);
745
998
  controller = typeof AbortController !== "undefined" ? new AbortController() : null;
746
999
  timeoutId = setTimeout(function() {
747
1000
  return controller === null || controller === void 0 ? void 0 : controller.abort();
748
- }, DEFAULT_TIMEOUT_MS);
1001
+ }, REQUEST_TIMEOUT_MS);
749
1002
  _state.label = 1;
750
1003
  case 1:
751
1004
  _state.trys.push([
752
1005
  1,
753
- 4,
754
1006
  ,
1007
+ 4,
755
1008
  5
756
1009
  ]);
757
- fetchOptions = {
1010
+ requestInit = {
758
1011
  method: "GET",
759
1012
  mode: "cors",
760
1013
  credentials: "omit",
@@ -763,62 +1016,34 @@ function createVastManager() {
763
1016
  },
764
1017
  referrerPolicy: "no-referrer-when-downgrade"
765
1018
  };
766
- if (controller) fetchOptions.signal = controller.signal;
1019
+ if (controller) {
1020
+ requestInit.signal = controller.signal;
1021
+ }
767
1022
  return [
768
1023
  4,
769
- fetch(url, fetchOptions)
1024
+ fetch(vastUrl, requestInit)
770
1025
  ];
771
1026
  case 2:
772
1027
  response = _state.sent();
773
- clearTimeout(timeoutId);
774
1028
  if (!response.ok) {
775
- throw new Error("VAST request returned HTTP ".concat(response.status));
1029
+ throw new Error("Failed to fetch VAST: ".concat(response.status, " ").concat(response.statusText));
776
1030
  }
777
1031
  return [
778
1032
  4,
779
1033
  response.text()
780
1034
  ];
781
1035
  case 3:
782
- vastXml = _state.sent();
783
- log("VAST XML received, length:", vastXml.length);
784
- vastAd = parseVastXml(vastXml, "mp4-first", "[VastManager]");
785
- if (!vastAd) {
786
- log("VAST parsed but no usable ad found");
787
- return [
788
- 2,
789
- []
790
- ];
791
- }
792
- log("Ad parsed: id=".concat(vastAd.id, ", duration=").concat(vastAd.duration, "s, mediaFiles=").concat(vastAd.mediaFiles.length));
793
- bid = {
794
- bidder: "vast-direct",
795
- cpm: 0,
796
- vastXml: vastXml,
797
- width: (_ref = (_vastAd_mediaFiles_ = vastAd.mediaFiles[0]) === null || _vastAd_mediaFiles_ === void 0 ? void 0 : _vastAd_mediaFiles_.width) !== null && _ref !== void 0 ? _ref : 0,
798
- 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,
799
- adId: vastAd.id,
800
- impId: correlator,
801
- creativeId: vastAd.id,
802
- currency: "USD",
803
- durationSec: vastAd.duration
804
- };
1036
+ xmlText = _state.sent();
1037
+ log("VAST response received, length:", xmlText.length);
805
1038
  return [
806
1039
  2,
807
- [
808
- bid
809
- ]
1040
+ parseVastXml(xmlText)
810
1041
  ];
811
1042
  case 4:
812
- error = _state.sent();
813
1043
  clearTimeout(timeoutId);
814
- if ((error === null || error === void 0 ? void 0 : error.name) === "AbortError") {
815
- warn("VAST request timed out after ".concat(DEFAULT_TIMEOUT_MS, "ms"));
816
- return [
817
- 2,
818
- []
819
- ];
820
- }
821
- throw error;
1044
+ return [
1045
+ 7
1046
+ ];
822
1047
  case 5:
823
1048
  return [
824
1049
  2
@@ -827,14 +1052,14 @@ function createVastManager() {
827
1052
  });
828
1053
  })();
829
1054
  }
830
- function requestBidsUntilResponse(context) {
1055
+ function fetchVast(durationSeconds) {
831
1056
  return _async_to_generator(function() {
832
1057
  var _loop, lastError, attempt, _ret;
833
1058
  return _ts_generator(this, function(_state) {
834
1059
  switch(_state.label){
835
1060
  case 0:
836
1061
  _loop = function(attempt) {
837
- var bids, err, delay;
1062
+ var ads, error, delay;
838
1063
  return _ts_generator(this, function(_state) {
839
1064
  switch(_state.label){
840
1065
  case 0:
@@ -846,39 +1071,39 @@ function createVastManager() {
846
1071
  ]);
847
1072
  return [
848
1073
  4,
849
- requestBids(context)
1074
+ fetchVastOnce(durationSeconds)
850
1075
  ];
851
1076
  case 1:
852
- bids = _state.sent();
853
- if (bids.length > 0) {
854
- log("requestBidsUntilResponse: got ".concat(bids.length, " ad(s) on attempt ").concat(attempt));
855
- return [
856
- 2,
857
- {
858
- v: bids
859
- }
860
- ];
861
- }
862
- log("requestBidsUntilResponse: no ads on attempt ".concat(attempt, "/").concat(MAX_RETRIES));
1077
+ ads = _state.sent();
1078
+ if (ads.length > 0) return [
1079
+ 2,
1080
+ {
1081
+ v: ads
1082
+ }
1083
+ ];
1084
+ log("No ad returned from VAST on attempt ".concat(attempt, "/").concat(REQUEST_MAX_RETRIES));
863
1085
  return [
864
1086
  3,
865
1087
  3
866
1088
  ];
867
1089
  case 2:
868
- err = _state.sent();
869
- lastError = err;
870
- warn("requestBidsUntilResponse: attempt ".concat(attempt, "/").concat(MAX_RETRIES, " failed:"), err);
1090
+ error = _state.sent();
1091
+ lastError = error;
1092
+ if ((error === null || error === void 0 ? void 0 : error.name) === "AbortError") {
1093
+ console.warn("[AdStormPlayer] VAST request timed out (".concat(REQUEST_TIMEOUT_MS, "ms), attempt ").concat(attempt, "/").concat(REQUEST_MAX_RETRIES));
1094
+ } else {
1095
+ console.warn("[AdStormPlayer] VAST request failed on attempt ".concat(attempt, "/").concat(REQUEST_MAX_RETRIES, ":"), error);
1096
+ }
871
1097
  return [
872
1098
  3,
873
1099
  3
874
1100
  ];
875
1101
  case 3:
876
- if (!(attempt < MAX_RETRIES)) return [
1102
+ if (!(attempt < REQUEST_MAX_RETRIES)) return [
877
1103
  3,
878
1104
  5
879
1105
  ];
880
- delay = RETRY_BACKOFF_MS * attempt;
881
- log("requestBidsUntilResponse: waiting ".concat(delay, "ms before retry"));
1106
+ delay = REQUEST_RETRY_BACKOFF_MS * attempt;
882
1107
  return [
883
1108
  4,
884
1109
  new Promise(function(resolve) {
@@ -895,13 +1120,10 @@ function createVastManager() {
895
1120
  }
896
1121
  });
897
1122
  };
898
- if (!initialized) {
899
- throw new Error("VastManager not initialized. Call initialize() first.");
900
- }
901
1123
  attempt = 1;
902
1124
  _state.label = 1;
903
1125
  case 1:
904
- if (!(attempt <= MAX_RETRIES)) return [
1126
+ if (!(attempt <= REQUEST_MAX_RETRIES)) return [
905
1127
  3,
906
1128
  4
907
1129
  ];
@@ -923,7 +1145,9 @@ function createVastManager() {
923
1145
  1
924
1146
  ];
925
1147
  case 4:
926
- if (_instanceof(lastError, Error)) throw lastError;
1148
+ if (_instanceof(lastError, Error)) {
1149
+ throw lastError;
1150
+ }
927
1151
  return [
928
1152
  2,
929
1153
  []
@@ -932,946 +1156,468 @@ function createVastManager() {
932
1156
  });
933
1157
  })();
934
1158
  }
935
- function destroy() {
936
- initialized = false;
937
- log("Destroyed");
938
- }
939
- return {
940
- initialize: initialize,
941
- requestBids: requestBids,
942
- requestBidsUntilResponse: requestBidsUntilResponse,
943
- destroy: destroy,
944
- get isInitialized () {
945
- return initialized;
946
- }
947
- };
948
- }
949
- // src/sdk/vastAdLayer.ts
950
- var import_hls = __toESM(require("hls.js"), 1);
951
- var LOG = "[VastAdLayer]";
952
- function resolveBidToVastAd(winner, logPrefix) {
953
- if (winner.vastXml) {
954
- var ad = parseVastXml(winner.vastXml, "mp4-first", logPrefix);
955
- return Promise.resolve(ad);
956
- }
957
- if (winner.vastUrl) {
958
- return fetchAndParseVastAd(winner.vastUrl, "mp4-first", logPrefix);
959
- }
960
- return Promise.resolve(null);
961
- }
962
- function createVastAdLayer(contentVideo, options) {
963
- var _ref, _ref1, _ref2, _ref3, _ref4;
964
- var adPlaying = false;
965
- var originalMutedState = false;
966
- var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
967
- var listeners = /* @__PURE__ */ new Map();
968
- var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
969
- var continueLiveStreamDuringAds = (_ref = options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) !== null && _ref !== void 0 ? _ref : false;
970
- var smartTVMode = (_ref1 = options === null || options === void 0 ? void 0 : options.smartTVMode) !== null && _ref1 !== void 0 ? _ref1 : false;
971
- var singleElementMode = (_ref2 = options === null || options === void 0 ? void 0 : options.singleElementMode) !== null && _ref2 !== void 0 ? _ref2 : false;
972
- var forceMP4Ads = (_ref3 = options === null || options === void 0 ? void 0 : options.forceMP4Ads) !== null && _ref3 !== void 0 ? _ref3 : smartTVMode || singleElementMode;
973
- var debug = (_ref4 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref4 !== void 0 ? _ref4 : false;
974
- var adVideoElement;
975
- var adHls;
976
- var adContainerEl;
977
- var currentAd;
978
- var sessionId;
979
- var destroyed = false;
980
- var tornDown = false;
981
- var trackingFired = createEmptyTrackingState();
982
- var adStallTimerId;
983
- var currentAdEventHandlers;
984
- var preloadSlots = /* @__PURE__ */ new Map();
985
- function emit(event, payload) {
986
- var set = listeners.get(event);
987
- if (!set) return;
988
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
989
- try {
990
- for(var _iterator = Array.from(set)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
991
- var fn = _step.value;
992
- try {
993
- fn(payload);
994
- } catch (error) {
995
- console.warn("".concat(LOG, " Error in event listener for ").concat(event, ":"), error);
996
- }
997
- }
998
- } catch (err) {
999
- _didIteratorError = true;
1000
- _iteratorError = err;
1001
- } finally{
1002
- try {
1003
- if (!_iteratorNormalCompletion && _iterator.return != null) {
1004
- _iterator.return();
1005
- }
1006
- } finally{
1007
- if (_didIteratorError) {
1008
- throw _iteratorError;
1009
- }
1010
- }
1011
- }
1012
- }
1013
- function generateSessionId() {
1014
- return "session-".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
1015
- }
1016
- function fireTrackingPixels2(urls) {
1017
- fireTrackingPixels(urls, sessionId, LOG);
1018
- }
1019
- function getMainStreamQuality() {
1020
- if (!(mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.levels)) return null;
1021
- var currentLevel = mainHlsInstance.currentLevel;
1022
- if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {
1023
- var autoLevel = mainHlsInstance.loadLevel;
1024
- if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {
1025
- var level2 = mainHlsInstance.levels[autoLevel];
1026
- return {
1027
- width: level2.width || 1920,
1028
- height: level2.height || 1080,
1029
- bitrate: level2.bitrate || 5e6
1030
- };
1031
- }
1032
- return null;
1033
- }
1034
- var level = mainHlsInstance.levels[currentLevel];
1035
- return {
1036
- width: level.width || 1920,
1037
- height: level.height || 1080,
1038
- bitrate: level.bitrate || 5e6
1039
- };
1040
- }
1041
- function selectBestMediaFile(mediaFiles) {
1042
- var _ref;
1043
- var _scoredFiles_;
1044
- if (mediaFiles.length === 0) throw new Error("No media files available");
1045
- var candidates = mediaFiles;
1046
- if (forceMP4Ads) {
1047
- var mp4Only = candidates.filter(function(f) {
1048
- return !isHlsMediaFile(f);
1049
- });
1050
- if (mp4Only.length > 0) {
1051
- candidates = mp4Only;
1052
- if (debug) console.log("".concat(LOG, " forceMP4Ads: filtered to ").concat(mp4Only.length, " MP4-only file(s)"));
1053
- } else if (debug) {
1054
- console.warn("".concat(LOG, " forceMP4Ads: no MP4 files available, falling back to all media files"));
1055
- }
1056
- } else {
1057
- var mp4Only1 = candidates.filter(function(f) {
1058
- return !isHlsMediaFile(f);
1059
- });
1060
- if (mp4Only1.length > 0) {
1061
- candidates = mp4Only1;
1062
- if (debug) console.log("".concat(LOG, " Preferring ").concat(mp4Only1.length, " MP4 file(s) over HLS (mp4-first)"));
1063
- }
1064
- }
1065
- var firstFile = candidates[0];
1066
- if (candidates.length === 1) return firstFile;
1067
- var mainQuality = getMainStreamQuality();
1068
- if (!mainQuality) {
1069
- if (debug) console.log("".concat(LOG, " No main stream quality info, using first media file"));
1070
- return firstFile;
1071
- }
1072
- var scoredFiles = candidates.map(function(file) {
1073
- var widthDiff = Math.abs(file.width - mainQuality.width);
1074
- var heightDiff = Math.abs(file.height - mainQuality.height);
1075
- var resolutionDiff = widthDiff + heightDiff;
1076
- var fileBitrate = (file.bitrate || 5e3) * 1e3;
1077
- var bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);
1078
- var score = resolutionDiff * 2 + bitrateDiff / 1e3;
1079
- return {
1080
- file: file,
1081
- score: score
1082
- };
1083
- });
1084
- scoredFiles.sort(function(a, b) {
1085
- return a.score - b.score;
1086
- });
1087
- return (_ref = (_scoredFiles_ = scoredFiles[0]) === null || _scoredFiles_ === void 0 ? void 0 : _scoredFiles_.file) !== null && _ref !== void 0 ? _ref : firstFile;
1088
- }
1089
- function isHlsMediaFile(file) {
1090
- return file.type === "application/x-mpegURL" || file.type.includes("m3u8");
1091
- }
1092
- function createAdVideoElement() {
1093
- var video = document.createElement("video");
1094
- video.style.position = "absolute";
1095
- video.style.left = "0";
1096
- video.style.top = "0";
1097
- video.style.width = "100%";
1098
- video.style.height = "100%";
1099
- video.style.objectFit = "contain";
1100
- video.style.backgroundColor = "#000";
1101
- video.playsInline = true;
1102
- video.muted = false;
1103
- video.volume = 1;
1104
- return video;
1105
- }
1106
- function clearAdStallTimer() {
1107
- if (adStallTimerId != null) {
1108
- clearTimeout(adStallTimerId);
1109
- adStallTimerId = void 0;
1110
- }
1111
- }
1112
- function removeAdEventListeners() {
1113
- clearAdStallTimer();
1114
- if (!currentAdEventHandlers || !adVideoElement) return;
1115
- var el = adVideoElement;
1116
- el.removeEventListener("timeupdate", currentAdEventHandlers.timeupdate);
1117
- el.removeEventListener("playing", currentAdEventHandlers.playing);
1118
- el.removeEventListener("ended", currentAdEventHandlers.ended);
1119
- el.removeEventListener("error", currentAdEventHandlers.error);
1120
- el.removeEventListener("volumechange", currentAdEventHandlers.volumechange);
1121
- el.removeEventListener("pause", currentAdEventHandlers.pause);
1122
- el.removeEventListener("play", currentAdEventHandlers.play);
1123
- el.removeEventListener("waiting", currentAdEventHandlers.waiting);
1124
- currentAdEventHandlers = void 0;
1125
- }
1126
- function setupAdEventListeners() {
1127
- if (!adVideoElement) return;
1128
- removeAdEventListeners();
1129
- var handlers = {
1130
- timeupdate: function timeupdate() {
1131
- var ad = currentAd;
1132
- if (!ad || !adVideoElement) return;
1133
- var progress = adVideoElement.currentTime / ad.duration;
1134
- if (progress >= 0.25 && !trackingFired.firstQuartile) {
1135
- trackingFired.firstQuartile = true;
1136
- fireTrackingPixels2(ad.trackingUrls.firstQuartile);
1137
- }
1138
- if (progress >= 0.5 && !trackingFired.midpoint) {
1139
- trackingFired.midpoint = true;
1140
- fireTrackingPixels2(ad.trackingUrls.midpoint);
1141
- }
1142
- if (progress >= 0.75 && !trackingFired.thirdQuartile) {
1143
- trackingFired.thirdQuartile = true;
1144
- fireTrackingPixels2(ad.trackingUrls.thirdQuartile);
1145
- }
1146
- },
1147
- playing: function playing() {
1148
- clearAdStallTimer();
1149
- var ad = currentAd;
1150
- if (!ad || trackingFired.start) return;
1151
- trackingFired.start = true;
1152
- fireTrackingPixels2(ad.trackingUrls.start);
1153
- if (debug) console.log("".concat(LOG, " Ad started playing"));
1154
- },
1155
- ended: function ended() {
1156
- if (tornDown || !currentAd || trackingFired.complete) return;
1157
- trackingFired.complete = true;
1158
- fireTrackingPixels2(currentAd.trackingUrls.complete);
1159
- if (debug) console.log("".concat(LOG, " Ad completed"));
1160
- handleAdComplete();
1161
- },
1162
- error: function error(e) {
1163
- if (tornDown) return;
1164
- console.error("".concat(LOG, " Ad video error:"), e);
1165
- if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);
1166
- handleAdError();
1167
- },
1168
- volumechange: function volumechange() {
1169
- if (!currentAd || !adVideoElement) return;
1170
- if (adVideoElement.muted) {
1171
- fireTrackingPixels2(currentAd.trackingUrls.mute);
1172
- } else {
1173
- fireTrackingPixels2(currentAd.trackingUrls.unmute);
1174
- }
1175
- },
1176
- pause: function pause() {
1177
- if (currentAd && adVideoElement && !adVideoElement.ended) {
1178
- fireTrackingPixels2(currentAd.trackingUrls.pause);
1179
- }
1180
- },
1181
- play: function play() {
1182
- if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1183
- fireTrackingPixels2(currentAd.trackingUrls.resume);
1184
- }
1185
- },
1186
- waiting: function waiting() {
1187
- clearAdStallTimer();
1188
- adStallTimerId = setTimeout(function() {
1189
- adStallTimerId = void 0;
1190
- if (adPlaying) {
1191
- if (debug) console.warn("".concat(LOG, " Ad video stalled for too long, treating as error"));
1192
- handleAdError();
1193
- }
1194
- }, 8e3);
1195
- }
1196
- };
1197
- adVideoElement.addEventListener("timeupdate", handlers.timeupdate);
1198
- adVideoElement.addEventListener("playing", handlers.playing);
1199
- adVideoElement.addEventListener("ended", handlers.ended);
1200
- adVideoElement.addEventListener("error", handlers.error);
1201
- adVideoElement.addEventListener("volumechange", handlers.volumechange);
1202
- adVideoElement.addEventListener("pause", handlers.pause);
1203
- adVideoElement.addEventListener("play", handlers.play);
1204
- adVideoElement.addEventListener("waiting", handlers.waiting);
1205
- currentAdEventHandlers = handlers;
1206
- }
1207
- function setAdPlayingFlag(isPlaying) {
1208
- if (isPlaying) {
1209
- contentVideo.dataset.stormcloudAdPlaying = "true";
1210
- } else {
1211
- delete contentVideo.dataset.stormcloudAdPlaying;
1159
+ function getDurationSecondsFromContext(requestContext) {
1160
+ var _ctx_remainingBreakSec;
1161
+ if (!requestContext || (typeof requestContext === "undefined" ? "undefined" : _type_of(requestContext)) !== "object") {
1162
+ return 30;
1212
1163
  }
1213
- }
1214
- function handleAdComplete() {
1215
- if (tornDown) return;
1216
- clearAdStallTimer();
1217
- if (debug) console.log("".concat(LOG, " Handling ad completion"));
1218
- adPlaying = false;
1219
- setAdPlayingFlag(false);
1220
- if (adContainerEl) {
1221
- adContainerEl.style.display = "none";
1222
- adContainerEl.style.pointerEvents = "none";
1164
+ var ctx = requestContext;
1165
+ var value = (_ctx_remainingBreakSec = ctx.remainingBreakSec) !== null && _ctx_remainingBreakSec !== void 0 ? _ctx_remainingBreakSec : ctx.breakDurationSec;
1166
+ if (typeof value !== "number" || Number.isNaN(value)) {
1167
+ return 30;
1223
1168
  }
1224
- emit("ad_impression");
1225
- emit("content_resume");
1169
+ return Math.max(1, Math.ceil(value));
1226
1170
  }
1227
- function handleAdError() {
1228
- if (tornDown) return;
1229
- if (!adPlaying) return;
1230
- clearAdStallTimer();
1231
- if (debug) console.log("".concat(LOG, " Handling ad error"));
1232
- adPlaying = false;
1233
- setAdPlayingFlag(false);
1234
- if (adContainerEl) {
1235
- adContainerEl.style.display = "none";
1236
- adContainerEl.style.pointerEvents = "none";
1237
- }
1238
- emit("ad_error");
1239
- }
1240
- function teardownCurrentPlayback() {
1241
- removeAdEventListeners();
1242
- if (adHls) {
1243
- adHls.destroy();
1244
- adHls = void 0;
1245
- }
1246
- if (adVideoElement) {
1247
- if (singleElementMode && adVideoElement === contentVideo) {
1248
- contentVideo.pause();
1249
- } else {
1250
- adVideoElement.pause();
1251
- adVideoElement.removeAttribute("src");
1252
- adVideoElement.load();
1253
- }
1254
- }
1255
- }
1256
- function startNativePlayback(mediaFile) {
1257
- if (!adVideoElement) return;
1258
- if (debug) console.log("".concat(LOG, " Starting native MP4 playback: ").concat(mediaFile.url));
1259
- adVideoElement.src = mediaFile.url;
1260
- adVideoElement.load();
1261
- adVideoElement.play().catch(function(error) {
1262
- console.error("".concat(LOG, " Error starting native ad playback:"), error);
1263
- handleAdError();
1264
- });
1265
- }
1266
- function startHlsPlayback(mediaFile) {
1267
- if (!adVideoElement) return;
1268
- if (debug) console.log("".concat(LOG, " Starting HLS playback: ").concat(mediaFile.url));
1269
- if (import_hls.default.isSupported()) {
1270
- if (adHls) {
1271
- adHls.destroy();
1272
- adHls = void 0;
1273
- }
1274
- adHls = new import_hls.default({
1275
- enableWorker: true,
1276
- lowLatencyMode: false
1277
- });
1278
- adHls.loadSource(mediaFile.url);
1279
- adHls.attachMedia(adVideoElement);
1280
- adHls.on(import_hls.default.Events.MANIFEST_PARSED, function() {
1281
- if (!adPlaying) return;
1282
- adVideoElement.play().catch(function(error) {
1283
- console.error("".concat(LOG, " Error starting HLS ad playback:"), error);
1284
- handleAdError();
1285
- });
1286
- });
1287
- var nonFatalNetworkErrors = 0;
1288
- adHls.on(import_hls.default.Events.ERROR, function(_event, data) {
1289
- if (data.fatal) {
1290
- handleAdError();
1291
- } else if (data.type === import_hls.default.ErrorTypes.NETWORK_ERROR) {
1292
- nonFatalNetworkErrors++;
1293
- if (nonFatalNetworkErrors >= 3) {
1294
- if (debug) console.warn("".concat(LOG, " Too many non-fatal HLS network errors (").concat(nonFatalNetworkErrors, "), treating as fatal"));
1295
- handleAdError();
1296
- }
1297
- }
1298
- });
1299
- } else if (adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
1300
- adVideoElement.src = mediaFile.url;
1301
- adVideoElement.play().catch(function(error) {
1302
- console.error("".concat(LOG, " Error starting native HLS ad playback:"), error);
1303
- handleAdError();
1304
- });
1305
- } else {
1306
- console.error("".concat(LOG, " HLS not supported on this platform"));
1307
- handleAdError();
1308
- }
1309
- }
1310
- function startPlayback(mediaFile) {
1311
- if (!adVideoElement) return;
1312
- if (singleElementMode && isHlsMediaFile(mediaFile)) {
1313
- var mp4Fallback = currentAd === null || currentAd === void 0 ? void 0 : currentAd.mediaFiles.find(function(f) {
1314
- return !isHlsMediaFile(f);
1315
- });
1316
- if (mp4Fallback) {
1317
- if (debug) console.log("".concat(LOG, " singleElementMode: HLS ad blocked, using MP4 fallback"));
1318
- startNativePlayback(mp4Fallback);
1319
- return;
1320
- }
1321
- }
1322
- if (isHlsMediaFile(mediaFile)) {
1323
- startHlsPlayback(mediaFile);
1324
- } else {
1325
- startNativePlayback(mediaFile);
1326
- }
1327
- }
1328
- function playAd(bids) {
1171
+ function requestAdFromApi(requestContext) {
1329
1172
  return _async_to_generator(function() {
1330
- var winner, ad, contentVolume, adVolume2, mediaFile2, _contentVideo_parentElement, container, adVolume, mediaFile;
1173
+ var durationSeconds, ads;
1331
1174
  return _ts_generator(this, function(_state) {
1332
1175
  switch(_state.label){
1333
1176
  case 0:
1334
- if (destroyed) {
1335
- return [
1336
- 2,
1337
- Promise.reject(new Error("Layer has been destroyed"))
1338
- ];
1339
- }
1340
- if (bids.length === 0) {
1341
- return [
1342
- 2,
1343
- Promise.reject(new Error("No bids provided"))
1344
- ];
1345
- }
1346
- winner = bids[0];
1347
- if (debug) {
1348
- console.log("".concat(LOG, " Winning bid: ").concat(winner.bidder, " $").concat(winner.cpm.toFixed(2), " ").concat(winner.currency));
1349
- }
1177
+ durationSeconds = getDurationSecondsFromContext(requestContext);
1350
1178
  return [
1351
1179
  4,
1352
- resolveBidToVastAd(winner, LOG)
1180
+ fetchVast(durationSeconds)
1353
1181
  ];
1354
1182
  case 1:
1355
- ad = _state.sent();
1356
- if (!ad) {
1357
- if (debug) console.warn("".concat(LOG, " Winning bid has no VAST URL or XML"));
1358
- emit("ad_error");
1359
- return [
1360
- 2,
1361
- Promise.reject(new Error("No VAST from bid"))
1362
- ];
1363
- }
1364
- if (debug) {
1365
- console.log("".concat(LOG, " Ad parsed: ").concat(ad.title, ", duration: ").concat(ad.duration, "s, mediaFiles: ").concat(ad.mediaFiles.length));
1366
- }
1367
- sessionId = generateSessionId();
1368
- currentAd = ad;
1369
- trackingFired = _object_spread({}, createEmptyTrackingState());
1370
- fireTrackingPixels2(ad.trackingUrls.impression);
1371
- trackingFired.impression = true;
1372
- contentVolume = contentVideo.volume;
1373
- originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1374
- if (!singleElementMode) return [
1375
- 3,
1376
- 3
1377
- ];
1378
- mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.detachMedia();
1379
- teardownCurrentPlayback();
1380
- adVideoElement = contentVideo;
1381
- adHls = void 0;
1382
- adPlaying = true;
1383
- setAdPlayingFlag(true);
1384
- contentVideo.removeAttribute("src");
1385
- contentVideo.load();
1386
- if (!continueLiveStreamDuringAds) {
1387
- contentVideo.pause();
1388
- }
1389
- contentVideo.muted = true;
1390
- contentVideo.volume = 0;
1183
+ ads = _state.sent();
1391
1184
  return [
1392
- 4,
1393
- new Promise(function(resolve) {
1394
- return setTimeout(resolve, 200);
1395
- })
1396
- ];
1397
- case 2:
1398
- _state.sent();
1399
- if (destroyed || tornDown) return [
1400
- 2
1401
- ];
1402
- contentVideo.style.visibility = "visible";
1403
- contentVideo.style.opacity = "1";
1404
- emit("content_pause");
1405
- setupAdEventListeners();
1406
- adVolume2 = originalMutedState ? 1 : originalVolume;
1407
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume2));
1408
- adVideoElement.muted = false;
1409
- mediaFile2 = selectBestMediaFile(ad.mediaFiles);
1410
- if (debug) console.log("".concat(LOG, " Loading ad from: ").concat(mediaFile2.url));
1411
- startPlayback(mediaFile2);
1412
- return [
1413
- 2
1414
- ];
1415
- case 3:
1416
- if (!adContainerEl) {
1417
- ;
1418
- container = document.createElement("div");
1419
- container.style.position = "absolute";
1420
- container.style.left = "0";
1421
- container.style.top = "0";
1422
- container.style.right = "0";
1423
- container.style.bottom = "0";
1424
- container.style.display = "none";
1425
- container.style.alignItems = "center";
1426
- container.style.justifyContent = "center";
1427
- container.style.pointerEvents = "none";
1428
- container.style.zIndex = "10";
1429
- container.style.backgroundColor = "#000";
1430
- (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1431
- adContainerEl = container;
1432
- }
1433
- if (!adVideoElement) {
1434
- adVideoElement = createAdVideoElement();
1435
- adContainerEl.appendChild(adVideoElement);
1436
- setupAdEventListeners();
1437
- } else {
1438
- teardownCurrentPlayback();
1439
- }
1440
- if (!continueLiveStreamDuringAds) {
1441
- contentVideo.pause();
1442
- }
1443
- contentVideo.muted = true;
1444
- contentVideo.volume = 0;
1445
- adPlaying = true;
1446
- setAdPlayingFlag(true);
1447
- adVolume = originalMutedState ? 1 : originalVolume;
1448
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
1449
- adVideoElement.muted = false;
1450
- if (adContainerEl) {
1451
- adContainerEl.style.display = "flex";
1452
- adContainerEl.style.pointerEvents = "auto";
1453
- }
1454
- emit("content_pause");
1455
- mediaFile = selectBestMediaFile(ad.mediaFiles);
1456
- if (debug) console.log("".concat(LOG, " Loading ad from: ").concat(mediaFile.url));
1457
- startPlayback(mediaFile);
1458
- return [
1459
- 2
1185
+ 2,
1186
+ ads[0] || null
1460
1187
  ];
1461
1188
  }
1462
1189
  });
1463
1190
  })();
1464
1191
  }
1465
- function ensureAdContainer() {
1466
- if (!adContainerEl) {
1467
- var _contentVideo_parentElement;
1468
- var container = document.createElement("div");
1469
- container.style.position = "absolute";
1470
- container.style.left = "0";
1471
- container.style.top = "0";
1472
- container.style.right = "0";
1473
- container.style.bottom = "0";
1474
- container.style.display = "none";
1475
- container.style.alignItems = "center";
1476
- container.style.justifyContent = "center";
1477
- container.style.pointerEvents = "none";
1478
- container.style.zIndex = "10";
1479
- container.style.backgroundColor = "#000";
1480
- (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1481
- adContainerEl = container;
1482
- }
1483
- return adContainerEl;
1192
+ function assignCurrentAd(ad) {
1193
+ currentAd = ad;
1194
+ sessionId = generateSessionId();
1195
+ trackingFired = {
1196
+ impression: false,
1197
+ start: false,
1198
+ firstQuartile: false,
1199
+ midpoint: false,
1200
+ thirdQuartile: false,
1201
+ complete: false
1202
+ };
1203
+ fireTrackingPixels2(currentAd.trackingUrls.impression);
1204
+ trackingFired.impression = true;
1205
+ emit("ad_impression");
1484
1206
  }
1485
- function preloadAd(bids, token) {
1486
- return _async_to_generator(function() {
1487
- var winner, ad, mediaFile, slot, videoEl, container, hls, slot1, slot2;
1488
- return _ts_generator(this, function(_state) {
1489
- switch(_state.label){
1490
- case 0:
1491
- if (destroyed) return [
1492
- 2
1493
- ];
1494
- winner = bids[0];
1495
- if (!winner) return [
1496
- 2
1497
- ];
1498
- if (debug) console.log("".concat(LOG, " [preload] Resolving VAST for token=").concat(token));
1499
- return [
1500
- 4,
1501
- resolveBidToVastAd(winner, LOG)
1502
- ];
1503
- case 1:
1504
- ad = _state.sent();
1505
- if (!ad || destroyed) return [
1506
- 2
1507
- ];
1508
- mediaFile = selectBestMediaFile(ad.mediaFiles);
1509
- if (!mediaFile) return [
1510
- 2
1511
- ];
1512
- if (smartTVMode || singleElementMode) {
1513
- slot = {
1514
- bids: bids,
1515
- ad: ad,
1516
- mediaFile: mediaFile,
1517
- videoEl: null,
1518
- ready: true
1519
- };
1520
- preloadSlots.set(token, slot);
1521
- if (debug) console.log("".concat(LOG, " [preload] Metadata-only preload (smartTV/singleElement), token=").concat(token, ", url=").concat(mediaFile.url));
1207
+ return {
1208
+ initialize: function initialize() {
1209
+ log("Initializing");
1210
+ if (!adContainerEl) {
1211
+ var _contentVideo_parentElement;
1212
+ var parent = contentVideo.parentElement;
1213
+ if (parent) {
1214
+ var computed = window.getComputedStyle(parent).position;
1215
+ if (computed === "static") {
1216
+ parent.style.position = "relative";
1217
+ parentPositionOverridden = true;
1218
+ }
1219
+ }
1220
+ var container = document.createElement("div");
1221
+ container.style.position = "absolute";
1222
+ container.style.left = "0";
1223
+ container.style.top = "0";
1224
+ container.style.right = "0";
1225
+ container.style.bottom = "0";
1226
+ container.style.display = "none";
1227
+ container.style.alignItems = "center";
1228
+ container.style.justifyContent = "center";
1229
+ container.style.pointerEvents = "none";
1230
+ container.style.zIndex = AD_LAYER_Z_INDEX;
1231
+ container.style.backgroundColor = "#000";
1232
+ container.style.transition = "opacity 0.3s ease-in-out";
1233
+ container.style.opacity = "0";
1234
+ container.style.isolation = "isolate";
1235
+ var countdown = document.createElement("div");
1236
+ countdown.style.position = "absolute";
1237
+ countdown.style.right = "12px";
1238
+ countdown.style.top = "12px";
1239
+ countdown.style.padding = "4px 8px";
1240
+ countdown.style.borderRadius = "4px";
1241
+ countdown.style.background = "rgba(0,0,0,0.75)";
1242
+ countdown.style.color = "#fff";
1243
+ countdown.style.fontFamily = "sans-serif";
1244
+ countdown.style.fontSize = "12px";
1245
+ countdown.style.lineHeight = "1.2";
1246
+ countdown.style.pointerEvents = "none";
1247
+ countdown.style.zIndex = COUNTDOWN_Z_INDEX;
1248
+ countdown.textContent = "Ad";
1249
+ container.appendChild(countdown);
1250
+ (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1251
+ adContainerEl = container;
1252
+ adCountdownEl = countdown;
1253
+ }
1254
+ },
1255
+ requestAds: function requestAds(duration) {
1256
+ return _async_to_generator(function() {
1257
+ var durationSeconds, parsed, ads, error;
1258
+ return _ts_generator(this, function(_state) {
1259
+ switch(_state.label){
1260
+ case 0:
1261
+ log("Requesting ads for duration:", duration);
1262
+ if (adPlaying) {
1263
+ return [
1264
+ 2,
1265
+ Promise.reject(new Error("Ad already playing"))
1266
+ ];
1267
+ }
1268
+ if (destroyed) {
1269
+ return [
1270
+ 2,
1271
+ Promise.reject(new Error("Player has been destroyed"))
1272
+ ];
1273
+ }
1274
+ _state.label = 1;
1275
+ case 1:
1276
+ _state.trys.push([
1277
+ 1,
1278
+ 3,
1279
+ ,
1280
+ 4
1281
+ ]);
1282
+ tornDown = false;
1283
+ durationSeconds = 30;
1284
+ parsed = parseInt(duration || "", 10);
1285
+ if (!isNaN(parsed) && parsed > 0) {
1286
+ durationSeconds = parsed;
1287
+ }
1288
+ return [
1289
+ 4,
1290
+ fetchVast(durationSeconds)
1291
+ ];
1292
+ case 2:
1293
+ ads = _state.sent();
1294
+ if (ads.length === 0) {
1295
+ log("No ads available from VAST response");
1296
+ emit("ad_error");
1297
+ return [
1298
+ 2,
1299
+ Promise.resolve()
1300
+ ];
1301
+ }
1302
+ assignCurrentAd(ads[0]);
1303
+ log("Ad loaded: ".concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1304
+ return [
1305
+ 2,
1306
+ Promise.resolve()
1307
+ ];
1308
+ case 3:
1309
+ error = _state.sent();
1310
+ console.error("[AdStormPlayer] Error requesting ads:", error);
1311
+ emit("ad_error");
1522
1312
  return [
1523
- 2
1313
+ 2,
1314
+ Promise.reject(error)
1524
1315
  ];
1525
- }
1526
- videoEl = createAdVideoElement();
1527
- videoEl.style.visibility = "hidden";
1528
- videoEl.style.pointerEvents = "none";
1529
- videoEl.preload = "auto";
1530
- container = ensureAdContainer();
1531
- container.appendChild(videoEl);
1532
- if (isHlsMediaFile(mediaFile) && import_hls.default.isSupported()) {
1533
- hls = new import_hls.default({
1534
- enableWorker: true,
1535
- lowLatencyMode: false
1536
- });
1537
- hls.loadSource(mediaFile.url);
1538
- hls.attachMedia(videoEl);
1539
- slot1 = {
1540
- bids: bids,
1541
- ad: ad,
1542
- mediaFile: mediaFile,
1543
- videoEl: videoEl,
1544
- hlsInstance: hls,
1545
- ready: false
1546
- };
1547
- preloadSlots.set(token, slot1);
1548
- hls.on(import_hls.default.Events.MANIFEST_PARSED, function() {
1549
- var s = preloadSlots.get(token);
1550
- if (s) s.ready = true;
1551
- if (debug) console.log("".concat(LOG, " [preload] HLS manifest parsed, token=").concat(token));
1552
- });
1553
- hls.on(import_hls.default.Events.ERROR, function(_evt, data) {
1554
- if (!preloadSlots.has(token)) return;
1555
- if (data.fatal) {
1556
- if (debug) console.warn("".concat(LOG, " [preload] HLS error for token=").concat(token));
1557
- preloadSlots.delete(token);
1558
- hls.destroy();
1559
- videoEl.remove();
1560
- }
1561
- });
1562
- } else {
1563
- videoEl.src = mediaFile.url;
1564
- videoEl.load();
1565
- slot2 = {
1566
- bids: bids,
1567
- ad: ad,
1568
- mediaFile: mediaFile,
1569
- videoEl: videoEl,
1570
- ready: false
1571
- };
1572
- preloadSlots.set(token, slot2);
1573
- videoEl.addEventListener("canplay", function() {
1574
- var s = preloadSlots.get(token);
1575
- if (s) s.ready = true;
1576
- if (debug) console.log("".concat(LOG, " [preload] canplay fired, token=").concat(token));
1577
- }, {
1578
- once: true
1579
- });
1580
- }
1581
- if (debug) console.log("".concat(LOG, " [preload] Started buffering token=").concat(token, ", url=").concat(mediaFile.url));
1582
- return [
1583
- 2
1584
- ];
1585
- }
1586
- });
1587
- })();
1588
- }
1589
- function playPreloaded(token) {
1590
- return _async_to_generator(function() {
1591
- var slot, contentVolume, adVolume2, videoEl, container2, adVolume21, nonFatalNetworkErrors, adVolume, container;
1592
- return _ts_generator(this, function(_state) {
1593
- switch(_state.label){
1594
- case 0:
1595
- if (destroyed) return [
1596
- 2,
1597
- Promise.reject(new Error("Layer has been destroyed"))
1598
- ];
1599
- slot = preloadSlots.get(token);
1600
- if (!slot) {
1601
- if (debug) console.warn("".concat(LOG, " [preload] No slot found for token=").concat(token, ", nothing to play"));
1316
+ case 4:
1602
1317
  return [
1603
1318
  2
1604
1319
  ];
1605
- }
1606
- preloadSlots.delete(token);
1607
- if (debug) console.log("".concat(LOG, " [preload] Playing preloaded ad, token=").concat(token, ", ready=").concat(slot.ready));
1608
- contentVolume = contentVideo.volume;
1609
- originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1610
- sessionId = generateSessionId();
1611
- currentAd = slot.ad;
1612
- trackingFired = _object_spread({}, createEmptyTrackingState());
1613
- fireTrackingPixels2(slot.ad.trackingUrls.impression);
1614
- trackingFired.impression = true;
1615
- if (!singleElementMode) return [
1616
- 3,
1617
- 2
1618
- ];
1619
- mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.detachMedia();
1620
- teardownCurrentPlayback();
1621
- adVideoElement = contentVideo;
1622
- adHls = void 0;
1623
- adPlaying = true;
1624
- setAdPlayingFlag(true);
1625
- contentVideo.removeAttribute("src");
1626
- contentVideo.load();
1627
- contentVideo.muted = true;
1628
- contentVideo.volume = 0;
1629
- return [
1630
- 4,
1631
- new Promise(function(resolve) {
1632
- return setTimeout(resolve, 200);
1633
- })
1634
- ];
1635
- case 1:
1636
- _state.sent();
1637
- if (destroyed || tornDown) return [
1638
- 2
1639
- ];
1640
- contentVideo.style.visibility = "visible";
1641
- contentVideo.style.opacity = "1";
1642
- emit("content_pause");
1643
- setupAdEventListeners();
1644
- adVolume2 = originalMutedState ? 1 : originalVolume;
1645
- contentVideo.volume = Math.max(0, Math.min(1, adVolume2));
1646
- contentVideo.muted = false;
1647
- if (debug) console.log("".concat(LOG, " [preload] singleElementMode: attaching ad to contentVideo, url=").concat(slot.mediaFile.url));
1648
- startPlayback(slot.mediaFile);
1649
- return [
1650
- 2
1651
- ];
1652
- case 2:
1653
- if (smartTVMode && !slot.videoEl) {
1654
- teardownCurrentPlayback();
1655
- if (adVideoElement) {
1656
- adVideoElement.remove();
1657
- adVideoElement = void 0;
1320
+ }
1321
+ });
1322
+ })();
1323
+ },
1324
+ play: function play() {
1325
+ return _async_to_generator(function() {
1326
+ var mediaFile, error;
1327
+ return _ts_generator(this, function(_state) {
1328
+ switch(_state.label){
1329
+ case 0:
1330
+ if (!currentAd) {
1331
+ return [
1332
+ 2,
1333
+ Promise.reject(new Error("No ad loaded"))
1334
+ ];
1335
+ }
1336
+ if (destroyed) {
1337
+ return [
1338
+ 2,
1339
+ Promise.reject(new Error("Player has been destroyed"))
1340
+ ];
1341
+ }
1342
+ log("Starting ad playback");
1343
+ _state.label = 1;
1344
+ case 1:
1345
+ _state.trys.push([
1346
+ 1,
1347
+ 3,
1348
+ ,
1349
+ 4
1350
+ ]);
1351
+ tornDown = false;
1352
+ if (adHideTimerId) {
1353
+ clearTimeout(adHideTimerId);
1354
+ adHideTimerId = void 0;
1355
+ }
1356
+ if (!adVideoElement) {
1357
+ adVideoElement = createAdVideoElement();
1358
+ adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.appendChild(adVideoElement);
1359
+ } else {
1360
+ teardownCurrentPlayback();
1658
1361
  }
1659
- videoEl = createAdVideoElement();
1660
- videoEl.style.visibility = "visible";
1661
- videoEl.style.pointerEvents = "none";
1662
- container2 = ensureAdContainer();
1663
- container2.appendChild(videoEl);
1664
- adVideoElement = videoEl;
1665
1362
  setupAdEventListeners();
1363
+ trackingFired = {
1364
+ impression: trackingFired.impression,
1365
+ start: false,
1366
+ firstQuartile: false,
1367
+ midpoint: false,
1368
+ thirdQuartile: false,
1369
+ complete: false
1370
+ };
1371
+ contentVideo.style.transition = "opacity 0.3s ease-in-out";
1372
+ contentVideo.style.opacity = "0";
1373
+ setTimeout(function() {
1374
+ contentVideo.style.visibility = "hidden";
1375
+ }, 300);
1376
+ contentVideo.muted = true;
1377
+ contentVideo.volume = 0;
1666
1378
  if (!continueLiveStreamDuringAds) {
1667
1379
  contentVideo.pause();
1668
1380
  }
1669
- contentVideo.muted = true;
1670
- contentVideo.volume = 0;
1671
1381
  adPlaying = true;
1672
1382
  setAdPlayingFlag(true);
1673
- adVolume21 = originalMutedState ? 1 : originalVolume;
1674
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume21));
1675
- adVideoElement.muted = false;
1676
- container2.style.display = "flex";
1677
- container2.style.pointerEvents = "auto";
1383
+ if (adVideoElement) {
1384
+ adVideoElement.volume = originalMutedState ? 0 : originalVolume;
1385
+ adVideoElement.muted = originalMutedState;
1386
+ }
1387
+ if (adContainerEl) {
1388
+ adContainerEl.style.display = "flex";
1389
+ adContainerEl.style.pointerEvents = "auto";
1390
+ adContainerEl.offsetHeight;
1391
+ adContainerEl.style.opacity = "1";
1392
+ }
1678
1393
  emit("content_pause");
1679
- if (debug) console.log("".concat(LOG, " [preload] smartTVMode deferred: creating video element and loading, url=").concat(slot.mediaFile.url));
1680
- startPlayback(slot.mediaFile);
1394
+ mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1395
+ if (!mediaFile) {
1396
+ throw new Error("No media file available");
1397
+ }
1398
+ log("Playing media file:", mediaFile.url);
1399
+ adVideoElement.src = mediaFile.url;
1400
+ adVideoElement.load();
1681
1401
  return [
1682
- 2
1402
+ 4,
1403
+ adVideoElement.play()
1683
1404
  ];
1684
- }
1685
- teardownCurrentPlayback();
1686
- if (adVideoElement && adVideoElement !== slot.videoEl) {
1687
- adVideoElement.remove();
1688
- }
1689
- slot.videoEl.style.visibility = "visible";
1690
- slot.videoEl.style.pointerEvents = "none";
1691
- adVideoElement = slot.videoEl;
1692
- adHls = slot.hlsInstance;
1693
- if (adHls) {
1694
- nonFatalNetworkErrors = 0;
1695
- adHls.on(import_hls.default.Events.ERROR, function(_event, data) {
1696
- if (!adPlaying) return;
1697
- if (data.fatal) {
1698
- handleAdError();
1699
- } else if (data.type === import_hls.default.ErrorTypes.NETWORK_ERROR) {
1700
- nonFatalNetworkErrors++;
1701
- if (nonFatalNetworkErrors >= 3) {
1702
- if (debug) console.warn("".concat(LOG, " [preload] Too many non-fatal HLS network errors during playback, treating as fatal"));
1703
- handleAdError();
1704
- }
1705
- }
1706
- });
1707
- }
1708
- setupAdEventListeners();
1709
- if (!continueLiveStreamDuringAds) {
1710
- contentVideo.pause();
1711
- }
1712
- contentVideo.muted = true;
1713
- contentVideo.volume = 0;
1714
- adPlaying = true;
1715
- setAdPlayingFlag(true);
1716
- adVolume = originalMutedState ? 1 : originalVolume;
1717
- adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
1718
- adVideoElement.muted = false;
1719
- container = ensureAdContainer();
1720
- container.style.display = "flex";
1721
- container.style.pointerEvents = "auto";
1722
- emit("content_pause");
1723
- adVideoElement.play().catch(function(error) {
1724
- console.error("".concat(LOG, " [preload] Error playing preloaded ad:"), error);
1405
+ case 2:
1406
+ _state.sent();
1407
+ return [
1408
+ 2,
1409
+ Promise.resolve()
1410
+ ];
1411
+ case 3:
1412
+ error = _state.sent();
1413
+ console.error("[AdStormPlayer] Error playing ad:", error);
1725
1414
  handleAdError();
1726
- });
1727
- return [
1728
- 2
1729
- ];
1730
- }
1731
- });
1732
- })();
1733
- }
1734
- function cancelPreload(token) {
1735
- var slot = preloadSlots.get(token);
1736
- if (!slot) return;
1737
- preloadSlots.delete(token);
1738
- if (slot.hlsInstance) {
1739
- slot.hlsInstance.destroy();
1740
- }
1741
- if (slot.videoEl) {
1742
- slot.videoEl.pause();
1743
- slot.videoEl.removeAttribute("src");
1744
- slot.videoEl.load();
1745
- slot.videoEl.remove();
1746
- }
1747
- if (debug) console.log("".concat(LOG, " [preload] Cancelled and cleaned up token=").concat(token));
1748
- }
1749
- return {
1750
- initialize: function initialize() {
1751
- if (debug) console.log("".concat(LOG, " Initializing"));
1752
- },
1753
- updateOptions: function updateOptions(opts) {
1754
- if (opts.continueLiveStreamDuringAds !== void 0) {
1755
- continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;
1756
- }
1757
- if (opts.mainHlsInstance !== void 0) {
1758
- var _opts_mainHlsInstance;
1759
- mainHlsInstance = (_opts_mainHlsInstance = opts.mainHlsInstance) !== null && _opts_mainHlsInstance !== void 0 ? _opts_mainHlsInstance : void 0;
1760
- }
1761
- },
1762
- playAd: playAd,
1763
- preloadAd: preloadAd,
1764
- playPreloaded: playPreloaded,
1765
- hasPreloaded: function hasPreloaded(token) {
1766
- return preloadSlots.has(token);
1767
- },
1768
- cancelPreload: cancelPreload,
1769
- pause: function pause() {
1770
- if (!adPlaying || !adVideoElement) return;
1771
- try {
1772
- if (!adVideoElement.paused) adVideoElement.pause();
1773
- } catch (error) {
1774
- if (debug) console.warn("".concat(LOG, " Error pausing ad:"), error);
1775
- }
1776
- },
1777
- resume: function resume() {
1778
- if (!adPlaying || !adVideoElement) return;
1779
- try {
1780
- if (adVideoElement.paused) adVideoElement.play().catch(function() {});
1781
- } catch (error) {
1782
- if (debug) console.warn("".concat(LOG, " Error resuming ad:"), error);
1783
- }
1415
+ return [
1416
+ 2,
1417
+ Promise.reject(error)
1418
+ ];
1419
+ case 4:
1420
+ return [
1421
+ 2
1422
+ ];
1423
+ }
1424
+ });
1425
+ })();
1784
1426
  },
1785
1427
  stop: function stop() {
1786
1428
  return _async_to_generator(function() {
1787
1429
  return _ts_generator(this, function(_state) {
1430
+ log("Stopping ad");
1788
1431
  tornDown = true;
1789
- if (debug) console.log("".concat(LOG, " Stopping ad"));
1790
1432
  adPlaying = false;
1791
1433
  setAdPlayingFlag(false);
1792
- contentVideo.muted = originalMutedState;
1793
- contentVideo.volume = originalMutedState ? 0 : originalVolume;
1434
+ clearAdStallTimer();
1435
+ clearAdCountdownTimer();
1436
+ if (adContainerEl) {
1437
+ adContainerEl.style.opacity = "0";
1438
+ adHideTimerId = setTimeout(function() {
1439
+ if (adContainerEl) {
1440
+ adContainerEl.style.display = "none";
1441
+ adContainerEl.style.pointerEvents = "none";
1442
+ }
1443
+ }, 300);
1444
+ }
1445
+ teardownCurrentPlayback();
1794
1446
  contentVideo.style.visibility = "visible";
1795
1447
  contentVideo.style.opacity = "1";
1796
- if (singleElementMode) {
1797
- teardownCurrentPlayback();
1798
- contentVideo.removeAttribute("src");
1799
- contentVideo.load();
1800
- adVideoElement = void 0;
1801
- } else {
1802
- if (adContainerEl) {
1803
- adContainerEl.style.display = "none";
1804
- adContainerEl.style.pointerEvents = "none";
1805
- }
1806
- if (continueLiveStreamDuringAds) {
1807
- contentVideo.play().catch(function() {});
1808
- }
1809
- teardownCurrentPlayback();
1810
- if (adVideoElement) {
1811
- adVideoElement.pause();
1812
- adVideoElement.removeAttribute("src");
1813
- adVideoElement.load();
1814
- }
1815
- }
1448
+ contentVideo.muted = originalMutedState;
1449
+ contentVideo.volume = originalVolume;
1816
1450
  currentAd = void 0;
1817
1451
  tornDown = false;
1818
1452
  return [
1819
- 2
1453
+ 2,
1454
+ Promise.resolve()
1820
1455
  ];
1821
1456
  });
1822
1457
  })();
1823
1458
  },
1459
+ pause: function pause() {
1460
+ if (!adPlaying || !adVideoElement) return;
1461
+ try {
1462
+ if (!adVideoElement.paused) adVideoElement.pause();
1463
+ } catch (error) {
1464
+ console.warn("[AdStormPlayer] Error pausing ad:", error);
1465
+ }
1466
+ },
1467
+ resume: function resume() {
1468
+ if (!adPlaying || !adVideoElement) return;
1469
+ try {
1470
+ if (adVideoElement.paused) adVideoElement.play().catch(function() {});
1471
+ } catch (error) {
1472
+ console.warn("[AdStormPlayer] Error resuming ad:", error);
1473
+ }
1474
+ },
1824
1475
  destroy: function destroy() {
1825
- tornDown = true;
1826
- if (debug) console.log("".concat(LOG, " Destroying"));
1476
+ log("Destroying");
1827
1477
  destroyed = true;
1478
+ tornDown = true;
1828
1479
  adPlaying = false;
1829
1480
  setAdPlayingFlag(false);
1481
+ clearAdStallTimer();
1482
+ clearAdCountdownTimer();
1483
+ if (adHideTimerId) {
1484
+ clearTimeout(adHideTimerId);
1485
+ adHideTimerId = void 0;
1486
+ }
1830
1487
  contentVideo.muted = originalMutedState;
1831
1488
  contentVideo.volume = originalVolume;
1832
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1833
- try {
1834
- for(var _iterator = Array.from(preloadSlots.entries())[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1835
- var _step_value = _sliced_to_array(_step.value, 1), token = _step_value[0];
1836
- cancelPreload(token);
1837
- }
1838
- } catch (err) {
1839
- _didIteratorError = true;
1840
- _iteratorError = err;
1841
- } finally{
1842
- try {
1843
- if (!_iteratorNormalCompletion && _iterator.return != null) {
1844
- _iterator.return();
1845
- }
1846
- } finally{
1847
- if (_didIteratorError) {
1848
- throw _iteratorError;
1849
- }
1850
- }
1851
- }
1489
+ contentVideo.style.visibility = "visible";
1490
+ contentVideo.style.opacity = "1";
1852
1491
  teardownCurrentPlayback();
1853
- if (adVideoElement) {
1854
- if (singleElementMode && adVideoElement === contentVideo) {
1855
- contentVideo.removeAttribute("src");
1856
- contentVideo.load();
1857
- } else {
1858
- adVideoElement.pause();
1859
- adVideoElement.removeAttribute("src");
1860
- adVideoElement.remove();
1861
- }
1862
- adVideoElement = void 0;
1863
- }
1492
+ adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.remove();
1493
+ adVideoElement = void 0;
1864
1494
  if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
1865
1495
  adContainerEl.parentElement.removeChild(adContainerEl);
1866
1496
  }
1867
1497
  adContainerEl = void 0;
1498
+ adCountdownEl = void 0;
1868
1499
  currentAd = void 0;
1500
+ sessionId = void 0;
1501
+ preloadSlots.clear();
1869
1502
  listeners.clear();
1503
+ if (parentPositionOverridden && contentVideo.parentElement) {
1504
+ contentVideo.parentElement.style.position = "";
1505
+ parentPositionOverridden = false;
1506
+ }
1507
+ },
1508
+ updateOptions: function updateOptions(opts) {
1509
+ if (opts.continueLiveStreamDuringAds !== void 0) {
1510
+ continueLiveStreamDuringAds = opts.continueLiveStreamDuringAds;
1511
+ }
1512
+ },
1513
+ playAd: function playAd(requestContext) {
1514
+ return _async_to_generator(function() {
1515
+ var ad;
1516
+ return _ts_generator(this, function(_state) {
1517
+ switch(_state.label){
1518
+ case 0:
1519
+ if (destroyed) return [
1520
+ 2,
1521
+ Promise.reject(new Error("Player has been destroyed"))
1522
+ ];
1523
+ if (!!currentAd) return [
1524
+ 3,
1525
+ 2
1526
+ ];
1527
+ return [
1528
+ 4,
1529
+ requestAdFromApi(requestContext)
1530
+ ];
1531
+ case 1:
1532
+ ad = _state.sent();
1533
+ if (!ad) {
1534
+ emit("ad_error", {
1535
+ message: "No valid ad from AdStorm API"
1536
+ });
1537
+ return [
1538
+ 2,
1539
+ Promise.reject(new Error("No valid ad from AdStorm API"))
1540
+ ];
1541
+ }
1542
+ assignCurrentAd(ad);
1543
+ _state.label = 2;
1544
+ case 2:
1545
+ return [
1546
+ 2,
1547
+ this.play()
1548
+ ];
1549
+ }
1550
+ });
1551
+ }).call(this);
1552
+ },
1553
+ preloadAd: function preloadAd(arg1, arg2) {
1554
+ return _async_to_generator(function() {
1555
+ var token, requestContext, ad;
1556
+ return _ts_generator(this, function(_state) {
1557
+ switch(_state.label){
1558
+ case 0:
1559
+ if (destroyed) return [
1560
+ 2
1561
+ ];
1562
+ token = typeof arg1 === "string" ? arg1 : typeof arg2 === "string" ? arg2 : void 0;
1563
+ if (!token) return [
1564
+ 2
1565
+ ];
1566
+ requestContext = typeof arg1 === "string" ? arg2 : arg1;
1567
+ return [
1568
+ 4,
1569
+ requestAdFromApi(requestContext)
1570
+ ];
1571
+ case 1:
1572
+ ad = _state.sent();
1573
+ if (!ad) return [
1574
+ 2
1575
+ ];
1576
+ preloadSlots.set(token, {
1577
+ ad: ad
1578
+ });
1579
+ return [
1580
+ 2
1581
+ ];
1582
+ }
1583
+ });
1584
+ })();
1585
+ },
1586
+ playPreloaded: function playPreloaded(token) {
1587
+ return _async_to_generator(function() {
1588
+ var slot;
1589
+ return _ts_generator(this, function(_state) {
1590
+ if (destroyed) return [
1591
+ 2,
1592
+ Promise.reject(new Error("Player has been destroyed"))
1593
+ ];
1594
+ slot = preloadSlots.get(token);
1595
+ if (!slot) {
1596
+ return [
1597
+ 2,
1598
+ Promise.reject(new Error("No preloaded ad for token ".concat(token)))
1599
+ ];
1600
+ }
1601
+ preloadSlots.delete(token);
1602
+ assignCurrentAd(slot.ad);
1603
+ return [
1604
+ 2,
1605
+ this.play()
1606
+ ];
1607
+ });
1608
+ }).call(this);
1609
+ },
1610
+ hasPreloaded: function hasPreloaded(token) {
1611
+ return preloadSlots.has(token);
1612
+ },
1613
+ cancelPreload: function cancelPreload(token) {
1614
+ preloadSlots.delete(token);
1870
1615
  },
1871
1616
  isAdPlaying: function isAdPlaying() {
1872
1617
  return adPlaying;
1873
1618
  },
1874
1619
  resize: function resize(width, height) {
1620
+ log("Resizing to ".concat(width, "x").concat(height));
1875
1621
  if (adContainerEl) {
1876
1622
  adContainerEl.style.width = "".concat(width, "px");
1877
1623
  adContainerEl.style.height = "".concat(height, "px");
@@ -1891,6 +1637,7 @@ function createVastAdLayer(contentVideo, options) {
1891
1637
  },
1892
1638
  updateOriginalMutedState: function updateOriginalMutedState(muted, volume) {
1893
1639
  var nextVolume = typeof volume === "number" && !Number.isNaN(volume) ? Math.max(0, Math.min(1, volume)) : originalVolume;
1640
+ log("updateOriginalMutedState: muted=".concat(muted, ", volume=").concat(nextVolume));
1894
1641
  originalMutedState = muted;
1895
1642
  originalVolume = nextVolume;
1896
1643
  },
@@ -1903,6 +1650,7 @@ function createVastAdLayer(contentVideo, options) {
1903
1650
  setAdVolume: function setAdVolume(volume) {
1904
1651
  if (adVideoElement && adPlaying) {
1905
1652
  adVideoElement.volume = Math.max(0, Math.min(1, volume));
1653
+ adVideoElement.muted = volume === 0;
1906
1654
  }
1907
1655
  },
1908
1656
  getAdVolume: function getAdVolume() {
@@ -1912,11 +1660,16 @@ function createVastAdLayer(contentVideo, options) {
1912
1660
  return 1;
1913
1661
  },
1914
1662
  showPlaceholder: function showPlaceholder() {
1915
- if (singleElementMode) return;
1916
- contentVideo.style.opacity = "0";
1917
- contentVideo.style.visibility = "hidden";
1918
1663
  if (!adContainerEl) {
1919
1664
  var _contentVideo_parentElement;
1665
+ var parent = contentVideo.parentElement;
1666
+ if (parent) {
1667
+ var computed = window.getComputedStyle(parent).position;
1668
+ if (computed === "static") {
1669
+ parent.style.position = "relative";
1670
+ parentPositionOverridden = true;
1671
+ }
1672
+ }
1920
1673
  var container = document.createElement("div");
1921
1674
  container.style.position = "absolute";
1922
1675
  container.style.left = "0";
@@ -1927,24 +1680,43 @@ function createVastAdLayer(contentVideo, options) {
1927
1680
  container.style.alignItems = "center";
1928
1681
  container.style.justifyContent = "center";
1929
1682
  container.style.pointerEvents = "none";
1930
- container.style.zIndex = "10";
1683
+ container.style.zIndex = AD_LAYER_Z_INDEX;
1931
1684
  container.style.backgroundColor = "#000";
1685
+ container.style.isolation = "isolate";
1686
+ var countdown = document.createElement("div");
1687
+ countdown.style.position = "absolute";
1688
+ countdown.style.right = "12px";
1689
+ countdown.style.top = "12px";
1690
+ countdown.style.padding = "4px 8px";
1691
+ countdown.style.borderRadius = "4px";
1692
+ countdown.style.background = "rgba(0,0,0,0.75)";
1693
+ countdown.style.color = "#fff";
1694
+ countdown.style.fontFamily = "sans-serif";
1695
+ countdown.style.fontSize = "12px";
1696
+ countdown.style.lineHeight = "1.2";
1697
+ countdown.style.pointerEvents = "none";
1698
+ countdown.style.zIndex = COUNTDOWN_Z_INDEX;
1699
+ countdown.textContent = "Ad";
1700
+ container.appendChild(countdown);
1932
1701
  (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1933
1702
  adContainerEl = container;
1703
+ adCountdownEl = countdown;
1934
1704
  }
1935
1705
  if (adContainerEl) {
1936
1706
  adContainerEl.style.display = "flex";
1707
+ adContainerEl.style.opacity = "1";
1937
1708
  adContainerEl.style.pointerEvents = "auto";
1938
1709
  }
1939
1710
  },
1940
1711
  hidePlaceholder: function hidePlaceholder() {
1941
1712
  if (adContainerEl) {
1942
- adContainerEl.style.display = "none";
1943
- adContainerEl.style.pointerEvents = "none";
1944
- }
1945
- if (!adPlaying) {
1946
- contentVideo.style.visibility = "visible";
1947
- contentVideo.style.opacity = "1";
1713
+ adContainerEl.style.opacity = "0";
1714
+ setTimeout(function() {
1715
+ if (adContainerEl) {
1716
+ adContainerEl.style.display = "none";
1717
+ adContainerEl.style.pointerEvents = "none";
1718
+ }
1719
+ }, 300);
1948
1720
  }
1949
1721
  }
1950
1722
  };
@@ -3047,6 +2819,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3047
2819
  this.backoffBaseMs = 1e3;
3048
2820
  this.maxBackoffMs = 15e3;
3049
2821
  this.MIN_AD_REMAINING_MS = 15e3;
2822
+ this.adRequestTimeoutMs = 5e3;
2823
+ this.adRequestMaxRetries = 3;
2824
+ this.adRequestRetryBackoffMs = 1500;
3050
2825
  this.preloadedTokens = [];
3051
2826
  initializePolyfills();
3052
2827
  var browserOverrides = getBrowserConfigOverrides();
@@ -3054,24 +2829,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3054
2829
  this.video = config.videoElement;
3055
2830
  this.adTransitionGapMs = (_this_config_adTransitionGapMs = this.config.adTransitionGapMs) !== null && _this_config_adTransitionGapMs !== void 0 ? _this_config_adTransitionGapMs : 100;
3056
2831
  logBrowserInfo(config.debugAdTiming);
3057
- this.vastManager = createVastManager(config.debugAdTiming !== void 0 ? {
3058
- debug: !!config.debugAdTiming
3059
- } : {});
3060
2832
  var browserForAdLayer = detectBrowser();
3061
2833
  var isSinglePipeline = browserForAdLayer.isSmartTV || !!this.config.singlePipelineMode;
3062
- this.adLayer = createVastAdLayer(this.video, {
3063
- continueLiveStreamDuringAds: false,
3064
- smartTVMode: isSinglePipeline,
3065
- singleElementMode: isSinglePipeline,
3066
- forceMP4Ads: isSinglePipeline,
2834
+ this.adLayer = createAdStormPlayer(this.video, {
2835
+ licenseKey: this.config.licenseKey || "",
3067
2836
  debug: !!config.debugAdTiming
3068
2837
  });
2838
+ this.adLayer.updateOptions({
2839
+ continueLiveStreamDuringAds: !isSinglePipeline && this.shouldContinueLiveStreamDuringAds()
2840
+ });
3069
2841
  }
3070
2842
  _create_class(StormcloudVideoPlayer, [
3071
2843
  {
3072
2844
  key: "adRequest",
3073
2845
  value: function adRequest(context) {
3074
2846
  return _async_to_generator(function() {
2847
+ var _ref, _ref1, durationSeconds;
3075
2848
  return _ts_generator(this, function(_state) {
3076
2849
  switch(_state.label){
3077
2850
  case 0:
@@ -3079,15 +2852,28 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3079
2852
  2,
3080
2853
  []
3081
2854
  ];
2855
+ 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));
3082
2856
  return [
3083
2857
  4,
3084
- this.vastManager.initialize()
2858
+ this.adLayer.requestAds(String(durationSeconds))
3085
2859
  ];
3086
2860
  case 1:
3087
2861
  _state.sent();
3088
2862
  return [
3089
2863
  2,
3090
- this.vastManager.requestBidsUntilResponse(context)
2864
+ [
2865
+ {
2866
+ bidder: "adstorm-direct",
2867
+ cpm: 0,
2868
+ width: 0,
2869
+ height: 0,
2870
+ adId: "adstorm",
2871
+ impId: "",
2872
+ creativeId: "adstorm",
2873
+ currency: "USD",
2874
+ durationSec: durationSeconds
2875
+ }
2876
+ ]
3091
2877
  ];
3092
2878
  }
3093
2879
  });
@@ -3144,7 +2930,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3144
2930
  2
3145
2931
  ];
3146
2932
  case 3:
3147
- this.hls = new import_hls2.default(_object_spread_props(_object_spread({
2933
+ this.hls = new import_hls.default(_object_spread_props(_object_spread({
3148
2934
  enableWorker: true,
3149
2935
  backBufferLength: 30,
3150
2936
  liveDurationInfinity: true,
@@ -3162,11 +2948,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3162
2948
  nudgeMaxRetry: 3,
3163
2949
  startPosition: -1
3164
2950
  }));
3165
- this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, function() {
2951
+ this.hls.on(import_hls.default.Events.MEDIA_ATTACHED, function() {
3166
2952
  var _this_hls;
3167
2953
  (_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.loadSource(_this.config.src);
3168
2954
  });
3169
- this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, function(_, data) {
2955
+ this.hls.on(import_hls.default.Events.MANIFEST_PARSED, function(_, data) {
3170
2956
  return _async_to_generator(function() {
3171
2957
  var _this_config_minSegmentsBeforePlay, _ref, _this_hls_levels, _this_hls, adBehavior, _this_hls1, minSegments, _this_video_play;
3172
2958
  return _ts_generator(this, function(_state) {
@@ -3228,7 +3014,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3228
3014
  });
3229
3015
  }).call(_this);
3230
3016
  });
3231
- this.hls.on(import_hls2.default.Events.LEVEL_LOADED, function(_evt, data) {
3017
+ this.hls.on(import_hls.default.Events.LEVEL_LOADED, function(_evt, data) {
3232
3018
  if (_this.inAdBreak || _this.pendingAdBreak) {
3233
3019
  return;
3234
3020
  }
@@ -3301,7 +3087,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3301
3087
  }
3302
3088
  }
3303
3089
  });
3304
- this.hls.on(import_hls2.default.Events.FRAG_BUFFERED, function(_evt, data) {
3090
+ this.hls.on(import_hls.default.Events.FRAG_BUFFERED, function(_evt, data) {
3305
3091
  return _async_to_generator(function() {
3306
3092
  var _this, _this_config_minSegmentsBeforePlay, minSegments, _this_video_play;
3307
3093
  return _ts_generator(this, function(_state) {
@@ -3361,7 +3147,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3361
3147
  });
3362
3148
  }).call(_this);
3363
3149
  });
3364
- this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, function(_evt, data) {
3150
+ this.hls.on(import_hls.default.Events.FRAG_PARSING_METADATA, function(_evt, data) {
3365
3151
  var id3Tags = ((data === null || data === void 0 ? void 0 : data.samples) || []).map(function(s) {
3366
3152
  return {
3367
3153
  key: "ID3",
@@ -3373,7 +3159,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3373
3159
  return _this.onId3Tag(tag);
3374
3160
  });
3375
3161
  });
3376
- this.hls.on(import_hls2.default.Events.FRAG_CHANGED, function(_evt, data) {
3162
+ this.hls.on(import_hls.default.Events.FRAG_CHANGED, function(_evt, data) {
3377
3163
  var frag = data === null || data === void 0 ? void 0 : data.frag;
3378
3164
  var tagList = frag === null || frag === void 0 ? void 0 : frag.tagList;
3379
3165
  if (!Array.isArray(tagList)) return;
@@ -3482,14 +3268,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3482
3268
  }
3483
3269
  }
3484
3270
  });
3485
- this.hls.on(import_hls2.default.Events.ERROR, function(_evt, data) {
3271
+ this.hls.on(import_hls.default.Events.ERROR, function(_evt, data) {
3486
3272
  if (data === null || data === void 0 ? void 0 : data.fatal) {
3487
3273
  switch(data.type){
3488
- case import_hls2.default.ErrorTypes.NETWORK_ERROR:
3274
+ case import_hls.default.ErrorTypes.NETWORK_ERROR:
3489
3275
  var _this_hls;
3490
3276
  (_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.startLoad();
3491
3277
  break;
3492
- case import_hls2.default.ErrorTypes.MEDIA_ERROR:
3278
+ case import_hls.default.ErrorTypes.MEDIA_ERROR:
3493
3279
  var _this_hls1;
3494
3280
  (_this_hls1 = _this.hls) === null || _this_hls1 === void 0 ? void 0 : _this_hls1.recoverMediaError();
3495
3281
  break;
@@ -3581,7 +3367,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3581
3367
  }
3582
3368
  });
3583
3369
  this.adLayer.on("content_resume", function() {
3370
+ var _ref, _ref1;
3371
+ var _this_savedMutedStateBeforeScte, _this_savedMutedStateBeforeScte1;
3584
3372
  var remaining = _this.getRemainingAdMs();
3373
+ 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();
3374
+ 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();
3585
3375
  if (_this.config.debugAdTiming) {
3586
3376
  console.log("[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s, preloadedTokens=%d, pendingNext=%s", _this.inAdBreak, remaining, _this.preloadedTokens.length, !!_this.pendingNextAdBids);
3587
3377
  }
@@ -3596,7 +3386,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3596
3386
  return;
3597
3387
  }
3598
3388
  _this.consecutiveFailures = 0;
3599
- if (!_this.video.muted) {
3389
+ if (!_this.config.disableFiller && !_this.video.muted) {
3600
3390
  _this.video.muted = true;
3601
3391
  _this.video.volume = 0;
3602
3392
  }
@@ -3663,6 +3453,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3663
3453
  if (!_this.config.disableFiller) {
3664
3454
  _this.showPlaceholderLayer();
3665
3455
  _this.adLayer.showPlaceholder();
3456
+ } else {
3457
+ _this.adLayer.hidePlaceholder();
3458
+ if (_this.video.muted !== breakMuted) {
3459
+ _this.video.muted = breakMuted;
3460
+ }
3461
+ if (Math.abs(_this.video.volume - breakVolume) > 0.01) {
3462
+ _this.video.volume = breakVolume;
3463
+ }
3464
+ if (_this.video.paused) {
3465
+ var _this_video_play;
3466
+ (_this_video_play = _this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
3467
+ }
3666
3468
  }
3667
3469
  _this.stopContinuousFetching();
3668
3470
  return;
@@ -4390,6 +4192,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4390
4192
  return this.totalAdsInBreak;
4391
4193
  }
4392
4194
  },
4195
+ {
4196
+ key: "getRemainingAdSeconds",
4197
+ value: function getRemainingAdSeconds() {
4198
+ var remainingMs = this.getRemainingAdMs();
4199
+ if (!Number.isFinite(remainingMs) || remainingMs <= 0 || remainingMs === Number.MAX_SAFE_INTEGER) {
4200
+ return 0;
4201
+ }
4202
+ return Math.ceil(remainingMs / 1e3);
4203
+ }
4204
+ },
4393
4205
  {
4394
4206
  key: "isAdPlaying",
4395
4207
  value: function isAdPlaying() {
@@ -5619,7 +5431,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5619
5431
  });
5620
5432
  };
5621
5433
  var onManifestParsedRestore = function onManifestParsedRestore1() {
5622
- hlsRef.off(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5434
+ hlsRef.off(import_hls.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5623
5435
  if (!_this.inAdBreak && !_this.adLayer.isAdPlaying()) {
5624
5436
  if (videoRef.muted !== savedMuted) videoRef.muted = savedMuted;
5625
5437
  if (Math.abs(videoRef.volume - savedVolume) > 0.01) videoRef.volume = savedVolume;
@@ -5632,7 +5444,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5632
5444
  }
5633
5445
  }
5634
5446
  };
5635
- hlsRef.on(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5447
+ hlsRef.on(import_hls.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5636
5448
  var pipelineDelayMs = 300;
5637
5449
  if (debugEnabled) {
5638
5450
  console.log("[StormcloudVideoPlayer] Smart TV: waiting ".concat(pipelineDelayMs, "ms for hardware pipeline release before re-attach"));
@@ -7246,7 +7058,8 @@ var StormcloudVideoPlayerComponent = import_react2.default.memo(function(props)
7246
7058
  var _import_react2_default_useState = _sliced_to_array(import_react2.default.useState({
7247
7059
  showAds: false,
7248
7060
  currentIndex: 0,
7249
- totalAds: 0
7061
+ totalAds: 0,
7062
+ remainingSeconds: 0
7250
7063
  }), 2), adStatus = _import_react2_default_useState[0], setAdStatus = _import_react2_default_useState[1];
7251
7064
  var _import_react2_default_useState1 = _sliced_to_array(import_react2.default.useState(true), 2), shouldShowNativeControls = _import_react2_default_useState1[0], setShouldShowNativeControls = _import_react2_default_useState1[1];
7252
7065
  var _import_react2_default_useState2 = _sliced_to_array(import_react2.default.useState(false), 2), isMuted = _import_react2_default_useState2[0], setIsMuted = _import_react2_default_useState2[1];
@@ -7498,15 +7311,17 @@ var StormcloudVideoPlayerComponent = import_react2.default.memo(function(props)
7498
7311
  var showAds = showAdsFromMethod || showAdsFromAttribute;
7499
7312
  var currentIndex = playerRef.current.getCurrentAdIndex();
7500
7313
  var totalAds = playerRef.current.getTotalAdsInBreak();
7314
+ var remainingSeconds = playerRef.current.getRemainingAdSeconds();
7501
7315
  setAdStatus(function(prev) {
7502
- if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds) {
7316
+ if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds || prev.remainingSeconds !== remainingSeconds) {
7503
7317
  if (showAds && !prev.showAds) {
7504
7318
  setShowCenterPlay(false);
7505
7319
  }
7506
7320
  return {
7507
7321
  showAds: showAds,
7508
7322
  currentIndex: currentIndex,
7509
- totalAds: totalAds
7323
+ totalAds: totalAds,
7324
+ remainingSeconds: remainingSeconds
7510
7325
  };
7511
7326
  }
7512
7327
  return prev;
@@ -7896,6 +7711,22 @@ var StormcloudVideoPlayerComponent = import_react2.default.memo(function(props)
7896
7711
  " of ",
7897
7712
  Math.max(adStatus.totalAds, adStatus.currentIndex)
7898
7713
  ]
7714
+ }),
7715
+ adStatus.remainingSeconds > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
7716
+ style: {
7717
+ background: "rgba(0, 0, 0, 0.5)",
7718
+ backdropFilter: "blur(12px)",
7719
+ color: "rgba(255, 255, 255, 0.9)",
7720
+ padding: "".concat(4 * responsiveScale, "px ").concat(10 * responsiveScale, "px"),
7721
+ borderRadius: "6px",
7722
+ fontSize: "".concat(11 * responsiveScale, "px"),
7723
+ fontWeight: "600",
7724
+ border: "1px solid rgba(255, 255, 255, 0.08)"
7725
+ },
7726
+ children: [
7727
+ adStatus.remainingSeconds,
7728
+ "s"
7729
+ ]
7899
7730
  })
7900
7731
  ]
7901
7732
  }),