stormcloud-video-player 0.2.13 → 0.2.15

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.
@@ -48,7 +48,8 @@ function getWebKitVersion(ua) {
48
48
  return match && match[1] ? parseInt(match[1], 10) : 0;
49
49
  }
50
50
  function getPlatform() {
51
- if ("userAgentData" in navigator && navigator.userAgentData?.platform) {
51
+ var _a;
52
+ if ("userAgentData" in navigator && ((_a = navigator.userAgentData) == null ? void 0 : _a.platform)) {
52
53
  return navigator.userAgentData.platform;
53
54
  }
54
55
  const ua = navigator.userAgent;
@@ -213,6 +214,7 @@ function createImaController(video, options) {
213
214
  }
214
215
  }
215
216
  function ensureImaLoaded() {
217
+ var _a, _b, _c;
216
218
  if (!supportsGoogleIMA()) {
217
219
  console.warn(
218
220
  "[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead."
@@ -223,7 +225,7 @@ function createImaController(video, options) {
223
225
  }
224
226
  try {
225
227
  const frameEl = window.frameElement;
226
- const sandboxAttr = frameEl?.getAttribute?.("sandbox") || "";
228
+ const sandboxAttr = ((_a = frameEl == null ? void 0 : frameEl.getAttribute) == null ? void 0 : _a.call(frameEl, "sandbox")) || "";
227
229
  if (sandboxAttr) {
228
230
  const tokens = new Set(
229
231
  sandboxAttr.split(/\s+/).map((t) => t.trim()).filter((t) => t.length > 0)
@@ -237,13 +239,13 @@ function createImaController(video, options) {
237
239
  }
238
240
  } catch {
239
241
  }
240
- if (typeof window !== "undefined" && window.google?.ima)
242
+ if (typeof window !== "undefined" && ((_b = window.google) == null ? void 0 : _b.ima))
241
243
  return Promise.resolve();
242
244
  const existing = document.querySelector(
243
245
  'script[data-ima="true"]'
244
246
  );
245
247
  if (existing) {
246
- if (window.google?.ima) {
248
+ if ((_c = window.google) == null ? void 0 : _c.ima) {
247
249
  return Promise.resolve();
248
250
  }
249
251
  return new Promise((resolve, reject) => {
@@ -301,6 +303,7 @@ function createImaController(video, options) {
301
303
  return {
302
304
  initialize() {
303
305
  ensureImaLoaded().then(() => {
306
+ var _a, _b;
304
307
  const google = window.google;
305
308
  if (!adDisplayContainer) {
306
309
  const container = document.createElement("div");
@@ -314,14 +317,14 @@ function createImaController(video, options) {
314
317
  container.style.justifyContent = "center";
315
318
  container.style.pointerEvents = "none";
316
319
  container.style.zIndex = "2";
317
- video.parentElement?.appendChild(container);
320
+ (_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
318
321
  adContainerEl = container;
319
322
  adDisplayContainer = new google.ima.AdDisplayContainer(
320
323
  container,
321
324
  video
322
325
  );
323
326
  try {
324
- adDisplayContainer.initialize?.();
327
+ (_b = adDisplayContainer.initialize) == null ? void 0 : _b.call(adDisplayContainer);
325
328
  } catch {
326
329
  }
327
330
  }
@@ -406,6 +409,7 @@ function createImaController(video, options) {
406
409
  adsManager.addEventListener(
407
410
  AdErrorEvent.AD_ERROR,
408
411
  (errorEvent) => {
412
+ var _a;
409
413
  console.error("[IMA] Ad error:", errorEvent.getError());
410
414
  destroyAdsManager();
411
415
  adPlaying = false;
@@ -436,10 +440,10 @@ function createImaController(video, options) {
436
440
  "[IMA] Max retries reached, emitting ad_error"
437
441
  );
438
442
  emit("ad_error");
439
- if (!options?.continueLiveStreamDuringAds) {
443
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
440
444
  if (video.paused) {
441
445
  console.log("[IMA] Resuming paused video after ad error");
442
- video.play()?.catch(() => {
446
+ (_a = video.play()) == null ? void 0 : _a.catch(() => {
443
447
  });
444
448
  }
445
449
  }
@@ -450,7 +454,7 @@ function createImaController(video, options) {
450
454
  AdEvent.CONTENT_PAUSE_REQUESTED,
451
455
  () => {
452
456
  console.log("[IMA] Content pause requested");
453
- if (!options?.continueLiveStreamDuringAds) {
457
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
454
458
  video.pause();
455
459
  console.log("[IMA] Video paused (VOD mode)");
456
460
  } else {
@@ -476,6 +480,7 @@ function createImaController(video, options) {
476
480
  adsManager.addEventListener(
477
481
  AdEvent.CONTENT_RESUME_REQUESTED,
478
482
  () => {
483
+ var _a;
479
484
  console.log("[IMA] Content resume requested");
480
485
  adPlaying = false;
481
486
  video.muted = originalMutedState;
@@ -486,8 +491,8 @@ function createImaController(video, options) {
486
491
  "[IMA] Ad container hidden - pointer events disabled"
487
492
  );
488
493
  }
489
- if (!options?.continueLiveStreamDuringAds) {
490
- video.play()?.catch(() => {
494
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
495
+ (_a = video.play()) == null ? void 0 : _a.catch(() => {
491
496
  });
492
497
  console.log("[IMA] Video resumed (VOD mode)");
493
498
  } else {
@@ -509,7 +514,7 @@ function createImaController(video, options) {
509
514
  "[IMA] Ad container hidden after all ads completed"
510
515
  );
511
516
  }
512
- if (!options?.continueLiveStreamDuringAds) {
517
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
513
518
  video.play().catch(() => {
514
519
  });
515
520
  console.log(
@@ -537,7 +542,7 @@ function createImaController(video, options) {
537
542
  adContainerEl.style.display = "none";
538
543
  console.log("[IMA] Ad container hidden after setup error");
539
544
  }
540
- if (!options?.continueLiveStreamDuringAds) {
545
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
541
546
  if (video.paused) {
542
547
  console.log("[IMA] Resuming paused video after setup error");
543
548
  video.play().catch(() => {
@@ -565,7 +570,7 @@ function createImaController(video, options) {
565
570
  adContainerEl.style.display = "none";
566
571
  console.log("[IMA] Ad container hidden after loader error");
567
572
  }
568
- if (!options?.continueLiveStreamDuringAds) {
573
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
569
574
  if (video.paused) {
570
575
  console.log("[IMA] Resuming paused video after loader error");
571
576
  video.play().catch(() => {
@@ -587,14 +592,15 @@ function createImaController(video, options) {
587
592
  return adsLoadedPromise;
588
593
  } catch (error) {
589
594
  console.error("[IMA] Failed to request ads:", error);
590
- currentReject?.(error);
595
+ currentReject == null ? void 0 : currentReject(error);
591
596
  adsLoadedReject = void 0;
592
597
  adsLoadedResolve = void 0;
593
598
  return Promise.reject(error);
594
599
  }
595
600
  },
596
601
  async play() {
597
- if (!window.google?.ima || !adDisplayContainer) {
602
+ var _a, _b;
603
+ if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
598
604
  console.warn(
599
605
  "[IMA] Cannot play ad: IMA SDK or ad container not available"
600
606
  );
@@ -616,14 +622,15 @@ function createImaController(video, options) {
616
622
  } catch (error) {
617
623
  console.error("[IMA] Error starting ad playback:", error);
618
624
  adPlaying = false;
619
- if (!options?.continueLiveStreamDuringAds) {
620
- video.play()?.catch(() => {
625
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
626
+ (_b = video.play()) == null ? void 0 : _b.catch(() => {
621
627
  });
622
628
  }
623
629
  return Promise.reject(error);
624
630
  }
625
631
  },
626
632
  async stop() {
633
+ var _a;
627
634
  adPlaying = false;
628
635
  video.muted = originalMutedState;
629
636
  if (adContainerEl) {
@@ -632,11 +639,11 @@ function createImaController(video, options) {
632
639
  console.log("[IMA] Ad container hidden after stop");
633
640
  }
634
641
  try {
635
- adsManager?.stop?.();
642
+ (_a = adsManager == null ? void 0 : adsManager.stop) == null ? void 0 : _a.call(adsManager);
636
643
  } catch {
637
644
  }
638
645
  destroyAdsManager();
639
- if (!options?.continueLiveStreamDuringAds) {
646
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
640
647
  video.play().catch(() => {
641
648
  });
642
649
  console.log("[IMA] Video resumed after stop (VOD mode)");
@@ -645,6 +652,7 @@ function createImaController(video, options) {
645
652
  }
646
653
  },
647
654
  destroy() {
655
+ var _a;
648
656
  destroyAdsManager();
649
657
  adPlaying = false;
650
658
  video.muted = originalMutedState;
@@ -653,10 +661,10 @@ function createImaController(video, options) {
653
661
  adContainerEl.style.display = "none";
654
662
  }
655
663
  try {
656
- adsLoader?.destroy?.();
664
+ (_a = adsLoader == null ? void 0 : adsLoader.destroy) == null ? void 0 : _a.call(adsLoader);
657
665
  } catch {
658
666
  }
659
- if (adContainerEl?.parentElement) {
667
+ if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
660
668
  adContainerEl.parentElement.removeChild(adContainerEl);
661
669
  }
662
670
  adContainerEl = void 0;
@@ -667,7 +675,8 @@ function createImaController(video, options) {
667
675
  return adPlaying;
668
676
  },
669
677
  resize(width, height) {
670
- if (!adsManager || !window.google?.ima) {
678
+ var _a;
679
+ if (!adsManager || !((_a = window.google) == null ? void 0 : _a.ima)) {
671
680
  console.warn(
672
681
  "[IMA] Cannot resize: No ads manager or IMA SDK available"
673
682
  );
@@ -685,7 +694,8 @@ function createImaController(video, options) {
685
694
  listeners.get(event).add(listener);
686
695
  },
687
696
  off(event, listener) {
688
- listeners.get(event)?.delete(listener);
697
+ var _a;
698
+ (_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
689
699
  },
690
700
  updateOriginalMutedState(muted) {
691
701
  originalMutedState = muted;
@@ -722,7 +732,8 @@ function createHlsAdPlayer(contentVideo, options) {
722
732
  let adPlaying = false;
723
733
  let originalMutedState = false;
724
734
  const listeners = /* @__PURE__ */ new Map();
725
- const licenseKey = options?.licenseKey;
735
+ const licenseKey = options == null ? void 0 : options.licenseKey;
736
+ const mainHlsInstance = options == null ? void 0 : options.mainHlsInstance;
726
737
  let adVideoElement;
727
738
  let adHls;
728
739
  let adContainerEl;
@@ -769,13 +780,80 @@ function createHlsAdPlayer(contentVideo, options) {
769
780
  }
770
781
  });
771
782
  }
783
+ function getMainStreamQuality() {
784
+ if (!mainHlsInstance || !mainHlsInstance.levels) {
785
+ return null;
786
+ }
787
+ const currentLevel = mainHlsInstance.currentLevel;
788
+ if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {
789
+ const autoLevel = mainHlsInstance.loadLevel;
790
+ if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {
791
+ const level2 = mainHlsInstance.levels[autoLevel];
792
+ return {
793
+ width: level2.width || 1920,
794
+ height: level2.height || 1080,
795
+ bitrate: level2.bitrate || 5e6
796
+ };
797
+ }
798
+ return null;
799
+ }
800
+ const level = mainHlsInstance.levels[currentLevel];
801
+ return {
802
+ width: level.width || 1920,
803
+ height: level.height || 1080,
804
+ bitrate: level.bitrate || 5e6
805
+ };
806
+ }
807
+ function selectBestMediaFile(mediaFiles) {
808
+ if (mediaFiles.length === 0) {
809
+ throw new Error("No media files available");
810
+ }
811
+ const firstFile = mediaFiles[0];
812
+ if (!firstFile) {
813
+ throw new Error("No media files available");
814
+ }
815
+ if (mediaFiles.length === 1) {
816
+ return firstFile;
817
+ }
818
+ const mainQuality = getMainStreamQuality();
819
+ if (!mainQuality) {
820
+ console.log("[HlsAdPlayer] No main stream quality info, using first media file");
821
+ return firstFile;
822
+ }
823
+ console.log("[HlsAdPlayer] Main stream quality:", mainQuality);
824
+ const scoredFiles = mediaFiles.map((file) => {
825
+ const widthDiff = Math.abs(file.width - mainQuality.width);
826
+ const heightDiff = Math.abs(file.height - mainQuality.height);
827
+ const resolutionDiff = widthDiff + heightDiff;
828
+ const fileBitrate = (file.bitrate || 5e3) * 1e3;
829
+ const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);
830
+ const score = resolutionDiff * 2 + bitrateDiff / 1e3;
831
+ return { file, score, resolutionDiff, bitrateDiff };
832
+ });
833
+ scoredFiles.sort((a, b) => a.score - b.score);
834
+ const bestMatch = scoredFiles[0];
835
+ if (!bestMatch) {
836
+ console.log("[HlsAdPlayer] No best match found, using first media file");
837
+ return firstFile;
838
+ }
839
+ console.log("[HlsAdPlayer] Selected media file:", {
840
+ url: bestMatch.file.url,
841
+ resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,
842
+ bitrate: bestMatch.file.bitrate,
843
+ score: bestMatch.score,
844
+ resolutionDiff: bestMatch.resolutionDiff,
845
+ bitrateDiff: bestMatch.bitrateDiff
846
+ });
847
+ return bestMatch.file;
848
+ }
772
849
  function parseVastXml(xmlString) {
850
+ var _a, _b, _c, _d;
773
851
  try {
774
852
  const parser = new DOMParser();
775
853
  const xmlDoc = parser.parseFromString(xmlString, "text/xml");
776
854
  const parserError = xmlDoc.querySelector("parsererror");
777
855
  if (parserError) {
778
- console.error("[HlsAdPlayer] XML parsing error:", parserError.textContent);
856
+ console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
779
857
  return null;
780
858
  }
781
859
  const adElement = xmlDoc.querySelector("Ad");
@@ -784,28 +862,46 @@ function createHlsAdPlayer(contentVideo, options) {
784
862
  return null;
785
863
  }
786
864
  const adId = adElement.getAttribute("id") || "unknown";
787
- const title = xmlDoc.querySelector("AdTitle")?.textContent || "Ad";
788
- const durationText = xmlDoc.querySelector("Duration")?.textContent || "00:00:30";
865
+ const title = ((_a = xmlDoc.querySelector("AdTitle")) == null ? void 0 : _a.textContent) || "Ad";
866
+ const isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
867
+ const durationText = ((_b = xmlDoc.querySelector("Duration")) == null ? void 0 : _b.textContent) || "00:00:30";
789
868
  const durationParts = durationText.split(":");
790
869
  const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
791
870
  const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
792
871
  const mediaFiles = [];
793
- mediaFileElements.forEach((mf) => {
872
+ console.log(`[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`);
873
+ mediaFileElements.forEach((mf, index) => {
874
+ var _a2;
794
875
  const type = mf.getAttribute("type") || "";
876
+ const url = ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "";
877
+ const width = mf.getAttribute("width") || "";
878
+ const height = mf.getAttribute("height") || "";
879
+ console.log(`[HlsAdPlayer] MediaFile ${index}: type="${type}", url="${url}", width="${width}", height="${height}"`);
795
880
  if (type === "application/x-mpegURL" || type.includes("m3u8")) {
881
+ if (!url) {
882
+ console.warn(`[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`);
883
+ return;
884
+ }
796
885
  const bitrateAttr = mf.getAttribute("bitrate");
797
886
  const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
798
887
  mediaFiles.push({
799
- url: mf.textContent?.trim() || "",
888
+ url,
800
889
  type,
801
- width: parseInt(mf.getAttribute("width") || "1920", 10),
802
- height: parseInt(mf.getAttribute("height") || "1080", 10),
890
+ width: parseInt(width || "1920", 10),
891
+ height: parseInt(height || "1080", 10),
803
892
  bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
804
893
  });
894
+ console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);
895
+ } else {
896
+ console.log(`[HlsAdPlayer] MediaFile ${index} ignored (type="${type}" is not HLS)`);
805
897
  }
806
898
  });
807
899
  if (mediaFiles.length === 0) {
808
- console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
900
+ if (isNoAdAvailable) {
901
+ console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
902
+ } else {
903
+ console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
904
+ }
809
905
  return null;
810
906
  }
811
907
  const trackingUrls = {
@@ -825,12 +921,14 @@ function createHlsAdPlayer(contentVideo, options) {
825
921
  error: []
826
922
  };
827
923
  xmlDoc.querySelectorAll("Impression").forEach((el) => {
828
- const url = el.textContent?.trim();
924
+ var _a2;
925
+ const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
829
926
  if (url) trackingUrls.impression.push(url);
830
927
  });
831
928
  xmlDoc.querySelectorAll("Tracking").forEach((el) => {
929
+ var _a2;
832
930
  const event = el.getAttribute("event");
833
- const url = el.textContent?.trim();
931
+ const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
834
932
  if (event && url) {
835
933
  const eventKey = event;
836
934
  if (trackingUrls[eventKey]) {
@@ -838,7 +936,7 @@ function createHlsAdPlayer(contentVideo, options) {
838
936
  }
839
937
  }
840
938
  });
841
- const clickThrough = xmlDoc.querySelector("ClickThrough")?.textContent?.trim();
939
+ const clickThrough = (_d = (_c = xmlDoc.querySelector("ClickThrough")) == null ? void 0 : _c.textContent) == null ? void 0 : _d.trim();
842
940
  return {
843
941
  id: adId,
844
942
  title,
@@ -930,7 +1028,7 @@ function createHlsAdPlayer(contentVideo, options) {
930
1028
  adContainerEl.style.display = "none";
931
1029
  adContainerEl.style.pointerEvents = "none";
932
1030
  }
933
- if (!options?.continueLiveStreamDuringAds) {
1031
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
934
1032
  contentVideo.play().catch(() => {
935
1033
  });
936
1034
  console.log("[HlsAdPlayer] Content resumed (VOD mode)");
@@ -948,7 +1046,7 @@ function createHlsAdPlayer(contentVideo, options) {
948
1046
  adContainerEl.style.display = "none";
949
1047
  adContainerEl.style.pointerEvents = "none";
950
1048
  }
951
- if (!options?.continueLiveStreamDuringAds) {
1049
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
952
1050
  if (contentVideo.paused) {
953
1051
  contentVideo.play().catch(() => {
954
1052
  });
@@ -958,6 +1056,7 @@ function createHlsAdPlayer(contentVideo, options) {
958
1056
  }
959
1057
  return {
960
1058
  initialize() {
1059
+ var _a;
961
1060
  console.log("[HlsAdPlayer] Initializing");
962
1061
  if (!adContainerEl) {
963
1062
  const container = document.createElement("div");
@@ -972,7 +1071,7 @@ function createHlsAdPlayer(contentVideo, options) {
972
1071
  container.style.pointerEvents = "none";
973
1072
  container.style.zIndex = "2";
974
1073
  container.style.backgroundColor = "#000";
975
- contentVideo.parentElement?.appendChild(container);
1074
+ (_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
976
1075
  adContainerEl = container;
977
1076
  }
978
1077
  },
@@ -990,9 +1089,11 @@ function createHlsAdPlayer(contentVideo, options) {
990
1089
  }
991
1090
  const vastXml = await response.text();
992
1091
  console.log("[HlsAdPlayer] VAST XML received");
1092
+ console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
993
1093
  const ad = parseVastXml(vastXml);
994
1094
  if (!ad) {
995
- throw new Error("Failed to parse VAST XML or no ads available");
1095
+ console.warn("[HlsAdPlayer] No ads available from VAST response");
1096
+ return Promise.resolve();
996
1097
  }
997
1098
  currentAd = ad;
998
1099
  console.log(`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`);
@@ -1007,14 +1108,14 @@ function createHlsAdPlayer(contentVideo, options) {
1007
1108
  },
1008
1109
  async play() {
1009
1110
  if (!currentAd) {
1010
- console.warn("[HlsAdPlayer] Cannot play: No ad loaded");
1111
+ console.warn("[HlsAdPlayer] Cannot play: No ad loaded (no ads available)");
1011
1112
  return Promise.reject(new Error("No ad loaded"));
1012
1113
  }
1013
1114
  console.log("[HlsAdPlayer] Starting ad playback");
1014
1115
  try {
1015
1116
  if (!adVideoElement) {
1016
1117
  adVideoElement = createAdVideoElement();
1017
- adContainerEl?.appendChild(adVideoElement);
1118
+ adContainerEl == null ? void 0 : adContainerEl.appendChild(adVideoElement);
1018
1119
  setupAdEventListeners();
1019
1120
  }
1020
1121
  trackingFired = {
@@ -1025,7 +1126,7 @@ function createHlsAdPlayer(contentVideo, options) {
1025
1126
  thirdQuartile: false,
1026
1127
  complete: false
1027
1128
  };
1028
- if (!options?.continueLiveStreamDuringAds) {
1129
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
1029
1130
  contentVideo.pause();
1030
1131
  console.log("[HlsAdPlayer] Content paused (VOD mode)");
1031
1132
  } else {
@@ -1038,7 +1139,7 @@ function createHlsAdPlayer(contentVideo, options) {
1038
1139
  adContainerEl.style.pointerEvents = "auto";
1039
1140
  }
1040
1141
  emit("content_pause");
1041
- const mediaFile = currentAd.mediaFiles[0];
1142
+ const mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1042
1143
  if (!mediaFile) {
1043
1144
  throw new Error("No media file available for ad");
1044
1145
  }
@@ -1098,7 +1199,7 @@ function createHlsAdPlayer(contentVideo, options) {
1098
1199
  adVideoElement.pause();
1099
1200
  adVideoElement.src = "";
1100
1201
  }
1101
- if (!options?.continueLiveStreamDuringAds) {
1202
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
1102
1203
  contentVideo.play().catch(() => {
1103
1204
  });
1104
1205
  }
@@ -1118,7 +1219,7 @@ function createHlsAdPlayer(contentVideo, options) {
1118
1219
  adVideoElement.remove();
1119
1220
  adVideoElement = void 0;
1120
1221
  }
1121
- if (adContainerEl?.parentElement) {
1222
+ if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
1122
1223
  adContainerEl.parentElement.removeChild(adContainerEl);
1123
1224
  }
1124
1225
  adContainerEl = void 0;
@@ -1144,7 +1245,8 @@ function createHlsAdPlayer(contentVideo, options) {
1144
1245
  listeners.get(event).add(listener);
1145
1246
  },
1146
1247
  off(event, listener) {
1147
- listeners.get(event)?.delete(listener);
1248
+ var _a;
1249
+ (_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
1148
1250
  },
1149
1251
  updateOriginalMutedState(muted) {
1150
1252
  originalMutedState = muted;
@@ -1169,6 +1271,7 @@ function createHlsAdPlayer(contentVideo, options) {
1169
1271
  // src/utils/tracking.ts
1170
1272
  var cachedBrowserId = null;
1171
1273
  function getClientInfo() {
1274
+ var _a, _b, _c, _d;
1172
1275
  const ua = navigator.userAgent;
1173
1276
  const platform = navigator.platform;
1174
1277
  const vendor = navigator.vendor || "";
@@ -1176,12 +1279,12 @@ function getClientInfo() {
1176
1279
  const memory = navigator.deviceMemory || null;
1177
1280
  const hardwareConcurrency = navigator.hardwareConcurrency || 1;
1178
1281
  const screenInfo = {
1179
- width: screen?.width,
1180
- height: screen?.height,
1181
- availWidth: screen?.availWidth,
1182
- availHeight: screen?.availHeight,
1183
- orientation: screen?.orientation?.type || "",
1184
- pixelDepth: screen?.pixelDepth
1282
+ width: screen == null ? void 0 : screen.width,
1283
+ height: screen == null ? void 0 : screen.height,
1284
+ availWidth: screen == null ? void 0 : screen.availWidth,
1285
+ availHeight: screen == null ? void 0 : screen.availHeight,
1286
+ orientation: ((_a = screen == null ? void 0 : screen.orientation) == null ? void 0 : _a.type) || "",
1287
+ pixelDepth: screen == null ? void 0 : screen.pixelDepth
1185
1288
  };
1186
1289
  let deviceType = "desktop";
1187
1290
  let brand = "Unknown";
@@ -1278,10 +1381,10 @@ function getClientInfo() {
1278
1381
  if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
1279
1382
  }
1280
1383
  isWebView = /wv|WebView|Linux; U;/.test(ua);
1281
- if (window?.outerHeight === 0 && window?.outerWidth === 0) {
1384
+ if ((window == null ? void 0 : window.outerHeight) === 0 && (window == null ? void 0 : window.outerWidth) === 0) {
1282
1385
  isWebView = true;
1283
1386
  }
1284
- isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || window.screen?.orientation?.angle !== void 0;
1387
+ isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || ((_c = (_b = window.screen) == null ? void 0 : _b.orientation) == null ? void 0 : _c.angle) !== void 0;
1285
1388
  return {
1286
1389
  brand,
1287
1390
  os,
@@ -1302,7 +1405,7 @@ function getClientInfo() {
1302
1405
  deviceMemory: memory,
1303
1406
  maxTouchPoints,
1304
1407
  language: navigator.language,
1305
- languages: navigator.languages?.join(",") || "",
1408
+ languages: ((_d = navigator.languages) == null ? void 0 : _d.join(",")) || "",
1306
1409
  cookieEnabled: navigator.cookieEnabled,
1307
1410
  doNotTrack: navigator.doNotTrack || "",
1308
1411
  referrer: document.referrer,
@@ -1660,7 +1763,8 @@ var StormcloudVideoPlayer = class {
1660
1763
  }
1661
1764
  return createHlsAdPlayer(this.video, {
1662
1765
  continueLiveStreamDuringAds,
1663
- ...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {}
1766
+ ...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {},
1767
+ ...this.hls ? { mainHlsInstance: this.hls } : {}
1664
1768
  });
1665
1769
  } else {
1666
1770
  if (this.config.debugAdTiming) {
@@ -1672,6 +1776,7 @@ var StormcloudVideoPlayer = class {
1672
1776
  }
1673
1777
  }
1674
1778
  async load() {
1779
+ var _a, _b;
1675
1780
  if (!this.attached) {
1676
1781
  this.attach();
1677
1782
  }
@@ -1688,7 +1793,7 @@ var StormcloudVideoPlayer = class {
1688
1793
  this.initializeTracking();
1689
1794
  if (this.shouldUseNativeHls()) {
1690
1795
  this.video.src = this.config.src;
1691
- this.isLiveStream = this.config.lowLatencyMode ?? false;
1796
+ this.isLiveStream = (_a = this.config.lowLatencyMode) != null ? _a : false;
1692
1797
  if (this.config.debugAdTiming) {
1693
1798
  console.log(
1694
1799
  "[StormcloudVideoPlayer] allowNativeHls: true - VOD mode detected:",
@@ -1703,8 +1808,8 @@ var StormcloudVideoPlayer = class {
1703
1808
  this.ima = this.createAdPlayer(false);
1704
1809
  this.ima.initialize();
1705
1810
  if (this.config.autoplay) {
1706
- await this.video.play()?.catch(() => {
1707
- });
1811
+ await ((_b = this.video.play()) == null ? void 0 : _b.catch(() => {
1812
+ }));
1708
1813
  }
1709
1814
  return;
1710
1815
  }
@@ -1717,12 +1822,17 @@ var StormcloudVideoPlayer = class {
1717
1822
  ...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}
1718
1823
  });
1719
1824
  this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, () => {
1720
- this.hls?.loadSource(this.config.src);
1825
+ var _a2;
1826
+ (_a2 = this.hls) == null ? void 0 : _a2.loadSource(this.config.src);
1721
1827
  });
1722
1828
  this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, async (_, data) => {
1723
- this.isLiveStream = this.hls?.levels?.some(
1724
- (level) => level?.details?.live === true || level?.details?.type === "LIVE"
1725
- ) ?? false;
1829
+ var _a2, _b2, _c, _d;
1830
+ this.isLiveStream = (_c = (_b2 = (_a2 = this.hls) == null ? void 0 : _a2.levels) == null ? void 0 : _b2.some(
1831
+ (level) => {
1832
+ var _a3, _b3;
1833
+ return ((_a3 = level == null ? void 0 : level.details) == null ? void 0 : _a3.live) === true || ((_b3 = level == null ? void 0 : level.details) == null ? void 0 : _b3.type) === "LIVE";
1834
+ }
1835
+ )) != null ? _c : false;
1726
1836
  if (this.config.debugAdTiming) {
1727
1837
  const adBehavior = this.shouldContinueLiveStreamDuringAds() ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
1728
1838
  console.log("[StormcloudVideoPlayer] Stream type detected:", {
@@ -1735,28 +1845,29 @@ var StormcloudVideoPlayer = class {
1735
1845
  this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());
1736
1846
  this.ima.initialize();
1737
1847
  if (this.config.autoplay) {
1738
- await this.video.play()?.catch(() => {
1739
- });
1848
+ await ((_d = this.video.play()) == null ? void 0 : _d.catch(() => {
1849
+ }));
1740
1850
  }
1741
1851
  });
1742
1852
  this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, (_evt, data) => {
1743
- const id3Tags = (data?.samples || []).map((s) => ({
1853
+ const id3Tags = ((data == null ? void 0 : data.samples) || []).map((s) => ({
1744
1854
  key: "ID3",
1745
- value: s?.data,
1746
- ptsSeconds: s?.pts
1855
+ value: s == null ? void 0 : s.data,
1856
+ ptsSeconds: s == null ? void 0 : s.pts
1747
1857
  }));
1748
1858
  id3Tags.forEach((tag) => this.onId3Tag(tag));
1749
1859
  });
1750
1860
  this.hls.on(import_hls2.default.Events.FRAG_CHANGED, (_evt, data) => {
1751
- const frag = data?.frag;
1752
- const tagList = frag?.tagList;
1861
+ var _a2, _b2, _c;
1862
+ const frag = data == null ? void 0 : data.frag;
1863
+ const tagList = frag == null ? void 0 : frag.tagList;
1753
1864
  if (!Array.isArray(tagList)) return;
1754
1865
  for (const entry of tagList) {
1755
1866
  let tag = "";
1756
1867
  let value = "";
1757
1868
  if (Array.isArray(entry)) {
1758
- tag = String(entry[0] ?? "");
1759
- value = String(entry[1] ?? "");
1869
+ tag = String((_a2 = entry[0]) != null ? _a2 : "");
1870
+ value = String((_b2 = entry[1]) != null ? _b2 : "");
1760
1871
  } else if (typeof entry === "string") {
1761
1872
  const idx = entry.indexOf(":");
1762
1873
  if (idx >= 0) {
@@ -1780,8 +1891,8 @@ var StormcloudVideoPlayer = class {
1780
1891
  const prog = this.parseCueOutCont(value);
1781
1892
  const marker = {
1782
1893
  type: "progress",
1783
- ...prog?.duration !== void 0 ? { durationSeconds: prog.duration } : {},
1784
- ...prog?.elapsed !== void 0 ? { ptsSeconds: prog.elapsed } : {},
1894
+ ...(prog == null ? void 0 : prog.duration) !== void 0 ? { durationSeconds: prog.duration } : {},
1895
+ ...(prog == null ? void 0 : prog.elapsed) !== void 0 ? { ptsSeconds: prog.elapsed } : {},
1785
1896
  raw: { tag, value }
1786
1897
  };
1787
1898
  this.onScte35Marker(marker);
@@ -1791,7 +1902,7 @@ var StormcloudVideoPlayer = class {
1791
1902
  const attrs = this.parseAttributeList(value);
1792
1903
  const hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
1793
1904
  const hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
1794
- const klass = String(attrs["CLASS"] ?? "");
1905
+ const klass = String((_c = attrs["CLASS"]) != null ? _c : "");
1795
1906
  const duration = this.toNumber(attrs["DURATION"]);
1796
1907
  if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
1797
1908
  const marker = {
@@ -1808,13 +1919,14 @@ var StormcloudVideoPlayer = class {
1808
1919
  }
1809
1920
  });
1810
1921
  this.hls.on(import_hls2.default.Events.ERROR, (_evt, data) => {
1811
- if (data?.fatal) {
1922
+ var _a2, _b2;
1923
+ if (data == null ? void 0 : data.fatal) {
1812
1924
  switch (data.type) {
1813
1925
  case import_hls2.default.ErrorTypes.NETWORK_ERROR:
1814
- this.hls?.startLoad();
1926
+ (_a2 = this.hls) == null ? void 0 : _a2.startLoad();
1815
1927
  break;
1816
1928
  case import_hls2.default.ErrorTypes.MEDIA_ERROR:
1817
- this.hls?.recoverMediaError();
1929
+ (_b2 = this.hls) == null ? void 0 : _b2.recoverMediaError();
1818
1930
  break;
1819
1931
  default:
1820
1932
  this.destroy();
@@ -1916,11 +2028,12 @@ var StormcloudVideoPlayer = class {
1916
2028
  }
1917
2029
  }
1918
2030
  parseScte35FromId3(tag) {
2031
+ var _a, _b, _c, _d;
1919
2032
  const text = this.decodeId3ValueToText(tag.value);
1920
2033
  if (!text) return void 0;
1921
2034
  const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\r\n]*))?/i) || text.match(/CUE-OUT(?::([^\r\n]*))?/i);
1922
2035
  if (cueOutMatch) {
1923
- const arg = (cueOutMatch[1] ?? "").trim();
2036
+ const arg = ((_a = cueOutMatch[1]) != null ? _a : "").trim();
1924
2037
  const dur = this.parseCueOutDuration(arg);
1925
2038
  const marker = {
1926
2039
  type: "start",
@@ -1932,12 +2045,12 @@ var StormcloudVideoPlayer = class {
1932
2045
  }
1933
2046
  const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\r\n]*)/i);
1934
2047
  if (cueOutContMatch) {
1935
- const arg = (cueOutContMatch[1] ?? "").trim();
2048
+ const arg = ((_b = cueOutContMatch[1]) != null ? _b : "").trim();
1936
2049
  const cont = this.parseCueOutCont(arg);
1937
2050
  const marker = {
1938
2051
  type: "progress",
1939
2052
  ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},
1940
- ...cont?.duration !== void 0 ? { durationSeconds: cont.duration } : {},
2053
+ ...(cont == null ? void 0 : cont.duration) !== void 0 ? { durationSeconds: cont.duration } : {},
1941
2054
  raw: { id3: text }
1942
2055
  };
1943
2056
  return marker;
@@ -1953,10 +2066,10 @@ var StormcloudVideoPlayer = class {
1953
2066
  }
1954
2067
  const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\r\n]*)/i);
1955
2068
  if (daterangeMatch) {
1956
- const attrs = this.parseAttributeList(daterangeMatch[1] ?? "");
2069
+ const attrs = this.parseAttributeList((_c = daterangeMatch[1]) != null ? _c : "");
1957
2070
  const hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
1958
2071
  const hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
1959
- const klass = String(attrs["CLASS"] ?? "");
2072
+ const klass = String((_d = attrs["CLASS"]) != null ? _d : "");
1960
2073
  const duration = this.toNumber(attrs["DURATION"]);
1961
2074
  if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
1962
2075
  const marker = {
@@ -2013,6 +2126,7 @@ var StormcloudVideoPlayer = class {
2013
2126
  }
2014
2127
  }
2015
2128
  onScte35Marker(marker) {
2129
+ var _a, _b;
2016
2130
  if (this.config.debugAdTiming) {
2017
2131
  console.log("[StormcloudVideoPlayer] SCTE-35 marker detected:", {
2018
2132
  type: marker.type,
@@ -2028,7 +2142,7 @@ var StormcloudVideoPlayer = class {
2028
2142
  this.expectedAdBreakDurationMs = durationMs;
2029
2143
  this.currentAdBreakStartWallClockMs = Date.now();
2030
2144
  const isManifestMarker = this.isManifestBasedMarker(marker);
2031
- const forceImmediate = this.config.immediateManifestAds ?? true;
2145
+ const forceImmediate = (_a = this.config.immediateManifestAds) != null ? _a : true;
2032
2146
  if (this.config.debugAdTiming) {
2033
2147
  console.log("[StormcloudVideoPlayer] Ad start decision:", {
2034
2148
  isManifestMarker,
@@ -2045,7 +2159,7 @@ var StormcloudVideoPlayer = class {
2045
2159
  this.clearAdStartTimer();
2046
2160
  this.handleAdStart(marker);
2047
2161
  } else if (typeof marker.ptsSeconds === "number") {
2048
- const tol = this.config.driftToleranceMs ?? 1e3;
2162
+ const tol = (_b = this.config.driftToleranceMs) != null ? _b : 1e3;
2049
2163
  const nowMs = this.video.currentTime * 1e3;
2050
2164
  const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
2051
2165
  const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);
@@ -2155,12 +2269,13 @@ var StormcloudVideoPlayer = class {
2155
2269
  return void 0;
2156
2270
  }
2157
2271
  parseAttributeList(value) {
2272
+ var _a, _b, _c;
2158
2273
  const attrs = {};
2159
2274
  const regex = /([A-Z0-9-]+)=(("[^"]*")|([^",]*))(?:,|$)/gi;
2160
2275
  let match;
2161
2276
  while ((match = regex.exec(value)) !== null) {
2162
- const key = match[1] ?? "";
2163
- let rawVal = match[3] ?? match[4] ?? "";
2277
+ const key = (_a = match[1]) != null ? _a : "";
2278
+ let rawVal = (_c = (_b = match[3]) != null ? _b : match[4]) != null ? _c : "";
2164
2279
  if (rawVal.startsWith('"') && rawVal.endsWith('"')) {
2165
2280
  rawVal = rawVal.slice(1, -1);
2166
2281
  }
@@ -2324,6 +2439,7 @@ var StormcloudVideoPlayer = class {
2324
2439
  }
2325
2440
  }
2326
2441
  async fetchAdConfiguration() {
2442
+ var _a, _b, _c;
2327
2443
  const vastMode = this.config.vastMode || "default";
2328
2444
  if (this.config.debugAdTiming) {
2329
2445
  console.log(
@@ -2344,7 +2460,7 @@ var StormcloudVideoPlayer = class {
2344
2460
  this.apiVastTagUrl = vastEndpoint;
2345
2461
  if (this.config.debugAdTiming) {
2346
2462
  console.log(
2347
- "[StormcloudVideoPlayer] Using AdStorm VAST endpoint:",
2463
+ "[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):",
2348
2464
  vastEndpoint
2349
2465
  );
2350
2466
  }
@@ -2381,7 +2497,7 @@ var StormcloudVideoPlayer = class {
2381
2497
  return;
2382
2498
  }
2383
2499
  const data = await response.json();
2384
- const imaPayload = data.response?.ima?.["publisherdesk.ima"]?.payload;
2500
+ const imaPayload = (_c = (_b = (_a = data.response) == null ? void 0 : _a.ima) == null ? void 0 : _b["publisherdesk.ima"]) == null ? void 0 : _c.payload;
2385
2501
  if (imaPayload) {
2386
2502
  this.apiVastTagUrl = decodeURIComponent(imaPayload);
2387
2503
  if (this.config.debugAdTiming) {
@@ -2418,11 +2534,12 @@ var StormcloudVideoPlayer = class {
2418
2534
  return "other";
2419
2535
  }
2420
2536
  shouldShowNativeControls() {
2537
+ var _a, _b;
2421
2538
  const streamType = this.getStreamType();
2422
2539
  if (streamType === "other") {
2423
- return !(this.config.showCustomControls ?? false);
2540
+ return !((_a = this.config.showCustomControls) != null ? _a : false);
2424
2541
  }
2425
- return !!(this.config.allowNativeHls && !(this.config.showCustomControls ?? false));
2542
+ return !!(this.config.allowNativeHls && !((_b = this.config.showCustomControls) != null ? _b : false));
2426
2543
  }
2427
2544
  shouldContinueLiveStreamDuringAds() {
2428
2545
  if (this.config.allowNativeHls) {
@@ -2434,6 +2551,7 @@ var StormcloudVideoPlayer = class {
2434
2551
  return true;
2435
2552
  }
2436
2553
  async handleAdStart(_marker) {
2554
+ var _a;
2437
2555
  const scheduled = this.findCurrentOrNextBreak(
2438
2556
  this.video.currentTime * 1e3
2439
2557
  );
@@ -2484,17 +2602,18 @@ var StormcloudVideoPlayer = class {
2484
2602
  this.handleAdFailure();
2485
2603
  }
2486
2604
  }
2487
- if (this.expectedAdBreakDurationMs == null && scheduled?.durationMs != null) {
2605
+ if (this.expectedAdBreakDurationMs == null && (scheduled == null ? void 0 : scheduled.durationMs) != null) {
2488
2606
  this.expectedAdBreakDurationMs = scheduled.durationMs;
2489
- this.currentAdBreakStartWallClockMs = this.currentAdBreakStartWallClockMs ?? Date.now();
2607
+ this.currentAdBreakStartWallClockMs = (_a = this.currentAdBreakStartWallClockMs) != null ? _a : Date.now();
2490
2608
  this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
2491
2609
  }
2492
2610
  }
2493
2611
  findCurrentOrNextBreak(nowMs) {
2612
+ var _a;
2494
2613
  const schedule = [];
2495
2614
  let candidate;
2496
2615
  for (const b of schedule) {
2497
- const tol = this.config.driftToleranceMs ?? 1e3;
2616
+ const tol = (_a = this.config.driftToleranceMs) != null ? _a : 1e3;
2498
2617
  if (b.startTimeMs <= nowMs + tol && (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))) {
2499
2618
  candidate = b;
2500
2619
  }
@@ -2510,7 +2629,8 @@ var StormcloudVideoPlayer = class {
2510
2629
  }
2511
2630
  }
2512
2631
  async handleMidAdJoin(adBreak, nowMs) {
2513
- const durationMs = adBreak.durationMs ?? 0;
2632
+ var _a;
2633
+ const durationMs = (_a = adBreak.durationMs) != null ? _a : 0;
2514
2634
  const endMs = adBreak.startTimeMs + durationMs;
2515
2635
  if (durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs) {
2516
2636
  const remainingMs = endMs - nowMs;
@@ -2596,12 +2716,20 @@ var StormcloudVideoPlayer = class {
2596
2716
  this.startAdFailsafeTimer();
2597
2717
  try {
2598
2718
  await this.ima.requestAds(vastTagUrl);
2599
- if (this.config.debugAdTiming) {
2600
- console.log("[StormcloudVideoPlayer] Ad request successful, starting playback");
2601
- }
2602
- await this.ima.play();
2603
- if (this.config.debugAdTiming) {
2604
- console.log("[StormcloudVideoPlayer] Ad playback started successfully");
2719
+ try {
2720
+ if (this.config.debugAdTiming) {
2721
+ console.log("[StormcloudVideoPlayer] Ad request completed, attempting playback");
2722
+ }
2723
+ await this.ima.play();
2724
+ if (this.config.debugAdTiming) {
2725
+ console.log("[StormcloudVideoPlayer] Ad playback started successfully");
2726
+ }
2727
+ } catch (playError) {
2728
+ if (this.config.debugAdTiming) {
2729
+ console.log("[StormcloudVideoPlayer] No ads available, skipping playback");
2730
+ }
2731
+ this.handleAdFailure();
2732
+ return;
2605
2733
  }
2606
2734
  } catch (error) {
2607
2735
  if (this.config.debugAdTiming) {
@@ -2611,6 +2739,7 @@ var StormcloudVideoPlayer = class {
2611
2739
  }
2612
2740
  }
2613
2741
  handleAdFailure() {
2742
+ var _a;
2614
2743
  if (this.config.debugAdTiming) {
2615
2744
  console.log(
2616
2745
  "[StormcloudVideoPlayer] Handling ad failure - resuming content",
@@ -2643,7 +2772,7 @@ var StormcloudVideoPlayer = class {
2643
2772
  if (this.config.debugAdTiming) {
2644
2773
  console.log("[StormcloudVideoPlayer] Resuming paused video");
2645
2774
  }
2646
- this.video.play()?.catch((error) => {
2775
+ (_a = this.video.play()) == null ? void 0 : _a.catch((error) => {
2647
2776
  if (this.config.debugAdTiming) {
2648
2777
  console.error(
2649
2778
  "[StormcloudVideoPlayer] Failed to resume video after ad failure:",
@@ -2658,8 +2787,9 @@ var StormcloudVideoPlayer = class {
2658
2787
  }
2659
2788
  }
2660
2789
  startAdFailsafeTimer() {
2790
+ var _a;
2661
2791
  this.clearAdFailsafeTimer();
2662
- const failsafeMs = this.config.adFailsafeTimeoutMs ?? 1e4;
2792
+ const failsafeMs = (_a = this.config.adFailsafeTimeoutMs) != null ? _a : 1e4;
2663
2793
  if (this.config.debugAdTiming) {
2664
2794
  console.log(
2665
2795
  `[StormcloudVideoPlayer] Starting failsafe timer (${failsafeMs}ms)`
@@ -2795,6 +2925,7 @@ var StormcloudVideoPlayer = class {
2795
2925
  }
2796
2926
  }
2797
2927
  destroy() {
2928
+ var _a, _b;
2798
2929
  this.clearAdStartTimer();
2799
2930
  this.clearAdStopTimer();
2800
2931
  this.clearAdFailsafeTimer();
@@ -2802,8 +2933,8 @@ var StormcloudVideoPlayer = class {
2802
2933
  clearInterval(this.heartbeatInterval);
2803
2934
  this.heartbeatInterval = void 0;
2804
2935
  }
2805
- this.hls?.destroy();
2806
- this.ima?.destroy();
2936
+ (_a = this.hls) == null ? void 0 : _a.destroy();
2937
+ (_b = this.ima) == null ? void 0 : _b.destroy();
2807
2938
  }
2808
2939
  };
2809
2940
 
@@ -2815,7 +2946,8 @@ var CRITICAL_PROPS = [
2815
2946
  "allowNativeHls",
2816
2947
  "licenseKey",
2817
2948
  "lowLatencyMode",
2818
- "driftToleranceMs"
2949
+ "driftToleranceMs",
2950
+ "vastMode"
2819
2951
  ];
2820
2952
  var StormcloudVideoPlayerComponent = import_react.default.memo(
2821
2953
  (props) => {
@@ -2843,6 +2975,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
2843
2975
  poster,
2844
2976
  children,
2845
2977
  licenseKey,
2978
+ vastMode,
2979
+ vastTagUrl,
2980
+ adPlayerType,
2846
2981
  ...restVideoAttrs
2847
2982
  } = props;
2848
2983
  const videoRef = (0, import_react.useRef)(null);
@@ -2910,11 +3045,11 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
2910
3045
  }
2911
3046
  setShowSpeedMenu(false);
2912
3047
  };
2913
- const isHlsStream = src?.toLowerCase().includes(".m3u8") || src?.toLowerCase().includes("/hls/");
3048
+ const isHlsStream = (src == null ? void 0 : src.toLowerCase().includes(".m3u8")) || (src == null ? void 0 : src.toLowerCase().includes("/hls/"));
2914
3049
  const shouldShowEnhancedControls = showCustomControls && (isHlsStream ? allowNativeHls : true);
2915
3050
  const criticalPropsKey = (0, import_react.useMemo)(() => {
2916
3051
  return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join("|");
2917
- }, [src, allowNativeHls, licenseKey, lowLatencyMode, driftToleranceMs]);
3052
+ }, [src, allowNativeHls, licenseKey, lowLatencyMode, driftToleranceMs, vastMode]);
2918
3053
  (0, import_react.useEffect)(() => {
2919
3054
  if (typeof window === "undefined") return;
2920
3055
  const el = videoRef.current;
@@ -2955,18 +3090,21 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
2955
3090
  cfg.onFullscreenToggle = onFullscreenToggle;
2956
3091
  if (onControlClick !== void 0) cfg.onControlClick = onControlClick;
2957
3092
  if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
3093
+ if (vastMode !== void 0) cfg.vastMode = vastMode;
3094
+ if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;
3095
+ if (adPlayerType !== void 0) cfg.adPlayerType = adPlayerType;
2958
3096
  const player = new StormcloudVideoPlayer(cfg);
2959
3097
  playerRef.current = player;
2960
3098
  player.load().then(() => {
2961
3099
  const showNative = player.shouldShowNativeControls();
2962
3100
  setShouldShowNativeControls(showNative);
2963
- onReady?.(player);
3101
+ onReady == null ? void 0 : onReady(player);
2964
3102
  }).catch((error) => {
2965
3103
  console.error(
2966
3104
  "StormcloudVideoPlayer: Failed to load player:",
2967
3105
  error
2968
3106
  );
2969
- onReady?.(player);
3107
+ onReady == null ? void 0 : onReady(player);
2970
3108
  });
2971
3109
  return () => {
2972
3110
  try {
@@ -3022,6 +3160,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3022
3160
  (0, import_react.useEffect)(() => {
3023
3161
  if (!playerRef.current || !videoRef.current) return;
3024
3162
  const updateStates = () => {
3163
+ var _a;
3025
3164
  if (playerRef.current && videoRef.current) {
3026
3165
  setIsMuted(playerRef.current.isMuted());
3027
3166
  setIsPlaying(!videoRef.current.paused);
@@ -3039,13 +3178,14 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3039
3178
  );
3040
3179
  }
3041
3180
  setIsFullscreen(
3042
- document.fullscreenElement === videoRef.current?.parentElement
3181
+ document.fullscreenElement === ((_a = videoRef.current) == null ? void 0 : _a.parentElement)
3043
3182
  );
3044
3183
  };
3045
3184
  const interval = setInterval(updateStates, 200);
3046
3185
  const handleFullscreenChange = () => {
3186
+ var _a;
3047
3187
  setIsFullscreen(
3048
- document.fullscreenElement === videoRef.current?.parentElement
3188
+ document.fullscreenElement === ((_a = videoRef.current) == null ? void 0 : _a.parentElement)
3049
3189
  );
3050
3190
  };
3051
3191
  document.addEventListener("fullscreenchange", handleFullscreenChange);