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
package/lib/index.cjs CHANGED
@@ -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
  });
@@ -216,9 +215,7 @@ function _object_without_properties_loose(source, excluded) {
216
215
  return target;
217
216
  }
218
217
  function _possible_constructor_return(self, call) {
219
- if (call && (_type_of(call) === "object" || typeof call === "function")) {
220
- return call;
221
- }
218
+ if (call && (_type_of(call) === "object" || typeof call === "function")) return call;
222
219
  return _assert_this_initialized(self);
223
220
  }
224
221
  function _set_prototype_of(o, p) {
@@ -234,26 +231,6 @@ function _sliced_to_array(arr, i) {
234
231
  function _to_consumable_array(arr) {
235
232
  return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
236
233
  }
237
- function _type_of(obj) {
238
- "@swc/helpers - typeof";
239
- return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
240
- }
241
- function _unsupported_iterable_to_array(o, minLen) {
242
- if (!o) return;
243
- if (typeof o === "string") return _array_like_to_array(o, minLen);
244
- var n = Object.prototype.toString.call(o).slice(8, -1);
245
- if (n === "Object" && o.constructor) n = o.constructor.name;
246
- if (n === "Map" || n === "Set") return Array.from(n);
247
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
248
- }
249
- function _is_native_reflect_construct() {
250
- try {
251
- var result = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}));
252
- } catch (_) {}
253
- return (_is_native_reflect_construct = function() {
254
- return !!result;
255
- })();
256
- }
257
234
  function _ts_generator(thisArg, body) {
258
235
  var f, y, t, _ = {
259
236
  label: 0,
@@ -355,18 +332,36 @@ function _ts_generator(thisArg, body) {
355
332
  }
356
333
  function _ts_values(o) {
357
334
  var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
358
- if (m) return m.call(o);
359
- if (o && typeof o.length === "number") return {
360
- next: function() {
361
- if (o && i >= o.length) o = void 0;
362
- return {
363
- value: o && o[i++],
364
- done: !o
365
- };
366
- }
367
- };
335
+ if (m) {
336
+ return m.call(o);
337
+ }
338
+ if (o && typeof o.length === "number") {
339
+ return {
340
+ next: function() {
341
+ if (o && i >= o.length) {
342
+ o = void 0;
343
+ }
344
+ return {
345
+ value: o && o[i++],
346
+ done: !o
347
+ };
348
+ }
349
+ };
350
+ }
368
351
  throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
369
352
  }
353
+ function _type_of(obj) {
354
+ "@swc/helpers - typeof";
355
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
356
+ }
357
+ function _unsupported_iterable_to_array(o, minLen) {
358
+ if (!o) return;
359
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
360
+ var n = Object.prototype.toString.call(o).slice(8, -1);
361
+ if (n === "Object" && o.constructor) n = o.constructor.name;
362
+ if (n === "Map" || n === "Set") return Array.from(n);
363
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
364
+ }
370
365
  var __create = Object.create;
371
366
  var __defProp = Object.defineProperty;
372
367
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -804,6 +799,7 @@ function createHlsAdPlayer(contentVideo, options) {
804
799
  var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
805
800
  var adEventHandlers = [];
806
801
  var currentAd;
802
+ var currentAdMediaUrl;
807
803
  var podAds = [];
808
804
  var podIndex = 0;
809
805
  var sessionId;
@@ -1621,9 +1617,9 @@ function createHlsAdPlayer(contentVideo, options) {
1621
1617
  delete contentVideo.dataset.stormcloudAdPlaying;
1622
1618
  }
1623
1619
  }
1624
- function resetQuartileTracking(preserveImpression) {
1620
+ function resetQuartileTracking() {
1625
1621
  trackingFired = {
1626
- impression: preserveImpression ? trackingFired.impression : false,
1622
+ impression: false,
1627
1623
  start: false,
1628
1624
  firstQuartile: false,
1629
1625
  midpoint: false,
@@ -1631,6 +1627,27 @@ function createHlsAdPlayer(contentVideo, options) {
1631
1627
  complete: false
1632
1628
  };
1633
1629
  }
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
+ }
1634
1651
  function isRvfcSupported(video) {
1635
1652
  return typeof video.requestVideoFrameCallback === "function";
1636
1653
  }
@@ -1693,6 +1710,7 @@ function createHlsAdPlayer(contentVideo, options) {
1693
1710
  if (!mediaFile) {
1694
1711
  throw new Error("No media file available for ad");
1695
1712
  }
1713
+ currentAdMediaUrl = mediaFile.url;
1696
1714
  var isHlsAd = isHlsMediaFile(mediaFile);
1697
1715
  console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad (pod ").concat(podIndex + 1, "/").concat(podAds.length || 1, ") from: ").concat(mediaFile.url));
1698
1716
  if (isHlsAd && import_hls.default.isSupported()) {
@@ -1736,10 +1754,9 @@ function createHlsAdPlayer(contentVideo, options) {
1736
1754
  }
1737
1755
  podIndex++;
1738
1756
  currentAd = podAds[podIndex];
1739
- resetQuartileTracking(false);
1757
+ currentAdMediaUrl = void 0;
1758
+ resetQuartileTracking();
1740
1759
  if (currentAd) {
1741
- fireTrackingPixels(currentAd.trackingUrls.impression);
1742
- trackingFired.impression = true;
1743
1760
  console.log("[HlsAdPlayer] Advancing to next pod ad (".concat(podIndex + 1, "/").concat(podAds.length, "): ").concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1744
1761
  }
1745
1762
  clearStallWatchdog();
@@ -1834,6 +1851,7 @@ function createHlsAdPlayer(contentVideo, options) {
1834
1851
  if (!adPlaying) return;
1835
1852
  sawDecodedVideoFrame = true;
1836
1853
  markRvfcReliable();
1854
+ markCreativeRendered("first_presented_frame");
1837
1855
  };
1838
1856
  try {
1839
1857
  videoFrameCallbackHandle = rvfc.call(adVideoElement, onPresentedFrame);
@@ -1868,6 +1886,7 @@ function createHlsAdPlayer(contentVideo, options) {
1868
1886
  if (decodedFrames !== void 0 && decodedFrames > 0) {
1869
1887
  sawDecodedVideoFrame = true;
1870
1888
  markFrameCounterReliable();
1889
+ markCreativeRendered("decoded_frames");
1871
1890
  } else if (adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S) {
1872
1891
  var timeAdvancing = adVideoElement.currentTime > lastAdProgressPosition + 0.05;
1873
1892
  if (isRvfcSupported(adVideoElement) && timeAdvancing && isRvfcReliable()) {
@@ -1880,6 +1899,9 @@ function createHlsAdPlayer(contentVideo, options) {
1880
1899
  }
1881
1900
  }
1882
1901
  }
1902
+ if (!trackingFired.impression && !adVideoElement.paused && adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S && (sawDecodedVideoFrame || !canDetectBlackFrames())) {
1903
+ markCreativeRendered(sawDecodedVideoFrame ? "decoded_frames" : "sustained_playback");
1904
+ }
1883
1905
  if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
1884
1906
  noteAdProgress();
1885
1907
  return;
@@ -2018,11 +2040,9 @@ function createHlsAdPlayer(contentVideo, options) {
2018
2040
  podAds = ads;
2019
2041
  podIndex = 0;
2020
2042
  currentAd = ads[0];
2043
+ currentAdMediaUrl = void 0;
2044
+ resetQuartileTracking();
2021
2045
  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"));
2022
- if (currentAd) {
2023
- fireTrackingPixels(currentAd.trackingUrls.impression);
2024
- trackingFired.impression = true;
2025
- }
2026
2046
  return [
2027
2047
  2,
2028
2048
  Promise.resolve()
@@ -2062,7 +2082,7 @@ function createHlsAdPlayer(contentVideo, options) {
2062
2082
  contentVideo[AD_VIDEO_PROP] = adVideoElement;
2063
2083
  }
2064
2084
  setupAdEventListeners();
2065
- resetQuartileTracking(true);
2085
+ resetQuartileTracking();
2066
2086
  contentVolume = contentVideo.volume;
2067
2087
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
2068
2088
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -2152,6 +2172,7 @@ function createHlsAdPlayer(contentVideo, options) {
2152
2172
  }
2153
2173
  }
2154
2174
  currentAd = void 0;
2175
+ currentAdMediaUrl = void 0;
2155
2176
  podAds = [];
2156
2177
  podIndex = 0;
2157
2178
  return [
@@ -3487,7 +3508,7 @@ function buildPlayerMetricEvent() {
3487
3508
  if (debugAdTiming) {
3488
3509
  console.log("[StormcloudVideoPlayer] playerId: ", playerId);
3489
3510
  }
3490
- captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : /* @__PURE__ */ new Date().toISOString();
3511
+ captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : (/* @__PURE__ */ new Date()).toISOString();
3491
3512
  return [
3492
3513
  2,
3493
3514
  _object_spread({
@@ -3506,8 +3527,19 @@ function buildPlayerMetricEvent() {
3506
3527
  }).apply(this, arguments);
3507
3528
  }
3508
3529
  function publishTracking(licenseKey, channel, body) {
3530
+ var debug = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : false;
3509
3531
  ensureMQTTClient();
3510
- publishMQTT(buildPlayerTopic(licenseKey, channel), body);
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
+ }
3511
3543
  }
3512
3544
  function sendInitialTracking(_0) {
3513
3545
  return _async_to_generator(function(licenseKey) {
@@ -3541,7 +3573,7 @@ function sendInitialTracking(_0) {
3541
3573
  events: [
3542
3574
  metricEvent
3543
3575
  ]
3544
- });
3576
+ }, !!context.debugAdTiming);
3545
3577
  return [
3546
3578
  3,
3547
3579
  4
@@ -3651,7 +3683,7 @@ function sendAdLoadedTracking(_0, _1) {
3651
3683
  }
3652
3684
  function sendAdImpressionTracking(_0, _1) {
3653
3685
  return _async_to_generator(function(licenseKey, adImpressionInfo) {
3654
- var context, metricEvent, error;
3686
+ var context, _adImpressionInfo_adUrl, metricEvent, error;
3655
3687
  var _arguments = arguments;
3656
3688
  return _ts_generator(this, function(_state) {
3657
3689
  switch(_state.label){
@@ -3676,17 +3708,18 @@ function sendAdImpressionTracking(_0, _1) {
3676
3708
  ];
3677
3709
  case 2:
3678
3710
  metricEvent = _state.sent();
3679
- publishTracking(licenseKey, "heartbeat", metricEvent);
3711
+ publishTracking(licenseKey, "heartbeat", metricEvent, !!context.debugAdTiming);
3680
3712
  publishTracking(licenseKey, "impressions", {
3681
3713
  events: [
3682
3714
  {
3715
+ event_id: createUuid(),
3683
3716
  player_id: metricEvent.player_id,
3684
3717
  ad_played_count: 1,
3685
- ad_url: adImpressionInfo.adUrl,
3718
+ ad_url: (_adImpressionInfo_adUrl = adImpressionInfo.adUrl) !== null && _adImpressionInfo_adUrl !== void 0 ? _adImpressionInfo_adUrl : adImpressionInfo.adId,
3686
3719
  capture_at: adImpressionInfo.timestamp
3687
3720
  }
3688
3721
  ]
3689
- });
3722
+ }, !!context.debugAdTiming);
3690
3723
  return [
3691
3724
  3,
3692
3725
  4
@@ -3731,7 +3764,7 @@ function sendHeartbeat(_0) {
3731
3764
  ];
3732
3765
  case 2:
3733
3766
  heartbeatData = _state.sent();
3734
- publishTracking(licenseKey, "heartbeat", heartbeatData);
3767
+ publishTracking(licenseKey, "heartbeat", heartbeatData, !!context.debugAdTiming);
3735
3768
  return [
3736
3769
  3,
3737
3770
  4
@@ -6564,7 +6597,7 @@ var AdTimingService = /*#__PURE__*/ function() {
6564
6597
  var _this_callbacks_getAdState = this.callbacks.getAdState(), inAdBreak = _this_callbacks_getAdState.inAdBreak, showAds = _this_callbacks_getAdState.showAds, adPlaying = _this_callbacks_getAdState.adPlaying;
6565
6598
  console.log("[StormcloudVideoPlayer][AdState]", _object_spread({
6566
6599
  event: event,
6567
- timestamp: /* @__PURE__ */ new Date().toISOString(),
6600
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6568
6601
  showAds: showAds,
6569
6602
  adPlaying: adPlaying,
6570
6603
  inAdBreak: inAdBreak,
@@ -6725,6 +6758,7 @@ var HlsEngine = /*#__PURE__*/ function() {
6725
6758
  this.bufferedSegmentsCount = 0;
6726
6759
  this.shouldAutoplayAfterBuffering = false;
6727
6760
  this.hasInitialBufferCompleted = false;
6761
+ this.latencyProfileApplied = false;
6728
6762
  this.config = config;
6729
6763
  this.video = video;
6730
6764
  this.cueManager = cueManager;
@@ -6793,24 +6827,21 @@ var HlsEngine = /*#__PURE__*/ function() {
6793
6827
  key: "setupHls",
6794
6828
  value: function setupHls() {
6795
6829
  var _this = this;
6796
- this.hls = new import_hls2.default(_object_spread_props(_object_spread({
6830
+ this.hls = new import_hls2.default({
6797
6831
  enableWorker: true,
6798
6832
  backBufferLength: 30,
6799
6833
  liveDurationInfinity: true,
6800
6834
  lowLatencyMode: !!this.config.lowLatencyMode,
6801
- maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1
6802
- }, this.config.lowLatencyMode ? {
6803
- liveSyncDuration: 2
6804
- } : {}), {
6835
+ maxLiveSyncPlaybackRate: 1.1,
6805
6836
  maxBufferLength: 30,
6806
6837
  maxMaxBufferLength: 600,
6807
6838
  maxBufferSize: 60 * 1e3 * 1e3,
6808
- maxBufferHole: 0.5,
6839
+ maxBufferHole: 1,
6809
6840
  highBufferWatchdogPeriod: 2,
6810
- nudgeOffset: 0.1,
6811
- nudgeMaxRetry: 3,
6841
+ nudgeOffset: 0.2,
6842
+ nudgeMaxRetry: 5,
6812
6843
  startPosition: -1
6813
- }));
6844
+ });
6814
6845
  this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, function() {
6815
6846
  var _this_hls;
6816
6847
  (_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.loadSource(_this.config.src);
@@ -6834,6 +6865,8 @@ var HlsEngine = /*#__PURE__*/ function() {
6834
6865
  this.bufferedSegmentsCount = 0;
6835
6866
  this.hasInitialBufferCompleted = false;
6836
6867
  this.shouldAutoplayAfterBuffering = !!this.config.autoplay;
6868
+ this.latencyProfileApplied = false;
6869
+ this.detectedLowLatencyStream = void 0;
6837
6870
  minSegments = (_this_config_minSegmentsBeforePlay = this.config.minSegmentsBeforePlay) !== null && _this_config_minSegmentsBeforePlay !== void 0 ? _this_config_minSegmentsBeforePlay : 2;
6838
6871
  if (this.debug) {
6839
6872
  console.log("[StormcloudVideoPlayer] Waiting for", minSegments, "segments to buffer before playback");
@@ -6864,6 +6897,7 @@ var HlsEngine = /*#__PURE__*/ function() {
6864
6897
  }).call(_this);
6865
6898
  });
6866
6899
  this.hls.on(import_hls2.default.Events.LEVEL_LOADED, function(_evt, data) {
6900
+ _this.applyStreamLatencyProfile(data === null || data === void 0 ? void 0 : data.details);
6867
6901
  if (_this.callbacks.isInAdBreak() || _this.callbacks.hasPendingAdBreak()) {
6868
6902
  return;
6869
6903
  }
@@ -7137,6 +7171,70 @@ var HlsEngine = /*#__PURE__*/ function() {
7137
7171
  this.hls.attachMedia(this.video);
7138
7172
  }
7139
7173
  },
7174
+ {
7175
+ key: "isLowLatencyStream",
7176
+ value: function isLowLatencyStream() {
7177
+ return this.detectedLowLatencyStream;
7178
+ }
7179
+ },
7180
+ {
7181
+ key: "applyStreamLatencyProfile",
7182
+ value: function applyStreamLatencyProfile(details) {
7183
+ if (this.latencyProfileApplied || !this.hls) {
7184
+ return;
7185
+ }
7186
+ if (!details) {
7187
+ return;
7188
+ }
7189
+ if (details.live !== true) {
7190
+ this.latencyProfileApplied = true;
7191
+ this.detectedLowLatencyStream = false;
7192
+ return;
7193
+ }
7194
+ var isLowLatencyManifest = this.isLowLatencyManifest(details);
7195
+ var useLowLatency = isLowLatencyManifest && !!this.config.lowLatencyMode;
7196
+ this.detectedLowLatencyStream = useLowLatency;
7197
+ this.latencyProfileApplied = true;
7198
+ var cfg = this.hls.config;
7199
+ if (useLowLatency) {
7200
+ cfg.maxLiveSyncPlaybackRate = 1.5;
7201
+ cfg.maxBufferHole = 0.5;
7202
+ delete cfg.liveSyncDuration;
7203
+ } else {
7204
+ cfg.maxLiveSyncPlaybackRate = 1.1;
7205
+ cfg.maxBufferHole = 1;
7206
+ delete cfg.liveSyncDuration;
7207
+ cfg.liveSyncDurationCount = 3;
7208
+ }
7209
+ if (this.debug) {
7210
+ var _details_targetduration;
7211
+ console.log("[StormcloudVideoPlayer] Live latency profile: ".concat(useLowLatency ? "LL-HLS (low latency)" : "standard live (stability)"), {
7212
+ isLowLatencyManifest: isLowLatencyManifest,
7213
+ lowLatencyModeRequested: !!this.config.lowLatencyMode,
7214
+ canBlockReload: details.canBlockReload,
7215
+ partTarget: details.partTarget,
7216
+ partHoldBack: details.partHoldBack,
7217
+ partListLength: Array.isArray(details.partList) ? details.partList.length : 0,
7218
+ targetDuration: (_details_targetduration = details.targetduration) !== null && _details_targetduration !== void 0 ? _details_targetduration : details.targetDuration,
7219
+ maxLiveSyncPlaybackRate: cfg.maxLiveSyncPlaybackRate,
7220
+ maxBufferHole: cfg.maxBufferHole
7221
+ });
7222
+ }
7223
+ }
7224
+ },
7225
+ {
7226
+ key: "isLowLatencyManifest",
7227
+ value: function isLowLatencyManifest(details) {
7228
+ if (!details) {
7229
+ return false;
7230
+ }
7231
+ var hasParts = Array.isArray(details.partList) && details.partList.length > 0;
7232
+ var hasPartTarget = typeof details.partTarget === "number" && details.partTarget > 0;
7233
+ var hasPartHoldBack = typeof details.partHoldBack === "number" && details.partHoldBack > 0;
7234
+ var canBlockReload = details.canBlockReload === true;
7235
+ return hasParts || hasPartTarget || hasPartHoldBack || canBlockReload;
7236
+ }
7237
+ },
7140
7238
  {
7141
7239
  key: "onId3Tag",
7142
7240
  value: function onId3Tag(tag) {
@@ -7460,27 +7558,22 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7460
7558
  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 : "?"));
7461
7559
  }
7462
7560
  });
7463
- adPlayer.on("all_ads_completed", function() {
7464
- sendAdImpressionTracking(_this.host.config.licenseKey, {
7561
+ adPlayer.on("ad_impression", function(payload) {
7562
+ var impressionInfo = {
7465
7563
  source: "hls",
7466
7564
  adIndex: _this.timing.currentAdIndex,
7467
- timestamp: /* @__PURE__ */ new Date().toISOString()
7468
- }, _this.analyticsContext).catch(function() {});
7469
- _this.timing.recordPlayedAdDuration(_this.host.getAdPlayer());
7470
- var remaining = _this.timing.getRemainingAdMs();
7471
- _this.timing.consecutiveFailures = 0;
7472
- if (_this.debug) {
7473
- console.log("[StormcloudVideoPlayer] all_ads_completed event received - remaining=".concat(remaining, "ms, queued ads=").concat(_this.adRequestQueue.length), _this.adRequestQueue.length > 0 ? {
7474
- queuedUrls: _to_consumable_array(_this.adRequestQueue)
7475
- } : {});
7565
+ 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;
7476
7571
  }
7477
- if (_this.inAdBreak) {
7478
- if (_this.timing.hasTimeToStartAnotherAd()) {
7479
- _this.tryNextAvailableAdWithRateLimit();
7480
- } else {
7481
- _this.handleAdPodComplete();
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);
7482
7575
  }
7483
- }
7576
+ });
7484
7577
  });
7485
7578
  adPlayer.on("ad_error", function(errorPayload) {
7486
7579
  var errorMessage = "Ad playback failed";
@@ -7523,11 +7616,6 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7523
7616
  }
7524
7617
  });
7525
7618
  adPlayer.on("content_resume", function() {
7526
- sendAdImpressionTracking(_this.host.config.licenseKey, {
7527
- source: "hls",
7528
- adIndex: _this.timing.currentAdIndex,
7529
- timestamp: /* @__PURE__ */ new Date().toISOString()
7530
- }, _this.analyticsContext).catch(function() {});
7531
7619
  if (!_this.host.video.muted) {
7532
7620
  _this.host.video.muted = true;
7533
7621
  if (_this.debug) {
@@ -7765,7 +7853,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7765
7853
  sendAdLoadedTracking(this.host.config.licenseKey, {
7766
7854
  source: "hls",
7767
7855
  vastUrl: podUrl,
7768
- timestamp: /* @__PURE__ */ new Date().toISOString()
7856
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
7769
7857
  }, this.analyticsContext).catch(function() {});
7770
7858
  this.timing.startAdFailsafeTimer(requestToken);
7771
7859
  return [
@@ -8285,7 +8373,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8285
8373
  sendAdLoadedTracking(this.host.config.licenseKey, {
8286
8374
  source: "hls",
8287
8375
  vastUrl: vastTagUrl,
8288
- timestamp: /* @__PURE__ */ new Date().toISOString()
8376
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
8289
8377
  }, this.analyticsContext).catch(function() {});
8290
8378
  this.timing.clearAdRequestWatchdog();
8291
8379
  if (this.timing.activeAdRequestToken !== requestToken) return [
@@ -9266,7 +9354,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9266
9354
  if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;
9267
9355
  sendAdDetectTracking(this.config.licenseKey, _object_spread({
9268
9356
  source: "scte35",
9269
- timestamp: /* @__PURE__ */ new Date().toISOString()
9357
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
9270
9358
  }, detectPayload), buildAnalyticsContext(this.config)).catch(function() {});
9271
9359
  }
9272
9360
  var hasPrefetchedAds = this.adBreak.pendingAdBreak && this.adBreak.pendingAdBreak.vastUrls.length > 0;
@@ -9442,7 +9530,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9442
9530
  if (fragmentSn !== void 0) detectPayload.detectedAtFragmentSn = fragmentSn;
9443
9531
  sendAdDetectTracking(this.config.licenseKey, _object_spread({
9444
9532
  source: "scte35",
9445
- timestamp: /* @__PURE__ */ new Date().toISOString()
9533
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
9446
9534
  }, detectPayload), buildAnalyticsContext(this.config)).catch(function() {});
9447
9535
  if (this.debug) {
9448
9536
  console.log("[PREFETCH] Starting ad prefetch for upcoming ad break");
@@ -9622,6 +9710,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9622
9710
  return this.hlsEngine.isLiveStream;
9623
9711
  }
9624
9712
  },
9713
+ {
9714
+ key: "isLowLatencyStream",
9715
+ value: function isLowLatencyStream() {
9716
+ return this.hlsEngine.isLowLatencyStream();
9717
+ }
9718
+ },
9625
9719
  {
9626
9720
  key: "videoElement",
9627
9721
  get: function get() {