stormcloud-video-player 0.8.55 → 0.8.56

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.
Files changed (56) hide show
  1. package/dist/stormcloud-vp.min.js +2 -2
  2. package/lib/index.cjs +222 -82
  3. package/lib/index.cjs.map +1 -1
  4. package/lib/index.d.cts +0 -1
  5. package/lib/index.d.ts +0 -1
  6. package/lib/index.js +222 -82
  7. package/lib/index.js.map +1 -1
  8. package/lib/player/AdBreakOrchestrator.cjs +27 -29
  9. package/lib/player/AdBreakOrchestrator.cjs.map +1 -1
  10. package/lib/player/AdBreakOrchestrator.d.cts +1 -1
  11. package/lib/player/AdConfigManager.cjs +3 -14
  12. package/lib/player/AdConfigManager.cjs.map +1 -1
  13. package/lib/player/AdConfigManager.d.cts +1 -1
  14. package/lib/player/AdTimingService.d.cts +1 -1
  15. package/lib/player/HlsEngine.cjs.map +1 -1
  16. package/lib/player/HlsEngine.d.cts +1 -1
  17. package/lib/player/PlaceholderLayer.cjs.map +1 -1
  18. package/lib/player/PlayerControls.cjs.map +1 -1
  19. package/lib/player/PlayerControls.d.cts +1 -1
  20. package/lib/player/Scte35CueManager.cjs.map +1 -1
  21. package/lib/player/Scte35CueManager.d.cts +1 -1
  22. package/lib/player/Scte35Parser.cjs.map +1 -1
  23. package/lib/player/Scte35Parser.d.cts +1 -1
  24. package/lib/player/StormcloudVideoPlayer.cjs +222 -82
  25. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  26. package/lib/player/StormcloudVideoPlayer.d.cts +1 -1
  27. package/lib/player/playerTypes.cjs.map +1 -1
  28. package/lib/player/playerTypes.d.cts +1 -1
  29. package/lib/players/HlsPlayer.cjs +222 -82
  30. package/lib/players/HlsPlayer.cjs.map +1 -1
  31. package/lib/players/HlsPlayer.d.cts +1 -1
  32. package/lib/players/index.cjs +222 -82
  33. package/lib/players/index.cjs.map +1 -1
  34. package/lib/sdk/hlsAdPlayer.cjs +194 -52
  35. package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
  36. package/lib/sdk/hlsAdPlayer.d.cts +1 -1
  37. package/lib/{types-DpbgEvSH.d.cts → types-cTqIKw_D.d.cts} +0 -1
  38. package/lib/ui/StormcloudVideoPlayer.cjs +222 -82
  39. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  40. package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
  41. package/lib/utils/browserCompat.cjs.map +1 -1
  42. package/lib/utils/ctvVastSignals.cjs.map +1 -1
  43. package/lib/utils/devUrl.cjs.map +1 -1
  44. package/lib/utils/mqttClient.cjs.map +1 -1
  45. package/lib/utils/polyfills.cjs.map +1 -1
  46. package/lib/utils/tracking.cjs +7 -19
  47. package/lib/utils/tracking.cjs.map +1 -1
  48. package/lib/utils/tracking.d.cts +1 -1
  49. package/lib/utils/vastEnvironmentSignals.cjs +0 -4
  50. package/lib/utils/vastEnvironmentSignals.cjs.map +1 -1
  51. package/lib/utils/vastEnvironmentSignals.d.cts +1 -2
  52. package/lib/utils/vastMacros.cjs.map +1 -1
  53. package/lib/utils/vastTrackingMacros.cjs +185 -0
  54. package/lib/utils/vastTrackingMacros.cjs.map +1 -0
  55. package/lib/utils/vastTrackingMacros.d.cts +19 -0
  56. package/package.json +1 -1
package/lib/index.cjs CHANGED
@@ -780,15 +780,147 @@ function supportsFeature(feature) {
780
780
  return false;
781
781
  }
782
782
  }
783
+ // src/utils/vastTrackingMacros.ts
784
+ var VAST_MACRO_PATTERN = /\[([A-Z][A-Z0-9_]*)\]/g;
785
+ var CACHEBUSTING_ALIASES = /\[CACHEBUSTER\]|\[cachebuster\]|\[timestamp\]|\[random\]|\[INSERT_RANDOM_NUMBER\]|%%CACHEBUSTER%%|%%CACHEBUST%%|\$\{CACHEBUSTER\}|\$\{CACHEBUSTING\}|\{cachebuster\}|\{random\}/g;
786
+ var KNOWN_VAST_MACROS = /* @__PURE__ */ new Set([
787
+ "ADCATEGORIES",
788
+ "ADCOUNT",
789
+ "ADPLAYHEAD",
790
+ "ADSERVINGID",
791
+ "ADTYPE",
792
+ "APIFRAMEWORKS",
793
+ "APPBUNDLE",
794
+ "ASSETURI",
795
+ "BLOCKEDADCATEGORIES",
796
+ "BREAKMAXADLENGTH",
797
+ "BREAKMAXADS",
798
+ "BREAKMAXDURATION",
799
+ "BREAKMINADLENGTH",
800
+ "BREAKPOSITION",
801
+ "CACHEBUSTING",
802
+ "CLICKPOS",
803
+ "CLICKTYPE",
804
+ "CLIENTUA",
805
+ "CONTENTID",
806
+ "CONTENTPLAYHEAD",
807
+ "CONTENTURI",
808
+ "DEVICEIP",
809
+ "DEVICEUA",
810
+ "DOMAIN",
811
+ "ERRORCODE",
812
+ "EXTENSIONS",
813
+ "GDPRCONSENT",
814
+ "IFA",
815
+ "IFATYPE",
816
+ "INVENTORYSTATE",
817
+ "LATLONG",
818
+ "LIMITADTRACKING",
819
+ "MEDIAMIME",
820
+ "MEDIAPLAYHEAD",
821
+ "OMIDPARTNER",
822
+ "PAGEURL",
823
+ "PLACEMENTTYPE",
824
+ "PLAYERCAPABILITIES",
825
+ "PLAYERSIZE",
826
+ "PLAYERSTATE",
827
+ "PODSEQUENCE",
828
+ "REGULATIONS",
829
+ "SERVERSIDE",
830
+ "SERVERUA",
831
+ "TIMESTAMP",
832
+ "TRANSACTIONID",
833
+ "UNIVERSALADID",
834
+ "VASTVERSIONS",
835
+ "VERIFICATIONVENDORS"
836
+ ]);
837
+ function generateCachebuster() {
838
+ return String(Math.floor(Math.random() * 9e7) + 1e7);
839
+ }
840
+ function formatPlayhead(seconds) {
841
+ if (seconds == null || !Number.isFinite(seconds) || seconds < 0) {
842
+ return void 0;
843
+ }
844
+ var total = Math.floor(seconds);
845
+ var hh = String(Math.floor(total / 3600)).padStart(2, "0");
846
+ var mm = String(Math.floor(total % 3600 / 60)).padStart(2, "0");
847
+ var ss = String(total % 60).padStart(2, "0");
848
+ var ms = String(Math.floor((seconds - total) * 1e3)).padStart(3, "0");
849
+ return "".concat(hh, ":").concat(mm, ":").concat(ss, ".").concat(ms);
850
+ }
851
+ function resolveMacroValues(ctx) {
852
+ var values = /* @__PURE__ */ new Map();
853
+ var set = function set(key, value) {
854
+ if (value != null && value !== "") values.set(key, value);
855
+ };
856
+ var adPlayhead = formatPlayhead(ctx.adPlayheadSeconds);
857
+ set("ADPLAYHEAD", adPlayhead);
858
+ set("MEDIAPLAYHEAD", adPlayhead);
859
+ set("CONTENTPLAYHEAD", formatPlayhead(ctx.contentPlayheadSeconds));
860
+ set("ASSETURI", ctx.assetUri);
861
+ set("MEDIAMIME", ctx.mediaMime);
862
+ set("TIMESTAMP", (/* @__PURE__ */ new Date()).toISOString());
863
+ set("SERVERSIDE", "0");
864
+ if (ctx.errorCode != null && ctx.errorCode !== "") {
865
+ set("ERRORCODE", String(ctx.errorCode));
866
+ }
867
+ if (ctx.playerWidth != null && ctx.playerHeight != null) {
868
+ set("PLAYERSIZE", "".concat(Math.round(ctx.playerWidth), ",").concat(Math.round(ctx.playerHeight)));
869
+ }
870
+ set("IFA", ctx.deviceId);
871
+ set("IFATYPE", ctx.deviceIdType);
872
+ if (ctx.limitAdTracking != null) {
873
+ set("LIMITADTRACKING", ctx.limitAdTracking ? "1" : "0");
874
+ }
875
+ set("PAGEURL", ctx.pageUrl);
876
+ if (ctx.pageUrl) {
877
+ try {
878
+ set("DOMAIN", new URL(ctx.pageUrl).hostname);
879
+ } catch (unused) {}
880
+ }
881
+ set("CLIENTUA", ctx.clientUa);
882
+ set("DEVICEUA", ctx.clientUa);
883
+ if (ctx.podSequence != null) {
884
+ set("PODSEQUENCE", String(ctx.podSequence));
885
+ }
886
+ return values;
887
+ }
888
+ function substituteVastTrackingMacros(url) {
889
+ var ctx = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
890
+ if (!url) return url;
891
+ var values = resolveMacroValues(ctx);
892
+ return url.replace(CACHEBUSTING_ALIASES, function() {
893
+ return generateCachebuster();
894
+ }).replace(VAST_MACRO_PATTERN, function(match, name) {
895
+ if (name === "CACHEBUSTING") return generateCachebuster();
896
+ var value = values.get(name);
897
+ if (value != null) return encodeURIComponent(value);
898
+ return KNOWN_VAST_MACROS.has(name) ? "" : match;
899
+ });
900
+ }
783
901
  // src/sdk/hlsAdPlayer.ts
784
902
  var MAX_VAST_WRAPPER_DEPTH = 5;
903
+ var BEACON_TIMEOUT_MS = 3e4;
904
+ var inFlightBeacons = /* @__PURE__ */ new Set();
905
+ var VAST_ERROR_MEDIA_DISPLAY = 405;
906
+ function toVastMediaErrorCode(error) {
907
+ switch(error === null || error === void 0 ? void 0 : error.code){
908
+ case 1:
909
+ return 400;
910
+ case 2:
911
+ return 401;
912
+ case 4:
913
+ return 403;
914
+ default:
915
+ return VAST_ERROR_MEDIA_DISPLAY;
916
+ }
917
+ }
785
918
  function createHlsAdPlayer(contentVideo, options) {
786
919
  var _contentVideo_AD_VIDEO_PROP, _contentVideo_AD_CONTAINER_PROP;
787
920
  var adPlaying = false;
788
921
  var originalMutedState = false;
789
922
  var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
790
923
  var listeners = /* @__PURE__ */ new Map();
791
- var licenseKey = options === null || options === void 0 ? void 0 : options.licenseKey;
792
924
  var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
793
925
  var AD_CONTAINER_PROP = "__stormcloudAdContainer";
794
926
  var AD_VIDEO_PROP = "__stormcloudAdVideo";
@@ -799,10 +931,9 @@ function createHlsAdPlayer(contentVideo, options) {
799
931
  var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
800
932
  var adEventHandlers = [];
801
933
  var currentAd;
802
- var currentAdMediaUrl;
934
+ var currentAdMediaFile;
803
935
  var podAds = [];
804
936
  var podIndex = 0;
805
- var sessionId;
806
937
  var preloadedAds = /* @__PURE__ */ new Map();
807
938
  var preloadingAds = /* @__PURE__ */ new Map();
808
939
  var destroyed = false;
@@ -852,21 +983,47 @@ function createHlsAdPlayer(contentVideo, options) {
852
983
  }
853
984
  }
854
985
  }
855
- function generateSessionId() {
856
- return "session-".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
986
+ function buildTrackingMacroContext(errorCode) {
987
+ var context = {
988
+ adPlayheadSeconds: adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.currentTime,
989
+ contentPlayheadSeconds: contentVideo.currentTime,
990
+ assetUri: currentAdMediaFile === null || currentAdMediaFile === void 0 ? void 0 : currentAdMediaFile.url,
991
+ mediaMime: currentAdMediaFile === null || currentAdMediaFile === void 0 ? void 0 : currentAdMediaFile.type,
992
+ playerWidth: (adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.clientWidth) || (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.clientWidth),
993
+ playerHeight: (adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.clientHeight) || (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.clientHeight)
994
+ };
995
+ if (errorCode != null) {
996
+ context.errorCode = errorCode;
997
+ }
998
+ if (typeof navigator !== "undefined" && navigator.userAgent) {
999
+ context.clientUa = navigator.userAgent;
1000
+ }
1001
+ if (typeof location !== "undefined" && location.href) {
1002
+ context.pageUrl = location.href;
1003
+ }
1004
+ if (podAds.length > 0) {
1005
+ context.podSequence = podIndex + 1;
1006
+ }
1007
+ return context;
857
1008
  }
858
- function fireTrackingPixels(urls) {
1009
+ function fireTrackingPixels(urls, options2) {
859
1010
  if (!urls || urls.length === 0) return;
1011
+ var macroContext = buildTrackingMacroContext(options2 === null || options2 === void 0 ? void 0 : options2.errorCode);
860
1012
  urls.forEach(function(url) {
861
1013
  try {
862
- var trackingUrl = url;
863
- if (sessionId) {
864
- trackingUrl = "".concat(trackingUrl).concat(trackingUrl.includes("?") ? "&" : "?", "session_id=").concat(sessionId);
865
- }
866
- if (licenseKey) {
867
- trackingUrl = "".concat(trackingUrl).concat(trackingUrl.includes("?") ? "&" : "?", "license_key=").concat(licenseKey);
868
- }
1014
+ var trackingUrl = substituteVastTrackingMacros(url, macroContext);
869
1015
  var img = new Image(1, 1);
1016
+ inFlightBeacons.add(img);
1017
+ var timeoutId;
1018
+ var release = function release() {
1019
+ if (timeoutId !== void 0) clearTimeout(timeoutId);
1020
+ img.onload = null;
1021
+ img.onerror = null;
1022
+ inFlightBeacons.delete(img);
1023
+ };
1024
+ img.onload = release;
1025
+ img.onerror = release;
1026
+ timeoutId = setTimeout(release, BEACON_TIMEOUT_MS);
870
1027
  img.src = trackingUrl;
871
1028
  console.log("[HlsAdPlayer] Fired tracking pixel: ".concat(trackingUrl));
872
1029
  } catch (error) {
@@ -1505,7 +1662,9 @@ function createHlsAdPlayer(contentVideo, options) {
1505
1662
  if (!adPlaying) return;
1506
1663
  console.error("[HlsAdPlayer] Ad video error:", e);
1507
1664
  if (currentAd) {
1508
- fireTrackingPixels(currentAd.trackingUrls.error);
1665
+ fireTrackingPixels(currentAd.trackingUrls.error, {
1666
+ errorCode: toVastMediaErrorCode(adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.error)
1667
+ });
1509
1668
  }
1510
1669
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1511
1670
  return;
@@ -1617,9 +1776,9 @@ function createHlsAdPlayer(contentVideo, options) {
1617
1776
  delete contentVideo.dataset.stormcloudAdPlaying;
1618
1777
  }
1619
1778
  }
1620
- function resetQuartileTracking() {
1779
+ function resetQuartileTracking(preserveImpression) {
1621
1780
  trackingFired = {
1622
- impression: false,
1781
+ impression: preserveImpression ? trackingFired.impression : false,
1623
1782
  start: false,
1624
1783
  firstQuartile: false,
1625
1784
  midpoint: false,
@@ -1627,27 +1786,6 @@ function createHlsAdPlayer(contentVideo, options) {
1627
1786
  complete: false
1628
1787
  };
1629
1788
  }
1630
- function markCreativeRendered(reason) {
1631
- if (!currentAd || trackingFired.impression) return;
1632
- trackingFired.impression = true;
1633
- fireTrackingPixels(currentAd.trackingUrls.impression);
1634
- console.log("[HlsAdPlayer] Impression (pod ".concat(podIndex + 1, "/").concat(podAds.length || 1, ", reason: ").concat(reason, "): ").concat(currentAd.title));
1635
- emit("ad_impression", {
1636
- adId: currentAd.id,
1637
- title: currentAd.title,
1638
- durationSeconds: currentAd.duration,
1639
- mediaUrl: currentAdMediaUrl,
1640
- podIndex: podIndex,
1641
- podSize: podAds.length || 1,
1642
- reason: reason
1643
- });
1644
- }
1645
- function canDetectBlackFrames() {
1646
- if (!adVideoElement) return false;
1647
- if (requiresMediaPipelineResetAfterAds()) return false;
1648
- if (isRvfcSupported(adVideoElement)) return true;
1649
- return getDecodedVideoFrameCount(adVideoElement) !== void 0;
1650
- }
1651
1789
  function isRvfcSupported(video) {
1652
1790
  return typeof video.requestVideoFrameCallback === "function";
1653
1791
  }
@@ -1710,7 +1848,7 @@ function createHlsAdPlayer(contentVideo, options) {
1710
1848
  if (!mediaFile) {
1711
1849
  throw new Error("No media file available for ad");
1712
1850
  }
1713
- currentAdMediaUrl = mediaFile.url;
1851
+ currentAdMediaFile = mediaFile;
1714
1852
  var isHlsAd = isHlsMediaFile(mediaFile);
1715
1853
  console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad (pod ").concat(podIndex + 1, "/").concat(podAds.length || 1, ") from: ").concat(mediaFile.url));
1716
1854
  if (isHlsAd && import_hls.default.isSupported()) {
@@ -1754,9 +1892,11 @@ function createHlsAdPlayer(contentVideo, options) {
1754
1892
  }
1755
1893
  podIndex++;
1756
1894
  currentAd = podAds[podIndex];
1757
- currentAdMediaUrl = void 0;
1758
- resetQuartileTracking();
1895
+ currentAdMediaFile = void 0;
1896
+ resetQuartileTracking(false);
1759
1897
  if (currentAd) {
1898
+ fireTrackingPixels(currentAd.trackingUrls.impression);
1899
+ trackingFired.impression = true;
1760
1900
  console.log("[HlsAdPlayer] Advancing to next pod ad (".concat(podIndex + 1, "/").concat(podAds.length, "): ").concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1761
1901
  }
1762
1902
  clearStallWatchdog();
@@ -1795,7 +1935,9 @@ function createHlsAdPlayer(contentVideo, options) {
1795
1935
  console.warn("[HlsAdPlayer] Ad playback stalled (no progress) - recovering to avoid a blank frame");
1796
1936
  clearStallWatchdog();
1797
1937
  if (currentAd) {
1798
- fireTrackingPixels(currentAd.trackingUrls.error);
1938
+ fireTrackingPixels(currentAd.trackingUrls.error, {
1939
+ errorCode: VAST_ERROR_MEDIA_DISPLAY
1940
+ });
1799
1941
  }
1800
1942
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1801
1943
  return;
@@ -1851,7 +1993,6 @@ function createHlsAdPlayer(contentVideo, options) {
1851
1993
  if (!adPlaying) return;
1852
1994
  sawDecodedVideoFrame = true;
1853
1995
  markRvfcReliable();
1854
- markCreativeRendered("first_presented_frame");
1855
1996
  };
1856
1997
  try {
1857
1998
  videoFrameCallbackHandle = rvfc.call(adVideoElement, onPresentedFrame);
@@ -1864,7 +2005,9 @@ function createHlsAdPlayer(contentVideo, options) {
1864
2005
  console.warn("[HlsAdPlayer] Ad audio is advancing but no video frames decoded (black screen) - skipping this creative");
1865
2006
  clearStallWatchdog();
1866
2007
  if (currentAd) {
1867
- fireTrackingPixels(currentAd.trackingUrls.error);
2008
+ fireTrackingPixels(currentAd.trackingUrls.error, {
2009
+ errorCode: VAST_ERROR_MEDIA_DISPLAY
2010
+ });
1868
2011
  }
1869
2012
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1870
2013
  return;
@@ -1886,7 +2029,6 @@ function createHlsAdPlayer(contentVideo, options) {
1886
2029
  if (decodedFrames !== void 0 && decodedFrames > 0) {
1887
2030
  sawDecodedVideoFrame = true;
1888
2031
  markFrameCounterReliable();
1889
- markCreativeRendered("decoded_frames");
1890
2032
  } else if (adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S) {
1891
2033
  var timeAdvancing = adVideoElement.currentTime > lastAdProgressPosition + 0.05;
1892
2034
  if (isRvfcSupported(adVideoElement) && timeAdvancing && isRvfcReliable()) {
@@ -1899,9 +2041,6 @@ function createHlsAdPlayer(contentVideo, options) {
1899
2041
  }
1900
2042
  }
1901
2043
  }
1902
- if (!trackingFired.impression && !adVideoElement.paused && adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S && (sawDecodedVideoFrame || !canDetectBlackFrames())) {
1903
- markCreativeRendered(sawDecodedVideoFrame ? "decoded_frames" : "sustained_playback");
1904
- }
1905
2044
  if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
1906
2045
  noteAdProgress();
1907
2046
  return;
@@ -2002,7 +2141,6 @@ function createHlsAdPlayer(contentVideo, options) {
2002
2141
  ,
2003
2142
  6
2004
2143
  ]);
2005
- sessionId = generateSessionId();
2006
2144
  ads = [];
2007
2145
  if (!preloadedAds.has(vastTagUrl)) return [
2008
2146
  3,
@@ -2040,9 +2178,12 @@ function createHlsAdPlayer(contentVideo, options) {
2040
2178
  podAds = ads;
2041
2179
  podIndex = 0;
2042
2180
  currentAd = ads[0];
2043
- currentAdMediaUrl = void 0;
2044
- resetQuartileTracking();
2181
+ currentAdMediaFile = void 0;
2045
2182
  console.log("[HlsAdPlayer] Pod parsed: ".concat(ads.length, ' ad(s), first="').concat(currentAd === null || currentAd === void 0 ? void 0 : currentAd.title, '", duration=').concat(currentAd === null || currentAd === void 0 ? void 0 : currentAd.duration, "s"));
2183
+ if (currentAd) {
2184
+ fireTrackingPixels(currentAd.trackingUrls.impression);
2185
+ trackingFired.impression = true;
2186
+ }
2046
2187
  return [
2047
2188
  2,
2048
2189
  Promise.resolve()
@@ -2082,7 +2223,7 @@ function createHlsAdPlayer(contentVideo, options) {
2082
2223
  contentVideo[AD_VIDEO_PROP] = adVideoElement;
2083
2224
  }
2084
2225
  setupAdEventListeners();
2085
- resetQuartileTracking();
2226
+ resetQuartileTracking(true);
2086
2227
  contentVolume = contentVideo.volume;
2087
2228
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
2088
2229
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -2172,7 +2313,7 @@ function createHlsAdPlayer(contentVideo, options) {
2172
2313
  }
2173
2314
  }
2174
2315
  currentAd = void 0;
2175
- currentAdMediaUrl = void 0;
2316
+ currentAdMediaFile = void 0;
2176
2317
  podAds = [];
2177
2318
  podIndex = 0;
2178
2319
  return [
@@ -2213,6 +2354,7 @@ function createHlsAdPlayer(contentVideo, options) {
2213
2354
  teardownAdEventListeners();
2214
2355
  releaseAdDecoder();
2215
2356
  currentAd = void 0;
2357
+ currentAdMediaFile = void 0;
2216
2358
  podAds = [];
2217
2359
  podIndex = 0;
2218
2360
  listeners.clear();
@@ -3527,19 +3669,8 @@ function buildPlayerMetricEvent() {
3527
3669
  }).apply(this, arguments);
3528
3670
  }
3529
3671
  function publishTracking(licenseKey, channel, body) {
3530
- var debug = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : false;
3531
3672
  ensureMQTTClient();
3532
- var topic = buildPlayerTopic(licenseKey, channel);
3533
- var published = publishMQTT(topic, body);
3534
- if (debug) {
3535
- console.log("[StormcloudVideoPlayer] publishTracking:", JSON.stringify({
3536
- licenseKey: licenseKey,
3537
- channel: channel,
3538
- topic: topic,
3539
- body: body,
3540
- published: published
3541
- }, null, 2));
3542
- }
3673
+ publishMQTT(buildPlayerTopic(licenseKey, channel), body);
3543
3674
  }
3544
3675
  function sendInitialTracking(_0) {
3545
3676
  return _async_to_generator(function(licenseKey) {
@@ -3573,7 +3704,7 @@ function sendInitialTracking(_0) {
3573
3704
  events: [
3574
3705
  metricEvent
3575
3706
  ]
3576
- }, !!context.debugAdTiming);
3707
+ });
3577
3708
  return [
3578
3709
  3,
3579
3710
  4
@@ -3683,7 +3814,7 @@ function sendAdLoadedTracking(_0, _1) {
3683
3814
  }
3684
3815
  function sendAdImpressionTracking(_0, _1) {
3685
3816
  return _async_to_generator(function(licenseKey, adImpressionInfo) {
3686
- var context, _adImpressionInfo_adUrl, metricEvent, error;
3817
+ var context, metricEvent, error;
3687
3818
  var _arguments = arguments;
3688
3819
  return _ts_generator(this, function(_state) {
3689
3820
  switch(_state.label){
@@ -3708,18 +3839,17 @@ function sendAdImpressionTracking(_0, _1) {
3708
3839
  ];
3709
3840
  case 2:
3710
3841
  metricEvent = _state.sent();
3711
- publishTracking(licenseKey, "heartbeat", metricEvent, !!context.debugAdTiming);
3842
+ publishTracking(licenseKey, "heartbeat", metricEvent);
3712
3843
  publishTracking(licenseKey, "impressions", {
3713
3844
  events: [
3714
3845
  {
3715
- event_id: createUuid(),
3716
3846
  player_id: metricEvent.player_id,
3717
3847
  ad_played_count: 1,
3718
- ad_url: (_adImpressionInfo_adUrl = adImpressionInfo.adUrl) !== null && _adImpressionInfo_adUrl !== void 0 ? _adImpressionInfo_adUrl : adImpressionInfo.adId,
3848
+ ad_url: adImpressionInfo.adUrl,
3719
3849
  capture_at: adImpressionInfo.timestamp
3720
3850
  }
3721
3851
  ]
3722
- }, !!context.debugAdTiming);
3852
+ });
3723
3853
  return [
3724
3854
  3,
3725
3855
  4
@@ -3764,7 +3894,7 @@ function sendHeartbeat(_0) {
3764
3894
  ];
3765
3895
  case 2:
3766
3896
  heartbeatData = _state.sent();
3767
- publishTracking(licenseKey, "heartbeat", heartbeatData, !!context.debugAdTiming);
3897
+ publishTracking(licenseKey, "heartbeat", heartbeatData);
3768
3898
  return [
3769
3899
  3,
3770
3900
  4
@@ -7558,22 +7688,27 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7558
7688
  console.log("[POD] Playing pod ad ".concat((payload === null || payload === void 0 ? void 0 : payload.index) != null ? payload.index + 1 : "?", "/").concat((_ref = payload === null || payload === void 0 ? void 0 : payload.total) !== null && _ref !== void 0 ? _ref : "?"));
7559
7689
  }
7560
7690
  });
7561
- adPlayer.on("ad_impression", function(payload) {
7562
- var impressionInfo = {
7691
+ adPlayer.on("all_ads_completed", function() {
7692
+ sendAdImpressionTracking(_this.host.config.licenseKey, {
7563
7693
  source: "hls",
7564
7694
  adIndex: _this.timing.currentAdIndex,
7565
7695
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
7566
- };
7567
- if (payload === null || payload === void 0 ? void 0 : payload.adId) impressionInfo.adId = payload.adId;
7568
- if (payload === null || payload === void 0 ? void 0 : payload.mediaUrl) impressionInfo.adUrl = payload.mediaUrl;
7569
- if ((payload === null || payload === void 0 ? void 0 : payload.durationSeconds) != null) {
7570
- impressionInfo.durationSeconds = payload.durationSeconds;
7696
+ }, _this.analyticsContext).catch(function() {});
7697
+ _this.timing.recordPlayedAdDuration(_this.host.getAdPlayer());
7698
+ var remaining = _this.timing.getRemainingAdMs();
7699
+ _this.timing.consecutiveFailures = 0;
7700
+ if (_this.debug) {
7701
+ console.log("[StormcloudVideoPlayer] all_ads_completed event received - remaining=".concat(remaining, "ms, queued ads=").concat(_this.adRequestQueue.length), _this.adRequestQueue.length > 0 ? {
7702
+ queuedUrls: _to_consumable_array(_this.adRequestQueue)
7703
+ } : {});
7571
7704
  }
7572
- sendAdImpressionTracking(_this.host.config.licenseKey, impressionInfo, _this.analyticsContext).catch(function(error) {
7573
- if (_this.debug) {
7574
- console.warn("[AdBreakOrchestrator] Failed to send ad impression tracking:", error);
7705
+ if (_this.inAdBreak) {
7706
+ if (_this.timing.hasTimeToStartAnotherAd()) {
7707
+ _this.tryNextAvailableAdWithRateLimit();
7708
+ } else {
7709
+ _this.handleAdPodComplete();
7575
7710
  }
7576
- });
7711
+ }
7577
7712
  });
7578
7713
  adPlayer.on("ad_error", function(errorPayload) {
7579
7714
  var errorMessage = "Ad playback failed";
@@ -7616,6 +7751,11 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7616
7751
  }
7617
7752
  });
7618
7753
  adPlayer.on("content_resume", function() {
7754
+ sendAdImpressionTracking(_this.host.config.licenseKey, {
7755
+ source: "hls",
7756
+ adIndex: _this.timing.currentAdIndex,
7757
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
7758
+ }, _this.analyticsContext).catch(function() {});
7619
7759
  if (!_this.host.video.muted) {
7620
7760
  _this.host.video.muted = true;
7621
7761
  if (_this.debug) {