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