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
@@ -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;
@@ -591,6 +586,7 @@ function createHlsAdPlayer(contentVideo, options) {
591
586
  var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
592
587
  var adEventHandlers = [];
593
588
  var currentAd;
589
+ var currentAdMediaUrl;
594
590
  var podAds = [];
595
591
  var podIndex = 0;
596
592
  var sessionId;
@@ -1408,9 +1404,9 @@ function createHlsAdPlayer(contentVideo, options) {
1408
1404
  delete contentVideo.dataset.stormcloudAdPlaying;
1409
1405
  }
1410
1406
  }
1411
- function resetQuartileTracking(preserveImpression) {
1407
+ function resetQuartileTracking() {
1412
1408
  trackingFired = {
1413
- impression: preserveImpression ? trackingFired.impression : false,
1409
+ impression: false,
1414
1410
  start: false,
1415
1411
  firstQuartile: false,
1416
1412
  midpoint: false,
@@ -1418,6 +1414,27 @@ function createHlsAdPlayer(contentVideo, options) {
1418
1414
  complete: false
1419
1415
  };
1420
1416
  }
1417
+ function markCreativeRendered(reason) {
1418
+ if (!currentAd || trackingFired.impression) return;
1419
+ trackingFired.impression = true;
1420
+ fireTrackingPixels(currentAd.trackingUrls.impression);
1421
+ console.log("[HlsAdPlayer] Impression (pod ".concat(podIndex + 1, "/").concat(podAds.length || 1, ", reason: ").concat(reason, "): ").concat(currentAd.title));
1422
+ emit("ad_impression", {
1423
+ adId: currentAd.id,
1424
+ title: currentAd.title,
1425
+ durationSeconds: currentAd.duration,
1426
+ mediaUrl: currentAdMediaUrl,
1427
+ podIndex: podIndex,
1428
+ podSize: podAds.length || 1,
1429
+ reason: reason
1430
+ });
1431
+ }
1432
+ function canDetectBlackFrames() {
1433
+ if (!adVideoElement) return false;
1434
+ if (requiresMediaPipelineResetAfterAds()) return false;
1435
+ if (isRvfcSupported(adVideoElement)) return true;
1436
+ return getDecodedVideoFrameCount(adVideoElement) !== void 0;
1437
+ }
1421
1438
  function isRvfcSupported(video) {
1422
1439
  return typeof video.requestVideoFrameCallback === "function";
1423
1440
  }
@@ -1480,6 +1497,7 @@ function createHlsAdPlayer(contentVideo, options) {
1480
1497
  if (!mediaFile) {
1481
1498
  throw new Error("No media file available for ad");
1482
1499
  }
1500
+ currentAdMediaUrl = mediaFile.url;
1483
1501
  var isHlsAd = isHlsMediaFile(mediaFile);
1484
1502
  console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad (pod ").concat(podIndex + 1, "/").concat(podAds.length || 1, ") from: ").concat(mediaFile.url));
1485
1503
  if (isHlsAd && import_hls.default.isSupported()) {
@@ -1523,10 +1541,9 @@ function createHlsAdPlayer(contentVideo, options) {
1523
1541
  }
1524
1542
  podIndex++;
1525
1543
  currentAd = podAds[podIndex];
1526
- resetQuartileTracking(false);
1544
+ currentAdMediaUrl = void 0;
1545
+ resetQuartileTracking();
1527
1546
  if (currentAd) {
1528
- fireTrackingPixels(currentAd.trackingUrls.impression);
1529
- trackingFired.impression = true;
1530
1547
  console.log("[HlsAdPlayer] Advancing to next pod ad (".concat(podIndex + 1, "/").concat(podAds.length, "): ").concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1531
1548
  }
1532
1549
  clearStallWatchdog();
@@ -1621,6 +1638,7 @@ function createHlsAdPlayer(contentVideo, options) {
1621
1638
  if (!adPlaying) return;
1622
1639
  sawDecodedVideoFrame = true;
1623
1640
  markRvfcReliable();
1641
+ markCreativeRendered("first_presented_frame");
1624
1642
  };
1625
1643
  try {
1626
1644
  videoFrameCallbackHandle = rvfc.call(adVideoElement, onPresentedFrame);
@@ -1655,6 +1673,7 @@ function createHlsAdPlayer(contentVideo, options) {
1655
1673
  if (decodedFrames !== void 0 && decodedFrames > 0) {
1656
1674
  sawDecodedVideoFrame = true;
1657
1675
  markFrameCounterReliable();
1676
+ markCreativeRendered("decoded_frames");
1658
1677
  } else if (adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S) {
1659
1678
  var timeAdvancing = adVideoElement.currentTime > lastAdProgressPosition + 0.05;
1660
1679
  if (isRvfcSupported(adVideoElement) && timeAdvancing && isRvfcReliable()) {
@@ -1667,6 +1686,9 @@ function createHlsAdPlayer(contentVideo, options) {
1667
1686
  }
1668
1687
  }
1669
1688
  }
1689
+ if (!trackingFired.impression && !adVideoElement.paused && adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S && (sawDecodedVideoFrame || !canDetectBlackFrames())) {
1690
+ markCreativeRendered(sawDecodedVideoFrame ? "decoded_frames" : "sustained_playback");
1691
+ }
1670
1692
  if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
1671
1693
  noteAdProgress();
1672
1694
  return;
@@ -1805,11 +1827,9 @@ function createHlsAdPlayer(contentVideo, options) {
1805
1827
  podAds = ads;
1806
1828
  podIndex = 0;
1807
1829
  currentAd = ads[0];
1830
+ currentAdMediaUrl = void 0;
1831
+ resetQuartileTracking();
1808
1832
  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"));
1809
- if (currentAd) {
1810
- fireTrackingPixels(currentAd.trackingUrls.impression);
1811
- trackingFired.impression = true;
1812
- }
1813
1833
  return [
1814
1834
  2,
1815
1835
  Promise.resolve()
@@ -1849,7 +1869,7 @@ function createHlsAdPlayer(contentVideo, options) {
1849
1869
  contentVideo[AD_VIDEO_PROP] = adVideoElement;
1850
1870
  }
1851
1871
  setupAdEventListeners();
1852
- resetQuartileTracking(true);
1872
+ resetQuartileTracking();
1853
1873
  contentVolume = contentVideo.volume;
1854
1874
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1855
1875
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -1939,6 +1959,7 @@ function createHlsAdPlayer(contentVideo, options) {
1939
1959
  }
1940
1960
  }
1941
1961
  currentAd = void 0;
1962
+ currentAdMediaUrl = void 0;
1942
1963
  podAds = [];
1943
1964
  podIndex = 0;
1944
1965
  return [
@@ -3253,7 +3274,7 @@ function buildPlayerMetricEvent() {
3253
3274
  if (debugAdTiming) {
3254
3275
  console.log("[StormcloudVideoPlayer] playerId: ", playerId);
3255
3276
  }
3256
- captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : /* @__PURE__ */ new Date().toISOString();
3277
+ captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : (/* @__PURE__ */ new Date()).toISOString();
3257
3278
  return [
3258
3279
  2,
3259
3280
  _object_spread({
@@ -3272,8 +3293,19 @@ function buildPlayerMetricEvent() {
3272
3293
  }).apply(this, arguments);
3273
3294
  }
3274
3295
  function publishTracking(licenseKey, channel, body) {
3296
+ var debug = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : false;
3275
3297
  ensureMQTTClient();
3276
- publishMQTT(buildPlayerTopic(licenseKey, channel), body);
3298
+ var topic = buildPlayerTopic(licenseKey, channel);
3299
+ var published = publishMQTT(topic, body);
3300
+ if (debug) {
3301
+ console.log("[StormcloudVideoPlayer] publishTracking:", JSON.stringify({
3302
+ licenseKey: licenseKey,
3303
+ channel: channel,
3304
+ topic: topic,
3305
+ body: body,
3306
+ published: published
3307
+ }, null, 2));
3308
+ }
3277
3309
  }
3278
3310
  function sendInitialTracking(_0) {
3279
3311
  return _async_to_generator(function(licenseKey) {
@@ -3307,7 +3339,7 @@ function sendInitialTracking(_0) {
3307
3339
  events: [
3308
3340
  metricEvent
3309
3341
  ]
3310
- });
3342
+ }, !!context.debugAdTiming);
3311
3343
  return [
3312
3344
  3,
3313
3345
  4
@@ -3417,7 +3449,7 @@ function sendAdLoadedTracking(_0, _1) {
3417
3449
  }
3418
3450
  function sendAdImpressionTracking(_0, _1) {
3419
3451
  return _async_to_generator(function(licenseKey, adImpressionInfo) {
3420
- var context, metricEvent, error;
3452
+ var context, _adImpressionInfo_adUrl, metricEvent, error;
3421
3453
  var _arguments = arguments;
3422
3454
  return _ts_generator(this, function(_state) {
3423
3455
  switch(_state.label){
@@ -3442,17 +3474,18 @@ function sendAdImpressionTracking(_0, _1) {
3442
3474
  ];
3443
3475
  case 2:
3444
3476
  metricEvent = _state.sent();
3445
- publishTracking(licenseKey, "heartbeat", metricEvent);
3477
+ publishTracking(licenseKey, "heartbeat", metricEvent, !!context.debugAdTiming);
3446
3478
  publishTracking(licenseKey, "impressions", {
3447
3479
  events: [
3448
3480
  {
3481
+ event_id: createUuid(),
3449
3482
  player_id: metricEvent.player_id,
3450
3483
  ad_played_count: 1,
3451
- ad_url: adImpressionInfo.adUrl,
3484
+ ad_url: (_adImpressionInfo_adUrl = adImpressionInfo.adUrl) !== null && _adImpressionInfo_adUrl !== void 0 ? _adImpressionInfo_adUrl : adImpressionInfo.adId,
3452
3485
  capture_at: adImpressionInfo.timestamp
3453
3486
  }
3454
3487
  ]
3455
- });
3488
+ }, !!context.debugAdTiming);
3456
3489
  return [
3457
3490
  3,
3458
3491
  4
@@ -3497,7 +3530,7 @@ function sendHeartbeat(_0) {
3497
3530
  ];
3498
3531
  case 2:
3499
3532
  heartbeatData = _state.sent();
3500
- publishTracking(licenseKey, "heartbeat", heartbeatData);
3533
+ publishTracking(licenseKey, "heartbeat", heartbeatData, !!context.debugAdTiming);
3501
3534
  return [
3502
3535
  3,
3503
3536
  4
@@ -6330,7 +6363,7 @@ var AdTimingService = /*#__PURE__*/ function() {
6330
6363
  var _this_callbacks_getAdState = this.callbacks.getAdState(), inAdBreak = _this_callbacks_getAdState.inAdBreak, showAds = _this_callbacks_getAdState.showAds, adPlaying = _this_callbacks_getAdState.adPlaying;
6331
6364
  console.log("[StormcloudVideoPlayer][AdState]", _object_spread({
6332
6365
  event: event,
6333
- timestamp: /* @__PURE__ */ new Date().toISOString(),
6366
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6334
6367
  showAds: showAds,
6335
6368
  adPlaying: adPlaying,
6336
6369
  inAdBreak: inAdBreak,
@@ -6491,6 +6524,7 @@ var HlsEngine = /*#__PURE__*/ function() {
6491
6524
  this.bufferedSegmentsCount = 0;
6492
6525
  this.shouldAutoplayAfterBuffering = false;
6493
6526
  this.hasInitialBufferCompleted = false;
6527
+ this.latencyProfileApplied = false;
6494
6528
  this.config = config;
6495
6529
  this.video = video;
6496
6530
  this.cueManager = cueManager;
@@ -6559,24 +6593,21 @@ var HlsEngine = /*#__PURE__*/ function() {
6559
6593
  key: "setupHls",
6560
6594
  value: function setupHls() {
6561
6595
  var _this = this;
6562
- this.hls = new import_hls2.default(_object_spread_props(_object_spread({
6596
+ this.hls = new import_hls2.default({
6563
6597
  enableWorker: true,
6564
6598
  backBufferLength: 30,
6565
6599
  liveDurationInfinity: true,
6566
6600
  lowLatencyMode: !!this.config.lowLatencyMode,
6567
- maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1
6568
- }, this.config.lowLatencyMode ? {
6569
- liveSyncDuration: 2
6570
- } : {}), {
6601
+ maxLiveSyncPlaybackRate: 1.1,
6571
6602
  maxBufferLength: 30,
6572
6603
  maxMaxBufferLength: 600,
6573
6604
  maxBufferSize: 60 * 1e3 * 1e3,
6574
- maxBufferHole: 0.5,
6605
+ maxBufferHole: 1,
6575
6606
  highBufferWatchdogPeriod: 2,
6576
- nudgeOffset: 0.1,
6577
- nudgeMaxRetry: 3,
6607
+ nudgeOffset: 0.2,
6608
+ nudgeMaxRetry: 5,
6578
6609
  startPosition: -1
6579
- }));
6610
+ });
6580
6611
  this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, function() {
6581
6612
  var _this_hls;
6582
6613
  (_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.loadSource(_this.config.src);
@@ -6600,6 +6631,8 @@ var HlsEngine = /*#__PURE__*/ function() {
6600
6631
  this.bufferedSegmentsCount = 0;
6601
6632
  this.hasInitialBufferCompleted = false;
6602
6633
  this.shouldAutoplayAfterBuffering = !!this.config.autoplay;
6634
+ this.latencyProfileApplied = false;
6635
+ this.detectedLowLatencyStream = void 0;
6603
6636
  minSegments = (_this_config_minSegmentsBeforePlay = this.config.minSegmentsBeforePlay) !== null && _this_config_minSegmentsBeforePlay !== void 0 ? _this_config_minSegmentsBeforePlay : 2;
6604
6637
  if (this.debug) {
6605
6638
  console.log("[StormcloudVideoPlayer] Waiting for", minSegments, "segments to buffer before playback");
@@ -6630,6 +6663,7 @@ var HlsEngine = /*#__PURE__*/ function() {
6630
6663
  }).call(_this);
6631
6664
  });
6632
6665
  this.hls.on(import_hls2.default.Events.LEVEL_LOADED, function(_evt, data) {
6666
+ _this.applyStreamLatencyProfile(data === null || data === void 0 ? void 0 : data.details);
6633
6667
  if (_this.callbacks.isInAdBreak() || _this.callbacks.hasPendingAdBreak()) {
6634
6668
  return;
6635
6669
  }
@@ -6903,6 +6937,70 @@ var HlsEngine = /*#__PURE__*/ function() {
6903
6937
  this.hls.attachMedia(this.video);
6904
6938
  }
6905
6939
  },
6940
+ {
6941
+ key: "isLowLatencyStream",
6942
+ value: function isLowLatencyStream() {
6943
+ return this.detectedLowLatencyStream;
6944
+ }
6945
+ },
6946
+ {
6947
+ key: "applyStreamLatencyProfile",
6948
+ value: function applyStreamLatencyProfile(details) {
6949
+ if (this.latencyProfileApplied || !this.hls) {
6950
+ return;
6951
+ }
6952
+ if (!details) {
6953
+ return;
6954
+ }
6955
+ if (details.live !== true) {
6956
+ this.latencyProfileApplied = true;
6957
+ this.detectedLowLatencyStream = false;
6958
+ return;
6959
+ }
6960
+ var isLowLatencyManifest = this.isLowLatencyManifest(details);
6961
+ var useLowLatency = isLowLatencyManifest && !!this.config.lowLatencyMode;
6962
+ this.detectedLowLatencyStream = useLowLatency;
6963
+ this.latencyProfileApplied = true;
6964
+ var cfg = this.hls.config;
6965
+ if (useLowLatency) {
6966
+ cfg.maxLiveSyncPlaybackRate = 1.5;
6967
+ cfg.maxBufferHole = 0.5;
6968
+ delete cfg.liveSyncDuration;
6969
+ } else {
6970
+ cfg.maxLiveSyncPlaybackRate = 1.1;
6971
+ cfg.maxBufferHole = 1;
6972
+ delete cfg.liveSyncDuration;
6973
+ cfg.liveSyncDurationCount = 3;
6974
+ }
6975
+ if (this.debug) {
6976
+ var _details_targetduration;
6977
+ console.log("[StormcloudVideoPlayer] Live latency profile: ".concat(useLowLatency ? "LL-HLS (low latency)" : "standard live (stability)"), {
6978
+ isLowLatencyManifest: isLowLatencyManifest,
6979
+ lowLatencyModeRequested: !!this.config.lowLatencyMode,
6980
+ canBlockReload: details.canBlockReload,
6981
+ partTarget: details.partTarget,
6982
+ partHoldBack: details.partHoldBack,
6983
+ partListLength: Array.isArray(details.partList) ? details.partList.length : 0,
6984
+ targetDuration: (_details_targetduration = details.targetduration) !== null && _details_targetduration !== void 0 ? _details_targetduration : details.targetDuration,
6985
+ maxLiveSyncPlaybackRate: cfg.maxLiveSyncPlaybackRate,
6986
+ maxBufferHole: cfg.maxBufferHole
6987
+ });
6988
+ }
6989
+ }
6990
+ },
6991
+ {
6992
+ key: "isLowLatencyManifest",
6993
+ value: function isLowLatencyManifest(details) {
6994
+ if (!details) {
6995
+ return false;
6996
+ }
6997
+ var hasParts = Array.isArray(details.partList) && details.partList.length > 0;
6998
+ var hasPartTarget = typeof details.partTarget === "number" && details.partTarget > 0;
6999
+ var hasPartHoldBack = typeof details.partHoldBack === "number" && details.partHoldBack > 0;
7000
+ var canBlockReload = details.canBlockReload === true;
7001
+ return hasParts || hasPartTarget || hasPartHoldBack || canBlockReload;
7002
+ }
7003
+ },
6906
7004
  {
6907
7005
  key: "onId3Tag",
6908
7006
  value: function onId3Tag(tag) {
@@ -7226,27 +7324,22 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7226
7324
  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 : "?"));
7227
7325
  }
7228
7326
  });
7229
- adPlayer.on("all_ads_completed", function() {
7230
- sendAdImpressionTracking(_this.host.config.licenseKey, {
7327
+ adPlayer.on("ad_impression", function(payload) {
7328
+ var impressionInfo = {
7231
7329
  source: "hls",
7232
7330
  adIndex: _this.timing.currentAdIndex,
7233
- timestamp: /* @__PURE__ */ new Date().toISOString()
7234
- }, _this.analyticsContext).catch(function() {});
7235
- _this.timing.recordPlayedAdDuration(_this.host.getAdPlayer());
7236
- var remaining = _this.timing.getRemainingAdMs();
7237
- _this.timing.consecutiveFailures = 0;
7238
- if (_this.debug) {
7239
- console.log("[StormcloudVideoPlayer] all_ads_completed event received - remaining=".concat(remaining, "ms, queued ads=").concat(_this.adRequestQueue.length), _this.adRequestQueue.length > 0 ? {
7240
- queuedUrls: _to_consumable_array(_this.adRequestQueue)
7241
- } : {});
7331
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
7332
+ };
7333
+ if (payload === null || payload === void 0 ? void 0 : payload.adId) impressionInfo.adId = payload.adId;
7334
+ if (payload === null || payload === void 0 ? void 0 : payload.mediaUrl) impressionInfo.adUrl = payload.mediaUrl;
7335
+ if ((payload === null || payload === void 0 ? void 0 : payload.durationSeconds) != null) {
7336
+ impressionInfo.durationSeconds = payload.durationSeconds;
7242
7337
  }
7243
- if (_this.inAdBreak) {
7244
- if (_this.timing.hasTimeToStartAnotherAd()) {
7245
- _this.tryNextAvailableAdWithRateLimit();
7246
- } else {
7247
- _this.handleAdPodComplete();
7338
+ sendAdImpressionTracking(_this.host.config.licenseKey, impressionInfo, _this.analyticsContext).catch(function(error) {
7339
+ if (_this.debug) {
7340
+ console.warn("[AdBreakOrchestrator] Failed to send ad impression tracking:", error);
7248
7341
  }
7249
- }
7342
+ });
7250
7343
  });
7251
7344
  adPlayer.on("ad_error", function(errorPayload) {
7252
7345
  var errorMessage = "Ad playback failed";
@@ -7289,11 +7382,6 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7289
7382
  }
7290
7383
  });
7291
7384
  adPlayer.on("content_resume", function() {
7292
- sendAdImpressionTracking(_this.host.config.licenseKey, {
7293
- source: "hls",
7294
- adIndex: _this.timing.currentAdIndex,
7295
- timestamp: /* @__PURE__ */ new Date().toISOString()
7296
- }, _this.analyticsContext).catch(function() {});
7297
7385
  if (!_this.host.video.muted) {
7298
7386
  _this.host.video.muted = true;
7299
7387
  if (_this.debug) {
@@ -7531,7 +7619,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7531
7619
  sendAdLoadedTracking(this.host.config.licenseKey, {
7532
7620
  source: "hls",
7533
7621
  vastUrl: podUrl,
7534
- timestamp: /* @__PURE__ */ new Date().toISOString()
7622
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
7535
7623
  }, this.analyticsContext).catch(function() {});
7536
7624
  this.timing.startAdFailsafeTimer(requestToken);
7537
7625
  return [
@@ -8051,7 +8139,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8051
8139
  sendAdLoadedTracking(this.host.config.licenseKey, {
8052
8140
  source: "hls",
8053
8141
  vastUrl: vastTagUrl,
8054
- timestamp: /* @__PURE__ */ new Date().toISOString()
8142
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
8055
8143
  }, this.analyticsContext).catch(function() {});
8056
8144
  this.timing.clearAdRequestWatchdog();
8057
8145
  if (this.timing.activeAdRequestToken !== requestToken) return [
@@ -9032,7 +9120,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9032
9120
  if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;
9033
9121
  sendAdDetectTracking(this.config.licenseKey, _object_spread({
9034
9122
  source: "scte35",
9035
- timestamp: /* @__PURE__ */ new Date().toISOString()
9123
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
9036
9124
  }, detectPayload), buildAnalyticsContext(this.config)).catch(function() {});
9037
9125
  }
9038
9126
  var hasPrefetchedAds = this.adBreak.pendingAdBreak && this.adBreak.pendingAdBreak.vastUrls.length > 0;
@@ -9208,7 +9296,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9208
9296
  if (fragmentSn !== void 0) detectPayload.detectedAtFragmentSn = fragmentSn;
9209
9297
  sendAdDetectTracking(this.config.licenseKey, _object_spread({
9210
9298
  source: "scte35",
9211
- timestamp: /* @__PURE__ */ new Date().toISOString()
9299
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
9212
9300
  }, detectPayload), buildAnalyticsContext(this.config)).catch(function() {});
9213
9301
  if (this.debug) {
9214
9302
  console.log("[PREFETCH] Starting ad prefetch for upcoming ad break");
@@ -9388,6 +9476,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9388
9476
  return this.hlsEngine.isLiveStream;
9389
9477
  }
9390
9478
  },
9479
+ {
9480
+ key: "isLowLatencyStream",
9481
+ value: function isLowLatencyStream() {
9482
+ return this.hlsEngine.isLowLatencyStream();
9483
+ }
9484
+ },
9391
9485
  {
9392
9486
  key: "videoElement",
9393
9487
  get: function get() {