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
@@ -1,4 +1,4 @@
1
- import { A as AdController } from '../types-DpbgEvSH.cjs';
1
+ import { A as AdController } from '../types-cTqIKw_D.cjs';
2
2
  import Hls from 'hls.js';
3
3
 
4
4
  declare function createHlsAdPlayer(contentVideo: HTMLVideoElement, options?: {
@@ -125,7 +125,6 @@ interface AdLoadedInfo {
125
125
  interface AdImpressionInfo {
126
126
  source: "vast" | "hls";
127
127
  adIndex: number;
128
- adId?: string;
129
128
  adUrl?: string;
130
129
  durationSeconds?: number;
131
130
  timestamp: string;
@@ -557,15 +557,147 @@ function logBrowserInfo() {
557
557
  userAgent: navigator.userAgent
558
558
  }));
559
559
  }
560
+ // src/utils/vastTrackingMacros.ts
561
+ var VAST_MACRO_PATTERN = /\[([A-Z][A-Z0-9_]*)\]/g;
562
+ var CACHEBUSTING_ALIASES = /\[CACHEBUSTER\]|\[cachebuster\]|\[timestamp\]|\[random\]|\[INSERT_RANDOM_NUMBER\]|%%CACHEBUSTER%%|%%CACHEBUST%%|\$\{CACHEBUSTER\}|\$\{CACHEBUSTING\}|\{cachebuster\}|\{random\}/g;
563
+ var KNOWN_VAST_MACROS = /* @__PURE__ */ new Set([
564
+ "ADCATEGORIES",
565
+ "ADCOUNT",
566
+ "ADPLAYHEAD",
567
+ "ADSERVINGID",
568
+ "ADTYPE",
569
+ "APIFRAMEWORKS",
570
+ "APPBUNDLE",
571
+ "ASSETURI",
572
+ "BLOCKEDADCATEGORIES",
573
+ "BREAKMAXADLENGTH",
574
+ "BREAKMAXADS",
575
+ "BREAKMAXDURATION",
576
+ "BREAKMINADLENGTH",
577
+ "BREAKPOSITION",
578
+ "CACHEBUSTING",
579
+ "CLICKPOS",
580
+ "CLICKTYPE",
581
+ "CLIENTUA",
582
+ "CONTENTID",
583
+ "CONTENTPLAYHEAD",
584
+ "CONTENTURI",
585
+ "DEVICEIP",
586
+ "DEVICEUA",
587
+ "DOMAIN",
588
+ "ERRORCODE",
589
+ "EXTENSIONS",
590
+ "GDPRCONSENT",
591
+ "IFA",
592
+ "IFATYPE",
593
+ "INVENTORYSTATE",
594
+ "LATLONG",
595
+ "LIMITADTRACKING",
596
+ "MEDIAMIME",
597
+ "MEDIAPLAYHEAD",
598
+ "OMIDPARTNER",
599
+ "PAGEURL",
600
+ "PLACEMENTTYPE",
601
+ "PLAYERCAPABILITIES",
602
+ "PLAYERSIZE",
603
+ "PLAYERSTATE",
604
+ "PODSEQUENCE",
605
+ "REGULATIONS",
606
+ "SERVERSIDE",
607
+ "SERVERUA",
608
+ "TIMESTAMP",
609
+ "TRANSACTIONID",
610
+ "UNIVERSALADID",
611
+ "VASTVERSIONS",
612
+ "VERIFICATIONVENDORS"
613
+ ]);
614
+ function generateCachebuster() {
615
+ return String(Math.floor(Math.random() * 9e7) + 1e7);
616
+ }
617
+ function formatPlayhead(seconds) {
618
+ if (seconds == null || !Number.isFinite(seconds) || seconds < 0) {
619
+ return void 0;
620
+ }
621
+ var total = Math.floor(seconds);
622
+ var hh = String(Math.floor(total / 3600)).padStart(2, "0");
623
+ var mm = String(Math.floor(total % 3600 / 60)).padStart(2, "0");
624
+ var ss = String(total % 60).padStart(2, "0");
625
+ var ms = String(Math.floor((seconds - total) * 1e3)).padStart(3, "0");
626
+ return "".concat(hh, ":").concat(mm, ":").concat(ss, ".").concat(ms);
627
+ }
628
+ function resolveMacroValues(ctx) {
629
+ var values = /* @__PURE__ */ new Map();
630
+ var set = function set(key, value) {
631
+ if (value != null && value !== "") values.set(key, value);
632
+ };
633
+ var adPlayhead = formatPlayhead(ctx.adPlayheadSeconds);
634
+ set("ADPLAYHEAD", adPlayhead);
635
+ set("MEDIAPLAYHEAD", adPlayhead);
636
+ set("CONTENTPLAYHEAD", formatPlayhead(ctx.contentPlayheadSeconds));
637
+ set("ASSETURI", ctx.assetUri);
638
+ set("MEDIAMIME", ctx.mediaMime);
639
+ set("TIMESTAMP", (/* @__PURE__ */ new Date()).toISOString());
640
+ set("SERVERSIDE", "0");
641
+ if (ctx.errorCode != null && ctx.errorCode !== "") {
642
+ set("ERRORCODE", String(ctx.errorCode));
643
+ }
644
+ if (ctx.playerWidth != null && ctx.playerHeight != null) {
645
+ set("PLAYERSIZE", "".concat(Math.round(ctx.playerWidth), ",").concat(Math.round(ctx.playerHeight)));
646
+ }
647
+ set("IFA", ctx.deviceId);
648
+ set("IFATYPE", ctx.deviceIdType);
649
+ if (ctx.limitAdTracking != null) {
650
+ set("LIMITADTRACKING", ctx.limitAdTracking ? "1" : "0");
651
+ }
652
+ set("PAGEURL", ctx.pageUrl);
653
+ if (ctx.pageUrl) {
654
+ try {
655
+ set("DOMAIN", new URL(ctx.pageUrl).hostname);
656
+ } catch (unused) {}
657
+ }
658
+ set("CLIENTUA", ctx.clientUa);
659
+ set("DEVICEUA", ctx.clientUa);
660
+ if (ctx.podSequence != null) {
661
+ set("PODSEQUENCE", String(ctx.podSequence));
662
+ }
663
+ return values;
664
+ }
665
+ function substituteVastTrackingMacros(url) {
666
+ var ctx = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
667
+ if (!url) return url;
668
+ var values = resolveMacroValues(ctx);
669
+ return url.replace(CACHEBUSTING_ALIASES, function() {
670
+ return generateCachebuster();
671
+ }).replace(VAST_MACRO_PATTERN, function(match, name) {
672
+ if (name === "CACHEBUSTING") return generateCachebuster();
673
+ var value = values.get(name);
674
+ if (value != null) return encodeURIComponent(value);
675
+ return KNOWN_VAST_MACROS.has(name) ? "" : match;
676
+ });
677
+ }
560
678
  // src/sdk/hlsAdPlayer.ts
561
679
  var MAX_VAST_WRAPPER_DEPTH = 5;
680
+ var BEACON_TIMEOUT_MS = 3e4;
681
+ var inFlightBeacons = /* @__PURE__ */ new Set();
682
+ var VAST_ERROR_MEDIA_DISPLAY = 405;
683
+ function toVastMediaErrorCode(error) {
684
+ switch(error === null || error === void 0 ? void 0 : error.code){
685
+ case 1:
686
+ return 400;
687
+ case 2:
688
+ return 401;
689
+ case 4:
690
+ return 403;
691
+ default:
692
+ return VAST_ERROR_MEDIA_DISPLAY;
693
+ }
694
+ }
562
695
  function createHlsAdPlayer(contentVideo, options) {
563
696
  var _contentVideo_AD_VIDEO_PROP, _contentVideo_AD_CONTAINER_PROP;
564
697
  var adPlaying = false;
565
698
  var originalMutedState = false;
566
699
  var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
567
700
  var listeners = /* @__PURE__ */ new Map();
568
- var licenseKey = options === null || options === void 0 ? void 0 : options.licenseKey;
569
701
  var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
570
702
  var AD_CONTAINER_PROP = "__stormcloudAdContainer";
571
703
  var AD_VIDEO_PROP = "__stormcloudAdVideo";
@@ -576,10 +708,9 @@ function createHlsAdPlayer(contentVideo, options) {
576
708
  var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
577
709
  var adEventHandlers = [];
578
710
  var currentAd;
579
- var currentAdMediaUrl;
711
+ var currentAdMediaFile;
580
712
  var podAds = [];
581
713
  var podIndex = 0;
582
- var sessionId;
583
714
  var preloadedAds = /* @__PURE__ */ new Map();
584
715
  var preloadingAds = /* @__PURE__ */ new Map();
585
716
  var destroyed = false;
@@ -629,21 +760,47 @@ function createHlsAdPlayer(contentVideo, options) {
629
760
  }
630
761
  }
631
762
  }
632
- function generateSessionId() {
633
- return "session-".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
763
+ function buildTrackingMacroContext(errorCode) {
764
+ var context = {
765
+ adPlayheadSeconds: adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.currentTime,
766
+ contentPlayheadSeconds: contentVideo.currentTime,
767
+ assetUri: currentAdMediaFile === null || currentAdMediaFile === void 0 ? void 0 : currentAdMediaFile.url,
768
+ mediaMime: currentAdMediaFile === null || currentAdMediaFile === void 0 ? void 0 : currentAdMediaFile.type,
769
+ playerWidth: (adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.clientWidth) || (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.clientWidth),
770
+ playerHeight: (adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.clientHeight) || (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.clientHeight)
771
+ };
772
+ if (errorCode != null) {
773
+ context.errorCode = errorCode;
774
+ }
775
+ if (typeof navigator !== "undefined" && navigator.userAgent) {
776
+ context.clientUa = navigator.userAgent;
777
+ }
778
+ if (typeof location !== "undefined" && location.href) {
779
+ context.pageUrl = location.href;
780
+ }
781
+ if (podAds.length > 0) {
782
+ context.podSequence = podIndex + 1;
783
+ }
784
+ return context;
634
785
  }
635
- function fireTrackingPixels(urls) {
786
+ function fireTrackingPixels(urls, options2) {
636
787
  if (!urls || urls.length === 0) return;
788
+ var macroContext = buildTrackingMacroContext(options2 === null || options2 === void 0 ? void 0 : options2.errorCode);
637
789
  urls.forEach(function(url) {
638
790
  try {
639
- var trackingUrl = url;
640
- if (sessionId) {
641
- trackingUrl = "".concat(trackingUrl).concat(trackingUrl.includes("?") ? "&" : "?", "session_id=").concat(sessionId);
642
- }
643
- if (licenseKey) {
644
- trackingUrl = "".concat(trackingUrl).concat(trackingUrl.includes("?") ? "&" : "?", "license_key=").concat(licenseKey);
645
- }
791
+ var trackingUrl = substituteVastTrackingMacros(url, macroContext);
646
792
  var img = new Image(1, 1);
793
+ inFlightBeacons.add(img);
794
+ var timeoutId;
795
+ var release = function release() {
796
+ if (timeoutId !== void 0) clearTimeout(timeoutId);
797
+ img.onload = null;
798
+ img.onerror = null;
799
+ inFlightBeacons.delete(img);
800
+ };
801
+ img.onload = release;
802
+ img.onerror = release;
803
+ timeoutId = setTimeout(release, BEACON_TIMEOUT_MS);
647
804
  img.src = trackingUrl;
648
805
  console.log("[HlsAdPlayer] Fired tracking pixel: ".concat(trackingUrl));
649
806
  } catch (error) {
@@ -1282,7 +1439,9 @@ function createHlsAdPlayer(contentVideo, options) {
1282
1439
  if (!adPlaying) return;
1283
1440
  console.error("[HlsAdPlayer] Ad video error:", e);
1284
1441
  if (currentAd) {
1285
- fireTrackingPixels(currentAd.trackingUrls.error);
1442
+ fireTrackingPixels(currentAd.trackingUrls.error, {
1443
+ errorCode: toVastMediaErrorCode(adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.error)
1444
+ });
1286
1445
  }
1287
1446
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1288
1447
  return;
@@ -1394,9 +1553,9 @@ function createHlsAdPlayer(contentVideo, options) {
1394
1553
  delete contentVideo.dataset.stormcloudAdPlaying;
1395
1554
  }
1396
1555
  }
1397
- function resetQuartileTracking() {
1556
+ function resetQuartileTracking(preserveImpression) {
1398
1557
  trackingFired = {
1399
- impression: false,
1558
+ impression: preserveImpression ? trackingFired.impression : false,
1400
1559
  start: false,
1401
1560
  firstQuartile: false,
1402
1561
  midpoint: false,
@@ -1404,27 +1563,6 @@ function createHlsAdPlayer(contentVideo, options) {
1404
1563
  complete: false
1405
1564
  };
1406
1565
  }
1407
- function markCreativeRendered(reason) {
1408
- if (!currentAd || trackingFired.impression) return;
1409
- trackingFired.impression = true;
1410
- fireTrackingPixels(currentAd.trackingUrls.impression);
1411
- console.log("[HlsAdPlayer] Impression (pod ".concat(podIndex + 1, "/").concat(podAds.length || 1, ", reason: ").concat(reason, "): ").concat(currentAd.title));
1412
- emit("ad_impression", {
1413
- adId: currentAd.id,
1414
- title: currentAd.title,
1415
- durationSeconds: currentAd.duration,
1416
- mediaUrl: currentAdMediaUrl,
1417
- podIndex: podIndex,
1418
- podSize: podAds.length || 1,
1419
- reason: reason
1420
- });
1421
- }
1422
- function canDetectBlackFrames() {
1423
- if (!adVideoElement) return false;
1424
- if (requiresMediaPipelineResetAfterAds()) return false;
1425
- if (isRvfcSupported(adVideoElement)) return true;
1426
- return getDecodedVideoFrameCount(adVideoElement) !== void 0;
1427
- }
1428
1566
  function isRvfcSupported(video) {
1429
1567
  return typeof video.requestVideoFrameCallback === "function";
1430
1568
  }
@@ -1487,7 +1625,7 @@ function createHlsAdPlayer(contentVideo, options) {
1487
1625
  if (!mediaFile) {
1488
1626
  throw new Error("No media file available for ad");
1489
1627
  }
1490
- currentAdMediaUrl = mediaFile.url;
1628
+ currentAdMediaFile = mediaFile;
1491
1629
  var isHlsAd = isHlsMediaFile(mediaFile);
1492
1630
  console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad (pod ").concat(podIndex + 1, "/").concat(podAds.length || 1, ") from: ").concat(mediaFile.url));
1493
1631
  if (isHlsAd && import_hls.default.isSupported()) {
@@ -1531,9 +1669,11 @@ function createHlsAdPlayer(contentVideo, options) {
1531
1669
  }
1532
1670
  podIndex++;
1533
1671
  currentAd = podAds[podIndex];
1534
- currentAdMediaUrl = void 0;
1535
- resetQuartileTracking();
1672
+ currentAdMediaFile = void 0;
1673
+ resetQuartileTracking(false);
1536
1674
  if (currentAd) {
1675
+ fireTrackingPixels(currentAd.trackingUrls.impression);
1676
+ trackingFired.impression = true;
1537
1677
  console.log("[HlsAdPlayer] Advancing to next pod ad (".concat(podIndex + 1, "/").concat(podAds.length, "): ").concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1538
1678
  }
1539
1679
  clearStallWatchdog();
@@ -1572,7 +1712,9 @@ function createHlsAdPlayer(contentVideo, options) {
1572
1712
  console.warn("[HlsAdPlayer] Ad playback stalled (no progress) - recovering to avoid a blank frame");
1573
1713
  clearStallWatchdog();
1574
1714
  if (currentAd) {
1575
- fireTrackingPixels(currentAd.trackingUrls.error);
1715
+ fireTrackingPixels(currentAd.trackingUrls.error, {
1716
+ errorCode: VAST_ERROR_MEDIA_DISPLAY
1717
+ });
1576
1718
  }
1577
1719
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1578
1720
  return;
@@ -1628,7 +1770,6 @@ function createHlsAdPlayer(contentVideo, options) {
1628
1770
  if (!adPlaying) return;
1629
1771
  sawDecodedVideoFrame = true;
1630
1772
  markRvfcReliable();
1631
- markCreativeRendered("first_presented_frame");
1632
1773
  };
1633
1774
  try {
1634
1775
  videoFrameCallbackHandle = rvfc.call(adVideoElement, onPresentedFrame);
@@ -1641,7 +1782,9 @@ function createHlsAdPlayer(contentVideo, options) {
1641
1782
  console.warn("[HlsAdPlayer] Ad audio is advancing but no video frames decoded (black screen) - skipping this creative");
1642
1783
  clearStallWatchdog();
1643
1784
  if (currentAd) {
1644
- fireTrackingPixels(currentAd.trackingUrls.error);
1785
+ fireTrackingPixels(currentAd.trackingUrls.error, {
1786
+ errorCode: VAST_ERROR_MEDIA_DISPLAY
1787
+ });
1645
1788
  }
1646
1789
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1647
1790
  return;
@@ -1663,7 +1806,6 @@ function createHlsAdPlayer(contentVideo, options) {
1663
1806
  if (decodedFrames !== void 0 && decodedFrames > 0) {
1664
1807
  sawDecodedVideoFrame = true;
1665
1808
  markFrameCounterReliable();
1666
- markCreativeRendered("decoded_frames");
1667
1809
  } else if (adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S) {
1668
1810
  var timeAdvancing = adVideoElement.currentTime > lastAdProgressPosition + 0.05;
1669
1811
  if (isRvfcSupported(adVideoElement) && timeAdvancing && isRvfcReliable()) {
@@ -1676,9 +1818,6 @@ function createHlsAdPlayer(contentVideo, options) {
1676
1818
  }
1677
1819
  }
1678
1820
  }
1679
- if (!trackingFired.impression && !adVideoElement.paused && adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S && (sawDecodedVideoFrame || !canDetectBlackFrames())) {
1680
- markCreativeRendered(sawDecodedVideoFrame ? "decoded_frames" : "sustained_playback");
1681
- }
1682
1821
  if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
1683
1822
  noteAdProgress();
1684
1823
  return;
@@ -1779,7 +1918,6 @@ function createHlsAdPlayer(contentVideo, options) {
1779
1918
  ,
1780
1919
  6
1781
1920
  ]);
1782
- sessionId = generateSessionId();
1783
1921
  ads = [];
1784
1922
  if (!preloadedAds.has(vastTagUrl)) return [
1785
1923
  3,
@@ -1817,9 +1955,12 @@ function createHlsAdPlayer(contentVideo, options) {
1817
1955
  podAds = ads;
1818
1956
  podIndex = 0;
1819
1957
  currentAd = ads[0];
1820
- currentAdMediaUrl = void 0;
1821
- resetQuartileTracking();
1958
+ currentAdMediaFile = void 0;
1822
1959
  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"));
1960
+ if (currentAd) {
1961
+ fireTrackingPixels(currentAd.trackingUrls.impression);
1962
+ trackingFired.impression = true;
1963
+ }
1823
1964
  return [
1824
1965
  2,
1825
1966
  Promise.resolve()
@@ -1859,7 +2000,7 @@ function createHlsAdPlayer(contentVideo, options) {
1859
2000
  contentVideo[AD_VIDEO_PROP] = adVideoElement;
1860
2001
  }
1861
2002
  setupAdEventListeners();
1862
- resetQuartileTracking();
2003
+ resetQuartileTracking(true);
1863
2004
  contentVolume = contentVideo.volume;
1864
2005
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1865
2006
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -1949,7 +2090,7 @@ function createHlsAdPlayer(contentVideo, options) {
1949
2090
  }
1950
2091
  }
1951
2092
  currentAd = void 0;
1952
- currentAdMediaUrl = void 0;
2093
+ currentAdMediaFile = void 0;
1953
2094
  podAds = [];
1954
2095
  podIndex = 0;
1955
2096
  return [
@@ -1990,6 +2131,7 @@ function createHlsAdPlayer(contentVideo, options) {
1990
2131
  teardownAdEventListeners();
1991
2132
  releaseAdDecoder();
1992
2133
  currentAd = void 0;
2134
+ currentAdMediaFile = void 0;
1993
2135
  podAds = [];
1994
2136
  podIndex = 0;
1995
2137
  listeners.clear();
@@ -3283,19 +3425,8 @@ function buildPlayerMetricEvent() {
3283
3425
  }).apply(this, arguments);
3284
3426
  }
3285
3427
  function publishTracking(licenseKey, channel, body) {
3286
- var debug = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : false;
3287
3428
  ensureMQTTClient();
3288
- var topic = buildPlayerTopic(licenseKey, channel);
3289
- var published = publishMQTT(topic, body);
3290
- if (debug) {
3291
- console.log("[StormcloudVideoPlayer] publishTracking:", JSON.stringify({
3292
- licenseKey: licenseKey,
3293
- channel: channel,
3294
- topic: topic,
3295
- body: body,
3296
- published: published
3297
- }, null, 2));
3298
- }
3429
+ publishMQTT(buildPlayerTopic(licenseKey, channel), body);
3299
3430
  }
3300
3431
  function sendInitialTracking(_0) {
3301
3432
  return _async_to_generator(function(licenseKey) {
@@ -3329,7 +3460,7 @@ function sendInitialTracking(_0) {
3329
3460
  events: [
3330
3461
  metricEvent
3331
3462
  ]
3332
- }, !!context.debugAdTiming);
3463
+ });
3333
3464
  return [
3334
3465
  3,
3335
3466
  4
@@ -3439,7 +3570,7 @@ function sendAdLoadedTracking(_0, _1) {
3439
3570
  }
3440
3571
  function sendAdImpressionTracking(_0, _1) {
3441
3572
  return _async_to_generator(function(licenseKey, adImpressionInfo) {
3442
- var context, _adImpressionInfo_adUrl, metricEvent, error;
3573
+ var context, metricEvent, error;
3443
3574
  var _arguments = arguments;
3444
3575
  return _ts_generator(this, function(_state) {
3445
3576
  switch(_state.label){
@@ -3464,18 +3595,17 @@ function sendAdImpressionTracking(_0, _1) {
3464
3595
  ];
3465
3596
  case 2:
3466
3597
  metricEvent = _state.sent();
3467
- publishTracking(licenseKey, "heartbeat", metricEvent, !!context.debugAdTiming);
3598
+ publishTracking(licenseKey, "heartbeat", metricEvent);
3468
3599
  publishTracking(licenseKey, "impressions", {
3469
3600
  events: [
3470
3601
  {
3471
- event_id: createUuid(),
3472
3602
  player_id: metricEvent.player_id,
3473
3603
  ad_played_count: 1,
3474
- ad_url: (_adImpressionInfo_adUrl = adImpressionInfo.adUrl) !== null && _adImpressionInfo_adUrl !== void 0 ? _adImpressionInfo_adUrl : adImpressionInfo.adId,
3604
+ ad_url: adImpressionInfo.adUrl,
3475
3605
  capture_at: adImpressionInfo.timestamp
3476
3606
  }
3477
3607
  ]
3478
- }, !!context.debugAdTiming);
3608
+ });
3479
3609
  return [
3480
3610
  3,
3481
3611
  4
@@ -3520,7 +3650,7 @@ function sendHeartbeat(_0) {
3520
3650
  ];
3521
3651
  case 2:
3522
3652
  heartbeatData = _state.sent();
3523
- publishTracking(licenseKey, "heartbeat", heartbeatData, !!context.debugAdTiming);
3653
+ publishTracking(licenseKey, "heartbeat", heartbeatData);
3524
3654
  return [
3525
3655
  3,
3526
3656
  4
@@ -7314,22 +7444,27 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7314
7444
  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 : "?"));
7315
7445
  }
7316
7446
  });
7317
- adPlayer.on("ad_impression", function(payload) {
7318
- var impressionInfo = {
7447
+ adPlayer.on("all_ads_completed", function() {
7448
+ sendAdImpressionTracking(_this.host.config.licenseKey, {
7319
7449
  source: "hls",
7320
7450
  adIndex: _this.timing.currentAdIndex,
7321
7451
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
7322
- };
7323
- if (payload === null || payload === void 0 ? void 0 : payload.adId) impressionInfo.adId = payload.adId;
7324
- if (payload === null || payload === void 0 ? void 0 : payload.mediaUrl) impressionInfo.adUrl = payload.mediaUrl;
7325
- if ((payload === null || payload === void 0 ? void 0 : payload.durationSeconds) != null) {
7326
- impressionInfo.durationSeconds = payload.durationSeconds;
7452
+ }, _this.analyticsContext).catch(function() {});
7453
+ _this.timing.recordPlayedAdDuration(_this.host.getAdPlayer());
7454
+ var remaining = _this.timing.getRemainingAdMs();
7455
+ _this.timing.consecutiveFailures = 0;
7456
+ if (_this.debug) {
7457
+ console.log("[StormcloudVideoPlayer] all_ads_completed event received - remaining=".concat(remaining, "ms, queued ads=").concat(_this.adRequestQueue.length), _this.adRequestQueue.length > 0 ? {
7458
+ queuedUrls: _to_consumable_array(_this.adRequestQueue)
7459
+ } : {});
7327
7460
  }
7328
- sendAdImpressionTracking(_this.host.config.licenseKey, impressionInfo, _this.analyticsContext).catch(function(error) {
7329
- if (_this.debug) {
7330
- console.warn("[AdBreakOrchestrator] Failed to send ad impression tracking:", error);
7461
+ if (_this.inAdBreak) {
7462
+ if (_this.timing.hasTimeToStartAnotherAd()) {
7463
+ _this.tryNextAvailableAdWithRateLimit();
7464
+ } else {
7465
+ _this.handleAdPodComplete();
7331
7466
  }
7332
- });
7467
+ }
7333
7468
  });
7334
7469
  adPlayer.on("ad_error", function(errorPayload) {
7335
7470
  var errorMessage = "Ad playback failed";
@@ -7372,6 +7507,11 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7372
7507
  }
7373
7508
  });
7374
7509
  adPlayer.on("content_resume", function() {
7510
+ sendAdImpressionTracking(_this.host.config.licenseKey, {
7511
+ source: "hls",
7512
+ adIndex: _this.timing.currentAdIndex,
7513
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
7514
+ }, _this.analyticsContext).catch(function() {});
7375
7515
  if (!_this.host.video.muted) {
7376
7516
  _this.host.video.muted = true;
7377
7517
  if (_this.debug) {