stormcloud-video-player 0.8.53 → 0.8.55

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 (70) hide show
  1. package/dist/stormcloud-vp.min.js +1 -1
  2. package/lib/index.cjs +204 -110
  3. package/lib/index.cjs.map +1 -1
  4. package/lib/index.d.cts +2 -0
  5. package/lib/index.d.ts +2 -0
  6. package/lib/index.js +204 -110
  7. package/lib/index.js.map +1 -1
  8. package/lib/player/AdBreakOrchestrator.cjs +69 -66
  9. package/lib/player/AdBreakOrchestrator.cjs.map +1 -1
  10. package/lib/player/AdBreakOrchestrator.d.cts +1 -1
  11. package/lib/player/AdConfigManager.cjs +38 -33
  12. package/lib/player/AdConfigManager.cjs.map +1 -1
  13. package/lib/player/AdConfigManager.d.cts +1 -1
  14. package/lib/player/AdTimingService.cjs +18 -25
  15. package/lib/player/AdTimingService.cjs.map +1 -1
  16. package/lib/player/AdTimingService.d.cts +1 -1
  17. package/lib/player/HlsEngine.cjs +86 -30
  18. package/lib/player/HlsEngine.cjs.map +1 -1
  19. package/lib/player/HlsEngine.d.cts +6 -1
  20. package/lib/player/PlaceholderLayer.cjs +1 -3
  21. package/lib/player/PlaceholderLayer.cjs.map +1 -1
  22. package/lib/player/PlayerControls.cjs.map +1 -1
  23. package/lib/player/PlayerControls.d.cts +1 -1
  24. package/lib/player/Scte35CueManager.cjs +2 -4
  25. package/lib/player/Scte35CueManager.cjs.map +1 -1
  26. package/lib/player/Scte35CueManager.d.cts +1 -1
  27. package/lib/player/Scte35Parser.cjs +6 -12
  28. package/lib/player/Scte35Parser.cjs.map +1 -1
  29. package/lib/player/Scte35Parser.d.cts +1 -1
  30. package/lib/player/StormcloudVideoPlayer.cjs +194 -96
  31. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  32. package/lib/player/StormcloudVideoPlayer.d.cts +2 -1
  33. package/lib/player/playerTypes.cjs.map +1 -1
  34. package/lib/player/playerTypes.d.cts +1 -1
  35. package/lib/players/FilePlayer.cjs +17 -26
  36. package/lib/players/FilePlayer.cjs.map +1 -1
  37. package/lib/players/HlsPlayer.cjs +204 -110
  38. package/lib/players/HlsPlayer.cjs.map +1 -1
  39. package/lib/players/HlsPlayer.d.cts +1 -1
  40. package/lib/players/index.cjs +204 -110
  41. package/lib/players/index.cjs.map +1 -1
  42. package/lib/sdk/hlsAdPlayer.cjs +42 -19
  43. package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
  44. package/lib/sdk/hlsAdPlayer.d.cts +1 -1
  45. package/lib/sdk/pal.cjs +6 -9
  46. package/lib/sdk/pal.cjs.map +1 -1
  47. package/lib/{types-cTqIKw_D.d.cts → types-DpbgEvSH.d.cts} +1 -0
  48. package/lib/ui/StormcloudVideoPlayer.cjs +194 -96
  49. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  50. package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
  51. package/lib/utils/browserCompat.cjs +3 -6
  52. package/lib/utils/browserCompat.cjs.map +1 -1
  53. package/lib/utils/ctvVastSignals.cjs +3 -6
  54. package/lib/utils/ctvVastSignals.cjs.map +1 -1
  55. package/lib/utils/devUrl.cjs.map +1 -1
  56. package/lib/utils/mqttClient.cjs +1 -3
  57. package/lib/utils/mqttClient.cjs.map +1 -1
  58. package/lib/utils/mqttConfig.cjs +1 -3
  59. package/lib/utils/mqttConfig.cjs.map +1 -1
  60. package/lib/utils/polyfills.cjs +4 -7
  61. package/lib/utils/polyfills.cjs.map +1 -1
  62. package/lib/utils/tracking.cjs +27 -20
  63. package/lib/utils/tracking.cjs.map +1 -1
  64. package/lib/utils/tracking.d.cts +1 -1
  65. package/lib/utils/vastEnvironmentSignals.cjs +7 -6
  66. package/lib/utils/vastEnvironmentSignals.cjs.map +1 -1
  67. package/lib/utils/vastEnvironmentSignals.d.cts +2 -1
  68. package/lib/utils/vastMacros.cjs +4 -2
  69. package/lib/utils/vastMacros.cjs.map +1 -1
  70. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { Component } from 'react';
2
- import { a as StormcloudVideoPlayerConfig } from '../types-cTqIKw_D.cjs';
2
+ import { a as StormcloudVideoPlayerConfig } from '../types-DpbgEvSH.cjs';
3
3
 
4
4
  interface HlsPlayerProps extends StormcloudVideoPlayerConfig {
5
5
  onMount?: (player: any) => void;
@@ -11,9 +11,7 @@ function _array_without_holes(arr) {
11
11
  if (Array.isArray(arr)) return _array_like_to_array(arr);
12
12
  }
13
13
  function _assert_this_initialized(self) {
14
- if (self === void 0) {
15
- throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
16
- }
14
+ if (self === void 0) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
17
15
  return self;
18
16
  }
19
17
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
@@ -24,11 +22,8 @@ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
24
22
  reject(error);
25
23
  return;
26
24
  }
27
- if (info.done) {
28
- resolve(value);
29
- } else {
30
- Promise.resolve(value).then(_next, _throw);
31
- }
25
+ if (info.done) resolve(value);
26
+ else Promise.resolve(value).then(_next, _throw);
32
27
  }
33
28
  function _async_to_generator(fn) {
34
29
  return function() {
@@ -50,9 +45,7 @@ function _call_super(_this, derived, args) {
50
45
  return _possible_constructor_return(_this, _is_native_reflect_construct() ? Reflect.construct(derived, args || [], _get_prototype_of(_this).constructor) : derived.apply(_this, args));
51
46
  }
52
47
  function _class_call_check(instance, Constructor) {
53
- if (!(instance instanceof Constructor)) {
54
- throw new TypeError("Cannot call a class as a function");
55
- }
48
+ if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
56
49
  }
57
50
  function _defineProperties(target, props) {
58
51
  for(var i = 0; i < props.length; i++){
@@ -76,9 +69,7 @@ function _define_property(obj, key, value) {
76
69
  configurable: true,
77
70
  writable: true
78
71
  });
79
- } else {
80
- obj[key] = value;
81
- }
72
+ } else obj[key] = value;
82
73
  return obj;
83
74
  }
84
75
  function _get_prototype_of(o) {
@@ -101,14 +92,23 @@ function _inherits(subClass, superClass) {
101
92
  if (superClass) _set_prototype_of(subClass, superClass);
102
93
  }
103
94
  function _instanceof(left, right) {
95
+ "@swc/helpers - instanceof";
104
96
  if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
105
97
  return !!right[Symbol.hasInstance](left);
106
- } else {
107
- return left instanceof right;
108
- }
98
+ } else return left instanceof right;
99
+ }
100
+ function _is_native_reflect_construct() {
101
+ try {
102
+ var result = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
103
+ } catch (_) {}
104
+ return (_is_native_reflect_construct = function() {
105
+ return !!result;
106
+ })();
109
107
  }
110
108
  function _iterable_to_array(iter) {
111
- if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
109
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) {
110
+ return Array.from(iter);
111
+ }
112
112
  }
113
113
  function _iterable_to_array_limit(arr, i) {
114
114
  var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
@@ -135,10 +135,10 @@ function _iterable_to_array_limit(arr, i) {
135
135
  return _arr;
136
136
  }
137
137
  function _non_iterable_rest() {
138
- throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
138
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
139
139
  }
140
140
  function _non_iterable_spread() {
141
- throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
141
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
142
142
  }
143
143
  function _object_spread(target) {
144
144
  for(var i = 1; i < arguments.length; i++){
@@ -170,9 +170,8 @@ function ownKeys(object, enumerableOnly) {
170
170
  }
171
171
  function _object_spread_props(target, source) {
172
172
  source = source != null ? source : {};
173
- if (Object.getOwnPropertyDescriptors) {
174
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
175
- } else {
173
+ if (Object.getOwnPropertyDescriptors) Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
174
+ else {
176
175
  ownKeys(Object(source)).forEach(function(key) {
177
176
  Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
178
177
  });
@@ -180,9 +179,7 @@ function _object_spread_props(target, source) {
180
179
  return target;
181
180
  }
182
181
  function _possible_constructor_return(self, call) {
183
- if (call && (_type_of(call) === "object" || typeof call === "function")) {
184
- return call;
185
- }
182
+ if (call && (_type_of(call) === "object" || typeof call === "function")) return call;
186
183
  return _assert_this_initialized(self);
187
184
  }
188
185
  function _set_prototype_of(o, p) {
@@ -198,26 +195,6 @@ function _sliced_to_array(arr, i) {
198
195
  function _to_consumable_array(arr) {
199
196
  return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
200
197
  }
201
- function _type_of(obj) {
202
- "@swc/helpers - typeof";
203
- return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
204
- }
205
- function _unsupported_iterable_to_array(o, minLen) {
206
- if (!o) return;
207
- if (typeof o === "string") return _array_like_to_array(o, minLen);
208
- var n = Object.prototype.toString.call(o).slice(8, -1);
209
- if (n === "Object" && o.constructor) n = o.constructor.name;
210
- if (n === "Map" || n === "Set") return Array.from(n);
211
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
212
- }
213
- function _is_native_reflect_construct() {
214
- try {
215
- var result = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
216
- } catch (_) {}
217
- return (_is_native_reflect_construct = function() {
218
- return !!result;
219
- })();
220
- }
221
198
  function _ts_generator(thisArg, body) {
222
199
  var f, y, t, _ = {
223
200
  label: 0,
@@ -319,18 +296,36 @@ function _ts_generator(thisArg, body) {
319
296
  }
320
297
  function _ts_values(o) {
321
298
  var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
322
- if (m) return m.call(o);
323
- if (o && typeof o.length === "number") return {
324
- next: function() {
325
- if (o && i >= o.length) o = void 0;
326
- return {
327
- value: o && o[i++],
328
- done: !o
329
- };
330
- }
331
- };
299
+ if (m) {
300
+ return m.call(o);
301
+ }
302
+ if (o && typeof o.length === "number") {
303
+ return {
304
+ next: function() {
305
+ if (o && i >= o.length) {
306
+ o = void 0;
307
+ }
308
+ return {
309
+ value: o && o[i++],
310
+ done: !o
311
+ };
312
+ }
313
+ };
314
+ }
332
315
  throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
333
316
  }
317
+ function _type_of(obj) {
318
+ "@swc/helpers - typeof";
319
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
320
+ }
321
+ function _unsupported_iterable_to_array(o, minLen) {
322
+ if (!o) return;
323
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
324
+ var n = Object.prototype.toString.call(o).slice(8, -1);
325
+ if (n === "Object" && o.constructor) n = o.constructor.name;
326
+ if (n === "Map" || n === "Set") return Array.from(n);
327
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
328
+ }
334
329
  var __create = Object.create;
335
330
  var __defProp = Object.defineProperty;
336
331
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -627,6 +622,7 @@ function createHlsAdPlayer(contentVideo, options) {
627
622
  var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
628
623
  var adEventHandlers = [];
629
624
  var currentAd;
625
+ var currentAdMediaUrl;
630
626
  var podAds = [];
631
627
  var podIndex = 0;
632
628
  var sessionId;
@@ -1444,9 +1440,9 @@ function createHlsAdPlayer(contentVideo, options) {
1444
1440
  delete contentVideo.dataset.stormcloudAdPlaying;
1445
1441
  }
1446
1442
  }
1447
- function resetQuartileTracking(preserveImpression) {
1443
+ function resetQuartileTracking() {
1448
1444
  trackingFired = {
1449
- impression: preserveImpression ? trackingFired.impression : false,
1445
+ impression: false,
1450
1446
  start: false,
1451
1447
  firstQuartile: false,
1452
1448
  midpoint: false,
@@ -1454,6 +1450,27 @@ function createHlsAdPlayer(contentVideo, options) {
1454
1450
  complete: false
1455
1451
  };
1456
1452
  }
1453
+ function markCreativeRendered(reason) {
1454
+ if (!currentAd || trackingFired.impression) return;
1455
+ trackingFired.impression = true;
1456
+ fireTrackingPixels(currentAd.trackingUrls.impression);
1457
+ console.log("[HlsAdPlayer] Impression (pod ".concat(podIndex + 1, "/").concat(podAds.length || 1, ", reason: ").concat(reason, "): ").concat(currentAd.title));
1458
+ emit("ad_impression", {
1459
+ adId: currentAd.id,
1460
+ title: currentAd.title,
1461
+ durationSeconds: currentAd.duration,
1462
+ mediaUrl: currentAdMediaUrl,
1463
+ podIndex: podIndex,
1464
+ podSize: podAds.length || 1,
1465
+ reason: reason
1466
+ });
1467
+ }
1468
+ function canDetectBlackFrames() {
1469
+ if (!adVideoElement) return false;
1470
+ if (requiresMediaPipelineResetAfterAds()) return false;
1471
+ if (isRvfcSupported(adVideoElement)) return true;
1472
+ return getDecodedVideoFrameCount(adVideoElement) !== void 0;
1473
+ }
1457
1474
  function isRvfcSupported(video) {
1458
1475
  return typeof video.requestVideoFrameCallback === "function";
1459
1476
  }
@@ -1516,6 +1533,7 @@ function createHlsAdPlayer(contentVideo, options) {
1516
1533
  if (!mediaFile) {
1517
1534
  throw new Error("No media file available for ad");
1518
1535
  }
1536
+ currentAdMediaUrl = mediaFile.url;
1519
1537
  var isHlsAd = isHlsMediaFile(mediaFile);
1520
1538
  console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad (pod ").concat(podIndex + 1, "/").concat(podAds.length || 1, ") from: ").concat(mediaFile.url));
1521
1539
  if (isHlsAd && import_hls.default.isSupported()) {
@@ -1559,10 +1577,9 @@ function createHlsAdPlayer(contentVideo, options) {
1559
1577
  }
1560
1578
  podIndex++;
1561
1579
  currentAd = podAds[podIndex];
1562
- resetQuartileTracking(false);
1580
+ currentAdMediaUrl = void 0;
1581
+ resetQuartileTracking();
1563
1582
  if (currentAd) {
1564
- fireTrackingPixels(currentAd.trackingUrls.impression);
1565
- trackingFired.impression = true;
1566
1583
  console.log("[HlsAdPlayer] Advancing to next pod ad (".concat(podIndex + 1, "/").concat(podAds.length, "): ").concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1567
1584
  }
1568
1585
  clearStallWatchdog();
@@ -1657,6 +1674,7 @@ function createHlsAdPlayer(contentVideo, options) {
1657
1674
  if (!adPlaying) return;
1658
1675
  sawDecodedVideoFrame = true;
1659
1676
  markRvfcReliable();
1677
+ markCreativeRendered("first_presented_frame");
1660
1678
  };
1661
1679
  try {
1662
1680
  videoFrameCallbackHandle = rvfc.call(adVideoElement, onPresentedFrame);
@@ -1691,6 +1709,7 @@ function createHlsAdPlayer(contentVideo, options) {
1691
1709
  if (decodedFrames !== void 0 && decodedFrames > 0) {
1692
1710
  sawDecodedVideoFrame = true;
1693
1711
  markFrameCounterReliable();
1712
+ markCreativeRendered("decoded_frames");
1694
1713
  } else if (adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S) {
1695
1714
  var timeAdvancing = adVideoElement.currentTime > lastAdProgressPosition + 0.05;
1696
1715
  if (isRvfcSupported(adVideoElement) && timeAdvancing && isRvfcReliable()) {
@@ -1703,6 +1722,9 @@ function createHlsAdPlayer(contentVideo, options) {
1703
1722
  }
1704
1723
  }
1705
1724
  }
1725
+ if (!trackingFired.impression && !adVideoElement.paused && adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S && (sawDecodedVideoFrame || !canDetectBlackFrames())) {
1726
+ markCreativeRendered(sawDecodedVideoFrame ? "decoded_frames" : "sustained_playback");
1727
+ }
1706
1728
  if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
1707
1729
  noteAdProgress();
1708
1730
  return;
@@ -1841,11 +1863,9 @@ function createHlsAdPlayer(contentVideo, options) {
1841
1863
  podAds = ads;
1842
1864
  podIndex = 0;
1843
1865
  currentAd = ads[0];
1866
+ currentAdMediaUrl = void 0;
1867
+ resetQuartileTracking();
1844
1868
  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"));
1845
- if (currentAd) {
1846
- fireTrackingPixels(currentAd.trackingUrls.impression);
1847
- trackingFired.impression = true;
1848
- }
1849
1869
  return [
1850
1870
  2,
1851
1871
  Promise.resolve()
@@ -1885,7 +1905,7 @@ function createHlsAdPlayer(contentVideo, options) {
1885
1905
  contentVideo[AD_VIDEO_PROP] = adVideoElement;
1886
1906
  }
1887
1907
  setupAdEventListeners();
1888
- resetQuartileTracking(true);
1908
+ resetQuartileTracking();
1889
1909
  contentVolume = contentVideo.volume;
1890
1910
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1891
1911
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -1975,6 +1995,7 @@ function createHlsAdPlayer(contentVideo, options) {
1975
1995
  }
1976
1996
  }
1977
1997
  currentAd = void 0;
1998
+ currentAdMediaUrl = void 0;
1978
1999
  podAds = [];
1979
2000
  podIndex = 0;
1980
2001
  return [
@@ -3289,7 +3310,7 @@ function buildPlayerMetricEvent() {
3289
3310
  if (debugAdTiming) {
3290
3311
  console.log("[StormcloudVideoPlayer] playerId: ", playerId);
3291
3312
  }
3292
- captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : /* @__PURE__ */ new Date().toISOString();
3313
+ captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : (/* @__PURE__ */ new Date()).toISOString();
3293
3314
  return [
3294
3315
  2,
3295
3316
  _object_spread({
@@ -3308,8 +3329,19 @@ function buildPlayerMetricEvent() {
3308
3329
  }).apply(this, arguments);
3309
3330
  }
3310
3331
  function publishTracking(licenseKey, channel, body) {
3332
+ var debug = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : false;
3311
3333
  ensureMQTTClient();
3312
- publishMQTT(buildPlayerTopic(licenseKey, channel), body);
3334
+ var topic = buildPlayerTopic(licenseKey, channel);
3335
+ var published = publishMQTT(topic, body);
3336
+ if (debug) {
3337
+ console.log("[StormcloudVideoPlayer] publishTracking:", JSON.stringify({
3338
+ licenseKey: licenseKey,
3339
+ channel: channel,
3340
+ topic: topic,
3341
+ body: body,
3342
+ published: published
3343
+ }, null, 2));
3344
+ }
3313
3345
  }
3314
3346
  function sendInitialTracking(_0) {
3315
3347
  return _async_to_generator(function(licenseKey) {
@@ -3343,7 +3375,7 @@ function sendInitialTracking(_0) {
3343
3375
  events: [
3344
3376
  metricEvent
3345
3377
  ]
3346
- });
3378
+ }, !!context.debugAdTiming);
3347
3379
  return [
3348
3380
  3,
3349
3381
  4
@@ -3453,7 +3485,7 @@ function sendAdLoadedTracking(_0, _1) {
3453
3485
  }
3454
3486
  function sendAdImpressionTracking(_0, _1) {
3455
3487
  return _async_to_generator(function(licenseKey, adImpressionInfo) {
3456
- var context, metricEvent, error;
3488
+ var context, _adImpressionInfo_adUrl, metricEvent, error;
3457
3489
  var _arguments = arguments;
3458
3490
  return _ts_generator(this, function(_state) {
3459
3491
  switch(_state.label){
@@ -3478,17 +3510,18 @@ function sendAdImpressionTracking(_0, _1) {
3478
3510
  ];
3479
3511
  case 2:
3480
3512
  metricEvent = _state.sent();
3481
- publishTracking(licenseKey, "heartbeat", metricEvent);
3513
+ publishTracking(licenseKey, "heartbeat", metricEvent, !!context.debugAdTiming);
3482
3514
  publishTracking(licenseKey, "impressions", {
3483
3515
  events: [
3484
3516
  {
3517
+ event_id: createUuid(),
3485
3518
  player_id: metricEvent.player_id,
3486
3519
  ad_played_count: 1,
3487
- ad_url: adImpressionInfo.adUrl,
3520
+ ad_url: (_adImpressionInfo_adUrl = adImpressionInfo.adUrl) !== null && _adImpressionInfo_adUrl !== void 0 ? _adImpressionInfo_adUrl : adImpressionInfo.adId,
3488
3521
  capture_at: adImpressionInfo.timestamp
3489
3522
  }
3490
3523
  ]
3491
- });
3524
+ }, !!context.debugAdTiming);
3492
3525
  return [
3493
3526
  3,
3494
3527
  4
@@ -3533,7 +3566,7 @@ function sendHeartbeat(_0) {
3533
3566
  ];
3534
3567
  case 2:
3535
3568
  heartbeatData = _state.sent();
3536
- publishTracking(licenseKey, "heartbeat", heartbeatData);
3569
+ publishTracking(licenseKey, "heartbeat", heartbeatData, !!context.debugAdTiming);
3537
3570
  return [
3538
3571
  3,
3539
3572
  4
@@ -6366,7 +6399,7 @@ var AdTimingService = /*#__PURE__*/ function() {
6366
6399
  var _this_callbacks_getAdState = this.callbacks.getAdState(), inAdBreak = _this_callbacks_getAdState.inAdBreak, showAds = _this_callbacks_getAdState.showAds, adPlaying = _this_callbacks_getAdState.adPlaying;
6367
6400
  console.log("[StormcloudVideoPlayer][AdState]", _object_spread({
6368
6401
  event: event,
6369
- timestamp: /* @__PURE__ */ new Date().toISOString(),
6402
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6370
6403
  showAds: showAds,
6371
6404
  adPlaying: adPlaying,
6372
6405
  inAdBreak: inAdBreak,
@@ -6527,6 +6560,7 @@ var HlsEngine = /*#__PURE__*/ function() {
6527
6560
  this.bufferedSegmentsCount = 0;
6528
6561
  this.shouldAutoplayAfterBuffering = false;
6529
6562
  this.hasInitialBufferCompleted = false;
6563
+ this.latencyProfileApplied = false;
6530
6564
  this.config = config;
6531
6565
  this.video = video;
6532
6566
  this.cueManager = cueManager;
@@ -6595,24 +6629,21 @@ var HlsEngine = /*#__PURE__*/ function() {
6595
6629
  key: "setupHls",
6596
6630
  value: function setupHls() {
6597
6631
  var _this = this;
6598
- this.hls = new import_hls2.default(_object_spread_props(_object_spread({
6632
+ this.hls = new import_hls2.default({
6599
6633
  enableWorker: true,
6600
6634
  backBufferLength: 30,
6601
6635
  liveDurationInfinity: true,
6602
6636
  lowLatencyMode: !!this.config.lowLatencyMode,
6603
- maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1
6604
- }, this.config.lowLatencyMode ? {
6605
- liveSyncDuration: 2
6606
- } : {}), {
6637
+ maxLiveSyncPlaybackRate: 1.1,
6607
6638
  maxBufferLength: 30,
6608
6639
  maxMaxBufferLength: 600,
6609
6640
  maxBufferSize: 60 * 1e3 * 1e3,
6610
- maxBufferHole: 0.5,
6641
+ maxBufferHole: 1,
6611
6642
  highBufferWatchdogPeriod: 2,
6612
- nudgeOffset: 0.1,
6613
- nudgeMaxRetry: 3,
6643
+ nudgeOffset: 0.2,
6644
+ nudgeMaxRetry: 5,
6614
6645
  startPosition: -1
6615
- }));
6646
+ });
6616
6647
  this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, function() {
6617
6648
  var _this_hls;
6618
6649
  (_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.loadSource(_this.config.src);
@@ -6636,6 +6667,8 @@ var HlsEngine = /*#__PURE__*/ function() {
6636
6667
  this.bufferedSegmentsCount = 0;
6637
6668
  this.hasInitialBufferCompleted = false;
6638
6669
  this.shouldAutoplayAfterBuffering = !!this.config.autoplay;
6670
+ this.latencyProfileApplied = false;
6671
+ this.detectedLowLatencyStream = void 0;
6639
6672
  minSegments = (_this_config_minSegmentsBeforePlay = this.config.minSegmentsBeforePlay) !== null && _this_config_minSegmentsBeforePlay !== void 0 ? _this_config_minSegmentsBeforePlay : 2;
6640
6673
  if (this.debug) {
6641
6674
  console.log("[StormcloudVideoPlayer] Waiting for", minSegments, "segments to buffer before playback");
@@ -6666,6 +6699,7 @@ var HlsEngine = /*#__PURE__*/ function() {
6666
6699
  }).call(_this);
6667
6700
  });
6668
6701
  this.hls.on(import_hls2.default.Events.LEVEL_LOADED, function(_evt, data) {
6702
+ _this.applyStreamLatencyProfile(data === null || data === void 0 ? void 0 : data.details);
6669
6703
  if (_this.callbacks.isInAdBreak() || _this.callbacks.hasPendingAdBreak()) {
6670
6704
  return;
6671
6705
  }
@@ -6939,6 +6973,70 @@ var HlsEngine = /*#__PURE__*/ function() {
6939
6973
  this.hls.attachMedia(this.video);
6940
6974
  }
6941
6975
  },
6976
+ {
6977
+ key: "isLowLatencyStream",
6978
+ value: function isLowLatencyStream() {
6979
+ return this.detectedLowLatencyStream;
6980
+ }
6981
+ },
6982
+ {
6983
+ key: "applyStreamLatencyProfile",
6984
+ value: function applyStreamLatencyProfile(details) {
6985
+ if (this.latencyProfileApplied || !this.hls) {
6986
+ return;
6987
+ }
6988
+ if (!details) {
6989
+ return;
6990
+ }
6991
+ if (details.live !== true) {
6992
+ this.latencyProfileApplied = true;
6993
+ this.detectedLowLatencyStream = false;
6994
+ return;
6995
+ }
6996
+ var isLowLatencyManifest = this.isLowLatencyManifest(details);
6997
+ var useLowLatency = isLowLatencyManifest && !!this.config.lowLatencyMode;
6998
+ this.detectedLowLatencyStream = useLowLatency;
6999
+ this.latencyProfileApplied = true;
7000
+ var cfg = this.hls.config;
7001
+ if (useLowLatency) {
7002
+ cfg.maxLiveSyncPlaybackRate = 1.5;
7003
+ cfg.maxBufferHole = 0.5;
7004
+ delete cfg.liveSyncDuration;
7005
+ } else {
7006
+ cfg.maxLiveSyncPlaybackRate = 1.1;
7007
+ cfg.maxBufferHole = 1;
7008
+ delete cfg.liveSyncDuration;
7009
+ cfg.liveSyncDurationCount = 3;
7010
+ }
7011
+ if (this.debug) {
7012
+ var _details_targetduration;
7013
+ console.log("[StormcloudVideoPlayer] Live latency profile: ".concat(useLowLatency ? "LL-HLS (low latency)" : "standard live (stability)"), {
7014
+ isLowLatencyManifest: isLowLatencyManifest,
7015
+ lowLatencyModeRequested: !!this.config.lowLatencyMode,
7016
+ canBlockReload: details.canBlockReload,
7017
+ partTarget: details.partTarget,
7018
+ partHoldBack: details.partHoldBack,
7019
+ partListLength: Array.isArray(details.partList) ? details.partList.length : 0,
7020
+ targetDuration: (_details_targetduration = details.targetduration) !== null && _details_targetduration !== void 0 ? _details_targetduration : details.targetDuration,
7021
+ maxLiveSyncPlaybackRate: cfg.maxLiveSyncPlaybackRate,
7022
+ maxBufferHole: cfg.maxBufferHole
7023
+ });
7024
+ }
7025
+ }
7026
+ },
7027
+ {
7028
+ key: "isLowLatencyManifest",
7029
+ value: function isLowLatencyManifest(details) {
7030
+ if (!details) {
7031
+ return false;
7032
+ }
7033
+ var hasParts = Array.isArray(details.partList) && details.partList.length > 0;
7034
+ var hasPartTarget = typeof details.partTarget === "number" && details.partTarget > 0;
7035
+ var hasPartHoldBack = typeof details.partHoldBack === "number" && details.partHoldBack > 0;
7036
+ var canBlockReload = details.canBlockReload === true;
7037
+ return hasParts || hasPartTarget || hasPartHoldBack || canBlockReload;
7038
+ }
7039
+ },
6942
7040
  {
6943
7041
  key: "onId3Tag",
6944
7042
  value: function onId3Tag(tag) {
@@ -7262,27 +7360,22 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7262
7360
  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 : "?"));
7263
7361
  }
7264
7362
  });
7265
- adPlayer.on("all_ads_completed", function() {
7266
- sendAdImpressionTracking(_this.host.config.licenseKey, {
7363
+ adPlayer.on("ad_impression", function(payload) {
7364
+ var impressionInfo = {
7267
7365
  source: "hls",
7268
7366
  adIndex: _this.timing.currentAdIndex,
7269
- timestamp: /* @__PURE__ */ new Date().toISOString()
7270
- }, _this.analyticsContext).catch(function() {});
7271
- _this.timing.recordPlayedAdDuration(_this.host.getAdPlayer());
7272
- var remaining = _this.timing.getRemainingAdMs();
7273
- _this.timing.consecutiveFailures = 0;
7274
- if (_this.debug) {
7275
- console.log("[StormcloudVideoPlayer] all_ads_completed event received - remaining=".concat(remaining, "ms, queued ads=").concat(_this.adRequestQueue.length), _this.adRequestQueue.length > 0 ? {
7276
- queuedUrls: _to_consumable_array(_this.adRequestQueue)
7277
- } : {});
7367
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
7368
+ };
7369
+ if (payload === null || payload === void 0 ? void 0 : payload.adId) impressionInfo.adId = payload.adId;
7370
+ if (payload === null || payload === void 0 ? void 0 : payload.mediaUrl) impressionInfo.adUrl = payload.mediaUrl;
7371
+ if ((payload === null || payload === void 0 ? void 0 : payload.durationSeconds) != null) {
7372
+ impressionInfo.durationSeconds = payload.durationSeconds;
7278
7373
  }
7279
- if (_this.inAdBreak) {
7280
- if (_this.timing.hasTimeToStartAnotherAd()) {
7281
- _this.tryNextAvailableAdWithRateLimit();
7282
- } else {
7283
- _this.handleAdPodComplete();
7374
+ sendAdImpressionTracking(_this.host.config.licenseKey, impressionInfo, _this.analyticsContext).catch(function(error) {
7375
+ if (_this.debug) {
7376
+ console.warn("[AdBreakOrchestrator] Failed to send ad impression tracking:", error);
7284
7377
  }
7285
- }
7378
+ });
7286
7379
  });
7287
7380
  adPlayer.on("ad_error", function(errorPayload) {
7288
7381
  var errorMessage = "Ad playback failed";
@@ -7325,11 +7418,6 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7325
7418
  }
7326
7419
  });
7327
7420
  adPlayer.on("content_resume", function() {
7328
- sendAdImpressionTracking(_this.host.config.licenseKey, {
7329
- source: "hls",
7330
- adIndex: _this.timing.currentAdIndex,
7331
- timestamp: /* @__PURE__ */ new Date().toISOString()
7332
- }, _this.analyticsContext).catch(function() {});
7333
7421
  if (!_this.host.video.muted) {
7334
7422
  _this.host.video.muted = true;
7335
7423
  if (_this.debug) {
@@ -7567,7 +7655,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7567
7655
  sendAdLoadedTracking(this.host.config.licenseKey, {
7568
7656
  source: "hls",
7569
7657
  vastUrl: podUrl,
7570
- timestamp: /* @__PURE__ */ new Date().toISOString()
7658
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
7571
7659
  }, this.analyticsContext).catch(function() {});
7572
7660
  this.timing.startAdFailsafeTimer(requestToken);
7573
7661
  return [
@@ -8087,7 +8175,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8087
8175
  sendAdLoadedTracking(this.host.config.licenseKey, {
8088
8176
  source: "hls",
8089
8177
  vastUrl: vastTagUrl,
8090
- timestamp: /* @__PURE__ */ new Date().toISOString()
8178
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
8091
8179
  }, this.analyticsContext).catch(function() {});
8092
8180
  this.timing.clearAdRequestWatchdog();
8093
8181
  if (this.timing.activeAdRequestToken !== requestToken) return [
@@ -9068,7 +9156,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9068
9156
  if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;
9069
9157
  sendAdDetectTracking(this.config.licenseKey, _object_spread({
9070
9158
  source: "scte35",
9071
- timestamp: /* @__PURE__ */ new Date().toISOString()
9159
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
9072
9160
  }, detectPayload), buildAnalyticsContext(this.config)).catch(function() {});
9073
9161
  }
9074
9162
  var hasPrefetchedAds = this.adBreak.pendingAdBreak && this.adBreak.pendingAdBreak.vastUrls.length > 0;
@@ -9244,7 +9332,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9244
9332
  if (fragmentSn !== void 0) detectPayload.detectedAtFragmentSn = fragmentSn;
9245
9333
  sendAdDetectTracking(this.config.licenseKey, _object_spread({
9246
9334
  source: "scte35",
9247
- timestamp: /* @__PURE__ */ new Date().toISOString()
9335
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
9248
9336
  }, detectPayload), buildAnalyticsContext(this.config)).catch(function() {});
9249
9337
  if (this.debug) {
9250
9338
  console.log("[PREFETCH] Starting ad prefetch for upcoming ad break");
@@ -9424,6 +9512,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9424
9512
  return this.hlsEngine.isLiveStream;
9425
9513
  }
9426
9514
  },
9515
+ {
9516
+ key: "isLowLatencyStream",
9517
+ value: function isLowLatencyStream() {
9518
+ return this.hlsEngine.isLowLatencyStream();
9519
+ }
9520
+ },
9427
9521
  {
9428
9522
  key: "videoElement",
9429
9523
  get: function get() {