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
@@ -18,11 +18,8 @@ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
18
18
  reject(error);
19
19
  return;
20
20
  }
21
- if (info.done) {
22
- resolve(value);
23
- } else {
24
- Promise.resolve(value).then(_next, _throw);
25
- }
21
+ if (info.done) resolve(value);
22
+ else Promise.resolve(value).then(_next, _throw);
26
23
  }
27
24
  function _async_to_generator(fn) {
28
25
  return function() {
@@ -40,9 +37,7 @@ function _async_to_generator(fn) {
40
37
  };
41
38
  }
42
39
  function _class_call_check(instance, Constructor) {
43
- if (!(instance instanceof Constructor)) {
44
- throw new TypeError("Cannot call a class as a function");
45
- }
40
+ if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
46
41
  }
47
42
  function _defineProperties(target, props) {
48
43
  for(var i = 0; i < props.length; i++){
@@ -66,20 +61,19 @@ function _define_property(obj, key, value) {
66
61
  configurable: true,
67
62
  writable: true
68
63
  });
69
- } else {
70
- obj[key] = value;
71
- }
64
+ } else obj[key] = value;
72
65
  return obj;
73
66
  }
74
67
  function _instanceof(left, right) {
68
+ "@swc/helpers - instanceof";
75
69
  if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
76
70
  return !!right[Symbol.hasInstance](left);
77
- } else {
78
- return left instanceof right;
79
- }
71
+ } else return left instanceof right;
80
72
  }
81
73
  function _iterable_to_array(iter) {
82
- if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
74
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) {
75
+ return Array.from(iter);
76
+ }
83
77
  }
84
78
  function _iterable_to_array_limit(arr, i) {
85
79
  var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
@@ -106,10 +100,10 @@ function _iterable_to_array_limit(arr, i) {
106
100
  return _arr;
107
101
  }
108
102
  function _non_iterable_rest() {
109
- throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
103
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
110
104
  }
111
105
  function _non_iterable_spread() {
112
- throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
106
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
113
107
  }
114
108
  function _object_spread(target) {
115
109
  for(var i = 1; i < arguments.length; i++){
@@ -141,9 +135,8 @@ function ownKeys(object, enumerableOnly) {
141
135
  }
142
136
  function _object_spread_props(target, source) {
143
137
  source = source != null ? source : {};
144
- if (Object.getOwnPropertyDescriptors) {
145
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
146
- } else {
138
+ if (Object.getOwnPropertyDescriptors) Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
139
+ else {
147
140
  ownKeys(Object(source)).forEach(function(key) {
148
141
  Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
149
142
  });
@@ -192,18 +185,6 @@ function _sliced_to_array(arr, i) {
192
185
  function _to_consumable_array(arr) {
193
186
  return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
194
187
  }
195
- function _type_of(obj) {
196
- "@swc/helpers - typeof";
197
- return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
198
- }
199
- function _unsupported_iterable_to_array(o, minLen) {
200
- if (!o) return;
201
- if (typeof o === "string") return _array_like_to_array(o, minLen);
202
- var n = Object.prototype.toString.call(o).slice(8, -1);
203
- if (n === "Object" && o.constructor) n = o.constructor.name;
204
- if (n === "Map" || n === "Set") return Array.from(n);
205
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
206
- }
207
188
  function _ts_generator(thisArg, body) {
208
189
  var f, y, t, _ = {
209
190
  label: 0,
@@ -305,18 +286,36 @@ function _ts_generator(thisArg, body) {
305
286
  }
306
287
  function _ts_values(o) {
307
288
  var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
308
- if (m) return m.call(o);
309
- if (o && typeof o.length === "number") return {
310
- next: function() {
311
- if (o && i >= o.length) o = void 0;
312
- return {
313
- value: o && o[i++],
314
- done: !o
315
- };
316
- }
317
- };
289
+ if (m) {
290
+ return m.call(o);
291
+ }
292
+ if (o && typeof o.length === "number") {
293
+ return {
294
+ next: function() {
295
+ if (o && i >= o.length) {
296
+ o = void 0;
297
+ }
298
+ return {
299
+ value: o && o[i++],
300
+ done: !o
301
+ };
302
+ }
303
+ };
304
+ }
318
305
  throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
319
306
  }
307
+ function _type_of(obj) {
308
+ "@swc/helpers - typeof";
309
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
310
+ }
311
+ function _unsupported_iterable_to_array(o, minLen) {
312
+ if (!o) return;
313
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
314
+ var n = Object.prototype.toString.call(o).slice(8, -1);
315
+ if (n === "Object" && o.constructor) n = o.constructor.name;
316
+ if (n === "Map" || n === "Set") return Array.from(n);
317
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
318
+ }
320
319
  var __create = Object.create;
321
320
  var __defProp = Object.defineProperty;
322
321
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -577,6 +576,7 @@ function createHlsAdPlayer(contentVideo, options) {
577
576
  var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
578
577
  var adEventHandlers = [];
579
578
  var currentAd;
579
+ var currentAdMediaUrl;
580
580
  var podAds = [];
581
581
  var podIndex = 0;
582
582
  var sessionId;
@@ -1394,9 +1394,9 @@ function createHlsAdPlayer(contentVideo, options) {
1394
1394
  delete contentVideo.dataset.stormcloudAdPlaying;
1395
1395
  }
1396
1396
  }
1397
- function resetQuartileTracking(preserveImpression) {
1397
+ function resetQuartileTracking() {
1398
1398
  trackingFired = {
1399
- impression: preserveImpression ? trackingFired.impression : false,
1399
+ impression: false,
1400
1400
  start: false,
1401
1401
  firstQuartile: false,
1402
1402
  midpoint: false,
@@ -1404,6 +1404,27 @@ function createHlsAdPlayer(contentVideo, options) {
1404
1404
  complete: false
1405
1405
  };
1406
1406
  }
1407
+ function markCreativeRendered(reason) {
1408
+ if (!currentAd || trackingFired.impression) return;
1409
+ trackingFired.impression = true;
1410
+ fireTrackingPixels(currentAd.trackingUrls.impression);
1411
+ console.log("[HlsAdPlayer] Impression (pod ".concat(podIndex + 1, "/").concat(podAds.length || 1, ", reason: ").concat(reason, "): ").concat(currentAd.title));
1412
+ emit("ad_impression", {
1413
+ adId: currentAd.id,
1414
+ title: currentAd.title,
1415
+ durationSeconds: currentAd.duration,
1416
+ mediaUrl: currentAdMediaUrl,
1417
+ podIndex: podIndex,
1418
+ podSize: podAds.length || 1,
1419
+ reason: reason
1420
+ });
1421
+ }
1422
+ function canDetectBlackFrames() {
1423
+ if (!adVideoElement) return false;
1424
+ if (requiresMediaPipelineResetAfterAds()) return false;
1425
+ if (isRvfcSupported(adVideoElement)) return true;
1426
+ return getDecodedVideoFrameCount(adVideoElement) !== void 0;
1427
+ }
1407
1428
  function isRvfcSupported(video) {
1408
1429
  return typeof video.requestVideoFrameCallback === "function";
1409
1430
  }
@@ -1466,6 +1487,7 @@ function createHlsAdPlayer(contentVideo, options) {
1466
1487
  if (!mediaFile) {
1467
1488
  throw new Error("No media file available for ad");
1468
1489
  }
1490
+ currentAdMediaUrl = mediaFile.url;
1469
1491
  var isHlsAd = isHlsMediaFile(mediaFile);
1470
1492
  console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad (pod ").concat(podIndex + 1, "/").concat(podAds.length || 1, ") from: ").concat(mediaFile.url));
1471
1493
  if (isHlsAd && import_hls.default.isSupported()) {
@@ -1509,10 +1531,9 @@ function createHlsAdPlayer(contentVideo, options) {
1509
1531
  }
1510
1532
  podIndex++;
1511
1533
  currentAd = podAds[podIndex];
1512
- resetQuartileTracking(false);
1534
+ currentAdMediaUrl = void 0;
1535
+ resetQuartileTracking();
1513
1536
  if (currentAd) {
1514
- fireTrackingPixels(currentAd.trackingUrls.impression);
1515
- trackingFired.impression = true;
1516
1537
  console.log("[HlsAdPlayer] Advancing to next pod ad (".concat(podIndex + 1, "/").concat(podAds.length, "): ").concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1517
1538
  }
1518
1539
  clearStallWatchdog();
@@ -1607,6 +1628,7 @@ function createHlsAdPlayer(contentVideo, options) {
1607
1628
  if (!adPlaying) return;
1608
1629
  sawDecodedVideoFrame = true;
1609
1630
  markRvfcReliable();
1631
+ markCreativeRendered("first_presented_frame");
1610
1632
  };
1611
1633
  try {
1612
1634
  videoFrameCallbackHandle = rvfc.call(adVideoElement, onPresentedFrame);
@@ -1641,6 +1663,7 @@ function createHlsAdPlayer(contentVideo, options) {
1641
1663
  if (decodedFrames !== void 0 && decodedFrames > 0) {
1642
1664
  sawDecodedVideoFrame = true;
1643
1665
  markFrameCounterReliable();
1666
+ markCreativeRendered("decoded_frames");
1644
1667
  } else if (adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S) {
1645
1668
  var timeAdvancing = adVideoElement.currentTime > lastAdProgressPosition + 0.05;
1646
1669
  if (isRvfcSupported(adVideoElement) && timeAdvancing && isRvfcReliable()) {
@@ -1653,6 +1676,9 @@ function createHlsAdPlayer(contentVideo, options) {
1653
1676
  }
1654
1677
  }
1655
1678
  }
1679
+ if (!trackingFired.impression && !adVideoElement.paused && adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S && (sawDecodedVideoFrame || !canDetectBlackFrames())) {
1680
+ markCreativeRendered(sawDecodedVideoFrame ? "decoded_frames" : "sustained_playback");
1681
+ }
1656
1682
  if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
1657
1683
  noteAdProgress();
1658
1684
  return;
@@ -1791,11 +1817,9 @@ function createHlsAdPlayer(contentVideo, options) {
1791
1817
  podAds = ads;
1792
1818
  podIndex = 0;
1793
1819
  currentAd = ads[0];
1820
+ currentAdMediaUrl = void 0;
1821
+ resetQuartileTracking();
1794
1822
  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"));
1795
- if (currentAd) {
1796
- fireTrackingPixels(currentAd.trackingUrls.impression);
1797
- trackingFired.impression = true;
1798
- }
1799
1823
  return [
1800
1824
  2,
1801
1825
  Promise.resolve()
@@ -1835,7 +1859,7 @@ function createHlsAdPlayer(contentVideo, options) {
1835
1859
  contentVideo[AD_VIDEO_PROP] = adVideoElement;
1836
1860
  }
1837
1861
  setupAdEventListeners();
1838
- resetQuartileTracking(true);
1862
+ resetQuartileTracking();
1839
1863
  contentVolume = contentVideo.volume;
1840
1864
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1841
1865
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -1925,6 +1949,7 @@ function createHlsAdPlayer(contentVideo, options) {
1925
1949
  }
1926
1950
  }
1927
1951
  currentAd = void 0;
1952
+ currentAdMediaUrl = void 0;
1928
1953
  podAds = [];
1929
1954
  podIndex = 0;
1930
1955
  return [
@@ -3239,7 +3264,7 @@ function buildPlayerMetricEvent() {
3239
3264
  if (debugAdTiming) {
3240
3265
  console.log("[StormcloudVideoPlayer] playerId: ", playerId);
3241
3266
  }
3242
- captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : /* @__PURE__ */ new Date().toISOString();
3267
+ captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : (/* @__PURE__ */ new Date()).toISOString();
3243
3268
  return [
3244
3269
  2,
3245
3270
  _object_spread({
@@ -3258,8 +3283,19 @@ function buildPlayerMetricEvent() {
3258
3283
  }).apply(this, arguments);
3259
3284
  }
3260
3285
  function publishTracking(licenseKey, channel, body) {
3286
+ var debug = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : false;
3261
3287
  ensureMQTTClient();
3262
- publishMQTT(buildPlayerTopic(licenseKey, channel), body);
3288
+ var topic = buildPlayerTopic(licenseKey, channel);
3289
+ var published = publishMQTT(topic, body);
3290
+ if (debug) {
3291
+ console.log("[StormcloudVideoPlayer] publishTracking:", JSON.stringify({
3292
+ licenseKey: licenseKey,
3293
+ channel: channel,
3294
+ topic: topic,
3295
+ body: body,
3296
+ published: published
3297
+ }, null, 2));
3298
+ }
3263
3299
  }
3264
3300
  function sendInitialTracking(_0) {
3265
3301
  return _async_to_generator(function(licenseKey) {
@@ -3293,7 +3329,7 @@ function sendInitialTracking(_0) {
3293
3329
  events: [
3294
3330
  metricEvent
3295
3331
  ]
3296
- });
3332
+ }, !!context.debugAdTiming);
3297
3333
  return [
3298
3334
  3,
3299
3335
  4
@@ -3403,7 +3439,7 @@ function sendAdLoadedTracking(_0, _1) {
3403
3439
  }
3404
3440
  function sendAdImpressionTracking(_0, _1) {
3405
3441
  return _async_to_generator(function(licenseKey, adImpressionInfo) {
3406
- var context, metricEvent, error;
3442
+ var context, _adImpressionInfo_adUrl, metricEvent, error;
3407
3443
  var _arguments = arguments;
3408
3444
  return _ts_generator(this, function(_state) {
3409
3445
  switch(_state.label){
@@ -3428,17 +3464,18 @@ function sendAdImpressionTracking(_0, _1) {
3428
3464
  ];
3429
3465
  case 2:
3430
3466
  metricEvent = _state.sent();
3431
- publishTracking(licenseKey, "heartbeat", metricEvent);
3467
+ publishTracking(licenseKey, "heartbeat", metricEvent, !!context.debugAdTiming);
3432
3468
  publishTracking(licenseKey, "impressions", {
3433
3469
  events: [
3434
3470
  {
3471
+ event_id: createUuid(),
3435
3472
  player_id: metricEvent.player_id,
3436
3473
  ad_played_count: 1,
3437
- ad_url: adImpressionInfo.adUrl,
3474
+ ad_url: (_adImpressionInfo_adUrl = adImpressionInfo.adUrl) !== null && _adImpressionInfo_adUrl !== void 0 ? _adImpressionInfo_adUrl : adImpressionInfo.adId,
3438
3475
  capture_at: adImpressionInfo.timestamp
3439
3476
  }
3440
3477
  ]
3441
- });
3478
+ }, !!context.debugAdTiming);
3442
3479
  return [
3443
3480
  3,
3444
3481
  4
@@ -3483,7 +3520,7 @@ function sendHeartbeat(_0) {
3483
3520
  ];
3484
3521
  case 2:
3485
3522
  heartbeatData = _state.sent();
3486
- publishTracking(licenseKey, "heartbeat", heartbeatData);
3523
+ publishTracking(licenseKey, "heartbeat", heartbeatData, !!context.debugAdTiming);
3487
3524
  return [
3488
3525
  3,
3489
3526
  4
@@ -6316,7 +6353,7 @@ var AdTimingService = /*#__PURE__*/ function() {
6316
6353
  var _this_callbacks_getAdState = this.callbacks.getAdState(), inAdBreak = _this_callbacks_getAdState.inAdBreak, showAds = _this_callbacks_getAdState.showAds, adPlaying = _this_callbacks_getAdState.adPlaying;
6317
6354
  console.log("[StormcloudVideoPlayer][AdState]", _object_spread({
6318
6355
  event: event,
6319
- timestamp: /* @__PURE__ */ new Date().toISOString(),
6356
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6320
6357
  showAds: showAds,
6321
6358
  adPlaying: adPlaying,
6322
6359
  inAdBreak: inAdBreak,
@@ -6477,6 +6514,7 @@ var HlsEngine = /*#__PURE__*/ function() {
6477
6514
  this.bufferedSegmentsCount = 0;
6478
6515
  this.shouldAutoplayAfterBuffering = false;
6479
6516
  this.hasInitialBufferCompleted = false;
6517
+ this.latencyProfileApplied = false;
6480
6518
  this.config = config;
6481
6519
  this.video = video;
6482
6520
  this.cueManager = cueManager;
@@ -6545,24 +6583,21 @@ var HlsEngine = /*#__PURE__*/ function() {
6545
6583
  key: "setupHls",
6546
6584
  value: function setupHls() {
6547
6585
  var _this = this;
6548
- this.hls = new import_hls2.default(_object_spread_props(_object_spread({
6586
+ this.hls = new import_hls2.default({
6549
6587
  enableWorker: true,
6550
6588
  backBufferLength: 30,
6551
6589
  liveDurationInfinity: true,
6552
6590
  lowLatencyMode: !!this.config.lowLatencyMode,
6553
- maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1
6554
- }, this.config.lowLatencyMode ? {
6555
- liveSyncDuration: 2
6556
- } : {}), {
6591
+ maxLiveSyncPlaybackRate: 1.1,
6557
6592
  maxBufferLength: 30,
6558
6593
  maxMaxBufferLength: 600,
6559
6594
  maxBufferSize: 60 * 1e3 * 1e3,
6560
- maxBufferHole: 0.5,
6595
+ maxBufferHole: 1,
6561
6596
  highBufferWatchdogPeriod: 2,
6562
- nudgeOffset: 0.1,
6563
- nudgeMaxRetry: 3,
6597
+ nudgeOffset: 0.2,
6598
+ nudgeMaxRetry: 5,
6564
6599
  startPosition: -1
6565
- }));
6600
+ });
6566
6601
  this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, function() {
6567
6602
  var _this_hls;
6568
6603
  (_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.loadSource(_this.config.src);
@@ -6586,6 +6621,8 @@ var HlsEngine = /*#__PURE__*/ function() {
6586
6621
  this.bufferedSegmentsCount = 0;
6587
6622
  this.hasInitialBufferCompleted = false;
6588
6623
  this.shouldAutoplayAfterBuffering = !!this.config.autoplay;
6624
+ this.latencyProfileApplied = false;
6625
+ this.detectedLowLatencyStream = void 0;
6589
6626
  minSegments = (_this_config_minSegmentsBeforePlay = this.config.minSegmentsBeforePlay) !== null && _this_config_minSegmentsBeforePlay !== void 0 ? _this_config_minSegmentsBeforePlay : 2;
6590
6627
  if (this.debug) {
6591
6628
  console.log("[StormcloudVideoPlayer] Waiting for", minSegments, "segments to buffer before playback");
@@ -6616,6 +6653,7 @@ var HlsEngine = /*#__PURE__*/ function() {
6616
6653
  }).call(_this);
6617
6654
  });
6618
6655
  this.hls.on(import_hls2.default.Events.LEVEL_LOADED, function(_evt, data) {
6656
+ _this.applyStreamLatencyProfile(data === null || data === void 0 ? void 0 : data.details);
6619
6657
  if (_this.callbacks.isInAdBreak() || _this.callbacks.hasPendingAdBreak()) {
6620
6658
  return;
6621
6659
  }
@@ -6889,6 +6927,70 @@ var HlsEngine = /*#__PURE__*/ function() {
6889
6927
  this.hls.attachMedia(this.video);
6890
6928
  }
6891
6929
  },
6930
+ {
6931
+ key: "isLowLatencyStream",
6932
+ value: function isLowLatencyStream() {
6933
+ return this.detectedLowLatencyStream;
6934
+ }
6935
+ },
6936
+ {
6937
+ key: "applyStreamLatencyProfile",
6938
+ value: function applyStreamLatencyProfile(details) {
6939
+ if (this.latencyProfileApplied || !this.hls) {
6940
+ return;
6941
+ }
6942
+ if (!details) {
6943
+ return;
6944
+ }
6945
+ if (details.live !== true) {
6946
+ this.latencyProfileApplied = true;
6947
+ this.detectedLowLatencyStream = false;
6948
+ return;
6949
+ }
6950
+ var isLowLatencyManifest = this.isLowLatencyManifest(details);
6951
+ var useLowLatency = isLowLatencyManifest && !!this.config.lowLatencyMode;
6952
+ this.detectedLowLatencyStream = useLowLatency;
6953
+ this.latencyProfileApplied = true;
6954
+ var cfg = this.hls.config;
6955
+ if (useLowLatency) {
6956
+ cfg.maxLiveSyncPlaybackRate = 1.5;
6957
+ cfg.maxBufferHole = 0.5;
6958
+ delete cfg.liveSyncDuration;
6959
+ } else {
6960
+ cfg.maxLiveSyncPlaybackRate = 1.1;
6961
+ cfg.maxBufferHole = 1;
6962
+ delete cfg.liveSyncDuration;
6963
+ cfg.liveSyncDurationCount = 3;
6964
+ }
6965
+ if (this.debug) {
6966
+ var _details_targetduration;
6967
+ console.log("[StormcloudVideoPlayer] Live latency profile: ".concat(useLowLatency ? "LL-HLS (low latency)" : "standard live (stability)"), {
6968
+ isLowLatencyManifest: isLowLatencyManifest,
6969
+ lowLatencyModeRequested: !!this.config.lowLatencyMode,
6970
+ canBlockReload: details.canBlockReload,
6971
+ partTarget: details.partTarget,
6972
+ partHoldBack: details.partHoldBack,
6973
+ partListLength: Array.isArray(details.partList) ? details.partList.length : 0,
6974
+ targetDuration: (_details_targetduration = details.targetduration) !== null && _details_targetduration !== void 0 ? _details_targetduration : details.targetDuration,
6975
+ maxLiveSyncPlaybackRate: cfg.maxLiveSyncPlaybackRate,
6976
+ maxBufferHole: cfg.maxBufferHole
6977
+ });
6978
+ }
6979
+ }
6980
+ },
6981
+ {
6982
+ key: "isLowLatencyManifest",
6983
+ value: function isLowLatencyManifest(details) {
6984
+ if (!details) {
6985
+ return false;
6986
+ }
6987
+ var hasParts = Array.isArray(details.partList) && details.partList.length > 0;
6988
+ var hasPartTarget = typeof details.partTarget === "number" && details.partTarget > 0;
6989
+ var hasPartHoldBack = typeof details.partHoldBack === "number" && details.partHoldBack > 0;
6990
+ var canBlockReload = details.canBlockReload === true;
6991
+ return hasParts || hasPartTarget || hasPartHoldBack || canBlockReload;
6992
+ }
6993
+ },
6892
6994
  {
6893
6995
  key: "onId3Tag",
6894
6996
  value: function onId3Tag(tag) {
@@ -7212,27 +7314,22 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7212
7314
  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 : "?"));
7213
7315
  }
7214
7316
  });
7215
- adPlayer.on("all_ads_completed", function() {
7216
- sendAdImpressionTracking(_this.host.config.licenseKey, {
7317
+ adPlayer.on("ad_impression", function(payload) {
7318
+ var impressionInfo = {
7217
7319
  source: "hls",
7218
7320
  adIndex: _this.timing.currentAdIndex,
7219
- timestamp: /* @__PURE__ */ new Date().toISOString()
7220
- }, _this.analyticsContext).catch(function() {});
7221
- _this.timing.recordPlayedAdDuration(_this.host.getAdPlayer());
7222
- var remaining = _this.timing.getRemainingAdMs();
7223
- _this.timing.consecutiveFailures = 0;
7224
- if (_this.debug) {
7225
- console.log("[StormcloudVideoPlayer] all_ads_completed event received - remaining=".concat(remaining, "ms, queued ads=").concat(_this.adRequestQueue.length), _this.adRequestQueue.length > 0 ? {
7226
- queuedUrls: _to_consumable_array(_this.adRequestQueue)
7227
- } : {});
7321
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
7322
+ };
7323
+ if (payload === null || payload === void 0 ? void 0 : payload.adId) impressionInfo.adId = payload.adId;
7324
+ if (payload === null || payload === void 0 ? void 0 : payload.mediaUrl) impressionInfo.adUrl = payload.mediaUrl;
7325
+ if ((payload === null || payload === void 0 ? void 0 : payload.durationSeconds) != null) {
7326
+ impressionInfo.durationSeconds = payload.durationSeconds;
7228
7327
  }
7229
- if (_this.inAdBreak) {
7230
- if (_this.timing.hasTimeToStartAnotherAd()) {
7231
- _this.tryNextAvailableAdWithRateLimit();
7232
- } else {
7233
- _this.handleAdPodComplete();
7328
+ sendAdImpressionTracking(_this.host.config.licenseKey, impressionInfo, _this.analyticsContext).catch(function(error) {
7329
+ if (_this.debug) {
7330
+ console.warn("[AdBreakOrchestrator] Failed to send ad impression tracking:", error);
7234
7331
  }
7235
- }
7332
+ });
7236
7333
  });
7237
7334
  adPlayer.on("ad_error", function(errorPayload) {
7238
7335
  var errorMessage = "Ad playback failed";
@@ -7275,11 +7372,6 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7275
7372
  }
7276
7373
  });
7277
7374
  adPlayer.on("content_resume", function() {
7278
- sendAdImpressionTracking(_this.host.config.licenseKey, {
7279
- source: "hls",
7280
- adIndex: _this.timing.currentAdIndex,
7281
- timestamp: /* @__PURE__ */ new Date().toISOString()
7282
- }, _this.analyticsContext).catch(function() {});
7283
7375
  if (!_this.host.video.muted) {
7284
7376
  _this.host.video.muted = true;
7285
7377
  if (_this.debug) {
@@ -7517,7 +7609,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7517
7609
  sendAdLoadedTracking(this.host.config.licenseKey, {
7518
7610
  source: "hls",
7519
7611
  vastUrl: podUrl,
7520
- timestamp: /* @__PURE__ */ new Date().toISOString()
7612
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
7521
7613
  }, this.analyticsContext).catch(function() {});
7522
7614
  this.timing.startAdFailsafeTimer(requestToken);
7523
7615
  return [
@@ -8037,7 +8129,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8037
8129
  sendAdLoadedTracking(this.host.config.licenseKey, {
8038
8130
  source: "hls",
8039
8131
  vastUrl: vastTagUrl,
8040
- timestamp: /* @__PURE__ */ new Date().toISOString()
8132
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
8041
8133
  }, this.analyticsContext).catch(function() {});
8042
8134
  this.timing.clearAdRequestWatchdog();
8043
8135
  if (this.timing.activeAdRequestToken !== requestToken) return [
@@ -9018,7 +9110,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9018
9110
  if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;
9019
9111
  sendAdDetectTracking(this.config.licenseKey, _object_spread({
9020
9112
  source: "scte35",
9021
- timestamp: /* @__PURE__ */ new Date().toISOString()
9113
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
9022
9114
  }, detectPayload), buildAnalyticsContext(this.config)).catch(function() {});
9023
9115
  }
9024
9116
  var hasPrefetchedAds = this.adBreak.pendingAdBreak && this.adBreak.pendingAdBreak.vastUrls.length > 0;
@@ -9194,7 +9286,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9194
9286
  if (fragmentSn !== void 0) detectPayload.detectedAtFragmentSn = fragmentSn;
9195
9287
  sendAdDetectTracking(this.config.licenseKey, _object_spread({
9196
9288
  source: "scte35",
9197
- timestamp: /* @__PURE__ */ new Date().toISOString()
9289
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
9198
9290
  }, detectPayload), buildAnalyticsContext(this.config)).catch(function() {});
9199
9291
  if (this.debug) {
9200
9292
  console.log("[PREFETCH] Starting ad prefetch for upcoming ad break");
@@ -9374,6 +9466,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9374
9466
  return this.hlsEngine.isLiveStream;
9375
9467
  }
9376
9468
  },
9469
+ {
9470
+ key: "isLowLatencyStream",
9471
+ value: function isLowLatencyStream() {
9472
+ return this.hlsEngine.isLowLatencyStream();
9473
+ }
9474
+ },
9377
9475
  {
9378
9476
  key: "videoElement",
9379
9477
  get: function get() {