stormcloud-video-player 0.8.25 → 0.8.26

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 (42) hide show
  1. package/dist/stormcloud-vp.min.js +1 -1
  2. package/lib/index.cjs +631 -115
  3. package/lib/index.cjs.map +1 -1
  4. package/lib/index.d.cts +7 -0
  5. package/lib/index.d.ts +7 -0
  6. package/lib/index.js +631 -115
  7. package/lib/index.js.map +1 -1
  8. package/lib/player/AdBreakOrchestrator.cjs +198 -41
  9. package/lib/player/AdBreakOrchestrator.cjs.map +1 -1
  10. package/lib/player/AdBreakOrchestrator.d.cts +4 -1
  11. package/lib/player/AdConfigManager.cjs +61 -1
  12. package/lib/player/AdConfigManager.cjs.map +1 -1
  13. package/lib/player/AdConfigManager.d.cts +12 -1
  14. package/lib/player/AdPreloadPool.d.cts +1 -1
  15. package/lib/player/AdTimingService.cjs +7 -0
  16. package/lib/player/AdTimingService.cjs.map +1 -1
  17. package/lib/player/AdTimingService.d.cts +2 -1
  18. package/lib/player/HlsEngine.d.cts +1 -1
  19. package/lib/player/PlayerControls.d.cts +1 -1
  20. package/lib/player/Scte35CueManager.d.cts +1 -1
  21. package/lib/player/Scte35Parser.d.cts +1 -1
  22. package/lib/player/StormcloudVideoPlayer.cjs +631 -115
  23. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  24. package/lib/player/StormcloudVideoPlayer.d.cts +2 -1
  25. package/lib/player/playerTypes.d.cts +1 -1
  26. package/lib/players/HlsPlayer.cjs +631 -115
  27. package/lib/players/HlsPlayer.cjs.map +1 -1
  28. package/lib/players/HlsPlayer.d.cts +1 -1
  29. package/lib/players/index.cjs +631 -115
  30. package/lib/players/index.cjs.map +1 -1
  31. package/lib/sdk/hlsAdPlayer.cjs +343 -71
  32. package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
  33. package/lib/sdk/hlsAdPlayer.d.cts +1 -1
  34. package/lib/{types-Bz4aRmzc.d.cts → types-Xgz2_W1C.d.cts} +6 -0
  35. package/lib/ui/StormcloudVideoPlayer.cjs +631 -115
  36. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  37. package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
  38. package/lib/utils/tracking.d.cts +1 -1
  39. package/lib/utils/vastMacros.cjs +14 -1
  40. package/lib/utils/vastMacros.cjs.map +1 -1
  41. package/lib/utils/vastMacros.d.cts +3 -0
  42. package/package.json +1 -1
@@ -1217,13 +1217,26 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1217
1217
  }
1218
1218
  },
1219
1219
  {
1220
- // ───────────────────────────────────────────────────────────────
1220
+ key: "optimizedPodsEnabled",
1221
+ get: // ───────────────────────────────────────────────────────────────
1221
1222
  // IMA event listeners
1222
1223
  // ───────────────────────────────────────────────────────────────
1224
+ function get() {
1225
+ return !!this.host.config.optimizedPods;
1226
+ }
1227
+ },
1228
+ {
1223
1229
  key: "attachImaEventListeners",
1224
1230
  value: function attachImaEventListeners() {
1225
1231
  var _this = this;
1226
1232
  var adPlayer = this.host.getAdPlayer();
1233
+ adPlayer.on("pod_ad_started", function(payload) {
1234
+ _this.timing.notePodAdStarted();
1235
+ if (_this.debug) {
1236
+ var _ref;
1237
+ 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 : "?"));
1238
+ }
1239
+ });
1227
1240
  adPlayer.on("all_ads_completed", function() {
1228
1241
  sendAdImpressionTracking(_this.host.config.licenseKey, {
1229
1242
  source: "hls",
@@ -1381,7 +1394,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1381
1394
  // ───────────────────────────────────────────────────────────────
1382
1395
  function handleAdStart(_marker) {
1383
1396
  return _async_to_generator(function() {
1384
- var scheduled, tags, baseVastUrl, adBreakDurationMs, mode, currentMuted, currentVolume, firstAdUrl, usePreloadedAd, preloadedController, preloaded, firstAdUrlArray, adPlayer, preservedMuted, preservedVolume, adVolume, adPlayer1, adVolume1, error, fallbackPreloaded, ap, adVolume2, fallbackError;
1397
+ var scheduled, tags, baseVastUrl, adBreakDurationMs, mode, currentMuted, currentVolume, podPlayed, firstAdUrl, usePreloadedAd, preloadedController, preloaded, firstAdUrlArray, adPlayer, preservedMuted, preservedVolume, adVolume, adPlayer1, adVolume1, error, fallbackPreloaded, ap, adVolume2, fallbackError;
1385
1398
  return _ts_generator(this, function(_state) {
1386
1399
  switch(_state.label){
1387
1400
  case 0:
@@ -1428,6 +1441,26 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1428
1441
  if (this.timing.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {
1429
1442
  this.timing.expectedAdBreakDurationMs = adBreakDurationMs;
1430
1443
  }
1444
+ if (!this.optimizedPodsEnabled) return [
1445
+ 3,
1446
+ 2
1447
+ ];
1448
+ return [
1449
+ 4,
1450
+ this.startOptimizedPod(baseVastUrl, adBreakDurationMs, currentMuted, currentVolume)
1451
+ ];
1452
+ case 1:
1453
+ podPlayed = _state.sent();
1454
+ if (podPlayed) {
1455
+ return [
1456
+ 2
1457
+ ];
1458
+ }
1459
+ if (this.debug) {
1460
+ console.log("[POD] Optimized pod unavailable, falling back to sequential single-ad path");
1461
+ }
1462
+ _state.label = 2;
1463
+ case 2:
1431
1464
  usePreloadedAd = false;
1432
1465
  preloaded = this.preloadPool.getPreloadedAd();
1433
1466
  if (preloaded) {
@@ -1469,21 +1502,21 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1469
1502
  if (this.debug) {
1470
1503
  console.log("[CONTINUOUS-FETCH] First VAST URL:", firstAdUrl);
1471
1504
  }
1472
- _state.label = 1;
1473
- case 1:
1505
+ _state.label = 3;
1506
+ case 3:
1474
1507
  _state.trys.push([
1475
- 1,
1476
- 12,
1508
+ 3,
1509
+ 14,
1477
1510
  ,
1478
- 20
1511
+ 22
1479
1512
  ]);
1480
1513
  if (!(usePreloadedAd && preloadedController)) return [
1481
1514
  3,
1482
- 5
1515
+ 7
1483
1516
  ];
1484
1517
  if (!!this.timing.ensureLoadedAdFitsBudget(preloadedController)) return [
1485
1518
  3,
1486
- 3
1519
+ 5
1487
1520
  ];
1488
1521
  this.timing.rejectLoadedAdForDuration(preloadedController);
1489
1522
  this.startContinuousFetching(baseVastUrl);
@@ -1491,12 +1524,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1491
1524
  4,
1492
1525
  this.tryNextAvailableAdWithRateLimit()
1493
1526
  ];
1494
- case 2:
1527
+ case 4:
1495
1528
  _state.sent();
1496
1529
  return [
1497
1530
  2
1498
1531
  ];
1499
- case 3:
1532
+ case 5:
1500
1533
  adPlayer = this.host.getAdPlayer();
1501
1534
  preservedMuted = adPlayer.getOriginalMutedState();
1502
1535
  preservedVolume = adPlayer.getOriginalVolume();
@@ -1521,7 +1554,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1521
1554
  4,
1522
1555
  preloadedController.play()
1523
1556
  ];
1524
- case 4:
1557
+ case 6:
1525
1558
  _state.sent();
1526
1559
  this.timing.markAdStarted();
1527
1560
  if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {
@@ -1531,22 +1564,22 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1531
1564
  preloadedController.setAdVolume(adVolume);
1532
1565
  return [
1533
1566
  3,
1534
- 11
1567
+ 13
1535
1568
  ];
1536
- case 5:
1569
+ case 7:
1537
1570
  adPlayer1 = this.host.getAdPlayer();
1538
1571
  return [
1539
1572
  4,
1540
1573
  this.timing.enforceGlobalRateLimit()
1541
1574
  ];
1542
- case 6:
1575
+ case 8:
1543
1576
  _state.sent();
1544
1577
  this.timing.lastAdRequestTime = Date.now();
1545
1578
  return [
1546
1579
  4,
1547
1580
  adPlayer1.requestAds(firstAdUrl)
1548
1581
  ];
1549
- case 7:
1582
+ case 9:
1550
1583
  _state.sent();
1551
1584
  sendAdLoadedTracking(this.host.config.licenseKey, {
1552
1585
  source: "hls",
@@ -1558,7 +1591,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1558
1591
  }
1559
1592
  if (!!this.timing.ensureLoadedAdFitsBudget(adPlayer1)) return [
1560
1593
  3,
1561
- 9
1594
+ 11
1562
1595
  ];
1563
1596
  this.timing.rejectLoadedAdForDuration(adPlayer1);
1564
1597
  this.recreateAdController();
@@ -1567,12 +1600,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1567
1600
  4,
1568
1601
  this.tryNextAvailableAdWithRateLimit()
1569
1602
  ];
1570
- case 8:
1603
+ case 10:
1571
1604
  _state.sent();
1572
1605
  return [
1573
1606
  2
1574
1607
  ];
1575
- case 9:
1608
+ case 11:
1576
1609
  this.timing.consecutiveFailures = 0;
1577
1610
  this.startContinuousFetching(baseVastUrl);
1578
1611
  if (!this.preloadPool.active) {
@@ -1582,7 +1615,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1582
1615
  4,
1583
1616
  adPlayer1.play()
1584
1617
  ];
1585
- case 10:
1618
+ case 12:
1586
1619
  _state.sent();
1587
1620
  this.timing.markAdStarted();
1588
1621
  if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {
@@ -1590,40 +1623,40 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1590
1623
  }
1591
1624
  adVolume1 = currentMuted ? 0 : currentVolume;
1592
1625
  adPlayer1.setAdVolume(adVolume1);
1593
- _state.label = 11;
1594
- case 11:
1626
+ _state.label = 13;
1627
+ case 13:
1595
1628
  return [
1596
1629
  3,
1597
- 20
1630
+ 22
1598
1631
  ];
1599
- case 12:
1632
+ case 14:
1600
1633
  error = _state.sent();
1601
1634
  if (this.debug) {
1602
1635
  console.warn("[CONTINUOUS-FETCH] First ad request failed:", error);
1603
1636
  }
1604
1637
  if (!!usePreloadedAd) return [
1605
1638
  3,
1606
- 18
1639
+ 20
1607
1640
  ];
1608
1641
  fallbackPreloaded = this.preloadPool.getPreloadedAd();
1609
1642
  if (!fallbackPreloaded) return [
1610
1643
  3,
1611
- 18
1644
+ 20
1612
1645
  ];
1613
1646
  if (this.debug) {
1614
1647
  console.log("[CONTINUOUS-FETCH] First ad failed, using preloaded fallback");
1615
1648
  }
1616
- _state.label = 13;
1617
- case 13:
1649
+ _state.label = 15;
1650
+ case 15:
1618
1651
  _state.trys.push([
1619
- 13,
1620
- 17,
1652
+ 15,
1653
+ 19,
1621
1654
  ,
1622
- 18
1655
+ 20
1623
1656
  ]);
1624
1657
  if (!!this.timing.ensureLoadedAdFitsBudget(fallbackPreloaded.adController)) return [
1625
1658
  3,
1626
- 15
1659
+ 17
1627
1660
  ];
1628
1661
  this.timing.rejectLoadedAdForDuration(fallbackPreloaded.adController);
1629
1662
  this.startContinuousFetching(baseVastUrl);
@@ -1631,12 +1664,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1631
1664
  4,
1632
1665
  this.tryNextAvailableAdWithRateLimit()
1633
1666
  ];
1634
- case 14:
1667
+ case 16:
1635
1668
  _state.sent();
1636
1669
  return [
1637
1670
  2
1638
1671
  ];
1639
- case 15:
1672
+ case 17:
1640
1673
  this.swapToPreloadedAdPlayer(fallbackPreloaded.adController);
1641
1674
  this.timing.consecutiveFailures = 0;
1642
1675
  this.startContinuousFetching(baseVastUrl);
@@ -1649,7 +1682,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1649
1682
  4,
1650
1683
  ap.play()
1651
1684
  ];
1652
- case 16:
1685
+ case 18:
1653
1686
  _state.sent();
1654
1687
  this.timing.markAdStarted();
1655
1688
  if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {
@@ -1660,16 +1693,16 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1660
1693
  return [
1661
1694
  2
1662
1695
  ];
1663
- case 17:
1696
+ case 19:
1664
1697
  fallbackError = _state.sent();
1665
1698
  if (this.debug) {
1666
1699
  console.warn("[CONTINUOUS-FETCH] Preloaded fallback also failed:", fallbackError);
1667
1700
  }
1668
1701
  return [
1669
1702
  3,
1670
- 18
1703
+ 20
1671
1704
  ];
1672
- case 18:
1705
+ case 20:
1673
1706
  if (this.timing.isTemporaryAdError(error)) {
1674
1707
  this.timing.temporaryFailureUrls.set(firstAdUrl, Date.now());
1675
1708
  if (this.debug) {
@@ -1687,13 +1720,137 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
1687
1720
  4,
1688
1721
  this.tryNextAvailableAdWithRateLimit()
1689
1722
  ];
1690
- case 19:
1723
+ case 21:
1691
1724
  _state.sent();
1692
1725
  return [
1693
1726
  3,
1694
- 20
1727
+ 22
1695
1728
  ];
1696
- case 20:
1729
+ case 22:
1730
+ return [
1731
+ 2
1732
+ ];
1733
+ }
1734
+ });
1735
+ }).call(this);
1736
+ }
1737
+ },
1738
+ {
1739
+ key: "startOptimizedPod",
1740
+ value: // ───────────────────────────────────────────────────────────────
1741
+ // Optimized pod (single multi-ad request)
1742
+ // ───────────────────────────────────────────────────────────────
1743
+ function startOptimizedPod(baseVastUrl, breakDurationMs, currentMuted, currentVolume) {
1744
+ return _async_to_generator(function() {
1745
+ var podUrl, adPlayer, requestToken, _ref, _adPlayer_getPodAdCount, podCount, error;
1746
+ return _ts_generator(this, function(_state) {
1747
+ switch(_state.label){
1748
+ case 0:
1749
+ if (this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0) {
1750
+ podUrl = this.pendingAdBreak.vastUrls[0];
1751
+ this.clearPendingAdBreak();
1752
+ } else {
1753
+ podUrl = this.host.generatePodVastUrl(baseVastUrl, breakDurationMs);
1754
+ }
1755
+ if (!podUrl) {
1756
+ return [
1757
+ 2,
1758
+ false
1759
+ ];
1760
+ }
1761
+ this.continuousFetchingActive = false;
1762
+ this.recreateAdController();
1763
+ adPlayer = this.host.getAdPlayer();
1764
+ requestToken = ++this.timing.adRequestTokenCounter;
1765
+ this.timing.activeAdRequestToken = requestToken;
1766
+ this.timing.startAdRequestWatchdog(requestToken);
1767
+ _state.label = 1;
1768
+ case 1:
1769
+ _state.trys.push([
1770
+ 1,
1771
+ 5,
1772
+ ,
1773
+ 6
1774
+ ]);
1775
+ return [
1776
+ 4,
1777
+ this.timing.enforceGlobalRateLimit()
1778
+ ];
1779
+ case 2:
1780
+ _state.sent();
1781
+ this.timing.lastAdRequestTime = Date.now();
1782
+ return [
1783
+ 4,
1784
+ adPlayer.requestAds(podUrl)
1785
+ ];
1786
+ case 3:
1787
+ _state.sent();
1788
+ this.timing.clearAdRequestWatchdog();
1789
+ if (this.timing.activeAdRequestToken !== requestToken) {
1790
+ return [
1791
+ 2,
1792
+ true
1793
+ ];
1794
+ }
1795
+ podCount = (_ref = (_adPlayer_getPodAdCount = adPlayer.getPodAdCount) === null || _adPlayer_getPodAdCount === void 0 ? void 0 : _adPlayer_getPodAdCount.call(adPlayer)) !== null && _ref !== void 0 ? _ref : 1;
1796
+ if (podCount < 1) {
1797
+ return [
1798
+ 2,
1799
+ false
1800
+ ];
1801
+ }
1802
+ if (this.debug) {
1803
+ console.log(podCount === 1 ? "[POD] Response contained a single ad; playing it and enabling sequential top-up" : "[POD] Optimized pod returned ".concat(podCount, " ads; playing pod in one controller"));
1804
+ }
1805
+ sendAdLoadedTracking(this.host.config.licenseKey, {
1806
+ source: "hls",
1807
+ vastUrl: podUrl,
1808
+ timestamp: /* @__PURE__ */ new Date().toISOString()
1809
+ }, this.analyticsContext).catch(function() {});
1810
+ this.timing.startAdFailsafeTimer(requestToken);
1811
+ return [
1812
+ 4,
1813
+ adPlayer.play()
1814
+ ];
1815
+ case 4:
1816
+ _state.sent();
1817
+ this.timing.markAdStarted();
1818
+ if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {
1819
+ this.timing.scheduleAdStopAtBreakBoundary();
1820
+ }
1821
+ adPlayer.setAdVolume(currentMuted ? 0 : currentVolume);
1822
+ this.timing.consecutiveFailures = 0;
1823
+ if (podCount === 1) {
1824
+ this.continuousFetchingActive = true;
1825
+ this.startContinuousFetching(baseVastUrl);
1826
+ if (!this.preloadPool.active) {
1827
+ this.preloadPool.startPreloadPool(baseVastUrl, []);
1828
+ }
1829
+ }
1830
+ return [
1831
+ 2,
1832
+ true
1833
+ ];
1834
+ case 5:
1835
+ error = _state.sent();
1836
+ this.timing.clearAdRequestWatchdog();
1837
+ this.timing.clearAdFailsafeTimer();
1838
+ if (this.timing.activeAdRequestToken === requestToken) {
1839
+ this.timing.activeAdRequestToken = null;
1840
+ }
1841
+ if (this.debug) {
1842
+ console.warn("[POD] Optimized pod request/play failed:", error);
1843
+ }
1844
+ if (this.timing.isTemporaryAdError(error)) {
1845
+ this.timing.temporaryFailureUrls.set(podUrl, Date.now());
1846
+ }
1847
+ this.continuousFetchingActive = true;
1848
+ this.recreateAdController();
1849
+ return [
1850
+ 2,
1851
+ false
1852
+ ];
1853
+ case 6:
1697
1854
  return [
1698
1855
  2
1699
1856
  ];