stormcloud-video-player 0.2.13 → 0.2.14

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.
@@ -45,7 +45,8 @@ function getWebKitVersion(ua) {
45
45
  return match && match[1] ? parseInt(match[1], 10) : 0;
46
46
  }
47
47
  function getPlatform() {
48
- if ("userAgentData" in navigator && navigator.userAgentData?.platform) {
48
+ var _a;
49
+ if ("userAgentData" in navigator && ((_a = navigator.userAgentData) == null ? void 0 : _a.platform)) {
49
50
  return navigator.userAgentData.platform;
50
51
  }
51
52
  const ua = navigator.userAgent;
@@ -210,6 +211,7 @@ function createImaController(video, options) {
210
211
  }
211
212
  }
212
213
  function ensureImaLoaded() {
214
+ var _a, _b, _c;
213
215
  if (!supportsGoogleIMA()) {
214
216
  console.warn(
215
217
  "[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead."
@@ -220,7 +222,7 @@ function createImaController(video, options) {
220
222
  }
221
223
  try {
222
224
  const frameEl = window.frameElement;
223
- const sandboxAttr = frameEl?.getAttribute?.("sandbox") || "";
225
+ const sandboxAttr = ((_a = frameEl == null ? void 0 : frameEl.getAttribute) == null ? void 0 : _a.call(frameEl, "sandbox")) || "";
224
226
  if (sandboxAttr) {
225
227
  const tokens = new Set(
226
228
  sandboxAttr.split(/\s+/).map((t) => t.trim()).filter((t) => t.length > 0)
@@ -234,13 +236,13 @@ function createImaController(video, options) {
234
236
  }
235
237
  } catch {
236
238
  }
237
- if (typeof window !== "undefined" && window.google?.ima)
239
+ if (typeof window !== "undefined" && ((_b = window.google) == null ? void 0 : _b.ima))
238
240
  return Promise.resolve();
239
241
  const existing = document.querySelector(
240
242
  'script[data-ima="true"]'
241
243
  );
242
244
  if (existing) {
243
- if (window.google?.ima) {
245
+ if ((_c = window.google) == null ? void 0 : _c.ima) {
244
246
  return Promise.resolve();
245
247
  }
246
248
  return new Promise((resolve, reject) => {
@@ -298,6 +300,7 @@ function createImaController(video, options) {
298
300
  return {
299
301
  initialize() {
300
302
  ensureImaLoaded().then(() => {
303
+ var _a, _b;
301
304
  const google = window.google;
302
305
  if (!adDisplayContainer) {
303
306
  const container = document.createElement("div");
@@ -311,14 +314,14 @@ function createImaController(video, options) {
311
314
  container.style.justifyContent = "center";
312
315
  container.style.pointerEvents = "none";
313
316
  container.style.zIndex = "2";
314
- video.parentElement?.appendChild(container);
317
+ (_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
315
318
  adContainerEl = container;
316
319
  adDisplayContainer = new google.ima.AdDisplayContainer(
317
320
  container,
318
321
  video
319
322
  );
320
323
  try {
321
- adDisplayContainer.initialize?.();
324
+ (_b = adDisplayContainer.initialize) == null ? void 0 : _b.call(adDisplayContainer);
322
325
  } catch {
323
326
  }
324
327
  }
@@ -403,6 +406,7 @@ function createImaController(video, options) {
403
406
  adsManager.addEventListener(
404
407
  AdErrorEvent.AD_ERROR,
405
408
  (errorEvent) => {
409
+ var _a;
406
410
  console.error("[IMA] Ad error:", errorEvent.getError());
407
411
  destroyAdsManager();
408
412
  adPlaying = false;
@@ -433,10 +437,10 @@ function createImaController(video, options) {
433
437
  "[IMA] Max retries reached, emitting ad_error"
434
438
  );
435
439
  emit("ad_error");
436
- if (!options?.continueLiveStreamDuringAds) {
440
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
437
441
  if (video.paused) {
438
442
  console.log("[IMA] Resuming paused video after ad error");
439
- video.play()?.catch(() => {
443
+ (_a = video.play()) == null ? void 0 : _a.catch(() => {
440
444
  });
441
445
  }
442
446
  }
@@ -447,7 +451,7 @@ function createImaController(video, options) {
447
451
  AdEvent.CONTENT_PAUSE_REQUESTED,
448
452
  () => {
449
453
  console.log("[IMA] Content pause requested");
450
- if (!options?.continueLiveStreamDuringAds) {
454
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
451
455
  video.pause();
452
456
  console.log("[IMA] Video paused (VOD mode)");
453
457
  } else {
@@ -473,6 +477,7 @@ function createImaController(video, options) {
473
477
  adsManager.addEventListener(
474
478
  AdEvent.CONTENT_RESUME_REQUESTED,
475
479
  () => {
480
+ var _a;
476
481
  console.log("[IMA] Content resume requested");
477
482
  adPlaying = false;
478
483
  video.muted = originalMutedState;
@@ -483,8 +488,8 @@ function createImaController(video, options) {
483
488
  "[IMA] Ad container hidden - pointer events disabled"
484
489
  );
485
490
  }
486
- if (!options?.continueLiveStreamDuringAds) {
487
- video.play()?.catch(() => {
491
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
492
+ (_a = video.play()) == null ? void 0 : _a.catch(() => {
488
493
  });
489
494
  console.log("[IMA] Video resumed (VOD mode)");
490
495
  } else {
@@ -506,7 +511,7 @@ function createImaController(video, options) {
506
511
  "[IMA] Ad container hidden after all ads completed"
507
512
  );
508
513
  }
509
- if (!options?.continueLiveStreamDuringAds) {
514
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
510
515
  video.play().catch(() => {
511
516
  });
512
517
  console.log(
@@ -534,7 +539,7 @@ function createImaController(video, options) {
534
539
  adContainerEl.style.display = "none";
535
540
  console.log("[IMA] Ad container hidden after setup error");
536
541
  }
537
- if (!options?.continueLiveStreamDuringAds) {
542
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
538
543
  if (video.paused) {
539
544
  console.log("[IMA] Resuming paused video after setup error");
540
545
  video.play().catch(() => {
@@ -562,7 +567,7 @@ function createImaController(video, options) {
562
567
  adContainerEl.style.display = "none";
563
568
  console.log("[IMA] Ad container hidden after loader error");
564
569
  }
565
- if (!options?.continueLiveStreamDuringAds) {
570
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
566
571
  if (video.paused) {
567
572
  console.log("[IMA] Resuming paused video after loader error");
568
573
  video.play().catch(() => {
@@ -584,14 +589,15 @@ function createImaController(video, options) {
584
589
  return adsLoadedPromise;
585
590
  } catch (error) {
586
591
  console.error("[IMA] Failed to request ads:", error);
587
- currentReject?.(error);
592
+ currentReject == null ? void 0 : currentReject(error);
588
593
  adsLoadedReject = void 0;
589
594
  adsLoadedResolve = void 0;
590
595
  return Promise.reject(error);
591
596
  }
592
597
  },
593
598
  async play() {
594
- if (!window.google?.ima || !adDisplayContainer) {
599
+ var _a, _b;
600
+ if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
595
601
  console.warn(
596
602
  "[IMA] Cannot play ad: IMA SDK or ad container not available"
597
603
  );
@@ -613,14 +619,15 @@ function createImaController(video, options) {
613
619
  } catch (error) {
614
620
  console.error("[IMA] Error starting ad playback:", error);
615
621
  adPlaying = false;
616
- if (!options?.continueLiveStreamDuringAds) {
617
- video.play()?.catch(() => {
622
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
623
+ (_b = video.play()) == null ? void 0 : _b.catch(() => {
618
624
  });
619
625
  }
620
626
  return Promise.reject(error);
621
627
  }
622
628
  },
623
629
  async stop() {
630
+ var _a;
624
631
  adPlaying = false;
625
632
  video.muted = originalMutedState;
626
633
  if (adContainerEl) {
@@ -629,11 +636,11 @@ function createImaController(video, options) {
629
636
  console.log("[IMA] Ad container hidden after stop");
630
637
  }
631
638
  try {
632
- adsManager?.stop?.();
639
+ (_a = adsManager == null ? void 0 : adsManager.stop) == null ? void 0 : _a.call(adsManager);
633
640
  } catch {
634
641
  }
635
642
  destroyAdsManager();
636
- if (!options?.continueLiveStreamDuringAds) {
643
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
637
644
  video.play().catch(() => {
638
645
  });
639
646
  console.log("[IMA] Video resumed after stop (VOD mode)");
@@ -642,6 +649,7 @@ function createImaController(video, options) {
642
649
  }
643
650
  },
644
651
  destroy() {
652
+ var _a;
645
653
  destroyAdsManager();
646
654
  adPlaying = false;
647
655
  video.muted = originalMutedState;
@@ -650,10 +658,10 @@ function createImaController(video, options) {
650
658
  adContainerEl.style.display = "none";
651
659
  }
652
660
  try {
653
- adsLoader?.destroy?.();
661
+ (_a = adsLoader == null ? void 0 : adsLoader.destroy) == null ? void 0 : _a.call(adsLoader);
654
662
  } catch {
655
663
  }
656
- if (adContainerEl?.parentElement) {
664
+ if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
657
665
  adContainerEl.parentElement.removeChild(adContainerEl);
658
666
  }
659
667
  adContainerEl = void 0;
@@ -664,7 +672,8 @@ function createImaController(video, options) {
664
672
  return adPlaying;
665
673
  },
666
674
  resize(width, height) {
667
- if (!adsManager || !window.google?.ima) {
675
+ var _a;
676
+ if (!adsManager || !((_a = window.google) == null ? void 0 : _a.ima)) {
668
677
  console.warn(
669
678
  "[IMA] Cannot resize: No ads manager or IMA SDK available"
670
679
  );
@@ -682,7 +691,8 @@ function createImaController(video, options) {
682
691
  listeners.get(event).add(listener);
683
692
  },
684
693
  off(event, listener) {
685
- listeners.get(event)?.delete(listener);
694
+ var _a;
695
+ (_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
686
696
  },
687
697
  updateOriginalMutedState(muted) {
688
698
  originalMutedState = muted;
@@ -719,7 +729,8 @@ function createHlsAdPlayer(contentVideo, options) {
719
729
  let adPlaying = false;
720
730
  let originalMutedState = false;
721
731
  const listeners = /* @__PURE__ */ new Map();
722
- const licenseKey = options?.licenseKey;
732
+ const licenseKey = options == null ? void 0 : options.licenseKey;
733
+ const mainHlsInstance = options == null ? void 0 : options.mainHlsInstance;
723
734
  let adVideoElement;
724
735
  let adHls;
725
736
  let adContainerEl;
@@ -766,7 +777,74 @@ function createHlsAdPlayer(contentVideo, options) {
766
777
  }
767
778
  });
768
779
  }
780
+ function getMainStreamQuality() {
781
+ if (!mainHlsInstance || !mainHlsInstance.levels) {
782
+ return null;
783
+ }
784
+ const currentLevel = mainHlsInstance.currentLevel;
785
+ if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {
786
+ const autoLevel = mainHlsInstance.loadLevel;
787
+ if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {
788
+ const level2 = mainHlsInstance.levels[autoLevel];
789
+ return {
790
+ width: level2.width || 1920,
791
+ height: level2.height || 1080,
792
+ bitrate: level2.bitrate || 5e6
793
+ };
794
+ }
795
+ return null;
796
+ }
797
+ const level = mainHlsInstance.levels[currentLevel];
798
+ return {
799
+ width: level.width || 1920,
800
+ height: level.height || 1080,
801
+ bitrate: level.bitrate || 5e6
802
+ };
803
+ }
804
+ function selectBestMediaFile(mediaFiles) {
805
+ if (mediaFiles.length === 0) {
806
+ throw new Error("No media files available");
807
+ }
808
+ const firstFile = mediaFiles[0];
809
+ if (!firstFile) {
810
+ throw new Error("No media files available");
811
+ }
812
+ if (mediaFiles.length === 1) {
813
+ return firstFile;
814
+ }
815
+ const mainQuality = getMainStreamQuality();
816
+ if (!mainQuality) {
817
+ console.log("[HlsAdPlayer] No main stream quality info, using first media file");
818
+ return firstFile;
819
+ }
820
+ console.log("[HlsAdPlayer] Main stream quality:", mainQuality);
821
+ const scoredFiles = mediaFiles.map((file) => {
822
+ const widthDiff = Math.abs(file.width - mainQuality.width);
823
+ const heightDiff = Math.abs(file.height - mainQuality.height);
824
+ const resolutionDiff = widthDiff + heightDiff;
825
+ const fileBitrate = (file.bitrate || 5e3) * 1e3;
826
+ const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);
827
+ const score = resolutionDiff * 2 + bitrateDiff / 1e3;
828
+ return { file, score, resolutionDiff, bitrateDiff };
829
+ });
830
+ scoredFiles.sort((a, b) => a.score - b.score);
831
+ const bestMatch = scoredFiles[0];
832
+ if (!bestMatch) {
833
+ console.log("[HlsAdPlayer] No best match found, using first media file");
834
+ return firstFile;
835
+ }
836
+ console.log("[HlsAdPlayer] Selected media file:", {
837
+ url: bestMatch.file.url,
838
+ resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,
839
+ bitrate: bestMatch.file.bitrate,
840
+ score: bestMatch.score,
841
+ resolutionDiff: bestMatch.resolutionDiff,
842
+ bitrateDiff: bestMatch.bitrateDiff
843
+ });
844
+ return bestMatch.file;
845
+ }
769
846
  function parseVastXml(xmlString) {
847
+ var _a, _b, _c, _d;
770
848
  try {
771
849
  const parser = new DOMParser();
772
850
  const xmlDoc = parser.parseFromString(xmlString, "text/xml");
@@ -781,19 +859,20 @@ function createHlsAdPlayer(contentVideo, options) {
781
859
  return null;
782
860
  }
783
861
  const adId = adElement.getAttribute("id") || "unknown";
784
- const title = xmlDoc.querySelector("AdTitle")?.textContent || "Ad";
785
- const durationText = xmlDoc.querySelector("Duration")?.textContent || "00:00:30";
862
+ const title = ((_a = xmlDoc.querySelector("AdTitle")) == null ? void 0 : _a.textContent) || "Ad";
863
+ const durationText = ((_b = xmlDoc.querySelector("Duration")) == null ? void 0 : _b.textContent) || "00:00:30";
786
864
  const durationParts = durationText.split(":");
787
865
  const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
788
866
  const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
789
867
  const mediaFiles = [];
790
868
  mediaFileElements.forEach((mf) => {
869
+ var _a2;
791
870
  const type = mf.getAttribute("type") || "";
792
871
  if (type === "application/x-mpegURL" || type.includes("m3u8")) {
793
872
  const bitrateAttr = mf.getAttribute("bitrate");
794
873
  const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
795
874
  mediaFiles.push({
796
- url: mf.textContent?.trim() || "",
875
+ url: ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "",
797
876
  type,
798
877
  width: parseInt(mf.getAttribute("width") || "1920", 10),
799
878
  height: parseInt(mf.getAttribute("height") || "1080", 10),
@@ -822,12 +901,14 @@ function createHlsAdPlayer(contentVideo, options) {
822
901
  error: []
823
902
  };
824
903
  xmlDoc.querySelectorAll("Impression").forEach((el) => {
825
- const url = el.textContent?.trim();
904
+ var _a2;
905
+ const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
826
906
  if (url) trackingUrls.impression.push(url);
827
907
  });
828
908
  xmlDoc.querySelectorAll("Tracking").forEach((el) => {
909
+ var _a2;
829
910
  const event = el.getAttribute("event");
830
- const url = el.textContent?.trim();
911
+ const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
831
912
  if (event && url) {
832
913
  const eventKey = event;
833
914
  if (trackingUrls[eventKey]) {
@@ -835,7 +916,7 @@ function createHlsAdPlayer(contentVideo, options) {
835
916
  }
836
917
  }
837
918
  });
838
- const clickThrough = xmlDoc.querySelector("ClickThrough")?.textContent?.trim();
919
+ const clickThrough = (_d = (_c = xmlDoc.querySelector("ClickThrough")) == null ? void 0 : _c.textContent) == null ? void 0 : _d.trim();
839
920
  return {
840
921
  id: adId,
841
922
  title,
@@ -927,7 +1008,7 @@ function createHlsAdPlayer(contentVideo, options) {
927
1008
  adContainerEl.style.display = "none";
928
1009
  adContainerEl.style.pointerEvents = "none";
929
1010
  }
930
- if (!options?.continueLiveStreamDuringAds) {
1011
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
931
1012
  contentVideo.play().catch(() => {
932
1013
  });
933
1014
  console.log("[HlsAdPlayer] Content resumed (VOD mode)");
@@ -945,7 +1026,7 @@ function createHlsAdPlayer(contentVideo, options) {
945
1026
  adContainerEl.style.display = "none";
946
1027
  adContainerEl.style.pointerEvents = "none";
947
1028
  }
948
- if (!options?.continueLiveStreamDuringAds) {
1029
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
949
1030
  if (contentVideo.paused) {
950
1031
  contentVideo.play().catch(() => {
951
1032
  });
@@ -955,6 +1036,7 @@ function createHlsAdPlayer(contentVideo, options) {
955
1036
  }
956
1037
  return {
957
1038
  initialize() {
1039
+ var _a;
958
1040
  console.log("[HlsAdPlayer] Initializing");
959
1041
  if (!adContainerEl) {
960
1042
  const container = document.createElement("div");
@@ -969,7 +1051,7 @@ function createHlsAdPlayer(contentVideo, options) {
969
1051
  container.style.pointerEvents = "none";
970
1052
  container.style.zIndex = "2";
971
1053
  container.style.backgroundColor = "#000";
972
- contentVideo.parentElement?.appendChild(container);
1054
+ (_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
973
1055
  adContainerEl = container;
974
1056
  }
975
1057
  },
@@ -1011,7 +1093,7 @@ function createHlsAdPlayer(contentVideo, options) {
1011
1093
  try {
1012
1094
  if (!adVideoElement) {
1013
1095
  adVideoElement = createAdVideoElement();
1014
- adContainerEl?.appendChild(adVideoElement);
1096
+ adContainerEl == null ? void 0 : adContainerEl.appendChild(adVideoElement);
1015
1097
  setupAdEventListeners();
1016
1098
  }
1017
1099
  trackingFired = {
@@ -1022,7 +1104,7 @@ function createHlsAdPlayer(contentVideo, options) {
1022
1104
  thirdQuartile: false,
1023
1105
  complete: false
1024
1106
  };
1025
- if (!options?.continueLiveStreamDuringAds) {
1107
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
1026
1108
  contentVideo.pause();
1027
1109
  console.log("[HlsAdPlayer] Content paused (VOD mode)");
1028
1110
  } else {
@@ -1035,7 +1117,7 @@ function createHlsAdPlayer(contentVideo, options) {
1035
1117
  adContainerEl.style.pointerEvents = "auto";
1036
1118
  }
1037
1119
  emit("content_pause");
1038
- const mediaFile = currentAd.mediaFiles[0];
1120
+ const mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1039
1121
  if (!mediaFile) {
1040
1122
  throw new Error("No media file available for ad");
1041
1123
  }
@@ -1095,7 +1177,7 @@ function createHlsAdPlayer(contentVideo, options) {
1095
1177
  adVideoElement.pause();
1096
1178
  adVideoElement.src = "";
1097
1179
  }
1098
- if (!options?.continueLiveStreamDuringAds) {
1180
+ if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
1099
1181
  contentVideo.play().catch(() => {
1100
1182
  });
1101
1183
  }
@@ -1115,7 +1197,7 @@ function createHlsAdPlayer(contentVideo, options) {
1115
1197
  adVideoElement.remove();
1116
1198
  adVideoElement = void 0;
1117
1199
  }
1118
- if (adContainerEl?.parentElement) {
1200
+ if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
1119
1201
  adContainerEl.parentElement.removeChild(adContainerEl);
1120
1202
  }
1121
1203
  adContainerEl = void 0;
@@ -1141,7 +1223,8 @@ function createHlsAdPlayer(contentVideo, options) {
1141
1223
  listeners.get(event).add(listener);
1142
1224
  },
1143
1225
  off(event, listener) {
1144
- listeners.get(event)?.delete(listener);
1226
+ var _a;
1227
+ (_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
1145
1228
  },
1146
1229
  updateOriginalMutedState(muted) {
1147
1230
  originalMutedState = muted;
@@ -1166,6 +1249,7 @@ function createHlsAdPlayer(contentVideo, options) {
1166
1249
  // src/utils/tracking.ts
1167
1250
  var cachedBrowserId = null;
1168
1251
  function getClientInfo() {
1252
+ var _a, _b, _c, _d;
1169
1253
  const ua = navigator.userAgent;
1170
1254
  const platform = navigator.platform;
1171
1255
  const vendor = navigator.vendor || "";
@@ -1173,12 +1257,12 @@ function getClientInfo() {
1173
1257
  const memory = navigator.deviceMemory || null;
1174
1258
  const hardwareConcurrency = navigator.hardwareConcurrency || 1;
1175
1259
  const screenInfo = {
1176
- width: screen?.width,
1177
- height: screen?.height,
1178
- availWidth: screen?.availWidth,
1179
- availHeight: screen?.availHeight,
1180
- orientation: screen?.orientation?.type || "",
1181
- pixelDepth: screen?.pixelDepth
1260
+ width: screen == null ? void 0 : screen.width,
1261
+ height: screen == null ? void 0 : screen.height,
1262
+ availWidth: screen == null ? void 0 : screen.availWidth,
1263
+ availHeight: screen == null ? void 0 : screen.availHeight,
1264
+ orientation: ((_a = screen == null ? void 0 : screen.orientation) == null ? void 0 : _a.type) || "",
1265
+ pixelDepth: screen == null ? void 0 : screen.pixelDepth
1182
1266
  };
1183
1267
  let deviceType = "desktop";
1184
1268
  let brand = "Unknown";
@@ -1275,10 +1359,10 @@ function getClientInfo() {
1275
1359
  if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
1276
1360
  }
1277
1361
  isWebView = /wv|WebView|Linux; U;/.test(ua);
1278
- if (window?.outerHeight === 0 && window?.outerWidth === 0) {
1362
+ if ((window == null ? void 0 : window.outerHeight) === 0 && (window == null ? void 0 : window.outerWidth) === 0) {
1279
1363
  isWebView = true;
1280
1364
  }
1281
- isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || window.screen?.orientation?.angle !== void 0;
1365
+ 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;
1282
1366
  return {
1283
1367
  brand,
1284
1368
  os,
@@ -1299,7 +1383,7 @@ function getClientInfo() {
1299
1383
  deviceMemory: memory,
1300
1384
  maxTouchPoints,
1301
1385
  language: navigator.language,
1302
- languages: navigator.languages?.join(",") || "",
1386
+ languages: ((_d = navigator.languages) == null ? void 0 : _d.join(",")) || "",
1303
1387
  cookieEnabled: navigator.cookieEnabled,
1304
1388
  doNotTrack: navigator.doNotTrack || "",
1305
1389
  referrer: document.referrer,
@@ -1657,7 +1741,8 @@ var StormcloudVideoPlayer = class {
1657
1741
  }
1658
1742
  return createHlsAdPlayer(this.video, {
1659
1743
  continueLiveStreamDuringAds,
1660
- ...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {}
1744
+ ...this.config.licenseKey ? { licenseKey: this.config.licenseKey } : {},
1745
+ ...this.hls ? { mainHlsInstance: this.hls } : {}
1661
1746
  });
1662
1747
  } else {
1663
1748
  if (this.config.debugAdTiming) {
@@ -1669,6 +1754,7 @@ var StormcloudVideoPlayer = class {
1669
1754
  }
1670
1755
  }
1671
1756
  async load() {
1757
+ var _a, _b;
1672
1758
  if (!this.attached) {
1673
1759
  this.attach();
1674
1760
  }
@@ -1685,7 +1771,7 @@ var StormcloudVideoPlayer = class {
1685
1771
  this.initializeTracking();
1686
1772
  if (this.shouldUseNativeHls()) {
1687
1773
  this.video.src = this.config.src;
1688
- this.isLiveStream = this.config.lowLatencyMode ?? false;
1774
+ this.isLiveStream = (_a = this.config.lowLatencyMode) != null ? _a : false;
1689
1775
  if (this.config.debugAdTiming) {
1690
1776
  console.log(
1691
1777
  "[StormcloudVideoPlayer] allowNativeHls: true - VOD mode detected:",
@@ -1700,8 +1786,8 @@ var StormcloudVideoPlayer = class {
1700
1786
  this.ima = this.createAdPlayer(false);
1701
1787
  this.ima.initialize();
1702
1788
  if (this.config.autoplay) {
1703
- await this.video.play()?.catch(() => {
1704
- });
1789
+ await ((_b = this.video.play()) == null ? void 0 : _b.catch(() => {
1790
+ }));
1705
1791
  }
1706
1792
  return;
1707
1793
  }
@@ -1714,12 +1800,17 @@ var StormcloudVideoPlayer = class {
1714
1800
  ...this.config.lowLatencyMode ? { liveSyncDuration: 2 } : {}
1715
1801
  });
1716
1802
  this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, () => {
1717
- this.hls?.loadSource(this.config.src);
1803
+ var _a2;
1804
+ (_a2 = this.hls) == null ? void 0 : _a2.loadSource(this.config.src);
1718
1805
  });
1719
1806
  this.hls.on(import_hls2.default.Events.MANIFEST_PARSED, async (_, data) => {
1720
- this.isLiveStream = this.hls?.levels?.some(
1721
- (level) => level?.details?.live === true || level?.details?.type === "LIVE"
1722
- ) ?? false;
1807
+ var _a2, _b2, _c, _d;
1808
+ this.isLiveStream = (_c = (_b2 = (_a2 = this.hls) == null ? void 0 : _a2.levels) == null ? void 0 : _b2.some(
1809
+ (level) => {
1810
+ var _a3, _b3;
1811
+ 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";
1812
+ }
1813
+ )) != null ? _c : false;
1723
1814
  if (this.config.debugAdTiming) {
1724
1815
  const adBehavior = this.shouldContinueLiveStreamDuringAds() ? "live (main video continues muted during ads)" : "vod (main video pauses during ads)";
1725
1816
  console.log("[StormcloudVideoPlayer] Stream type detected:", {
@@ -1732,28 +1823,29 @@ var StormcloudVideoPlayer = class {
1732
1823
  this.ima = this.createAdPlayer(this.shouldContinueLiveStreamDuringAds());
1733
1824
  this.ima.initialize();
1734
1825
  if (this.config.autoplay) {
1735
- await this.video.play()?.catch(() => {
1736
- });
1826
+ await ((_d = this.video.play()) == null ? void 0 : _d.catch(() => {
1827
+ }));
1737
1828
  }
1738
1829
  });
1739
1830
  this.hls.on(import_hls2.default.Events.FRAG_PARSING_METADATA, (_evt, data) => {
1740
- const id3Tags = (data?.samples || []).map((s) => ({
1831
+ const id3Tags = ((data == null ? void 0 : data.samples) || []).map((s) => ({
1741
1832
  key: "ID3",
1742
- value: s?.data,
1743
- ptsSeconds: s?.pts
1833
+ value: s == null ? void 0 : s.data,
1834
+ ptsSeconds: s == null ? void 0 : s.pts
1744
1835
  }));
1745
1836
  id3Tags.forEach((tag) => this.onId3Tag(tag));
1746
1837
  });
1747
1838
  this.hls.on(import_hls2.default.Events.FRAG_CHANGED, (_evt, data) => {
1748
- const frag = data?.frag;
1749
- const tagList = frag?.tagList;
1839
+ var _a2, _b2, _c;
1840
+ const frag = data == null ? void 0 : data.frag;
1841
+ const tagList = frag == null ? void 0 : frag.tagList;
1750
1842
  if (!Array.isArray(tagList)) return;
1751
1843
  for (const entry of tagList) {
1752
1844
  let tag = "";
1753
1845
  let value = "";
1754
1846
  if (Array.isArray(entry)) {
1755
- tag = String(entry[0] ?? "");
1756
- value = String(entry[1] ?? "");
1847
+ tag = String((_a2 = entry[0]) != null ? _a2 : "");
1848
+ value = String((_b2 = entry[1]) != null ? _b2 : "");
1757
1849
  } else if (typeof entry === "string") {
1758
1850
  const idx = entry.indexOf(":");
1759
1851
  if (idx >= 0) {
@@ -1777,8 +1869,8 @@ var StormcloudVideoPlayer = class {
1777
1869
  const prog = this.parseCueOutCont(value);
1778
1870
  const marker = {
1779
1871
  type: "progress",
1780
- ...prog?.duration !== void 0 ? { durationSeconds: prog.duration } : {},
1781
- ...prog?.elapsed !== void 0 ? { ptsSeconds: prog.elapsed } : {},
1872
+ ...(prog == null ? void 0 : prog.duration) !== void 0 ? { durationSeconds: prog.duration } : {},
1873
+ ...(prog == null ? void 0 : prog.elapsed) !== void 0 ? { ptsSeconds: prog.elapsed } : {},
1782
1874
  raw: { tag, value }
1783
1875
  };
1784
1876
  this.onScte35Marker(marker);
@@ -1788,7 +1880,7 @@ var StormcloudVideoPlayer = class {
1788
1880
  const attrs = this.parseAttributeList(value);
1789
1881
  const hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
1790
1882
  const hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
1791
- const klass = String(attrs["CLASS"] ?? "");
1883
+ const klass = String((_c = attrs["CLASS"]) != null ? _c : "");
1792
1884
  const duration = this.toNumber(attrs["DURATION"]);
1793
1885
  if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
1794
1886
  const marker = {
@@ -1805,13 +1897,14 @@ var StormcloudVideoPlayer = class {
1805
1897
  }
1806
1898
  });
1807
1899
  this.hls.on(import_hls2.default.Events.ERROR, (_evt, data) => {
1808
- if (data?.fatal) {
1900
+ var _a2, _b2;
1901
+ if (data == null ? void 0 : data.fatal) {
1809
1902
  switch (data.type) {
1810
1903
  case import_hls2.default.ErrorTypes.NETWORK_ERROR:
1811
- this.hls?.startLoad();
1904
+ (_a2 = this.hls) == null ? void 0 : _a2.startLoad();
1812
1905
  break;
1813
1906
  case import_hls2.default.ErrorTypes.MEDIA_ERROR:
1814
- this.hls?.recoverMediaError();
1907
+ (_b2 = this.hls) == null ? void 0 : _b2.recoverMediaError();
1815
1908
  break;
1816
1909
  default:
1817
1910
  this.destroy();
@@ -1913,11 +2006,12 @@ var StormcloudVideoPlayer = class {
1913
2006
  }
1914
2007
  }
1915
2008
  parseScte35FromId3(tag) {
2009
+ var _a, _b, _c, _d;
1916
2010
  const text = this.decodeId3ValueToText(tag.value);
1917
2011
  if (!text) return void 0;
1918
2012
  const cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\r\n]*))?/i) || text.match(/CUE-OUT(?::([^\r\n]*))?/i);
1919
2013
  if (cueOutMatch) {
1920
- const arg = (cueOutMatch[1] ?? "").trim();
2014
+ const arg = ((_a = cueOutMatch[1]) != null ? _a : "").trim();
1921
2015
  const dur = this.parseCueOutDuration(arg);
1922
2016
  const marker = {
1923
2017
  type: "start",
@@ -1929,12 +2023,12 @@ var StormcloudVideoPlayer = class {
1929
2023
  }
1930
2024
  const cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\r\n]*)/i);
1931
2025
  if (cueOutContMatch) {
1932
- const arg = (cueOutContMatch[1] ?? "").trim();
2026
+ const arg = ((_b = cueOutContMatch[1]) != null ? _b : "").trim();
1933
2027
  const cont = this.parseCueOutCont(arg);
1934
2028
  const marker = {
1935
2029
  type: "progress",
1936
2030
  ...tag.ptsSeconds !== void 0 ? { ptsSeconds: tag.ptsSeconds } : {},
1937
- ...cont?.duration !== void 0 ? { durationSeconds: cont.duration } : {},
2031
+ ...(cont == null ? void 0 : cont.duration) !== void 0 ? { durationSeconds: cont.duration } : {},
1938
2032
  raw: { id3: text }
1939
2033
  };
1940
2034
  return marker;
@@ -1950,10 +2044,10 @@ var StormcloudVideoPlayer = class {
1950
2044
  }
1951
2045
  const daterangeMatch = text.match(/EXT-X-DATERANGE:([^\r\n]*)/i);
1952
2046
  if (daterangeMatch) {
1953
- const attrs = this.parseAttributeList(daterangeMatch[1] ?? "");
2047
+ const attrs = this.parseAttributeList((_c = daterangeMatch[1]) != null ? _c : "");
1954
2048
  const hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
1955
2049
  const hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
1956
- const klass = String(attrs["CLASS"] ?? "");
2050
+ const klass = String((_d = attrs["CLASS"]) != null ? _d : "");
1957
2051
  const duration = this.toNumber(attrs["DURATION"]);
1958
2052
  if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
1959
2053
  const marker = {
@@ -2010,6 +2104,7 @@ var StormcloudVideoPlayer = class {
2010
2104
  }
2011
2105
  }
2012
2106
  onScte35Marker(marker) {
2107
+ var _a, _b;
2013
2108
  if (this.config.debugAdTiming) {
2014
2109
  console.log("[StormcloudVideoPlayer] SCTE-35 marker detected:", {
2015
2110
  type: marker.type,
@@ -2025,7 +2120,7 @@ var StormcloudVideoPlayer = class {
2025
2120
  this.expectedAdBreakDurationMs = durationMs;
2026
2121
  this.currentAdBreakStartWallClockMs = Date.now();
2027
2122
  const isManifestMarker = this.isManifestBasedMarker(marker);
2028
- const forceImmediate = this.config.immediateManifestAds ?? true;
2123
+ const forceImmediate = (_a = this.config.immediateManifestAds) != null ? _a : true;
2029
2124
  if (this.config.debugAdTiming) {
2030
2125
  console.log("[StormcloudVideoPlayer] Ad start decision:", {
2031
2126
  isManifestMarker,
@@ -2042,7 +2137,7 @@ var StormcloudVideoPlayer = class {
2042
2137
  this.clearAdStartTimer();
2043
2138
  this.handleAdStart(marker);
2044
2139
  } else if (typeof marker.ptsSeconds === "number") {
2045
- const tol = this.config.driftToleranceMs ?? 1e3;
2140
+ const tol = (_b = this.config.driftToleranceMs) != null ? _b : 1e3;
2046
2141
  const nowMs = this.video.currentTime * 1e3;
2047
2142
  const estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
2048
2143
  const deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);
@@ -2152,12 +2247,13 @@ var StormcloudVideoPlayer = class {
2152
2247
  return void 0;
2153
2248
  }
2154
2249
  parseAttributeList(value) {
2250
+ var _a, _b, _c;
2155
2251
  const attrs = {};
2156
2252
  const regex = /([A-Z0-9-]+)=(("[^"]*")|([^",]*))(?:,|$)/gi;
2157
2253
  let match;
2158
2254
  while ((match = regex.exec(value)) !== null) {
2159
- const key = match[1] ?? "";
2160
- let rawVal = match[3] ?? match[4] ?? "";
2255
+ const key = (_a = match[1]) != null ? _a : "";
2256
+ let rawVal = (_c = (_b = match[3]) != null ? _b : match[4]) != null ? _c : "";
2161
2257
  if (rawVal.startsWith('"') && rawVal.endsWith('"')) {
2162
2258
  rawVal = rawVal.slice(1, -1);
2163
2259
  }
@@ -2321,6 +2417,7 @@ var StormcloudVideoPlayer = class {
2321
2417
  }
2322
2418
  }
2323
2419
  async fetchAdConfiguration() {
2420
+ var _a, _b, _c;
2324
2421
  const vastMode = this.config.vastMode || "default";
2325
2422
  if (this.config.debugAdTiming) {
2326
2423
  console.log(
@@ -2378,7 +2475,7 @@ var StormcloudVideoPlayer = class {
2378
2475
  return;
2379
2476
  }
2380
2477
  const data = await response.json();
2381
- const imaPayload = data.response?.ima?.["publisherdesk.ima"]?.payload;
2478
+ const imaPayload = (_c = (_b = (_a = data.response) == null ? void 0 : _a.ima) == null ? void 0 : _b["publisherdesk.ima"]) == null ? void 0 : _c.payload;
2382
2479
  if (imaPayload) {
2383
2480
  this.apiVastTagUrl = decodeURIComponent(imaPayload);
2384
2481
  if (this.config.debugAdTiming) {
@@ -2415,11 +2512,12 @@ var StormcloudVideoPlayer = class {
2415
2512
  return "other";
2416
2513
  }
2417
2514
  shouldShowNativeControls() {
2515
+ var _a, _b;
2418
2516
  const streamType = this.getStreamType();
2419
2517
  if (streamType === "other") {
2420
- return !(this.config.showCustomControls ?? false);
2518
+ return !((_a = this.config.showCustomControls) != null ? _a : false);
2421
2519
  }
2422
- return !!(this.config.allowNativeHls && !(this.config.showCustomControls ?? false));
2520
+ return !!(this.config.allowNativeHls && !((_b = this.config.showCustomControls) != null ? _b : false));
2423
2521
  }
2424
2522
  shouldContinueLiveStreamDuringAds() {
2425
2523
  if (this.config.allowNativeHls) {
@@ -2431,6 +2529,7 @@ var StormcloudVideoPlayer = class {
2431
2529
  return true;
2432
2530
  }
2433
2531
  async handleAdStart(_marker) {
2532
+ var _a;
2434
2533
  const scheduled = this.findCurrentOrNextBreak(
2435
2534
  this.video.currentTime * 1e3
2436
2535
  );
@@ -2481,17 +2580,18 @@ var StormcloudVideoPlayer = class {
2481
2580
  this.handleAdFailure();
2482
2581
  }
2483
2582
  }
2484
- if (this.expectedAdBreakDurationMs == null && scheduled?.durationMs != null) {
2583
+ if (this.expectedAdBreakDurationMs == null && (scheduled == null ? void 0 : scheduled.durationMs) != null) {
2485
2584
  this.expectedAdBreakDurationMs = scheduled.durationMs;
2486
- this.currentAdBreakStartWallClockMs = this.currentAdBreakStartWallClockMs ?? Date.now();
2585
+ this.currentAdBreakStartWallClockMs = (_a = this.currentAdBreakStartWallClockMs) != null ? _a : Date.now();
2487
2586
  this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
2488
2587
  }
2489
2588
  }
2490
2589
  findCurrentOrNextBreak(nowMs) {
2590
+ var _a;
2491
2591
  const schedule = [];
2492
2592
  let candidate;
2493
2593
  for (const b of schedule) {
2494
- const tol = this.config.driftToleranceMs ?? 1e3;
2594
+ const tol = (_a = this.config.driftToleranceMs) != null ? _a : 1e3;
2495
2595
  if (b.startTimeMs <= nowMs + tol && (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))) {
2496
2596
  candidate = b;
2497
2597
  }
@@ -2507,7 +2607,8 @@ var StormcloudVideoPlayer = class {
2507
2607
  }
2508
2608
  }
2509
2609
  async handleMidAdJoin(adBreak, nowMs) {
2510
- const durationMs = adBreak.durationMs ?? 0;
2610
+ var _a;
2611
+ const durationMs = (_a = adBreak.durationMs) != null ? _a : 0;
2511
2612
  const endMs = adBreak.startTimeMs + durationMs;
2512
2613
  if (durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs) {
2513
2614
  const remainingMs = endMs - nowMs;
@@ -2608,6 +2709,7 @@ var StormcloudVideoPlayer = class {
2608
2709
  }
2609
2710
  }
2610
2711
  handleAdFailure() {
2712
+ var _a;
2611
2713
  if (this.config.debugAdTiming) {
2612
2714
  console.log(
2613
2715
  "[StormcloudVideoPlayer] Handling ad failure - resuming content",
@@ -2640,7 +2742,7 @@ var StormcloudVideoPlayer = class {
2640
2742
  if (this.config.debugAdTiming) {
2641
2743
  console.log("[StormcloudVideoPlayer] Resuming paused video");
2642
2744
  }
2643
- this.video.play()?.catch((error) => {
2745
+ (_a = this.video.play()) == null ? void 0 : _a.catch((error) => {
2644
2746
  if (this.config.debugAdTiming) {
2645
2747
  console.error(
2646
2748
  "[StormcloudVideoPlayer] Failed to resume video after ad failure:",
@@ -2655,8 +2757,9 @@ var StormcloudVideoPlayer = class {
2655
2757
  }
2656
2758
  }
2657
2759
  startAdFailsafeTimer() {
2760
+ var _a;
2658
2761
  this.clearAdFailsafeTimer();
2659
- const failsafeMs = this.config.adFailsafeTimeoutMs ?? 1e4;
2762
+ const failsafeMs = (_a = this.config.adFailsafeTimeoutMs) != null ? _a : 1e4;
2660
2763
  if (this.config.debugAdTiming) {
2661
2764
  console.log(
2662
2765
  `[StormcloudVideoPlayer] Starting failsafe timer (${failsafeMs}ms)`
@@ -2792,6 +2895,7 @@ var StormcloudVideoPlayer = class {
2792
2895
  }
2793
2896
  }
2794
2897
  destroy() {
2898
+ var _a, _b;
2795
2899
  this.clearAdStartTimer();
2796
2900
  this.clearAdStopTimer();
2797
2901
  this.clearAdFailsafeTimer();
@@ -2799,8 +2903,8 @@ var StormcloudVideoPlayer = class {
2799
2903
  clearInterval(this.heartbeatInterval);
2800
2904
  this.heartbeatInterval = void 0;
2801
2905
  }
2802
- this.hls?.destroy();
2803
- this.ima?.destroy();
2906
+ (_a = this.hls) == null ? void 0 : _a.destroy();
2907
+ (_b = this.ima) == null ? void 0 : _b.destroy();
2804
2908
  }
2805
2909
  };
2806
2910
  // Annotate the CommonJS export names for ESM import in node: