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
  });
@@ -156,18 +149,6 @@ function _sliced_to_array(arr, i) {
156
149
  function _to_consumable_array(arr) {
157
150
  return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
158
151
  }
159
- function _type_of(obj) {
160
- "@swc/helpers - typeof";
161
- return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
162
- }
163
- function _unsupported_iterable_to_array(o, minLen) {
164
- if (!o) return;
165
- if (typeof o === "string") return _array_like_to_array(o, minLen);
166
- var n = Object.prototype.toString.call(o).slice(8, -1);
167
- if (n === "Object" && o.constructor) n = o.constructor.name;
168
- if (n === "Map" || n === "Set") return Array.from(n);
169
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
170
- }
171
152
  function _ts_generator(thisArg, body) {
172
153
  var f, y, t, _ = {
173
154
  label: 0,
@@ -269,18 +250,36 @@ function _ts_generator(thisArg, body) {
269
250
  }
270
251
  function _ts_values(o) {
271
252
  var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
272
- if (m) return m.call(o);
273
- if (o && typeof o.length === "number") return {
274
- next: function() {
275
- if (o && i >= o.length) o = void 0;
276
- return {
277
- value: o && o[i++],
278
- done: !o
279
- };
280
- }
281
- };
253
+ if (m) {
254
+ return m.call(o);
255
+ }
256
+ if (o && typeof o.length === "number") {
257
+ return {
258
+ next: function() {
259
+ if (o && i >= o.length) {
260
+ o = void 0;
261
+ }
262
+ return {
263
+ value: o && o[i++],
264
+ done: !o
265
+ };
266
+ }
267
+ };
268
+ }
282
269
  throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
283
270
  }
271
+ function _type_of(obj) {
272
+ "@swc/helpers - typeof";
273
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
274
+ }
275
+ function _unsupported_iterable_to_array(o, minLen) {
276
+ if (!o) return;
277
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
278
+ var n = Object.prototype.toString.call(o).slice(8, -1);
279
+ if (n === "Object" && o.constructor) n = o.constructor.name;
280
+ if (n === "Map" || n === "Set") return Array.from(n);
281
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
282
+ }
284
283
  var __create = Object.create;
285
284
  var __defProp = Object.defineProperty;
286
285
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -540,6 +539,7 @@ function createHlsAdPlayer(contentVideo, options) {
540
539
  var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
541
540
  var adEventHandlers = [];
542
541
  var currentAd;
542
+ var currentAdMediaUrl;
543
543
  var podAds = [];
544
544
  var podIndex = 0;
545
545
  var sessionId;
@@ -1357,9 +1357,9 @@ function createHlsAdPlayer(contentVideo, options) {
1357
1357
  delete contentVideo.dataset.stormcloudAdPlaying;
1358
1358
  }
1359
1359
  }
1360
- function resetQuartileTracking(preserveImpression) {
1360
+ function resetQuartileTracking() {
1361
1361
  trackingFired = {
1362
- impression: preserveImpression ? trackingFired.impression : false,
1362
+ impression: false,
1363
1363
  start: false,
1364
1364
  firstQuartile: false,
1365
1365
  midpoint: false,
@@ -1367,6 +1367,27 @@ function createHlsAdPlayer(contentVideo, options) {
1367
1367
  complete: false
1368
1368
  };
1369
1369
  }
1370
+ function markCreativeRendered(reason) {
1371
+ if (!currentAd || trackingFired.impression) return;
1372
+ trackingFired.impression = true;
1373
+ fireTrackingPixels(currentAd.trackingUrls.impression);
1374
+ console.log("[HlsAdPlayer] Impression (pod ".concat(podIndex + 1, "/").concat(podAds.length || 1, ", reason: ").concat(reason, "): ").concat(currentAd.title));
1375
+ emit("ad_impression", {
1376
+ adId: currentAd.id,
1377
+ title: currentAd.title,
1378
+ durationSeconds: currentAd.duration,
1379
+ mediaUrl: currentAdMediaUrl,
1380
+ podIndex: podIndex,
1381
+ podSize: podAds.length || 1,
1382
+ reason: reason
1383
+ });
1384
+ }
1385
+ function canDetectBlackFrames() {
1386
+ if (!adVideoElement) return false;
1387
+ if (requiresMediaPipelineResetAfterAds()) return false;
1388
+ if (isRvfcSupported(adVideoElement)) return true;
1389
+ return getDecodedVideoFrameCount(adVideoElement) !== void 0;
1390
+ }
1370
1391
  function isRvfcSupported(video) {
1371
1392
  return typeof video.requestVideoFrameCallback === "function";
1372
1393
  }
@@ -1429,6 +1450,7 @@ function createHlsAdPlayer(contentVideo, options) {
1429
1450
  if (!mediaFile) {
1430
1451
  throw new Error("No media file available for ad");
1431
1452
  }
1453
+ currentAdMediaUrl = mediaFile.url;
1432
1454
  var isHlsAd = isHlsMediaFile(mediaFile);
1433
1455
  console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad (pod ").concat(podIndex + 1, "/").concat(podAds.length || 1, ") from: ").concat(mediaFile.url));
1434
1456
  if (isHlsAd && import_hls.default.isSupported()) {
@@ -1472,10 +1494,9 @@ function createHlsAdPlayer(contentVideo, options) {
1472
1494
  }
1473
1495
  podIndex++;
1474
1496
  currentAd = podAds[podIndex];
1475
- resetQuartileTracking(false);
1497
+ currentAdMediaUrl = void 0;
1498
+ resetQuartileTracking();
1476
1499
  if (currentAd) {
1477
- fireTrackingPixels(currentAd.trackingUrls.impression);
1478
- trackingFired.impression = true;
1479
1500
  console.log("[HlsAdPlayer] Advancing to next pod ad (".concat(podIndex + 1, "/").concat(podAds.length, "): ").concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1480
1501
  }
1481
1502
  clearStallWatchdog();
@@ -1570,6 +1591,7 @@ function createHlsAdPlayer(contentVideo, options) {
1570
1591
  if (!adPlaying) return;
1571
1592
  sawDecodedVideoFrame = true;
1572
1593
  markRvfcReliable();
1594
+ markCreativeRendered("first_presented_frame");
1573
1595
  };
1574
1596
  try {
1575
1597
  videoFrameCallbackHandle = rvfc.call(adVideoElement, onPresentedFrame);
@@ -1604,6 +1626,7 @@ function createHlsAdPlayer(contentVideo, options) {
1604
1626
  if (decodedFrames !== void 0 && decodedFrames > 0) {
1605
1627
  sawDecodedVideoFrame = true;
1606
1628
  markFrameCounterReliable();
1629
+ markCreativeRendered("decoded_frames");
1607
1630
  } else if (adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S) {
1608
1631
  var timeAdvancing = adVideoElement.currentTime > lastAdProgressPosition + 0.05;
1609
1632
  if (isRvfcSupported(adVideoElement) && timeAdvancing && isRvfcReliable()) {
@@ -1616,6 +1639,9 @@ function createHlsAdPlayer(contentVideo, options) {
1616
1639
  }
1617
1640
  }
1618
1641
  }
1642
+ if (!trackingFired.impression && !adVideoElement.paused && adVideoElement.currentTime >= BLACKFRAME_MIN_PLAYBACK_S && (sawDecodedVideoFrame || !canDetectBlackFrames())) {
1643
+ markCreativeRendered(sawDecodedVideoFrame ? "decoded_frames" : "sustained_playback");
1644
+ }
1619
1645
  if (adVideoElement.currentTime > lastAdProgressPosition + 0.05) {
1620
1646
  noteAdProgress();
1621
1647
  return;
@@ -1754,11 +1780,9 @@ function createHlsAdPlayer(contentVideo, options) {
1754
1780
  podAds = ads;
1755
1781
  podIndex = 0;
1756
1782
  currentAd = ads[0];
1783
+ currentAdMediaUrl = void 0;
1784
+ resetQuartileTracking();
1757
1785
  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"));
1758
- if (currentAd) {
1759
- fireTrackingPixels(currentAd.trackingUrls.impression);
1760
- trackingFired.impression = true;
1761
- }
1762
1786
  return [
1763
1787
  2,
1764
1788
  Promise.resolve()
@@ -1798,7 +1822,7 @@ function createHlsAdPlayer(contentVideo, options) {
1798
1822
  contentVideo[AD_VIDEO_PROP] = adVideoElement;
1799
1823
  }
1800
1824
  setupAdEventListeners();
1801
- resetQuartileTracking(true);
1825
+ resetQuartileTracking();
1802
1826
  contentVolume = contentVideo.volume;
1803
1827
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1804
1828
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -1888,6 +1912,7 @@ function createHlsAdPlayer(contentVideo, options) {
1888
1912
  }
1889
1913
  }
1890
1914
  currentAd = void 0;
1915
+ currentAdMediaUrl = void 0;
1891
1916
  podAds = [];
1892
1917
  podIndex = 0;
1893
1918
  return [
@@ -3202,7 +3227,7 @@ function buildPlayerMetricEvent() {
3202
3227
  if (debugAdTiming) {
3203
3228
  console.log("[StormcloudVideoPlayer] playerId: ", playerId);
3204
3229
  }
3205
- captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : /* @__PURE__ */ new Date().toISOString();
3230
+ captureAt = (_flags_captureAt = flags.captureAt) !== null && _flags_captureAt !== void 0 ? _flags_captureAt : (/* @__PURE__ */ new Date()).toISOString();
3206
3231
  return [
3207
3232
  2,
3208
3233
  _object_spread({
@@ -3221,8 +3246,19 @@ function buildPlayerMetricEvent() {
3221
3246
  }).apply(this, arguments);
3222
3247
  }
3223
3248
  function publishTracking(licenseKey, channel, body) {
3249
+ var debug = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : false;
3224
3250
  ensureMQTTClient();
3225
- publishMQTT(buildPlayerTopic(licenseKey, channel), body);
3251
+ var topic = buildPlayerTopic(licenseKey, channel);
3252
+ var published = publishMQTT(topic, body);
3253
+ if (debug) {
3254
+ console.log("[StormcloudVideoPlayer] publishTracking:", JSON.stringify({
3255
+ licenseKey: licenseKey,
3256
+ channel: channel,
3257
+ topic: topic,
3258
+ body: body,
3259
+ published: published
3260
+ }, null, 2));
3261
+ }
3226
3262
  }
3227
3263
  function sendInitialTracking(_0) {
3228
3264
  return _async_to_generator(function(licenseKey) {
@@ -3256,7 +3292,7 @@ function sendInitialTracking(_0) {
3256
3292
  events: [
3257
3293
  metricEvent
3258
3294
  ]
3259
- });
3295
+ }, !!context.debugAdTiming);
3260
3296
  return [
3261
3297
  3,
3262
3298
  4
@@ -3366,7 +3402,7 @@ function sendAdLoadedTracking(_0, _1) {
3366
3402
  }
3367
3403
  function sendAdImpressionTracking(_0, _1) {
3368
3404
  return _async_to_generator(function(licenseKey, adImpressionInfo) {
3369
- var context, metricEvent, error;
3405
+ var context, _adImpressionInfo_adUrl, metricEvent, error;
3370
3406
  var _arguments = arguments;
3371
3407
  return _ts_generator(this, function(_state) {
3372
3408
  switch(_state.label){
@@ -3391,17 +3427,18 @@ function sendAdImpressionTracking(_0, _1) {
3391
3427
  ];
3392
3428
  case 2:
3393
3429
  metricEvent = _state.sent();
3394
- publishTracking(licenseKey, "heartbeat", metricEvent);
3430
+ publishTracking(licenseKey, "heartbeat", metricEvent, !!context.debugAdTiming);
3395
3431
  publishTracking(licenseKey, "impressions", {
3396
3432
  events: [
3397
3433
  {
3434
+ event_id: createUuid(),
3398
3435
  player_id: metricEvent.player_id,
3399
3436
  ad_played_count: 1,
3400
- ad_url: adImpressionInfo.adUrl,
3437
+ ad_url: (_adImpressionInfo_adUrl = adImpressionInfo.adUrl) !== null && _adImpressionInfo_adUrl !== void 0 ? _adImpressionInfo_adUrl : adImpressionInfo.adId,
3401
3438
  capture_at: adImpressionInfo.timestamp
3402
3439
  }
3403
3440
  ]
3404
- });
3441
+ }, !!context.debugAdTiming);
3405
3442
  return [
3406
3443
  3,
3407
3444
  4
@@ -3446,7 +3483,7 @@ function sendHeartbeat(_0) {
3446
3483
  ];
3447
3484
  case 2:
3448
3485
  heartbeatData = _state.sent();
3449
- publishTracking(licenseKey, "heartbeat", heartbeatData);
3486
+ publishTracking(licenseKey, "heartbeat", heartbeatData, !!context.debugAdTiming);
3450
3487
  return [
3451
3488
  3,
3452
3489
  4
@@ -6279,7 +6316,7 @@ var AdTimingService = /*#__PURE__*/ function() {
6279
6316
  var _this_callbacks_getAdState = this.callbacks.getAdState(), inAdBreak = _this_callbacks_getAdState.inAdBreak, showAds = _this_callbacks_getAdState.showAds, adPlaying = _this_callbacks_getAdState.adPlaying;
6280
6317
  console.log("[StormcloudVideoPlayer][AdState]", _object_spread({
6281
6318
  event: event,
6282
- timestamp: /* @__PURE__ */ new Date().toISOString(),
6319
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6283
6320
  showAds: showAds,
6284
6321
  adPlaying: adPlaying,
6285
6322
  inAdBreak: inAdBreak,
@@ -6440,6 +6477,7 @@ var HlsEngine = /*#__PURE__*/ function() {
6440
6477
  this.bufferedSegmentsCount = 0;
6441
6478
  this.shouldAutoplayAfterBuffering = false;
6442
6479
  this.hasInitialBufferCompleted = false;
6480
+ this.latencyProfileApplied = false;
6443
6481
  this.config = config;
6444
6482
  this.video = video;
6445
6483
  this.cueManager = cueManager;
@@ -6508,24 +6546,21 @@ var HlsEngine = /*#__PURE__*/ function() {
6508
6546
  key: "setupHls",
6509
6547
  value: function setupHls() {
6510
6548
  var _this = this;
6511
- this.hls = new import_hls2.default(_object_spread_props(_object_spread({
6549
+ this.hls = new import_hls2.default({
6512
6550
  enableWorker: true,
6513
6551
  backBufferLength: 30,
6514
6552
  liveDurationInfinity: true,
6515
6553
  lowLatencyMode: !!this.config.lowLatencyMode,
6516
- maxLiveSyncPlaybackRate: this.config.lowLatencyMode ? 1.5 : 1
6517
- }, this.config.lowLatencyMode ? {
6518
- liveSyncDuration: 2
6519
- } : {}), {
6554
+ maxLiveSyncPlaybackRate: 1.1,
6520
6555
  maxBufferLength: 30,
6521
6556
  maxMaxBufferLength: 600,
6522
6557
  maxBufferSize: 60 * 1e3 * 1e3,
6523
- maxBufferHole: 0.5,
6558
+ maxBufferHole: 1,
6524
6559
  highBufferWatchdogPeriod: 2,
6525
- nudgeOffset: 0.1,
6526
- nudgeMaxRetry: 3,
6560
+ nudgeOffset: 0.2,
6561
+ nudgeMaxRetry: 5,
6527
6562
  startPosition: -1
6528
- }));
6563
+ });
6529
6564
  this.hls.on(import_hls2.default.Events.MEDIA_ATTACHED, function() {
6530
6565
  var _this_hls;
6531
6566
  (_this_hls = _this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.loadSource(_this.config.src);
@@ -6549,6 +6584,8 @@ var HlsEngine = /*#__PURE__*/ function() {
6549
6584
  this.bufferedSegmentsCount = 0;
6550
6585
  this.hasInitialBufferCompleted = false;
6551
6586
  this.shouldAutoplayAfterBuffering = !!this.config.autoplay;
6587
+ this.latencyProfileApplied = false;
6588
+ this.detectedLowLatencyStream = void 0;
6552
6589
  minSegments = (_this_config_minSegmentsBeforePlay = this.config.minSegmentsBeforePlay) !== null && _this_config_minSegmentsBeforePlay !== void 0 ? _this_config_minSegmentsBeforePlay : 2;
6553
6590
  if (this.debug) {
6554
6591
  console.log("[StormcloudVideoPlayer] Waiting for", minSegments, "segments to buffer before playback");
@@ -6579,6 +6616,7 @@ var HlsEngine = /*#__PURE__*/ function() {
6579
6616
  }).call(_this);
6580
6617
  });
6581
6618
  this.hls.on(import_hls2.default.Events.LEVEL_LOADED, function(_evt, data) {
6619
+ _this.applyStreamLatencyProfile(data === null || data === void 0 ? void 0 : data.details);
6582
6620
  if (_this.callbacks.isInAdBreak() || _this.callbacks.hasPendingAdBreak()) {
6583
6621
  return;
6584
6622
  }
@@ -6852,6 +6890,70 @@ var HlsEngine = /*#__PURE__*/ function() {
6852
6890
  this.hls.attachMedia(this.video);
6853
6891
  }
6854
6892
  },
6893
+ {
6894
+ key: "isLowLatencyStream",
6895
+ value: function isLowLatencyStream() {
6896
+ return this.detectedLowLatencyStream;
6897
+ }
6898
+ },
6899
+ {
6900
+ key: "applyStreamLatencyProfile",
6901
+ value: function applyStreamLatencyProfile(details) {
6902
+ if (this.latencyProfileApplied || !this.hls) {
6903
+ return;
6904
+ }
6905
+ if (!details) {
6906
+ return;
6907
+ }
6908
+ if (details.live !== true) {
6909
+ this.latencyProfileApplied = true;
6910
+ this.detectedLowLatencyStream = false;
6911
+ return;
6912
+ }
6913
+ var isLowLatencyManifest = this.isLowLatencyManifest(details);
6914
+ var useLowLatency = isLowLatencyManifest && !!this.config.lowLatencyMode;
6915
+ this.detectedLowLatencyStream = useLowLatency;
6916
+ this.latencyProfileApplied = true;
6917
+ var cfg = this.hls.config;
6918
+ if (useLowLatency) {
6919
+ cfg.maxLiveSyncPlaybackRate = 1.5;
6920
+ cfg.maxBufferHole = 0.5;
6921
+ delete cfg.liveSyncDuration;
6922
+ } else {
6923
+ cfg.maxLiveSyncPlaybackRate = 1.1;
6924
+ cfg.maxBufferHole = 1;
6925
+ delete cfg.liveSyncDuration;
6926
+ cfg.liveSyncDurationCount = 3;
6927
+ }
6928
+ if (this.debug) {
6929
+ var _details_targetduration;
6930
+ console.log("[StormcloudVideoPlayer] Live latency profile: ".concat(useLowLatency ? "LL-HLS (low latency)" : "standard live (stability)"), {
6931
+ isLowLatencyManifest: isLowLatencyManifest,
6932
+ lowLatencyModeRequested: !!this.config.lowLatencyMode,
6933
+ canBlockReload: details.canBlockReload,
6934
+ partTarget: details.partTarget,
6935
+ partHoldBack: details.partHoldBack,
6936
+ partListLength: Array.isArray(details.partList) ? details.partList.length : 0,
6937
+ targetDuration: (_details_targetduration = details.targetduration) !== null && _details_targetduration !== void 0 ? _details_targetduration : details.targetDuration,
6938
+ maxLiveSyncPlaybackRate: cfg.maxLiveSyncPlaybackRate,
6939
+ maxBufferHole: cfg.maxBufferHole
6940
+ });
6941
+ }
6942
+ }
6943
+ },
6944
+ {
6945
+ key: "isLowLatencyManifest",
6946
+ value: function isLowLatencyManifest(details) {
6947
+ if (!details) {
6948
+ return false;
6949
+ }
6950
+ var hasParts = Array.isArray(details.partList) && details.partList.length > 0;
6951
+ var hasPartTarget = typeof details.partTarget === "number" && details.partTarget > 0;
6952
+ var hasPartHoldBack = typeof details.partHoldBack === "number" && details.partHoldBack > 0;
6953
+ var canBlockReload = details.canBlockReload === true;
6954
+ return hasParts || hasPartTarget || hasPartHoldBack || canBlockReload;
6955
+ }
6956
+ },
6855
6957
  {
6856
6958
  key: "onId3Tag",
6857
6959
  value: function onId3Tag(tag) {
@@ -7175,27 +7277,22 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7175
7277
  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 : "?"));
7176
7278
  }
7177
7279
  });
7178
- adPlayer.on("all_ads_completed", function() {
7179
- sendAdImpressionTracking(_this.host.config.licenseKey, {
7280
+ adPlayer.on("ad_impression", function(payload) {
7281
+ var impressionInfo = {
7180
7282
  source: "hls",
7181
7283
  adIndex: _this.timing.currentAdIndex,
7182
- timestamp: /* @__PURE__ */ new Date().toISOString()
7183
- }, _this.analyticsContext).catch(function() {});
7184
- _this.timing.recordPlayedAdDuration(_this.host.getAdPlayer());
7185
- var remaining = _this.timing.getRemainingAdMs();
7186
- _this.timing.consecutiveFailures = 0;
7187
- if (_this.debug) {
7188
- console.log("[StormcloudVideoPlayer] all_ads_completed event received - remaining=".concat(remaining, "ms, queued ads=").concat(_this.adRequestQueue.length), _this.adRequestQueue.length > 0 ? {
7189
- queuedUrls: _to_consumable_array(_this.adRequestQueue)
7190
- } : {});
7284
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
7285
+ };
7286
+ if (payload === null || payload === void 0 ? void 0 : payload.adId) impressionInfo.adId = payload.adId;
7287
+ if (payload === null || payload === void 0 ? void 0 : payload.mediaUrl) impressionInfo.adUrl = payload.mediaUrl;
7288
+ if ((payload === null || payload === void 0 ? void 0 : payload.durationSeconds) != null) {
7289
+ impressionInfo.durationSeconds = payload.durationSeconds;
7191
7290
  }
7192
- if (_this.inAdBreak) {
7193
- if (_this.timing.hasTimeToStartAnotherAd()) {
7194
- _this.tryNextAvailableAdWithRateLimit();
7195
- } else {
7196
- _this.handleAdPodComplete();
7291
+ sendAdImpressionTracking(_this.host.config.licenseKey, impressionInfo, _this.analyticsContext).catch(function(error) {
7292
+ if (_this.debug) {
7293
+ console.warn("[AdBreakOrchestrator] Failed to send ad impression tracking:", error);
7197
7294
  }
7198
- }
7295
+ });
7199
7296
  });
7200
7297
  adPlayer.on("ad_error", function(errorPayload) {
7201
7298
  var errorMessage = "Ad playback failed";
@@ -7238,11 +7335,6 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7238
7335
  }
7239
7336
  });
7240
7337
  adPlayer.on("content_resume", function() {
7241
- sendAdImpressionTracking(_this.host.config.licenseKey, {
7242
- source: "hls",
7243
- adIndex: _this.timing.currentAdIndex,
7244
- timestamp: /* @__PURE__ */ new Date().toISOString()
7245
- }, _this.analyticsContext).catch(function() {});
7246
7338
  if (!_this.host.video.muted) {
7247
7339
  _this.host.video.muted = true;
7248
7340
  if (_this.debug) {
@@ -7480,7 +7572,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7480
7572
  sendAdLoadedTracking(this.host.config.licenseKey, {
7481
7573
  source: "hls",
7482
7574
  vastUrl: podUrl,
7483
- timestamp: /* @__PURE__ */ new Date().toISOString()
7575
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
7484
7576
  }, this.analyticsContext).catch(function() {});
7485
7577
  this.timing.startAdFailsafeTimer(requestToken);
7486
7578
  return [
@@ -8000,7 +8092,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8000
8092
  sendAdLoadedTracking(this.host.config.licenseKey, {
8001
8093
  source: "hls",
8002
8094
  vastUrl: vastTagUrl,
8003
- timestamp: /* @__PURE__ */ new Date().toISOString()
8095
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
8004
8096
  }, this.analyticsContext).catch(function() {});
8005
8097
  this.timing.clearAdRequestWatchdog();
8006
8098
  if (this.timing.activeAdRequestToken !== requestToken) return [
@@ -8981,7 +9073,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8981
9073
  if (marker.ptsSeconds != null) detectPayload.ptsSeconds = marker.ptsSeconds;
8982
9074
  sendAdDetectTracking(this.config.licenseKey, _object_spread({
8983
9075
  source: "scte35",
8984
- timestamp: /* @__PURE__ */ new Date().toISOString()
9076
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
8985
9077
  }, detectPayload), buildAnalyticsContext(this.config)).catch(function() {});
8986
9078
  }
8987
9079
  var hasPrefetchedAds = this.adBreak.pendingAdBreak && this.adBreak.pendingAdBreak.vastUrls.length > 0;
@@ -9157,7 +9249,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9157
9249
  if (fragmentSn !== void 0) detectPayload.detectedAtFragmentSn = fragmentSn;
9158
9250
  sendAdDetectTracking(this.config.licenseKey, _object_spread({
9159
9251
  source: "scte35",
9160
- timestamp: /* @__PURE__ */ new Date().toISOString()
9252
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
9161
9253
  }, detectPayload), buildAnalyticsContext(this.config)).catch(function() {});
9162
9254
  if (this.debug) {
9163
9255
  console.log("[PREFETCH] Starting ad prefetch for upcoming ad break");
@@ -9337,6 +9429,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9337
9429
  return this.hlsEngine.isLiveStream;
9338
9430
  }
9339
9431
  },
9432
+ {
9433
+ key: "isLowLatencyStream",
9434
+ value: function isLowLatencyStream() {
9435
+ return this.hlsEngine.isLowLatencyStream();
9436
+ }
9437
+ },
9340
9438
  {
9341
9439
  key: "videoElement",
9342
9440
  get: function get() {