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.
package/lib/index.cjs CHANGED
@@ -83,7 +83,8 @@ function getWebKitVersion(ua) {
83
83
  return match && match[1] ? parseInt(match[1], 10) : 0;
84
84
  }
85
85
  function getPlatform() {
86
- if ("userAgentData" in navigator && navigator.userAgentData?.platform) {
86
+ var _a;
87
+ if ("userAgentData" in navigator && ((_a = navigator.userAgentData) == null ? void 0 : _a.platform)) {
87
88
  return navigator.userAgentData.platform;
88
89
  }
89
90
  const ua = navigator.userAgent;
@@ -277,6 +278,7 @@ function createImaController(video, options) {
277
278
  }
278
279
  }
279
280
  function ensureImaLoaded() {
281
+ var _a, _b, _c;
280
282
  if (!supportsGoogleIMA()) {
281
283
  console.warn(
282
284
  "[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead."
@@ -287,7 +289,7 @@ function createImaController(video, options) {
287
289
  }
288
290
  try {
289
291
  const frameEl = window.frameElement;
290
- const sandboxAttr = frameEl?.getAttribute?.("sandbox") || "";
292
+ const sandboxAttr = ((_a = frameEl == null ? void 0 : frameEl.getAttribute) == null ? void 0 : _a.call(frameEl, "sandbox")) || "";
291
293
  if (sandboxAttr) {
292
294
  const tokens = new Set(
293
295
  sandboxAttr.split(/\s+/).map((t) => t.trim()).filter((t) => t.length > 0)
@@ -301,13 +303,13 @@ function createImaController(video, options) {
301
303
  }
302
304
  } catch {
303
305
  }
304
- if (typeof window !== "undefined" && window.google?.ima)
306
+ if (typeof window !== "undefined" && ((_b = window.google) == null ? void 0 : _b.ima))
305
307
  return Promise.resolve();
306
308
  const existing = document.querySelector(
307
309
  'script[data-ima="true"]'
308
310
  );
309
311
  if (existing) {
310
- if (window.google?.ima) {
312
+ if ((_c = window.google) == null ? void 0 : _c.ima) {
311
313
  return Promise.resolve();
312
314
  }
313
315
  return new Promise((resolve, reject) => {
@@ -365,6 +367,7 @@ function createImaController(video, options) {
365
367
  return {
366
368
  initialize() {
367
369
  ensureImaLoaded().then(() => {
370
+ var _a, _b;
368
371
  const google = window.google;
369
372
  if (!adDisplayContainer) {
370
373
  const container = document.createElement("div");
@@ -378,14 +381,14 @@ function createImaController(video, options) {
378
381
  container.style.justifyContent = "center";
379
382
  container.style.pointerEvents = "none";
380
383
  container.style.zIndex = "2";
381
- video.parentElement?.appendChild(container);
384
+ (_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
382
385
  adContainerEl = container;
383
386
  adDisplayContainer = new google.ima.AdDisplayContainer(
384
387
  container,
385
388
  video
386
389
  );
387
390
  try {
388
- adDisplayContainer.initialize?.();
391
+ (_b = adDisplayContainer.initialize) == null ? void 0 : _b.call(adDisplayContainer);
389
392
  } catch {
390
393
  }
391
394
  }
@@ -470,6 +473,7 @@ function createImaController(video, options) {
470
473
  adsManager.addEventListener(
471
474
  AdErrorEvent.AD_ERROR,
472
475
  (errorEvent) => {
476
+ var _a;
473
477
  console.error("[IMA] Ad error:", errorEvent.getError());
474
478
  destroyAdsManager();
475
479
  adPlaying = false;
@@ -500,10 +504,10 @@ function createImaController(video, options) {
500
504
  "[IMA] Max retries reached, emitting ad_error"
501
505
  );
502
506
  emit("ad_error");
503
- if (!options?.continueLiveStreamDuringAds) {
507
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
504
508
  if (video.paused) {
505
509
  console.log("[IMA] Resuming paused video after ad error");
506
- video.play()?.catch(() => {
510
+ (_a = video.play()) == null ? void 0 : _a.catch(() => {
507
511
  });
508
512
  }
509
513
  }
@@ -514,7 +518,7 @@ function createImaController(video, options) {
514
518
  AdEvent.CONTENT_PAUSE_REQUESTED,
515
519
  () => {
516
520
  console.log("[IMA] Content pause requested");
517
- if (!options?.continueLiveStreamDuringAds) {
521
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
518
522
  video.pause();
519
523
  console.log("[IMA] Video paused (VOD mode)");
520
524
  } else {
@@ -540,6 +544,7 @@ function createImaController(video, options) {
540
544
  adsManager.addEventListener(
541
545
  AdEvent.CONTENT_RESUME_REQUESTED,
542
546
  () => {
547
+ var _a;
543
548
  console.log("[IMA] Content resume requested");
544
549
  adPlaying = false;
545
550
  video.muted = originalMutedState;
@@ -550,8 +555,8 @@ function createImaController(video, options) {
550
555
  "[IMA] Ad container hidden - pointer events disabled"
551
556
  );
552
557
  }
553
- if (!options?.continueLiveStreamDuringAds) {
554
- video.play()?.catch(() => {
558
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
559
+ (_a = video.play()) == null ? void 0 : _a.catch(() => {
555
560
  });
556
561
  console.log("[IMA] Video resumed (VOD mode)");
557
562
  } else {
@@ -573,7 +578,7 @@ function createImaController(video, options) {
573
578
  "[IMA] Ad container hidden after all ads completed"
574
579
  );
575
580
  }
576
- if (!options?.continueLiveStreamDuringAds) {
581
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
577
582
  video.play().catch(() => {
578
583
  });
579
584
  console.log(
@@ -601,7 +606,7 @@ function createImaController(video, options) {
601
606
  adContainerEl.style.display = "none";
602
607
  console.log("[IMA] Ad container hidden after setup error");
603
608
  }
604
- if (!options?.continueLiveStreamDuringAds) {
609
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
605
610
  if (video.paused) {
606
611
  console.log("[IMA] Resuming paused video after setup error");
607
612
  video.play().catch(() => {
@@ -629,7 +634,7 @@ function createImaController(video, options) {
629
634
  adContainerEl.style.display = "none";
630
635
  console.log("[IMA] Ad container hidden after loader error");
631
636
  }
632
- if (!options?.continueLiveStreamDuringAds) {
637
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
633
638
  if (video.paused) {
634
639
  console.log("[IMA] Resuming paused video after loader error");
635
640
  video.play().catch(() => {
@@ -651,14 +656,15 @@ function createImaController(video, options) {
651
656
  return adsLoadedPromise;
652
657
  } catch (error) {
653
658
  console.error("[IMA] Failed to request ads:", error);
654
- currentReject?.(error);
659
+ currentReject == null ? void 0 : currentReject(error);
655
660
  adsLoadedReject = void 0;
656
661
  adsLoadedResolve = void 0;
657
662
  return Promise.reject(error);
658
663
  }
659
664
  },
660
665
  async play() {
661
- if (!window.google?.ima || !adDisplayContainer) {
666
+ var _a, _b;
667
+ if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
662
668
  console.warn(
663
669
  "[IMA] Cannot play ad: IMA SDK or ad container not available"
664
670
  );
@@ -680,14 +686,15 @@ function createImaController(video, options) {
680
686
  } catch (error) {
681
687
  console.error("[IMA] Error starting ad playback:", error);
682
688
  adPlaying = false;
683
- if (!options?.continueLiveStreamDuringAds) {
684
- video.play()?.catch(() => {
689
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
690
+ (_b = video.play()) == null ? void 0 : _b.catch(() => {
685
691
  });
686
692
  }
687
693
  return Promise.reject(error);
688
694
  }
689
695
  },
690
696
  async stop() {
697
+ var _a;
691
698
  adPlaying = false;
692
699
  video.muted = originalMutedState;
693
700
  if (adContainerEl) {
@@ -696,11 +703,11 @@ function createImaController(video, options) {
696
703
  console.log("[IMA] Ad container hidden after stop");
697
704
  }
698
705
  try {
699
- adsManager?.stop?.();
706
+ (_a = adsManager == null ? void 0 : adsManager.stop) == null ? void 0 : _a.call(adsManager);
700
707
  } catch {
701
708
  }
702
709
  destroyAdsManager();
703
- if (!options?.continueLiveStreamDuringAds) {
710
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
704
711
  video.play().catch(() => {
705
712
  });
706
713
  console.log("[IMA] Video resumed after stop (VOD mode)");
@@ -709,6 +716,7 @@ function createImaController(video, options) {
709
716
  }
710
717
  },
711
718
  destroy() {
719
+ var _a;
712
720
  destroyAdsManager();
713
721
  adPlaying = false;
714
722
  video.muted = originalMutedState;
@@ -717,10 +725,10 @@ function createImaController(video, options) {
717
725
  adContainerEl.style.display = "none";
718
726
  }
719
727
  try {
720
- adsLoader?.destroy?.();
728
+ (_a = adsLoader == null ? void 0 : adsLoader.destroy) == null ? void 0 : _a.call(adsLoader);
721
729
  } catch {
722
730
  }
723
- if (adContainerEl?.parentElement) {
731
+ if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
724
732
  adContainerEl.parentElement.removeChild(adContainerEl);
725
733
  }
726
734
  adContainerEl = void 0;
@@ -731,7 +739,8 @@ function createImaController(video, options) {
731
739
  return adPlaying;
732
740
  },
733
741
  resize(width, height) {
734
- if (!adsManager || !window.google?.ima) {
742
+ var _a;
743
+ if (!adsManager || !((_a = window.google) == null ? void 0 : _a.ima)) {
735
744
  console.warn(
736
745
  "[IMA] Cannot resize: No ads manager or IMA SDK available"
737
746
  );
@@ -749,7 +758,8 @@ function createImaController(video, options) {
749
758
  listeners.get(event).add(listener);
750
759
  },
751
760
  off(event, listener) {
752
- listeners.get(event)?.delete(listener);
761
+ var _a;
762
+ (_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
753
763
  },
754
764
  updateOriginalMutedState(muted) {
755
765
  originalMutedState = muted;
@@ -786,7 +796,8 @@ function createHlsAdPlayer(contentVideo, options) {
786
796
  let adPlaying = false;
787
797
  let originalMutedState = false;
788
798
  const listeners = /* @__PURE__ */ new Map();
789
- const licenseKey = options?.licenseKey;
799
+ const licenseKey = options == null ? void 0 : options.licenseKey;
800
+ const mainHlsInstance = options == null ? void 0 : options.mainHlsInstance;
790
801
  let adVideoElement;
791
802
  let adHls;
792
803
  let adContainerEl;
@@ -833,13 +844,80 @@ function createHlsAdPlayer(contentVideo, options) {
833
844
  }
834
845
  });
835
846
  }
847
+ function getMainStreamQuality() {
848
+ if (!mainHlsInstance || !mainHlsInstance.levels) {
849
+ return null;
850
+ }
851
+ const currentLevel = mainHlsInstance.currentLevel;
852
+ if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {
853
+ const autoLevel = mainHlsInstance.loadLevel;
854
+ if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {
855
+ const level2 = mainHlsInstance.levels[autoLevel];
856
+ return {
857
+ width: level2.width || 1920,
858
+ height: level2.height || 1080,
859
+ bitrate: level2.bitrate || 5e6
860
+ };
861
+ }
862
+ return null;
863
+ }
864
+ const level = mainHlsInstance.levels[currentLevel];
865
+ return {
866
+ width: level.width || 1920,
867
+ height: level.height || 1080,
868
+ bitrate: level.bitrate || 5e6
869
+ };
870
+ }
871
+ function selectBestMediaFile(mediaFiles) {
872
+ if (mediaFiles.length === 0) {
873
+ throw new Error("No media files available");
874
+ }
875
+ const firstFile = mediaFiles[0];
876
+ if (!firstFile) {
877
+ throw new Error("No media files available");
878
+ }
879
+ if (mediaFiles.length === 1) {
880
+ return firstFile;
881
+ }
882
+ const mainQuality = getMainStreamQuality();
883
+ if (!mainQuality) {
884
+ console.log("[HlsAdPlayer] No main stream quality info, using first media file");
885
+ return firstFile;
886
+ }
887
+ console.log("[HlsAdPlayer] Main stream quality:", mainQuality);
888
+ const scoredFiles = mediaFiles.map((file) => {
889
+ const widthDiff = Math.abs(file.width - mainQuality.width);
890
+ const heightDiff = Math.abs(file.height - mainQuality.height);
891
+ const resolutionDiff = widthDiff + heightDiff;
892
+ const fileBitrate = (file.bitrate || 5e3) * 1e3;
893
+ const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);
894
+ const score = resolutionDiff * 2 + bitrateDiff / 1e3;
895
+ return { file, score, resolutionDiff, bitrateDiff };
896
+ });
897
+ scoredFiles.sort((a, b) => a.score - b.score);
898
+ const bestMatch = scoredFiles[0];
899
+ if (!bestMatch) {
900
+ console.log("[HlsAdPlayer] No best match found, using first media file");
901
+ return firstFile;
902
+ }
903
+ console.log("[HlsAdPlayer] Selected media file:", {
904
+ url: bestMatch.file.url,
905
+ resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,
906
+ bitrate: bestMatch.file.bitrate,
907
+ score: bestMatch.score,
908
+ resolutionDiff: bestMatch.resolutionDiff,
909
+ bitrateDiff: bestMatch.bitrateDiff
910
+ });
911
+ return bestMatch.file;
912
+ }
836
913
  function parseVastXml(xmlString) {
914
+ var _a, _b, _c, _d;
837
915
  try {
838
916
  const parser = new DOMParser();
839
917
  const xmlDoc = parser.parseFromString(xmlString, "text/xml");
840
918
  const parserError = xmlDoc.querySelector("parsererror");
841
919
  if (parserError) {
842
- console.error("[HlsAdPlayer] XML parsing error:", parserError.textContent);
920
+ console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
843
921
  return null;
844
922
  }
845
923
  const adElement = xmlDoc.querySelector("Ad");
@@ -848,28 +926,46 @@ function createHlsAdPlayer(contentVideo, options) {
848
926
  return null;
849
927
  }
850
928
  const adId = adElement.getAttribute("id") || "unknown";
851
- const title = xmlDoc.querySelector("AdTitle")?.textContent || "Ad";
852
- const durationText = xmlDoc.querySelector("Duration")?.textContent || "00:00:30";
929
+ const title = ((_a = xmlDoc.querySelector("AdTitle")) == null ? void 0 : _a.textContent) || "Ad";
930
+ const isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
931
+ const durationText = ((_b = xmlDoc.querySelector("Duration")) == null ? void 0 : _b.textContent) || "00:00:30";
853
932
  const durationParts = durationText.split(":");
854
933
  const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
855
934
  const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
856
935
  const mediaFiles = [];
857
- mediaFileElements.forEach((mf) => {
936
+ console.log(`[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`);
937
+ mediaFileElements.forEach((mf, index) => {
938
+ var _a2;
858
939
  const type = mf.getAttribute("type") || "";
940
+ const url = ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "";
941
+ const width = mf.getAttribute("width") || "";
942
+ const height = mf.getAttribute("height") || "";
943
+ console.log(`[HlsAdPlayer] MediaFile ${index}: type="${type}", url="${url}", width="${width}", height="${height}"`);
859
944
  if (type === "application/x-mpegURL" || type.includes("m3u8")) {
945
+ if (!url) {
946
+ console.warn(`[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`);
947
+ return;
948
+ }
860
949
  const bitrateAttr = mf.getAttribute("bitrate");
861
950
  const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
862
951
  mediaFiles.push({
863
- url: mf.textContent?.trim() || "",
952
+ url,
864
953
  type,
865
- width: parseInt(mf.getAttribute("width") || "1920", 10),
866
- height: parseInt(mf.getAttribute("height") || "1080", 10),
954
+ width: parseInt(width || "1920", 10),
955
+ height: parseInt(height || "1080", 10),
867
956
  bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
868
957
  });
958
+ console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);
959
+ } else {
960
+ console.log(`[HlsAdPlayer] MediaFile ${index} ignored (type="${type}" is not HLS)`);
869
961
  }
870
962
  });
871
963
  if (mediaFiles.length === 0) {
872
- console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
964
+ if (isNoAdAvailable) {
965
+ console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
966
+ } else {
967
+ console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
968
+ }
873
969
  return null;
874
970
  }
875
971
  const trackingUrls = {
@@ -889,12 +985,14 @@ function createHlsAdPlayer(contentVideo, options) {
889
985
  error: []
890
986
  };
891
987
  xmlDoc.querySelectorAll("Impression").forEach((el) => {
892
- const url = el.textContent?.trim();
988
+ var _a2;
989
+ const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
893
990
  if (url) trackingUrls.impression.push(url);
894
991
  });
895
992
  xmlDoc.querySelectorAll("Tracking").forEach((el) => {
993
+ var _a2;
896
994
  const event = el.getAttribute("event");
897
- const url = el.textContent?.trim();
995
+ const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
898
996
  if (event && url) {
899
997
  const eventKey = event;
900
998
  if (trackingUrls[eventKey]) {
@@ -902,7 +1000,7 @@ function createHlsAdPlayer(contentVideo, options) {
902
1000
  }
903
1001
  }
904
1002
  });
905
- const clickThrough = xmlDoc.querySelector("ClickThrough")?.textContent?.trim();
1003
+ const clickThrough = (_d = (_c = xmlDoc.querySelector("ClickThrough")) == null ? void 0 : _c.textContent) == null ? void 0 : _d.trim();
906
1004
  return {
907
1005
  id: adId,
908
1006
  title,
@@ -994,7 +1092,7 @@ function createHlsAdPlayer(contentVideo, options) {
994
1092
  adContainerEl.style.display = "none";
995
1093
  adContainerEl.style.pointerEvents = "none";
996
1094
  }
997
- if (!options?.continueLiveStreamDuringAds) {
1095
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
998
1096
  contentVideo.play().catch(() => {
999
1097
  });
1000
1098
  console.log("[HlsAdPlayer] Content resumed (VOD mode)");
@@ -1012,7 +1110,7 @@ function createHlsAdPlayer(contentVideo, options) {
1012
1110
  adContainerEl.style.display = "none";
1013
1111
  adContainerEl.style.pointerEvents = "none";
1014
1112
  }
1015
- if (!options?.continueLiveStreamDuringAds) {
1113
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
1016
1114
  if (contentVideo.paused) {
1017
1115
  contentVideo.play().catch(() => {
1018
1116
  });
@@ -1022,6 +1120,7 @@ function createHlsAdPlayer(contentVideo, options) {
1022
1120
  }
1023
1121
  return {
1024
1122
  initialize() {
1123
+ var _a;
1025
1124
  console.log("[HlsAdPlayer] Initializing");
1026
1125
  if (!adContainerEl) {
1027
1126
  const container = document.createElement("div");
@@ -1036,7 +1135,7 @@ function createHlsAdPlayer(contentVideo, options) {
1036
1135
  container.style.pointerEvents = "none";
1037
1136
  container.style.zIndex = "2";
1038
1137
  container.style.backgroundColor = "#000";
1039
- contentVideo.parentElement?.appendChild(container);
1138
+ (_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
1040
1139
  adContainerEl = container;
1041
1140
  }
1042
1141
  },
@@ -1054,9 +1153,11 @@ function createHlsAdPlayer(contentVideo, options) {
1054
1153
  }
1055
1154
  const vastXml = await response.text();
1056
1155
  console.log("[HlsAdPlayer] VAST XML received");
1156
+ console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
1057
1157
  const ad = parseVastXml(vastXml);
1058
1158
  if (!ad) {
1059
- throw new Error("Failed to parse VAST XML or no ads available");
1159
+ console.warn("[HlsAdPlayer] No ads available from VAST response");
1160
+ return Promise.resolve();
1060
1161
  }
1061
1162
  currentAd = ad;
1062
1163
  console.log(`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`);
@@ -1071,14 +1172,14 @@ function createHlsAdPlayer(contentVideo, options) {
1071
1172
  },
1072
1173
  async play() {
1073
1174
  if (!currentAd) {
1074
- console.warn("[HlsAdPlayer] Cannot play: No ad loaded");
1175
+ console.warn("[HlsAdPlayer] Cannot play: No ad loaded (no ads available)");
1075
1176
  return Promise.reject(new Error("No ad loaded"));
1076
1177
  }
1077
1178
  console.log("[HlsAdPlayer] Starting ad playback");
1078
1179
  try {
1079
1180
  if (!adVideoElement) {
1080
1181
  adVideoElement = createAdVideoElement();
1081
- adContainerEl?.appendChild(adVideoElement);
1182
+ adContainerEl == null ? void 0 : adContainerEl.appendChild(adVideoElement);
1082
1183
  setupAdEventListeners();
1083
1184
  }
1084
1185
  trackingFired = {
@@ -1089,7 +1190,7 @@ function createHlsAdPlayer(contentVideo, options) {
1089
1190
  thirdQuartile: false,
1090
1191
  complete: false
1091
1192
  };
1092
- if (!options?.continueLiveStreamDuringAds) {
1193
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
1093
1194
  contentVideo.pause();
1094
1195
  console.log("[HlsAdPlayer] Content paused (VOD mode)");
1095
1196
  } else {
@@ -1102,7 +1203,7 @@ function createHlsAdPlayer(contentVideo, options) {
1102
1203
  adContainerEl.style.pointerEvents = "auto";
1103
1204
  }
1104
1205
  emit("content_pause");
1105
- const mediaFile = currentAd.mediaFiles[0];
1206
+ const mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1106
1207
  if (!mediaFile) {
1107
1208
  throw new Error("No media file available for ad");
1108
1209
  }
@@ -1162,7 +1263,7 @@ function createHlsAdPlayer(contentVideo, options) {
1162
1263
  adVideoElement.pause();
1163
1264
  adVideoElement.src = "";
1164
1265
  }
1165
- if (!options?.continueLiveStreamDuringAds) {
1266
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
1166
1267
  contentVideo.play().catch(() => {
1167
1268
  });
1168
1269
  }
@@ -1182,7 +1283,7 @@ function createHlsAdPlayer(contentVideo, options) {
1182
1283
  adVideoElement.remove();
1183
1284
  adVideoElement = void 0;
1184
1285
  }
1185
- if (adContainerEl?.parentElement) {
1286
+ if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
1186
1287
  adContainerEl.parentElement.removeChild(adContainerEl);
1187
1288
  }
1188
1289
  adContainerEl = void 0;
@@ -1208,7 +1309,8 @@ function createHlsAdPlayer(contentVideo, options) {
1208
1309
  listeners.get(event).add(listener);
1209
1310
  },
1210
1311
  off(event, listener) {
1211
- listeners.get(event)?.delete(listener);
1312
+ var _a;
1313
+ (_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
1212
1314
  },
1213
1315
  updateOriginalMutedState(muted) {
1214
1316
  originalMutedState = muted;
@@ -1233,6 +1335,7 @@ function createHlsAdPlayer(contentVideo, options) {
1233
1335
  // src/utils/tracking.ts
1234
1336
  var cachedBrowserId = null;
1235
1337
  function getClientInfo() {
1338
+ var _a, _b, _c, _d;
1236
1339
  const ua = navigator.userAgent;
1237
1340
  const platform = navigator.platform;
1238
1341
  const vendor = navigator.vendor || "";
@@ -1240,12 +1343,12 @@ function getClientInfo() {
1240
1343
  const memory = navigator.deviceMemory || null;
1241
1344
  const hardwareConcurrency = navigator.hardwareConcurrency || 1;
1242
1345
  const screenInfo = {
1243
- width: screen?.width,
1244
- height: screen?.height,
1245
- availWidth: screen?.availWidth,
1246
- availHeight: screen?.availHeight,
1247
- orientation: screen?.orientation?.type || "",
1248
- pixelDepth: screen?.pixelDepth
1346
+ width: screen == null ? void 0 : screen.width,
1347
+ height: screen == null ? void 0 : screen.height,
1348
+ availWidth: screen == null ? void 0 : screen.availWidth,
1349
+ availHeight: screen == null ? void 0 : screen.availHeight,
1350
+ orientation: ((_a = screen == null ? void 0 : screen.orientation) == null ? void 0 : _a.type) || "",
1351
+ pixelDepth: screen == null ? void 0 : screen.pixelDepth
1249
1352
  };
1250
1353
  let deviceType = "desktop";
1251
1354
  let brand = "Unknown";
@@ -1342,10 +1445,10 @@ function getClientInfo() {
1342
1445
  if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
1343
1446
  }
1344
1447
  isWebView = /wv|WebView|Linux; U;/.test(ua);
1345
- if (window?.outerHeight === 0 && window?.outerWidth === 0) {
1448
+ if ((window == null ? void 0 : window.outerHeight) === 0 && (window == null ? void 0 : window.outerWidth) === 0) {
1346
1449
  isWebView = true;
1347
1450
  }
1348
- isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || window.screen?.orientation?.angle !== void 0;
1451
+ 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;
1349
1452
  return {
1350
1453
  brand,
1351
1454
  os,
@@ -1366,7 +1469,7 @@ function getClientInfo() {
1366
1469
  deviceMemory: memory,
1367
1470
  maxTouchPoints,
1368
1471
  language: navigator.language,
1369
- languages: navigator.languages?.join(",") || "",
1472
+ languages: ((_d = navigator.languages) == null ? void 0 : _d.join(",")) || "",
1370
1473
  cookieEnabled: navigator.cookieEnabled,
1371
1474
  doNotTrack: navigator.doNotTrack || "",
1372
1475
  referrer: document.referrer,
@@ -1724,7 +1827,8 @@ var StormcloudVideoPlayer = class {
1724
1827
  }
1725
1828
  return createHlsAdPlayer(this.video, {
1726
1829
  continueLiveStreamDuringAds,
1727
- ...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {}
1830
+ ...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {},
1831
+ ...this.hls ? { mainHlsInstance: this.hls } : {}
1728
1832
  });
1729
1833
  } else {
1730
1834
  if (this.config.debugAdTiming) {
@@ -1736,6 +1840,7 @@ var StormcloudVideoPlayer = class {
1736
1840
  }
1737
1841
  }
1738
1842
  async load() {
1843
+ var _a, _b;
1739
1844
  if (!this.attached) {
1740
1845
  this.attach();
1741
1846
  }
@@ -1752,7 +1857,7 @@ var StormcloudVideoPlayer = class {
1752
1857
  this.initializeTracking();
1753
1858
  if (this.shouldUseNativeHls()) {
1754
1859
  this.video.src = this.config.src;
1755
- this.isLiveStream = this.config.lowLatencyMode ?? false;
1860
+ this.isLiveStream = (_a = this.config.lowLatencyMode) != null ? _a : false;
1756
1861
  if (this.config.debugAdTiming) {
1757
1862
  console.log(
1758
1863
  "[StormcloudVideoPlayer] allowNativeHls: true - VOD mode detected:",
@@ -1767,8 +1872,8 @@ var StormcloudVideoPlayer = class {
1767
1872
  this.ima = this.createAdPlayer(false);
1768
1873
  this.ima.initialize();
1769
1874
  if (this.config.autoplay) {
1770
- await this.video.play()?.catch(() => {
1771
- });
1875
+ await ((_b = this.video.play()) == null ? void 0 : _b.catch(() => {
1876
+ }));
1772
1877
  }
1773
1878
  return;
1774
1879
  }
@@ -1781,12 +1886,17 @@ var StormcloudVideoPlayer = class {
1781
1886
  ...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}
1782
1887
  });
1783
1888
  this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, () => {
1784
- this.hls?.loadSource(this.config.src);
1889
+ var _a2;
1890
+ (_a2 = this.hls) == null ? void 0 : _a2.loadSource(this.config.src);
1785
1891
  });
1786
1892
  this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, async (_, data) => {
1787
- this.isLiveStream = this.hls?.levels?.some(
1788
- (level) => level?.details?.live === true || level?.details?.type === "LIVE"
1789
- ) ?? false;
1893
+ var _a2, _b2, _c, _d;
1894
+ this.isLiveStream = (_c = (_b2 = (_a2 = this.hls) == null ? void 0 : _a2.levels) == null ? void 0 : _b2.some(
1895
+ (level) => {
1896
+ var _a3, _b3;
1897
+ 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";
1898
+ }
1899
+ )) != null ? _c : false;
1790
1900
  if (this.config.debugAdTiming) {
1791
1901
  const adBehavior = this.shouldContinueLiveStreamDuringAds() ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
1792
1902
  console.log("[StormcloudVideoPlayer] Stream type detected:", {
@@ -1799,28 +1909,29 @@ var StormcloudVideoPlayer = class {
1799
1909
  this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());
1800
1910
  this.ima.initialize();
1801
1911
  if (this.config.autoplay) {
1802
- await this.video.play()?.catch(() => {
1803
- });
1912
+ await ((_d = this.video.play()) == null ? void 0 : _d.catch(() => {
1913
+ }));
1804
1914
  }
1805
1915
  });
1806
1916
  this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, (_evt, data) => {
1807
- const id3Tags = (data?.samples || []).map((s) => ({
1917
+ const id3Tags = ((data == null ? void 0 : data.samples) || []).map((s) => ({
1808
1918
  key: "ID3",
1809
- value: s?.data,
1810
- ptsSeconds: s?.pts
1919
+ value: s == null ? void 0 : s.data,
1920
+ ptsSeconds: s == null ? void 0 : s.pts
1811
1921
  }));
1812
1922
  id3Tags.forEach((tag) => this.onId3Tag(tag));
1813
1923
  });
1814
1924
  this.hls.on(import_hls2.default.Events.FRAG_CHANGED, (_evt, data) => {
1815
- const frag = data?.frag;
1816
- const tagList = frag?.tagList;
1925
+ var _a2, _b2, _c;
1926
+ const frag = data == null ? void 0 : data.frag;
1927
+ const tagList = frag == null ? void 0 : frag.tagList;
1817
1928
  if (!Array.isArray(tagList)) return;
1818
1929
  for (const entry of tagList) {
1819
1930
  let tag = "";
1820
1931
  let value = "";
1821
1932
  if (Array.isArray(entry)) {
1822
- tag = String(entry[0] ?? "");
1823
- value = String(entry[1] ?? "");
1933
+ tag = String((_a2 = entry[0]) != null ? _a2 : "");
1934
+ value = String((_b2 = entry[1]) != null ? _b2 : "");
1824
1935
  } else if (typeof entry === "string") {
1825
1936
  const idx = entry.indexOf(":");
1826
1937
  if (idx >= 0) {
@@ -1844,8 +1955,8 @@ var StormcloudVideoPlayer = class {
1844
1955
  const prog = this.parseCueOutCont(value);
1845
1956
  const marker = {
1846
1957
  type: "progress",
1847
- ...prog?.duration !== void 0 ? { durationSeconds: prog.duration } : {},
1848
- ...prog?.elapsed !== void 0 ? { ptsSeconds: prog.elapsed } : {},
1958
+ ...(prog == null ? void 0 : prog.duration) !== void 0 ? { durationSeconds: prog.duration } : {},
1959
+ ...(prog == null ? void 0 : prog.elapsed) !== void 0 ? { ptsSeconds: prog.elapsed } : {},
1849
1960
  raw: { tag, value }
1850
1961
  };
1851
1962
  this.onScte35Marker(marker);
@@ -1855,7 +1966,7 @@ var StormcloudVideoPlayer = class {
1855
1966
  const attrs = this.parseAttributeList(value);
1856
1967
  const hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
1857
1968
  const hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
1858
- const klass = String(attrs["CLASS"] ?? "");
1969
+ const klass = String((_c = attrs["CLASS"]) != null ? _c : "");
1859
1970
  const duration = this.toNumber(attrs["DURATION"]);
1860
1971
  if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
1861
1972
  const marker = {
@@ -1872,13 +1983,14 @@ var StormcloudVideoPlayer = class {
1872
1983
  }
1873
1984
  });
1874
1985
  this.hls.on(import_hls2.default.Events.ERROR, (_evt, data) => {
1875
- if (data?.fatal) {
1986
+ var _a2, _b2;
1987
+ if (data == null ? void 0 : data.fatal) {
1876
1988
  switch (data.type) {
1877
1989
  case import_hls2.default.ErrorTypes.NETWORK_ERROR:
1878
- this.hls?.startLoad();
1990
+ (_a2 = this.hls) == null ? void 0 : _a2.startLoad();
1879
1991
  break;
1880
1992
  case import_hls2.default.ErrorTypes.MEDIA_ERROR:
1881
- this.hls?.recoverMediaError();
1993
+ (_b2 = this.hls) == null ? void 0 : _b2.recoverMediaError();
1882
1994
  break;
1883
1995
  default:
1884
1996
  this.destroy();
@@ -1980,11 +2092,12 @@ var StormcloudVideoPlayer = class {
1980
2092
  }
1981
2093
  }
1982
2094
  parseScte35FromId3(tag) {
2095
+ var _a, _b, _c, _d;
1983
2096
  const text = this.decodeId3ValueToText(tag.value);
1984
2097
  if (!text) return void 0;
1985
2098
  const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\r\n]*))?/i) || text.match(/CUE-OUT(?::([^\r\n]*))?/i);
1986
2099
  if (cueOutMatch) {
1987
- const arg = (cueOutMatch[1] ?? "").trim();
2100
+ const arg = ((_a = cueOutMatch[1]) != null ? _a : "").trim();
1988
2101
  const dur = this.parseCueOutDuration(arg);
1989
2102
  const marker = {
1990
2103
  type: "start",
@@ -1996,12 +2109,12 @@ var StormcloudVideoPlayer = class {
1996
2109
  }
1997
2110
  const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\r\n]*)/i);
1998
2111
  if (cueOutContMatch) {
1999
- const arg = (cueOutContMatch[1] ?? "").trim();
2112
+ const arg = ((_b = cueOutContMatch[1]) != null ? _b : "").trim();
2000
2113
  const cont = this.parseCueOutCont(arg);
2001
2114
  const marker = {
2002
2115
  type: "progress",
2003
2116
  ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},
2004
- ...cont?.duration !== void 0 ? { durationSeconds: cont.duration } : {},
2117
+ ...(cont == null ? void 0 : cont.duration) !== void 0 ? { durationSeconds: cont.duration } : {},
2005
2118
  raw: { id3: text }
2006
2119
  };
2007
2120
  return marker;
@@ -2017,10 +2130,10 @@ var StormcloudVideoPlayer = class {
2017
2130
  }
2018
2131
  const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\r\n]*)/i);
2019
2132
  if (daterangeMatch) {
2020
- const attrs = this.parseAttributeList(daterangeMatch[1] ?? "");
2133
+ const attrs = this.parseAttributeList((_c = daterangeMatch[1]) != null ? _c : "");
2021
2134
  const hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
2022
2135
  const hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
2023
- const klass = String(attrs["CLASS"] ?? "");
2136
+ const klass = String((_d = attrs["CLASS"]) != null ? _d : "");
2024
2137
  const duration = this.toNumber(attrs["DURATION"]);
2025
2138
  if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
2026
2139
  const marker = {
@@ -2077,6 +2190,7 @@ var StormcloudVideoPlayer = class {
2077
2190
  }
2078
2191
  }
2079
2192
  onScte35Marker(marker) {
2193
+ var _a, _b;
2080
2194
  if (this.config.debugAdTiming) {
2081
2195
  console.log("[StormcloudVideoPlayer] SCTE-35 marker detected:", {
2082
2196
  type: marker.type,
@@ -2092,7 +2206,7 @@ var StormcloudVideoPlayer = class {
2092
2206
  this.expectedAdBreakDurationMs = durationMs;
2093
2207
  this.currentAdBreakStartWallClockMs = Date.now();
2094
2208
  const isManifestMarker = this.isManifestBasedMarker(marker);
2095
- const forceImmediate = this.config.immediateManifestAds ?? true;
2209
+ const forceImmediate = (_a = this.config.immediateManifestAds) != null ? _a : true;
2096
2210
  if (this.config.debugAdTiming) {
2097
2211
  console.log("[StormcloudVideoPlayer] Ad start decision:", {
2098
2212
  isManifestMarker,
@@ -2109,7 +2223,7 @@ var StormcloudVideoPlayer = class {
2109
2223
  this.clearAdStartTimer();
2110
2224
  this.handleAdStart(marker);
2111
2225
  } else if (typeof marker.ptsSeconds === "number") {
2112
- const tol = this.config.driftToleranceMs ?? 1e3;
2226
+ const tol = (_b = this.config.driftToleranceMs) != null ? _b : 1e3;
2113
2227
  const nowMs = this.video.currentTime * 1e3;
2114
2228
  const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
2115
2229
  const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);
@@ -2219,12 +2333,13 @@ var StormcloudVideoPlayer = class {
2219
2333
  return void 0;
2220
2334
  }
2221
2335
  parseAttributeList(value) {
2336
+ var _a, _b, _c;
2222
2337
  const attrs = {};
2223
2338
  const regex = /([A-Z0-9-]+)=(("[^"]*")|([^",]*))(?:,|$)/gi;
2224
2339
  let match;
2225
2340
  while ((match = regex.exec(value)) !== null) {
2226
- const key = match[1] ?? "";
2227
- let rawVal = match[3] ?? match[4] ?? "";
2341
+ const key = (_a = match[1]) != null ? _a : "";
2342
+ let rawVal = (_c = (_b = match[3]) != null ? _b : match[4]) != null ? _c : "";
2228
2343
  if (rawVal.startsWith('"') && rawVal.endsWith('"')) {
2229
2344
  rawVal = rawVal.slice(1, -1);
2230
2345
  }
@@ -2388,6 +2503,7 @@ var StormcloudVideoPlayer = class {
2388
2503
  }
2389
2504
  }
2390
2505
  async fetchAdConfiguration() {
2506
+ var _a, _b, _c;
2391
2507
  const vastMode = this.config.vastMode || "default";
2392
2508
  if (this.config.debugAdTiming) {
2393
2509
  console.log(
@@ -2408,7 +2524,7 @@ var StormcloudVideoPlayer = class {
2408
2524
  this.apiVastTagUrl = vastEndpoint;
2409
2525
  if (this.config.debugAdTiming) {
2410
2526
  console.log(
2411
- "[StormcloudVideoPlayer] Using AdStorm VAST endpoint:",
2527
+ "[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):",
2412
2528
  vastEndpoint
2413
2529
  );
2414
2530
  }
@@ -2445,7 +2561,7 @@ var StormcloudVideoPlayer = class {
2445
2561
  return;
2446
2562
  }
2447
2563
  const data = await response.json();
2448
- const imaPayload = data.response?.ima?.["publisherdesk.ima"]?.payload;
2564
+ const imaPayload = (_c = (_b = (_a = data.response) == null ? void 0 : _a.ima) == null ? void 0 : _b["publisherdesk.ima"]) == null ? void 0 : _c.payload;
2449
2565
  if (imaPayload) {
2450
2566
  this.apiVastTagUrl = decodeURIComponent(imaPayload);
2451
2567
  if (this.config.debugAdTiming) {
@@ -2482,11 +2598,12 @@ var StormcloudVideoPlayer = class {
2482
2598
  return "other";
2483
2599
  }
2484
2600
  shouldShowNativeControls() {
2601
+ var _a, _b;
2485
2602
  const streamType = this.getStreamType();
2486
2603
  if (streamType === "other") {
2487
- return !(this.config.showCustomControls ?? false);
2604
+ return !((_a = this.config.showCustomControls) != null ? _a : false);
2488
2605
  }
2489
- return !!(this.config.allowNativeHls && !(this.config.showCustomControls ?? false));
2606
+ return !!(this.config.allowNativeHls && !((_b = this.config.showCustomControls) != null ? _b : false));
2490
2607
  }
2491
2608
  shouldContinueLiveStreamDuringAds() {
2492
2609
  if (this.config.allowNativeHls) {
@@ -2498,6 +2615,7 @@ var StormcloudVideoPlayer = class {
2498
2615
  return true;
2499
2616
  }
2500
2617
  async handleAdStart(_marker) {
2618
+ var _a;
2501
2619
  const scheduled = this.findCurrentOrNextBreak(
2502
2620
  this.video.currentTime * 1e3
2503
2621
  );
@@ -2548,17 +2666,18 @@ var StormcloudVideoPlayer = class {
2548
2666
  this.handleAdFailure();
2549
2667
  }
2550
2668
  }
2551
- if (this.expectedAdBreakDurationMs == null && scheduled?.durationMs != null) {
2669
+ if (this.expectedAdBreakDurationMs == null && (scheduled == null ? void 0 : scheduled.durationMs) != null) {
2552
2670
  this.expectedAdBreakDurationMs = scheduled.durationMs;
2553
- this.currentAdBreakStartWallClockMs = this.currentAdBreakStartWallClockMs ?? Date.now();
2671
+ this.currentAdBreakStartWallClockMs = (_a = this.currentAdBreakStartWallClockMs) != null ? _a : Date.now();
2554
2672
  this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
2555
2673
  }
2556
2674
  }
2557
2675
  findCurrentOrNextBreak(nowMs) {
2676
+ var _a;
2558
2677
  const schedule = [];
2559
2678
  let candidate;
2560
2679
  for (const b of schedule) {
2561
- const tol = this.config.driftToleranceMs ?? 1e3;
2680
+ const tol = (_a = this.config.driftToleranceMs) != null ? _a : 1e3;
2562
2681
  if (b.startTimeMs <= nowMs + tol && (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))) {
2563
2682
  candidate = b;
2564
2683
  }
@@ -2574,7 +2693,8 @@ var StormcloudVideoPlayer = class {
2574
2693
  }
2575
2694
  }
2576
2695
  async handleMidAdJoin(adBreak, nowMs) {
2577
- const durationMs = adBreak.durationMs ?? 0;
2696
+ var _a;
2697
+ const durationMs = (_a = adBreak.durationMs) != null ? _a : 0;
2578
2698
  const endMs = adBreak.startTimeMs + durationMs;
2579
2699
  if (durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs) {
2580
2700
  const remainingMs = endMs - nowMs;
@@ -2660,12 +2780,20 @@ var StormcloudVideoPlayer = class {
2660
2780
  this.startAdFailsafeTimer();
2661
2781
  try {
2662
2782
  await this.ima.requestAds(vastTagUrl);
2663
- if (this.config.debugAdTiming) {
2664
- console.log("[StormcloudVideoPlayer] Ad request successful, starting playback");
2665
- }
2666
- await this.ima.play();
2667
- if (this.config.debugAdTiming) {
2668
- console.log("[StormcloudVideoPlayer] Ad playback started successfully");
2783
+ try {
2784
+ if (this.config.debugAdTiming) {
2785
+ console.log("[StormcloudVideoPlayer] Ad request completed, attempting playback");
2786
+ }
2787
+ await this.ima.play();
2788
+ if (this.config.debugAdTiming) {
2789
+ console.log("[StormcloudVideoPlayer] Ad playback started successfully");
2790
+ }
2791
+ } catch (playError) {
2792
+ if (this.config.debugAdTiming) {
2793
+ console.log("[StormcloudVideoPlayer] No ads available, skipping playback");
2794
+ }
2795
+ this.handleAdFailure();
2796
+ return;
2669
2797
  }
2670
2798
  } catch (error) {
2671
2799
  if (this.config.debugAdTiming) {
@@ -2675,6 +2803,7 @@ var StormcloudVideoPlayer = class {
2675
2803
  }
2676
2804
  }
2677
2805
  handleAdFailure() {
2806
+ var _a;
2678
2807
  if (this.config.debugAdTiming) {
2679
2808
  console.log(
2680
2809
  "[StormcloudVideoPlayer] Handling ad failure - resuming content",
@@ -2707,7 +2836,7 @@ var StormcloudVideoPlayer = class {
2707
2836
  if (this.config.debugAdTiming) {
2708
2837
  console.log("[StormcloudVideoPlayer] Resuming paused video");
2709
2838
  }
2710
- this.video.play()?.catch((error) => {
2839
+ (_a = this.video.play()) == null ? void 0 : _a.catch((error) => {
2711
2840
  if (this.config.debugAdTiming) {
2712
2841
  console.error(
2713
2842
  "[StormcloudVideoPlayer] Failed to resume video after ad failure:",
@@ -2722,8 +2851,9 @@ var StormcloudVideoPlayer = class {
2722
2851
  }
2723
2852
  }
2724
2853
  startAdFailsafeTimer() {
2854
+ var _a;
2725
2855
  this.clearAdFailsafeTimer();
2726
- const failsafeMs = this.config.adFailsafeTimeoutMs ?? 1e4;
2856
+ const failsafeMs = (_a = this.config.adFailsafeTimeoutMs) != null ? _a : 1e4;
2727
2857
  if (this.config.debugAdTiming) {
2728
2858
  console.log(
2729
2859
  `[StormcloudVideoPlayer] Starting failsafe timer (${failsafeMs}ms)`
@@ -2859,6 +2989,7 @@ var StormcloudVideoPlayer = class {
2859
2989
  }
2860
2990
  }
2861
2991
  destroy() {
2992
+ var _a, _b;
2862
2993
  this.clearAdStartTimer();
2863
2994
  this.clearAdStopTimer();
2864
2995
  this.clearAdFailsafeTimer();
@@ -2866,8 +2997,8 @@ var StormcloudVideoPlayer = class {
2866
2997
  clearInterval(this.heartbeatInterval);
2867
2998
  this.heartbeatInterval = void 0;
2868
2999
  }
2869
- this.hls?.destroy();
2870
- this.ima?.destroy();
3000
+ (_a = this.hls) == null ? void 0 : _a.destroy();
3001
+ (_b = this.ima) == null ? void 0 : _b.destroy();
2871
3002
  }
2872
3003
  };
2873
3004
 
@@ -2879,7 +3010,8 @@ var CRITICAL_PROPS = [
2879
3010
  "allowNativeHls",
2880
3011
  "licenseKey",
2881
3012
  "lowLatencyMode",
2882
- "driftToleranceMs"
3013
+ "driftToleranceMs",
3014
+ "vastMode"
2883
3015
  ];
2884
3016
  var StormcloudVideoPlayerComponent = import_react.default.memo(
2885
3017
  (props) => {
@@ -2907,6 +3039,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
2907
3039
  poster,
2908
3040
  children,
2909
3041
  licenseKey,
3042
+ vastMode,
3043
+ vastTagUrl,
3044
+ adPlayerType,
2910
3045
  ...restVideoAttrs
2911
3046
  } = props;
2912
3047
  const videoRef = (0, import_react.useRef)(null);
@@ -2974,11 +3109,11 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
2974
3109
  }
2975
3110
  setShowSpeedMenu(false);
2976
3111
  };
2977
- const isHlsStream = src?.toLowerCase().includes(".m3u8") || src?.toLowerCase().includes("/hls/");
3112
+ const isHlsStream = (src == null ? void 0 : src.toLowerCase().includes(".m3u8")) || (src == null ? void 0 : src.toLowerCase().includes("/hls/"));
2978
3113
  const shouldShowEnhancedControls = showCustomControls && (isHlsStream ? allowNativeHls : true);
2979
3114
  const criticalPropsKey = (0, import_react.useMemo)(() => {
2980
3115
  return CRITICAL_PROPS.map((prop) => `${prop}:${props[prop]}`).join("|");
2981
- }, [src, allowNativeHls, licenseKey, lowLatencyMode, driftToleranceMs]);
3116
+ }, [src, allowNativeHls, licenseKey, lowLatencyMode, driftToleranceMs, vastMode]);
2982
3117
  (0, import_react.useEffect)(() => {
2983
3118
  if (typeof window === "undefined") return;
2984
3119
  const el = videoRef.current;
@@ -3019,18 +3154,21 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3019
3154
  cfg.onFullscreenToggle = onFullscreenToggle;
3020
3155
  if (onControlClick !== void 0) cfg.onControlClick = onControlClick;
3021
3156
  if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
3157
+ if (vastMode !== void 0) cfg.vastMode = vastMode;
3158
+ if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;
3159
+ if (adPlayerType !== void 0) cfg.adPlayerType = adPlayerType;
3022
3160
  const player = new StormcloudVideoPlayer(cfg);
3023
3161
  playerRef.current = player;
3024
3162
  player.load().then(() => {
3025
3163
  const showNative = player.shouldShowNativeControls();
3026
3164
  setShouldShowNativeControls(showNative);
3027
- onReady?.(player);
3165
+ onReady == null ? void 0 : onReady(player);
3028
3166
  }).catch((error) => {
3029
3167
  console.error(
3030
3168
  "StormcloudVideoPlayer: Failed to load player:",
3031
3169
  error
3032
3170
  );
3033
- onReady?.(player);
3171
+ onReady == null ? void 0 : onReady(player);
3034
3172
  });
3035
3173
  return () => {
3036
3174
  try {
@@ -3086,6 +3224,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3086
3224
  (0, import_react.useEffect)(() => {
3087
3225
  if (!playerRef.current || !videoRef.current) return;
3088
3226
  const updateStates = () => {
3227
+ var _a;
3089
3228
  if (playerRef.current && videoRef.current) {
3090
3229
  setIsMuted(playerRef.current.isMuted());
3091
3230
  setIsPlaying(!videoRef.current.paused);
@@ -3103,13 +3242,14 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(
3103
3242
  );
3104
3243
  }
3105
3244
  setIsFullscreen(
3106
- document.fullscreenElement === videoRef.current?.parentElement
3245
+ document.fullscreenElement === ((_a = videoRef.current) == null ? void 0 : _a.parentElement)
3107
3246
  );
3108
3247
  };
3109
3248
  const interval = setInterval(updateStates, 200);
3110
3249
  const handleFullscreenChange = () => {
3250
+ var _a;
3111
3251
  setIsFullscreen(
3112
- document.fullscreenElement === videoRef.current?.parentElement
3252
+ document.fullscreenElement === ((_a = videoRef.current) == null ? void 0 : _a.parentElement)
3113
3253
  );
3114
3254
  };
3115
3255
  document.addEventListener("fullscreenchange", handleFullscreenChange);
@@ -4552,6 +4692,7 @@ var HlsPlayer = class extends import_react3.Component {
4552
4692
  this.player = null;
4553
4693
  this.mounted = false;
4554
4694
  this.load = async () => {
4695
+ var _a, _b, _c, _d, _e, _f;
4555
4696
  if (!this.props.videoElement || !this.props.src) return;
4556
4697
  try {
4557
4698
  if (this.player) {
@@ -4588,27 +4729,29 @@ var HlsPlayer = class extends import_react3.Component {
4588
4729
  if (this.props.adFailsafeTimeoutMs !== void 0)
4589
4730
  config.adFailsafeTimeoutMs = this.props.adFailsafeTimeoutMs;
4590
4731
  this.player = new StormcloudVideoPlayer(config);
4591
- this.props.onMount?.(this);
4732
+ (_b = (_a = this.props).onMount) == null ? void 0 : _b.call(_a, this);
4592
4733
  await this.player.load();
4593
4734
  if (this.mounted) {
4594
- this.props.onReady?.();
4735
+ (_d = (_c = this.props).onReady) == null ? void 0 : _d.call(_c);
4595
4736
  }
4596
4737
  } catch (error) {
4597
4738
  if (this.mounted) {
4598
- this.props.onError?.(error);
4739
+ (_f = (_e = this.props).onError) == null ? void 0 : _f.call(_e, error);
4599
4740
  }
4600
4741
  }
4601
4742
  };
4602
4743
  this.play = () => {
4744
+ var _a, _b;
4603
4745
  if (this.props.videoElement) {
4604
4746
  this.props.videoElement.play();
4605
- this.props.onPlay?.();
4747
+ (_b = (_a = this.props).onPlay) == null ? void 0 : _b.call(_a);
4606
4748
  }
4607
4749
  };
4608
4750
  this.pause = () => {
4751
+ var _a, _b;
4609
4752
  if (this.props.videoElement) {
4610
4753
  this.props.videoElement.pause();
4611
- this.props.onPause?.();
4754
+ (_b = (_a = this.props).onPause) == null ? void 0 : _b.call(_a);
4612
4755
  }
4613
4756
  };
4614
4757
  this.stop = () => {
@@ -4703,37 +4846,44 @@ var FilePlayer = class extends import_react4.Component {
4703
4846
  this.mounted = false;
4704
4847
  this.ready = false;
4705
4848
  this.load = () => {
4849
+ var _a, _b;
4706
4850
  if (!this.props.videoElement || !this.props.src) return;
4707
4851
  const video = this.props.videoElement;
4708
4852
  const handleLoadedMetadata = () => {
4853
+ var _a2, _b2;
4709
4854
  if (this.mounted && !this.ready) {
4710
4855
  this.ready = true;
4711
- this.props.onReady?.();
4856
+ (_b2 = (_a2 = this.props).onReady) == null ? void 0 : _b2.call(_a2);
4712
4857
  }
4713
4858
  };
4714
4859
  const handlePlay = () => {
4860
+ var _a2, _b2;
4715
4861
  if (this.mounted) {
4716
- this.props.onPlay?.();
4862
+ (_b2 = (_a2 = this.props).onPlay) == null ? void 0 : _b2.call(_a2);
4717
4863
  }
4718
4864
  };
4719
4865
  const handlePause = () => {
4866
+ var _a2, _b2;
4720
4867
  if (this.mounted) {
4721
- this.props.onPause?.();
4868
+ (_b2 = (_a2 = this.props).onPause) == null ? void 0 : _b2.call(_a2);
4722
4869
  }
4723
4870
  };
4724
4871
  const handleEnded = () => {
4872
+ var _a2, _b2;
4725
4873
  if (this.mounted) {
4726
- this.props.onEnded?.();
4874
+ (_b2 = (_a2 = this.props).onEnded) == null ? void 0 : _b2.call(_a2);
4727
4875
  }
4728
4876
  };
4729
4877
  const handleError = (error) => {
4878
+ var _a2, _b2;
4730
4879
  if (this.mounted) {
4731
- this.props.onError?.(error);
4880
+ (_b2 = (_a2 = this.props).onError) == null ? void 0 : _b2.call(_a2, error);
4732
4881
  }
4733
4882
  };
4734
4883
  const handleLoadedData = () => {
4884
+ var _a2, _b2;
4735
4885
  if (this.mounted) {
4736
- this.props.onLoaded?.();
4886
+ (_b2 = (_a2 = this.props).onLoaded) == null ? void 0 : _b2.call(_a2);
4737
4887
  }
4738
4888
  };
4739
4889
  video.addEventListener("loadedmetadata", handleLoadedMetadata);
@@ -4752,7 +4902,7 @@ var FilePlayer = class extends import_react4.Component {
4752
4902
  if (this.props.preload !== void 0)
4753
4903
  video.preload = this.props.preload;
4754
4904
  if (this.props.poster !== void 0) video.poster = this.props.poster;
4755
- this.props.onMount?.(this);
4905
+ (_b = (_a = this.props).onMount) == null ? void 0 : _b.call(_a, this);
4756
4906
  return () => {
4757
4907
  video.removeEventListener("loadedmetadata", handleLoadedMetadata);
4758
4908
  video.removeEventListener("play", handlePlay);
@@ -4921,6 +5071,7 @@ var Player = class extends import_react5.Component {
4921
5071
  return this.player.getInternalPlayer(key);
4922
5072
  };
4923
5073
  this.progress = () => {
5074
+ var _a, _b;
4924
5075
  if (this.props.src && this.player && this.isReady) {
4925
5076
  const playedSeconds = this.getCurrentTime() || 0;
4926
5077
  const loadedSeconds = this.getSecondsLoaded();
@@ -4937,7 +5088,7 @@ var Player = class extends import_react5.Component {
4937
5088
  progress.loaded = loadedSeconds / duration;
4938
5089
  }
4939
5090
  if (progress.playedSeconds !== this.prevPlayed || progress.loadedSeconds !== this.prevLoaded) {
4940
- this.props.onProgress?.(progress);
5091
+ (_b = (_a = this.props).onProgress) == null ? void 0 : _b.call(_a, progress);
4941
5092
  }
4942
5093
  this.prevPlayed = progress.playedSeconds;
4943
5094
  this.prevLoaded = progress.loadedSeconds;
@@ -4973,10 +5124,10 @@ var Player = class extends import_react5.Component {
4973
5124
  if (this.player.setPlaybackRate && playbackRate !== 1) {
4974
5125
  this.player.setPlaybackRate(playbackRate);
4975
5126
  }
4976
- onStart?.();
5127
+ onStart == null ? void 0 : onStart();
4977
5128
  this.startOnPlay = false;
4978
5129
  }
4979
- onPlay?.();
5130
+ onPlay == null ? void 0 : onPlay();
4980
5131
  if (this.seekOnPlay) {
4981
5132
  this.seekTo(this.seekOnPlay);
4982
5133
  this.seekOnPlay = null;
@@ -4984,9 +5135,10 @@ var Player = class extends import_react5.Component {
4984
5135
  this.handleDurationCheck();
4985
5136
  };
4986
5137
  this.handlePause = (e) => {
5138
+ var _a, _b;
4987
5139
  this.isPlaying = false;
4988
5140
  if (!this.isLoading) {
4989
- this.props.onPause?.(e);
5141
+ (_b = (_a = this.props).onPause) == null ? void 0 : _b.call(_a, e);
4990
5142
  }
4991
5143
  };
4992
5144
  this.handleEnded = () => {
@@ -4996,19 +5148,21 @@ var Player = class extends import_react5.Component {
4996
5148
  }
4997
5149
  if (!loop) {
4998
5150
  this.isPlaying = false;
4999
- onEnded?.();
5151
+ onEnded == null ? void 0 : onEnded();
5000
5152
  }
5001
5153
  };
5002
5154
  this.handleError = (...args) => {
5155
+ var _a, _b;
5003
5156
  this.isLoading = false;
5004
- this.props.onError?.(args[0], args[1], args[2], args[3]);
5157
+ (_b = (_a = this.props).onError) == null ? void 0 : _b.call(_a, args[0], args[1], args[2], args[3]);
5005
5158
  };
5006
5159
  this.handleDurationCheck = () => {
5160
+ var _a, _b;
5007
5161
  clearTimeout(this.durationCheckTimeout);
5008
5162
  const duration = this.getDuration();
5009
5163
  if (duration) {
5010
5164
  if (!this.onDurationCalled) {
5011
- this.props.onDuration?.(duration);
5165
+ (_b = (_a = this.props).onDuration) == null ? void 0 : _b.call(_a, duration);
5012
5166
  this.onDurationCalled = true;
5013
5167
  }
5014
5168
  } else {
@@ -5207,7 +5361,8 @@ var createStormcloudPlayer = (playerList, fallback) => {
5207
5361
  return omit(this.props, SUPPORTED_PROPS);
5208
5362
  };
5209
5363
  this.handleReady = () => {
5210
- this.props.onReady?.(this);
5364
+ var _a2, _b;
5365
+ (_b = (_a2 = this.props).onReady) == null ? void 0 : _b.call(_a2, this);
5211
5366
  };
5212
5367
  this.seekTo = (fraction, type, keepPlaying) => {
5213
5368
  if (!this.player) return null;