stormcloud-video-player 0.8.73 → 0.8.74

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 (61) hide show
  1. package/README.md +10 -70
  2. package/dist/stormcloud-vp.min.js +1 -1
  3. package/lib/Player.d.cts +1 -0
  4. package/lib/StormcloudPlayer.cjs +987 -273
  5. package/lib/StormcloudPlayer.cjs.map +1 -1
  6. package/lib/StormcloudPlayer.d.cts +1 -0
  7. package/lib/index.cjs +998 -278
  8. package/lib/index.cjs.map +1 -1
  9. package/lib/index.d.cts +1 -0
  10. package/lib/index.d.ts +40 -3
  11. package/lib/index.js +991 -279
  12. package/lib/index.js.map +1 -1
  13. package/lib/player/AdBreakOrchestrator.cjs +767 -67
  14. package/lib/player/AdBreakOrchestrator.cjs.map +1 -1
  15. package/lib/player/AdBreakOrchestrator.d.cts +7 -9
  16. package/lib/player/AdConfigManager.cjs +314 -62
  17. package/lib/player/AdConfigManager.cjs.map +1 -1
  18. package/lib/player/AdConfigManager.d.cts +7 -12
  19. package/lib/player/AdTimingService.cjs +37 -1
  20. package/lib/player/AdTimingService.cjs.map +1 -1
  21. package/lib/player/AdTimingService.d.cts +8 -1
  22. package/lib/player/EdgePodRequest.d.cts +1 -0
  23. package/lib/player/FloorLadder.d.cts +1 -0
  24. package/lib/player/HlsEngine.d.cts +1 -0
  25. package/lib/player/OptimizedPodRequest.cjs +719 -0
  26. package/lib/player/OptimizedPodRequest.cjs.map +1 -0
  27. package/lib/player/OptimizedPodRequest.d.cts +101 -0
  28. package/lib/player/PlayerControls.d.cts +1 -0
  29. package/lib/player/Scte35CueManager.d.cts +1 -0
  30. package/lib/player/Scte35Parser.d.cts +1 -0
  31. package/lib/player/StormcloudVideoPlayer.cjs +987 -273
  32. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  33. package/lib/player/StormcloudVideoPlayer.d.cts +1 -0
  34. package/lib/player/playerTypes.d.cts +1 -0
  35. package/lib/players/HlsPlayer.cjs +987 -273
  36. package/lib/players/HlsPlayer.cjs.map +1 -1
  37. package/lib/players/HlsPlayer.d.cts +1 -0
  38. package/lib/players/index.cjs +987 -273
  39. package/lib/players/index.cjs.map +1 -1
  40. package/lib/props.d.cts +1 -0
  41. package/lib/sdk/hlsAdPlayer.cjs +316 -51
  42. package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
  43. package/lib/sdk/hlsAdPlayer.d.cts +3 -1
  44. package/lib/sdk/pal.cjs +108 -83
  45. package/lib/sdk/pal.cjs.map +1 -1
  46. package/lib/sdk/pal.d.cts +1 -0
  47. package/lib/types.d.cts +9 -2
  48. package/lib/ui/StormcloudVideoPlayer.cjs +990 -278
  49. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  50. package/lib/ui/StormcloudVideoPlayer.d.cts +1 -0
  51. package/lib/utils/ctvVastSignals.cjs +9 -7
  52. package/lib/utils/ctvVastSignals.cjs.map +1 -1
  53. package/lib/utils/tracking.cjs +17 -3
  54. package/lib/utils/tracking.cjs.map +1 -1
  55. package/lib/utils/tracking.d.cts +2 -1
  56. package/lib/utils/vastEnvironmentSignals.cjs +9 -7
  57. package/lib/utils/vastEnvironmentSignals.cjs.map +1 -1
  58. package/lib/utils/vastMacros.cjs +250 -10
  59. package/lib/utils/vastMacros.cjs.map +1 -1
  60. package/lib/utils/vastMacros.d.cts +13 -4
  61. package/package.json +5 -3
package/lib/index.cjs CHANGED
@@ -406,12 +406,18 @@ __export(index_exports, {
406
406
  DEFAULT_FLOOR_LADDER_BOUNDS: function DEFAULT_FLOOR_LADDER_BOUNDS1() {
407
407
  return DEFAULT_FLOOR_LADDER_BOUNDS;
408
408
  },
409
+ DEFAULT_REQUEST_SAFETY_MS: function DEFAULT_REQUEST_SAFETY_MS1() {
410
+ return DEFAULT_REQUEST_SAFETY_MS;
411
+ },
409
412
  DEFAULT_TRACKING_INGEST_CONFIG: function DEFAULT_TRACKING_INGEST_CONFIG1() {
410
413
  return DEFAULT_TRACKING_INGEST_CONFIG;
411
414
  },
412
415
  DEFAULT_WEB_FLOOR_LADDER_CONFIG: function DEFAULT_WEB_FLOOR_LADDER_CONFIG1() {
413
416
  return DEFAULT_WEB_FLOOR_LADDER_CONFIG;
414
417
  },
418
+ GAM_AD_OPPORTUNITY_DURATION_MS: function GAM_AD_OPPORTUNITY_DURATION_MS1() {
419
+ return GAM_AD_OPPORTUNITY_DURATION_MS;
420
+ },
415
421
  IS_BROWSER: function IS_BROWSER1() {
416
422
  return IS_BROWSER;
417
423
  },
@@ -577,21 +583,20 @@ var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
577
583
  "adid"
578
584
  ]);
579
585
  function resolveVastEnvironmentSignals(isCtv) {
580
- var _ref;
581
586
  var bridgeSignals = readNativeBridgeSignals();
582
587
  var platformDevice = readPlatformNativeDeviceId();
583
- var realDeviceId = bridgeSignals.deviceId || (isCtv ? readStoredDeviceId() : void 0) || platformDevice.deviceId;
588
+ var bridgeDeviceId = validDeviceId(bridgeSignals.deviceId);
589
+ var realDeviceId = bridgeDeviceId || (isCtv ? validDeviceId(readStoredDeviceId()) : void 0) || validDeviceId(platformDevice.deviceId);
584
590
  var deviceId = realDeviceId;
585
- var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || platformDevice.deviceIdType || inferDeviceIdType();
586
- var platformLat = bridgeSignals.deviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;
587
- var limitAdTracking = deviceId != null ? (_ref = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false : void 0;
591
+ var deviceIdType = (bridgeDeviceId ? bridgeSignals.deviceIdType : void 0) || readStoredString("deviceIdType") || readStoredString("idtype") || platformDevice.deviceIdType || inferDeviceIdType();
592
+ var platformLat = bridgeDeviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;
593
+ var limitAdTracking = deviceId != null ? platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking() : void 0;
588
594
  if (!deviceId && isCtv) {
589
595
  var dpid = getOrCreateStoredUuid(PLAYER_ID_STORAGE_KEY);
590
596
  if (dpid) {
591
- var _ref1;
592
597
  deviceId = dpid;
593
598
  deviceIdType = "dpid";
594
- limitAdTracking = (_ref1 = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking()) !== null && _ref1 !== void 0 ? _ref1 : false;
599
+ limitAdTracking = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking();
595
600
  }
596
601
  }
597
602
  var deviceTypeHint = resolveDeviceTypeHint(isCtv);
@@ -956,6 +961,9 @@ function isMacroPlaceholder(value) {
956
961
  var t = value.trim();
957
962
  return !t || /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/.test(t) || /^(unknown|null|undefined|none|n\/a|\$\{[^}]+\})$/i.test(t) || ZEROED_AD_ID_PATTERNS.has(t.toLowerCase());
958
963
  }
964
+ function validDeviceId(value) {
965
+ return value && !isMacroPlaceholder(value) ? value : void 0;
966
+ }
959
967
  function isZeroedAdId(value) {
960
968
  return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());
961
969
  }
@@ -1488,6 +1496,198 @@ function ensureVideoAdType(rawUrl) {
1488
1496
  return rawUrl;
1489
1497
  }
1490
1498
  }
1499
+ var SCVP_MACRO_DETECT = /\[SCVP-|%5BSCVP-|\(SCVP-|%28SCVP-/i;
1500
+ var SCVP_MACRO_PATTERN = /\[SCVP-([A-Z0-9-]+)\]|\(SCVP-([A-Z0-9-]+)\)/gi;
1501
+ var SCVP_WHOLE_VALUE_PATTERN = /^\s*(?:\[SCVP-([A-Z0-9-]+)\]|\(SCVP-([A-Z0-9-]+)\))\s*$/i;
1502
+ var NESTED_QUERY_PARAM_KEYS = /* @__PURE__ */ new Set([
1503
+ "cust_params"
1504
+ ]);
1505
+ var SCVP_POD_MACROS = /* @__PURE__ */ new Set([
1506
+ "PMND",
1507
+ "PMXD",
1508
+ "PMAD"
1509
+ ]);
1510
+ function hasScvpMacros(url) {
1511
+ return !!url && SCVP_MACRO_DETECT.test(url);
1512
+ }
1513
+ function safeDecode(value) {
1514
+ try {
1515
+ return decodeURIComponent(value.replace(/\+/g, " "));
1516
+ } catch (unused) {
1517
+ return value;
1518
+ }
1519
+ }
1520
+ function findScvpMacroNames(url) {
1521
+ if (!url) return [];
1522
+ var names = /* @__PURE__ */ new Set();
1523
+ var text = url;
1524
+ for(var pass = 0; pass < 3; pass++){
1525
+ text.replace(SCVP_MACRO_PATTERN, function(_m, bracketName, parenName) {
1526
+ names.add(String(bracketName || parenName).toUpperCase());
1527
+ return "";
1528
+ });
1529
+ var decoded = safeDecode(text);
1530
+ if (decoded === text) break;
1531
+ text = decoded;
1532
+ }
1533
+ return Array.from(names);
1534
+ }
1535
+ function resolveScvpMacroValues(ctx) {
1536
+ var _ctx_deviceId, _ctx_deviceIdType, _ctx_consent, _ctx_consent1, _ctx_consent2;
1537
+ var values = /* @__PURE__ */ new Map();
1538
+ var set = function set(name, value) {
1539
+ if (value == null) return;
1540
+ var str = String(value).trim();
1541
+ if (str) values.set(name, str);
1542
+ };
1543
+ var toFlag = function toFlag(value) {
1544
+ return value == null ? void 0 : value ? "1" : "0";
1545
+ };
1546
+ var deviceId = (_ctx_deviceId = ctx.deviceId) === null || _ctx_deviceId === void 0 ? void 0 : _ctx_deviceId.trim();
1547
+ var deviceIdType = deviceId ? ((_ctx_deviceIdType = ctx.deviceIdType) === null || _ctx_deviceIdType === void 0 ? void 0 : _ctx_deviceIdType.trim()) || inferDeviceIdType() : void 0;
1548
+ if (deviceId && deviceIdType) {
1549
+ set("RDID", deviceId);
1550
+ set("IDTYPE", deviceIdType);
1551
+ set("IS-LAT", toFlag(ctx.limitAdTracking));
1552
+ }
1553
+ set("SID", ctx.sessionId);
1554
+ set("DTH", ctx.deviceTypeHint);
1555
+ set("GIVN", ctx.palNonce);
1556
+ set("CT-TI", ctx.programTitle);
1557
+ set("CT-CH", ctx.channelName);
1558
+ set("POD", ctx.pod);
1559
+ set("CORRELATOR", ctx.correlator);
1560
+ set("SCOR", ctx.streamCorrelator);
1561
+ set("VPMUTE", toFlag(ctx.adWillPlayMuted));
1562
+ if (ctx.adWillAutoPlay != null) {
1563
+ set("VPA", ctx.adWillAutoPlay ? "auto" : "click");
1564
+ }
1565
+ set("GDPR", (_ctx_consent = ctx.consent) === null || _ctx_consent === void 0 ? void 0 : _ctx_consent.gdpr);
1566
+ set("GDPR-CONSENT", (_ctx_consent1 = ctx.consent) === null || _ctx_consent1 === void 0 ? void 0 : _ctx_consent1.gdprConsent);
1567
+ set("US-PRIVACY", (_ctx_consent2 = ctx.consent) === null || _ctx_consent2 === void 0 ? void 0 : _ctx_consent2.usPrivacy);
1568
+ return values;
1569
+ }
1570
+ var keepNone = function keepNone() {
1571
+ return false;
1572
+ };
1573
+ function substituteScvpParams(params, values, unresolved, keep, nested) {
1574
+ var out = [];
1575
+ var replaceMacro = function replaceMacro(match, bracketName, parenName) {
1576
+ var name = String(bracketName || parenName).toUpperCase();
1577
+ var value = values.get(name);
1578
+ if (value != null) return value;
1579
+ if (keep(name)) return match;
1580
+ unresolved.add(name);
1581
+ return "";
1582
+ };
1583
+ params.forEach(function(value, key) {
1584
+ var whole = value.match(SCVP_WHOLE_VALUE_PATTERN);
1585
+ if (whole) {
1586
+ var name = String(whole[1] || whole[2]).toUpperCase();
1587
+ var resolved = values.get(name);
1588
+ if (resolved != null) {
1589
+ out.push([
1590
+ key,
1591
+ resolved
1592
+ ]);
1593
+ } else if (keep(name)) {
1594
+ out.push([
1595
+ key,
1596
+ value
1597
+ ]);
1598
+ } else {
1599
+ unresolved.add(name);
1600
+ }
1601
+ return;
1602
+ }
1603
+ if (!SCVP_MACRO_DETECT.test(value)) {
1604
+ out.push([
1605
+ key,
1606
+ value
1607
+ ]);
1608
+ return;
1609
+ }
1610
+ if (!nested && NESTED_QUERY_PARAM_KEYS.has(key)) {
1611
+ var inner = substituteScvpParams(new URLSearchParams(value), values, unresolved, keep, true);
1612
+ if (inner.length > 0) {
1613
+ out.push([
1614
+ key,
1615
+ inner.map(function(param) {
1616
+ var _param = _sliced_to_array(param, 2), k = _param[0], v = _param[1];
1617
+ return "".concat(encodeURIComponent(k), "=").concat(encodeURIComponent(v));
1618
+ }).join("&")
1619
+ ]);
1620
+ }
1621
+ return;
1622
+ }
1623
+ out.push([
1624
+ key,
1625
+ value.replace(SCVP_MACRO_PATTERN, replaceMacro)
1626
+ ]);
1627
+ });
1628
+ return out;
1629
+ }
1630
+ function substituteScvpMacros(baseUrl, values) {
1631
+ var keep = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : keepNone;
1632
+ var unresolved = /* @__PURE__ */ new Set();
1633
+ var url;
1634
+ try {
1635
+ url = new URL(normalizeVastTagUrl(baseUrl));
1636
+ } catch (unused) {
1637
+ var replaced = baseUrl.replace(SCVP_MACRO_PATTERN, function(match, bracketName, parenName) {
1638
+ var name = String(bracketName || parenName).toUpperCase();
1639
+ var value = values.get(name);
1640
+ if (value != null) return encodeURIComponent(value);
1641
+ if (keep(name)) return match;
1642
+ unresolved.add(name);
1643
+ return "";
1644
+ });
1645
+ return {
1646
+ url: replaced,
1647
+ unresolved: Array.from(unresolved)
1648
+ };
1649
+ }
1650
+ var entries = substituteScvpParams(url.searchParams, values, unresolved, keep, false);
1651
+ var search = new URLSearchParams();
1652
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1653
+ try {
1654
+ for(var _iterator = entries[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1655
+ var _step_value = _sliced_to_array(_step.value, 2), key = _step_value[0], value = _step_value[1];
1656
+ search.append(key, value);
1657
+ }
1658
+ } catch (err) {
1659
+ _didIteratorError = true;
1660
+ _iteratorError = err;
1661
+ } finally{
1662
+ try {
1663
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1664
+ _iterator.return();
1665
+ }
1666
+ } finally{
1667
+ if (_didIteratorError) {
1668
+ throw _iteratorError;
1669
+ }
1670
+ }
1671
+ }
1672
+ url.search = search.toString();
1673
+ return {
1674
+ url: url.toString(),
1675
+ unresolved: Array.from(unresolved)
1676
+ };
1677
+ }
1678
+ function applyScvpMacros(baseUrl, ctx) {
1679
+ var deferred = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : /* @__PURE__ */ new Set();
1680
+ return substituteScvpMacros(baseUrl, resolveScvpMacroValues(ctx), function(name) {
1681
+ return deferred.has(name);
1682
+ });
1683
+ }
1684
+ function stripScvpMacros(url) {
1685
+ if (findScvpMacroNames(url).length === 0) return {
1686
+ url: url,
1687
+ unresolved: []
1688
+ };
1689
+ return substituteScvpMacros(url, /* @__PURE__ */ new Map());
1690
+ }
1491
1691
  function applyVastMacros(baseUrl, ctx) {
1492
1692
  var expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);
1493
1693
  var url;
@@ -1529,15 +1729,6 @@ function applyVastMacros(baseUrl, ctx) {
1529
1729
  }
1530
1730
  params.delete("ppos");
1531
1731
  params.delete("lip");
1532
- if (ctx.podMinDurationMs != null) {
1533
- params.set("pmnd", String(Math.max(0, Math.round(ctx.podMinDurationMs))));
1534
- }
1535
- if (ctx.podMaxDurationMs != null) {
1536
- params.set("pmxd", String(Math.max(0, Math.round(ctx.podMaxDurationMs))));
1537
- }
1538
- if (ctx.podMaxAds != null) {
1539
- params.set("pmad", String(Math.max(1, Math.round(ctx.podMaxAds))));
1540
- }
1541
1732
  var existingUrl = params.get("url") || "";
1542
1733
  if (EXAMPLE_COM_URL.test(existingUrl)) {
1543
1734
  params.delete("url");
@@ -2390,6 +2581,309 @@ function substituteVastTrackingMacros(url) {
2390
2581
  return KNOWN_VAST_MACROS.has(name) ? "" : match;
2391
2582
  });
2392
2583
  }
2584
+ // src/player/OptimizedPodRequest.ts
2585
+ var DEFAULT_REQUEST_SAFETY_MS = 1500;
2586
+ var GAM_AD_OPPORTUNITY_DURATION_MS = 3e4;
2587
+ var POD_PARAM_KEYS = [
2588
+ "pmnd",
2589
+ "pmxd",
2590
+ "pmad"
2591
+ ];
2592
+ var POSITIVE_INT = /^[1-9]\d*$/;
2593
+ var NON_NEGATIVE_INT = /^(0|[1-9]\d*)$/;
2594
+ function nonNegativeInt(value) {
2595
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : void 0;
2596
+ }
2597
+ function positiveInt(value) {
2598
+ return typeof value === "number" && Number.isFinite(value) && value >= 1 ? Math.floor(value) : void 0;
2599
+ }
2600
+ function resolveAdPodConfig(config) {
2601
+ var _config_adPodConfig, _nonNegativeInt, _nonNegativeInt1, _positiveInt;
2602
+ var pod = (_config_adPodConfig = config.adPodConfig) !== null && _config_adPodConfig !== void 0 ? _config_adPodConfig : {};
2603
+ return {
2604
+ requestSafetyMs: (_nonNegativeInt = nonNegativeInt(pod.requestSafetyMs)) !== null && _nonNegativeInt !== void 0 ? _nonNegativeInt : DEFAULT_REQUEST_SAFETY_MS,
2605
+ minPodDurationMs: (_nonNegativeInt1 = nonNegativeInt(pod.minPodDurationMs)) !== null && _nonNegativeInt1 !== void 0 ? _nonNegativeInt1 : 0,
2606
+ maxAdsPerBreak: pod.maxAdsPerBreak === void 0 ? positiveInt(config.podMaxAds) : positiveInt(pod.maxAdsPerBreak),
2607
+ maxPodDurationMs: (_positiveInt = positiveInt(pod.maxPodDurationMs)) !== null && _positiveInt !== void 0 ? _positiveInt : positiveInt(config.podMaxDurationMs),
2608
+ exactDuration: config.podExactDuration === true
2609
+ };
2610
+ }
2611
+ function measureBreakCapacity(timing, nowMonoMs) {
2612
+ var _timing_breakEndMonoMs;
2613
+ var scheduled = timing.scheduledBreakDurationMs;
2614
+ if (scheduled == null || !(scheduled > 0) || timing.breakStartMonoMs == null) {
2615
+ return void 0;
2616
+ }
2617
+ var endMonoMs = (_timing_breakEndMonoMs = timing.breakEndMonoMs) !== null && _timing_breakEndMonoMs !== void 0 ? _timing_breakEndMonoMs : timing.breakStartMonoMs + scheduled;
2618
+ var untilEnd = Math.min(scheduled, endMonoMs - nowMonoMs);
2619
+ var unplayed = scheduled - Math.max(0, timing.playedDurationMs);
2620
+ return {
2621
+ scheduledBreakDurationMs: scheduled,
2622
+ elapsedBeforeGamRequestMs: Math.max(0, nowMonoMs - timing.breakStartMonoMs),
2623
+ remainingAtGamDispatchMs: Math.max(0, Math.min(untilEnd, unplayed))
2624
+ };
2625
+ }
2626
+ function resolvePodParams(input) {
2627
+ var capacity = input.capacity, config = input.config;
2628
+ var pmxd;
2629
+ var source;
2630
+ if (capacity) {
2631
+ pmxd = Math.floor(capacity.remainingAtGamDispatchMs - config.requestSafetyMs);
2632
+ source = "break_remaining";
2633
+ } else if (config.maxPodDurationMs != null) {
2634
+ pmxd = config.maxPodDurationMs;
2635
+ source = "configured_cap";
2636
+ } else if (input.tagMaxDurationMs != null) {
2637
+ pmxd = input.tagMaxDurationMs;
2638
+ source = "tag_cap";
2639
+ } else {
2640
+ return {
2641
+ kind: "omit"
2642
+ };
2643
+ }
2644
+ var minUsable = Math.max(1, Math.floor(input.minUsablePmxdMs));
2645
+ if (!Number.isFinite(pmxd) || pmxd < minUsable) {
2646
+ return {
2647
+ kind: "abort",
2648
+ reason: capacity ? "insufficient_break_capacity" : "invalid_pod_cap",
2649
+ pmxdCandidateMs: Number.isFinite(pmxd) ? pmxd : 0
2650
+ };
2651
+ }
2652
+ var pmnd = config.exactDuration ? pmxd : Math.min(config.minPodDurationMs, pmxd);
2653
+ return {
2654
+ kind: "send",
2655
+ params: {
2656
+ pmnd: pmnd,
2657
+ pmxd: pmxd,
2658
+ pmad: config.maxAdsPerBreak
2659
+ },
2660
+ source: source
2661
+ };
2662
+ }
2663
+ function podRequestAborted(reason, message, diagnostics) {
2664
+ var error = new Error("Optimized pod request not sent (".concat(reason, "): ").concat(message));
2665
+ error.podRequestAborted = true;
2666
+ error.reason = reason;
2667
+ error.diagnostics = diagnostics;
2668
+ return error;
2669
+ }
2670
+ function isPodRequestAbortedError(error) {
2671
+ return !!error && error.podRequestAborted === true;
2672
+ }
2673
+ function firstPositiveIntParam(params, key) {
2674
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2675
+ try {
2676
+ for(var _iterator = params.getAll(key)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2677
+ var value = _step.value;
2678
+ if (POSITIVE_INT.test(value.trim())) return Number(value.trim());
2679
+ }
2680
+ } catch (err) {
2681
+ _didIteratorError = true;
2682
+ _iteratorError = err;
2683
+ } finally{
2684
+ try {
2685
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2686
+ _iterator.return();
2687
+ }
2688
+ } finally{
2689
+ if (_didIteratorError) {
2690
+ throw _iteratorError;
2691
+ }
2692
+ }
2693
+ }
2694
+ return void 0;
2695
+ }
2696
+ function isOptimizedPodUrl(url) {
2697
+ if (findScvpMacroNames(url).some(function(name) {
2698
+ return SCVP_POD_MACROS.has(name);
2699
+ })) return true;
2700
+ try {
2701
+ var params = new URL(url).searchParams;
2702
+ return POD_PARAM_KEYS.some(function(key) {
2703
+ return params.has(key);
2704
+ });
2705
+ } catch (unused) {
2706
+ return false;
2707
+ }
2708
+ }
2709
+ function finalizeGamRequestUrl(rawUrl, ctx) {
2710
+ var nowEpochMs = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : Date.now();
2711
+ var optimizedPod = isOptimizedPodUrl(rawUrl);
2712
+ var capacity = ctx.capacity;
2713
+ var base = {
2714
+ breakId: ctx.breakId,
2715
+ optimizedPod: optimizedPod,
2716
+ scteBreakDurationMs: capacity === null || capacity === void 0 ? void 0 : capacity.scheduledBreakDurationMs,
2717
+ elapsedBeforeGamRequestMs: capacity === null || capacity === void 0 ? void 0 : capacity.elapsedBeforeGamRequestMs,
2718
+ remainingAtGamDispatchMs: capacity === null || capacity === void 0 ? void 0 : capacity.remainingAtGamDispatchMs,
2719
+ safetyReserveMs: ctx.config.requestSafetyMs
2720
+ };
2721
+ var decision = {
2722
+ kind: "omit"
2723
+ };
2724
+ if (optimizedPod) {
2725
+ var tagMaxDurationMs;
2726
+ try {
2727
+ tagMaxDurationMs = firstPositiveIntParam(new URL(rawUrl).searchParams, "pmxd");
2728
+ } catch (unused) {}
2729
+ decision = resolvePodParams({
2730
+ capacity: capacity,
2731
+ config: ctx.config,
2732
+ minUsablePmxdMs: ctx.minUsablePmxdMs,
2733
+ tagMaxDurationMs: tagMaxDurationMs
2734
+ });
2735
+ if (decision.kind === "abort") {
2736
+ throw podRequestAborted(decision.reason, "pmxd would be ".concat(decision.pmxdCandidateMs, "ms (minimum ").concat(ctx.minUsablePmxdMs, "ms)"), base);
2737
+ }
2738
+ }
2739
+ var pod = decision.kind === "send" ? decision.params : void 0;
2740
+ var values = /* @__PURE__ */ new Map();
2741
+ if (pod) {
2742
+ values.set("PMND", String(pod.pmnd));
2743
+ values.set("PMXD", String(pod.pmxd));
2744
+ if (pod.pmad != null) values.set("PMAD", String(pod.pmad));
2745
+ }
2746
+ var substituted = substituteScvpMacros(rawUrl, values);
2747
+ var finalUrl;
2748
+ try {
2749
+ var url = new URL(normalizeVastTagUrl(substituted.url));
2750
+ if (pod) {
2751
+ url.searchParams.set("pmnd", String(pod.pmnd));
2752
+ url.searchParams.set("pmxd", String(pod.pmxd));
2753
+ if (pod.pmad != null) url.searchParams.set("pmad", String(pod.pmad));
2754
+ else url.searchParams.delete("pmad");
2755
+ } else {
2756
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2757
+ try {
2758
+ for(var _iterator = POD_PARAM_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2759
+ var key = _step.value;
2760
+ url.searchParams.delete(key);
2761
+ }
2762
+ } catch (err) {
2763
+ _didIteratorError = true;
2764
+ _iteratorError = err;
2765
+ } finally{
2766
+ try {
2767
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2768
+ _iterator.return();
2769
+ }
2770
+ } finally{
2771
+ if (_didIteratorError) {
2772
+ throw _iteratorError;
2773
+ }
2774
+ }
2775
+ }
2776
+ }
2777
+ finalUrl = url.toString();
2778
+ } catch (unused) {
2779
+ throw podRequestAborted("invalid_url", "GAM request URL could not be parsed", base);
2780
+ }
2781
+ var problems = validateGamRequestUrl(finalUrl, {
2782
+ optimizedPod: !!pod,
2783
+ remainingMs: decision.kind === "send" && decision.source === "break_remaining" ? capacity === null || capacity === void 0 ? void 0 : capacity.remainingAtGamDispatchMs : void 0
2784
+ });
2785
+ if (problems.length > 0) {
2786
+ throw podRequestAborted("invalid_url", problems.join("; "), base);
2787
+ }
2788
+ var givn = null;
2789
+ try {
2790
+ givn = new URL(finalUrl).searchParams.get("givn");
2791
+ } catch (unused) {}
2792
+ return {
2793
+ url: finalUrl,
2794
+ diagnostics: {
2795
+ breakId: ctx.breakId,
2796
+ optimizedPod: !!pod,
2797
+ pmxdSource: decision.kind === "send" ? decision.source : void 0,
2798
+ scteBreakDurationMs: capacity === null || capacity === void 0 ? void 0 : capacity.scheduledBreakDurationMs,
2799
+ elapsedBeforeGamRequestMs: capacity === null || capacity === void 0 ? void 0 : capacity.elapsedBeforeGamRequestMs,
2800
+ remainingAtGamDispatchMs: capacity === null || capacity === void 0 ? void 0 : capacity.remainingAtGamDispatchMs,
2801
+ safetyReserveMs: ctx.config.requestSafetyMs,
2802
+ pmndSent: pod === null || pod === void 0 ? void 0 : pod.pmnd,
2803
+ pmxdSent: pod === null || pod === void 0 ? void 0 : pod.pmxd,
2804
+ pmadSent: pod === null || pod === void 0 ? void 0 : pod.pmad,
2805
+ palNoncePresent: !!givn,
2806
+ gamRequestDispatchTimestamp: new Date(nowEpochMs).toISOString(),
2807
+ strippedMacros: substituted.unresolved.filter(function(name) {
2808
+ return !SCVP_POD_MACROS.has(name);
2809
+ })
2810
+ }
2811
+ };
2812
+ }
2813
+ function validateGamRequestUrl(url, expect) {
2814
+ var problems = [];
2815
+ var leftover = findScvpMacroNames(url);
2816
+ if (leftover.length > 0) problems.push("unresolved SCVP macros: ".concat(leftover.join(", ")));
2817
+ var params;
2818
+ try {
2819
+ params = new URL(url).searchParams;
2820
+ } catch (unused) {
2821
+ return problems.concat("URL could not be parsed");
2822
+ }
2823
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2824
+ try {
2825
+ for(var _iterator = POD_PARAM_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2826
+ var key = _step.value;
2827
+ if (params.getAll(key).length > 1) problems.push("duplicate ".concat(key));
2828
+ }
2829
+ } catch (err) {
2830
+ _didIteratorError = true;
2831
+ _iteratorError = err;
2832
+ } finally{
2833
+ try {
2834
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2835
+ _iterator.return();
2836
+ }
2837
+ } finally{
2838
+ if (_didIteratorError) {
2839
+ throw _iteratorError;
2840
+ }
2841
+ }
2842
+ }
2843
+ if (!expect.optimizedPod) {
2844
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
2845
+ try {
2846
+ for(var _iterator1 = POD_PARAM_KEYS[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
2847
+ var key1 = _step1.value;
2848
+ if (params.has(key1)) problems.push("".concat(key1, " present on a non-pod request"));
2849
+ }
2850
+ } catch (err) {
2851
+ _didIteratorError1 = true;
2852
+ _iteratorError1 = err;
2853
+ } finally{
2854
+ try {
2855
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2856
+ _iterator1.return();
2857
+ }
2858
+ } finally{
2859
+ if (_didIteratorError1) {
2860
+ throw _iteratorError1;
2861
+ }
2862
+ }
2863
+ }
2864
+ return problems;
2865
+ }
2866
+ var pmxd = params.get("pmxd");
2867
+ var pmnd = params.get("pmnd");
2868
+ var pmad = params.get("pmad");
2869
+ if (pmxd == null || !POSITIVE_INT.test(pmxd)) problems.push("pmxd must be a positive integer (got ".concat(pmxd, ")"));
2870
+ if (pmnd == null || !NON_NEGATIVE_INT.test(pmnd)) problems.push("pmnd must be a non-negative integer (got ".concat(pmnd, ")"));
2871
+ if (pmxd != null && pmnd != null && Number(pmnd) > Number(pmxd)) problems.push("pmnd exceeds pmxd");
2872
+ if (pmad != null && !POSITIVE_INT.test(pmad)) problems.push("pmad must be a positive integer or absent (got ".concat(pmad, ")"));
2873
+ if (expect.remainingMs != null && pmxd != null && Number(pmxd) > expect.remainingMs) {
2874
+ problems.push("pmxd ".concat(pmxd, " exceeds remaining break ").concat(expect.remainingMs, "ms"));
2875
+ }
2876
+ return problems;
2877
+ }
2878
+ function computePodResponseDiagnostics(pmxdSent, vastAdCount, totalVastCreativeDurationMs) {
2879
+ var estimatedUnusedPodMs = Math.max(0, pmxdSent - totalVastCreativeDurationMs);
2880
+ return {
2881
+ vastAdCount: vastAdCount,
2882
+ totalVastCreativeDurationMs: totalVastCreativeDurationMs,
2883
+ estimatedUnusedPodMs: estimatedUnusedPodMs,
2884
+ estimatedUnmatchedCount: Math.floor(estimatedUnusedPodMs / GAM_AD_OPPORTUNITY_DURATION_MS)
2885
+ };
2886
+ }
2393
2887
  // src/sdk/hlsAdPlayer.ts
2394
2888
  var LINEAR_TRACKING_EVENTS = [
2395
2889
  "creativeView",
@@ -2470,6 +2964,7 @@ function toVastMediaErrorCode(error) {
2470
2964
  return VAST_ERROR_MEDIA_DISPLAY;
2471
2965
  }
2472
2966
  }
2967
+ var gamCredentialsMode = "include";
2473
2968
  function createHlsAdPlayer(contentVideo, options) {
2474
2969
  var _contentVideo_AD_VIDEO_PROP, _contentVideo_AD_CONTAINER_PROP, _ref;
2475
2970
  var adPlaying = false;
@@ -3341,9 +3836,9 @@ function createHlsAdPlayer(contentVideo, options) {
3341
3836
  }
3342
3837
  }
3343
3838
  function fetchVastXml(vastTagUrl) {
3344
- var credentials = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "include", kind = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "gam";
3839
+ var credentials = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "include", kind = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "gam", finalizeRequestUrl = arguments.length > 3 ? arguments[3] : void 0;
3345
3840
  return _async_to_generator(function() {
3346
- var controller, timeoutId, startedAt, attempt, requestVast, response, error, error1;
3841
+ var controller, timeoutId, startedAt, attempt, resolveDispatchUrl, requestVast, response, error, error1;
3347
3842
  return _ts_generator(this, function(_state) {
3348
3843
  switch(_state.label){
3349
3844
  case 0:
@@ -3357,13 +3852,32 @@ function createHlsAdPlayer(contentVideo, options) {
3357
3852
  }, VAST_REQUEST_TIMEOUT_MS) : void 0;
3358
3853
  startedAt = Date.now();
3359
3854
  attempt = 0;
3855
+ resolveDispatchUrl = function resolveDispatchUrl() {
3856
+ if (kind === "wrapper") return vastTagUrl;
3857
+ if (finalizeRequestUrl) return finalizeRequestUrl(vastTagUrl, attempt);
3858
+ var _stripScvpMacros = stripScvpMacros(vastTagUrl), url = _stripScvpMacros.url, unresolved = _stripScvpMacros.unresolved;
3859
+ if (unresolved.length > 0) {
3860
+ console.warn("[HlsAdPlayer] Removed unresolved SCVP macros before dispatch:", unresolved.join(", "));
3861
+ }
3862
+ return url;
3863
+ };
3360
3864
  requestVast = function requestVast(creds) {
3361
3865
  return _async_to_generator(function() {
3362
- var response;
3866
+ var pending, response;
3363
3867
  return _ts_generator(this, function(_state) {
3364
3868
  switch(_state.label){
3365
3869
  case 0:
3366
3870
  attempt++;
3871
+ pending = fetch(resolveDispatchUrl(), _object_spread({
3872
+ mode: "cors",
3873
+ credentials: creds,
3874
+ headers: {
3875
+ "Accept": "application/xml, text/xml, */*"
3876
+ },
3877
+ referrerPolicy: "no-referrer-when-downgrade"
3878
+ }, controller ? {
3879
+ signal: controller.signal
3880
+ } : {}));
3367
3881
  if (kind !== "wrapper") {
3368
3882
  logFunnel("".concat(kind, "_http_request_sent"), {
3369
3883
  attempt: attempt,
@@ -3372,16 +3886,7 @@ function createHlsAdPlayer(contentVideo, options) {
3372
3886
  }
3373
3887
  return [
3374
3888
  4,
3375
- fetch(vastTagUrl, _object_spread({
3376
- mode: "cors",
3377
- credentials: creds,
3378
- headers: {
3379
- "Accept": "application/xml, text/xml, */*"
3380
- },
3381
- referrerPolicy: "no-referrer-when-downgrade"
3382
- }, controller ? {
3383
- signal: controller.signal
3384
- } : {}))
3889
+ pending
3385
3890
  ];
3386
3891
  case 1:
3387
3892
  response = _state.sent();
@@ -3405,9 +3910,9 @@ function createHlsAdPlayer(contentVideo, options) {
3405
3910
  case 1:
3406
3911
  _state.trys.push([
3407
3912
  1,
3408
- 10,
3409
- 11,
3410
- 12
3913
+ 7,
3914
+ 8,
3915
+ 9
3411
3916
  ]);
3412
3917
  _state.label = 2;
3413
3918
  case 2:
@@ -3415,7 +3920,7 @@ function createHlsAdPlayer(contentVideo, options) {
3415
3920
  2,
3416
3921
  4,
3417
3922
  ,
3418
- 8
3923
+ 5
3419
3924
  ]);
3420
3925
  return [
3421
3926
  4,
@@ -3425,36 +3930,21 @@ function createHlsAdPlayer(contentVideo, options) {
3425
3930
  response = _state.sent();
3426
3931
  return [
3427
3932
  3,
3428
- 8
3933
+ 5
3429
3934
  ];
3430
3935
  case 4:
3431
3936
  error = _state.sent();
3432
- if (!(credentials !== "omit" && !(controller === null || controller === void 0 ? void 0 : controller.signal.aborted))) return [
3433
- 3,
3434
- 6
3435
- ];
3436
- console.warn('[HlsAdPlayer] VAST fetch failed with credentials="'.concat(credentials, '", retrying without credentials:'), error);
3437
- logFunnel("vast_credentials_retry", {
3438
- errorMessage: error === null || error === void 0 ? void 0 : error.message
3439
- });
3440
- return [
3441
- 4,
3442
- requestVast("omit")
3443
- ];
3444
- case 5:
3445
- response = _state.sent();
3446
- return [
3447
- 3,
3448
- 7
3449
- ];
3450
- case 6:
3937
+ if (kind === "gam" && !(controller === null || controller === void 0 ? void 0 : controller.signal.aborted) && !isPodRequestAbortedError(error)) {
3938
+ gamCredentialsMode = credentials === "include" ? "omit" : "include";
3939
+ console.warn('[HlsAdPlayer] GAM fetch failed with credentials="'.concat(credentials, '"; next GAM request will use credentials="').concat(gamCredentialsMode, '":'), error);
3940
+ logFunnel("gam_credentials_mode_changed", {
3941
+ from: credentials,
3942
+ to: gamCredentialsMode,
3943
+ errorMessage: error === null || error === void 0 ? void 0 : error.message
3944
+ });
3945
+ }
3451
3946
  throw error;
3452
- case 7:
3453
- return [
3454
- 3,
3455
- 8
3456
- ];
3457
- case 8:
3947
+ case 5:
3458
3948
  if (!response.ok) {
3459
3949
  throw new Error("Failed to fetch VAST: HTTP ".concat(response.status, " ").concat(response.statusText));
3460
3950
  }
@@ -3462,12 +3952,12 @@ function createHlsAdPlayer(contentVideo, options) {
3462
3952
  4,
3463
3953
  response.text()
3464
3954
  ];
3465
- case 9:
3955
+ case 6:
3466
3956
  return [
3467
3957
  2,
3468
3958
  _state.sent()
3469
3959
  ];
3470
- case 10:
3960
+ case 7:
3471
3961
  error1 = _state.sent();
3472
3962
  if (controller === null || controller === void 0 ? void 0 : controller.signal.aborted) {
3473
3963
  if (pendingRequestAbortReason) {
@@ -3476,13 +3966,13 @@ function createHlsAdPlayer(contentVideo, options) {
3476
3966
  throw new Error("VAST request timeout after ".concat(VAST_REQUEST_TIMEOUT_MS, "ms: ").concat(vastTagUrl));
3477
3967
  }
3478
3968
  throw error1;
3479
- case 11:
3969
+ case 8:
3480
3970
  if (timeoutId !== void 0) clearTimeout(timeoutId);
3481
3971
  if (controller) pendingVastRequests.delete(controller);
3482
3972
  return [
3483
3973
  7
3484
3974
  ];
3485
- case 12:
3975
+ case 9:
3486
3976
  return [
3487
3977
  2
3488
3978
  ];
@@ -3615,7 +4105,7 @@ function createHlsAdPlayer(contentVideo, options) {
3615
4105
  });
3616
4106
  }
3617
4107
  function fetchAndParsePod(vastTagUrl) {
3618
- var source = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "gam";
4108
+ var source = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "gam", finalizeRequestUrl = arguments.length > 2 ? arguments[2] : void 0;
3619
4109
  return _async_to_generator(function() {
3620
4110
  var _root_getAttribute, _root_getAttribute1, isEdge, vastXml, trimmedXml, xmlDoc, root, adElements, _root_getAttribute2, _empty_errorUrls, empty, _empty_errorCode, resolveAd, candidates, podElements, buffet, resolveAll, ads, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, ad, err, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, ad1, err;
3621
4111
  return _ts_generator(this, function(_state) {
@@ -3625,7 +4115,7 @@ function createHlsAdPlayer(contentVideo, options) {
3625
4115
  isEdge = source === "edge";
3626
4116
  return [
3627
4117
  4,
3628
- fetchVastXml(vastTagUrl, isEdge ? "omit" : "include", source)
4118
+ fetchVastXml(vastTagUrl, isEdge ? "omit" : gamCredentialsMode, source, finalizeRequestUrl)
3629
4119
  ];
3630
4120
  case 1:
3631
4121
  vastXml = _state.sent();
@@ -4948,7 +5438,7 @@ function createHlsAdPlayer(contentVideo, options) {
4948
5438
  case 2:
4949
5439
  return [
4950
5440
  4,
4951
- fetchAndParsePod(vastTagUrl, source)
5441
+ fetchAndParsePod(vastTagUrl, source, requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.finalizeRequestUrl)
4952
5442
  ];
4953
5443
  case 3:
4954
5444
  ads = _state.sent();
@@ -5525,95 +6015,38 @@ function getOrCreateNonceLoader(allowStorage) {
5525
6015
  function createPalNonceManager() {
5526
6016
  var currentNonce = "";
5527
6017
  var currentNonceManager;
6018
+ var pendingNonce;
5528
6019
  return {
5529
6020
  generateNonce: function generateNonce() {
5530
- return _async_to_generator(function() {
5531
- var options, _options_allowStorage, _options_adWillAutoPlay, _options_adWillPlayMuted, _options_playerVolume, _options_continuousPlayback, loader, goog, request, manager, error;
5532
- var _arguments = arguments;
5533
- return _ts_generator(this, function(_state) {
5534
- switch(_state.label){
5535
- case 0:
5536
- options = _arguments.length > 0 && _arguments[0] !== void 0 ? _arguments[0] : {};
5537
- _state.label = 1;
5538
- case 1:
5539
- _state.trys.push([
5540
- 1,
5541
- 4,
5542
- ,
5543
- 5
5544
- ]);
5545
- return [
5546
- 4,
5547
- loadPalSdk()
5548
- ];
5549
- case 2:
5550
- _state.sent();
5551
- loader = getOrCreateNonceLoader((_options_allowStorage = options.allowStorage) !== null && _options_allowStorage !== void 0 ? _options_allowStorage : true);
5552
- goog = window.goog;
5553
- request = new goog.pal.NonceRequest();
5554
- request.adWillAutoPlay = (_options_adWillAutoPlay = options.adWillAutoPlay) !== null && _options_adWillAutoPlay !== void 0 ? _options_adWillAutoPlay : true;
5555
- request.adWillPlayMuted = (_options_adWillPlayMuted = options.adWillPlayMuted) !== null && _options_adWillPlayMuted !== void 0 ? _options_adWillPlayMuted : false;
5556
- request.playerVolume = (_options_playerVolume = options.playerVolume) !== null && _options_playerVolume !== void 0 ? _options_playerVolume : request.adWillPlayMuted ? 0 : 1;
5557
- request.continuousPlayback = (_options_continuousPlayback = options.continuousPlayback) !== null && _options_continuousPlayback !== void 0 ? _options_continuousPlayback : true;
5558
- request.descriptionUrl = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
5559
- request.iconsSupported = true;
5560
- request.playerType = "StormcloudVideoPlayer";
5561
- request.playerVersion = "1.0";
5562
- request.supportedApiFrameworks = "2,7,9";
5563
- request.url = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
5564
- request.videoWidth = options.videoWidth || 640;
5565
- request.videoHeight = options.videoHeight || 480;
5566
- if (options.ppid) request.ppid = options.ppid;
5567
- if (options.sessionId) request.sessionId = options.sessionId;
5568
- console.log("[PAL] NonceRequest before generateNonce:", JSON.stringify({
5569
- adWillAutoPlay: request.adWillAutoPlay,
5570
- adWillPlayMuted: request.adWillPlayMuted,
5571
- playerVolume: request.playerVolume,
5572
- continuousPlayback: request.continuousPlayback,
5573
- descriptionUrl: request.descriptionUrl,
5574
- iconsSupported: request.iconsSupported,
5575
- playerType: request.playerType,
5576
- playerVersion: request.playerVersion,
5577
- supportedApiFrameworks: request.supportedApiFrameworks,
5578
- url: request.url,
5579
- videoWidth: request.videoWidth,
5580
- videoHeight: request.videoHeight,
5581
- ppid: request.ppid,
5582
- sessionId: request.sessionId
5583
- }, null, 2));
5584
- return [
5585
- 4,
5586
- loader.loadNonceManager(request)
5587
- ];
5588
- case 3:
5589
- manager = _state.sent();
5590
- currentNonceManager = manager;
5591
- currentNonce = manager.getNonce();
5592
- console.log("[PAL] Nonce generated successfully");
5593
- return [
5594
- 2,
5595
- currentNonce
5596
- ];
5597
- case 4:
5598
- error = _state.sent();
5599
- console.warn("[PAL] Failed to generate nonce:", error);
5600
- currentNonce = "";
5601
- currentNonceManager = void 0;
5602
- return [
5603
- 2,
5604
- ""
5605
- ];
5606
- case 5:
5607
- return [
5608
- 2
5609
- ];
5610
- }
5611
- });
5612
- }).apply(this, arguments);
6021
+ var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
6022
+ var run = generate(options);
6023
+ pendingNonce = run;
6024
+ var settle = function settle() {
6025
+ if (pendingNonce === run) pendingNonce = void 0;
6026
+ };
6027
+ run.then(settle, settle);
6028
+ return run;
5613
6029
  },
5614
6030
  getCurrentNonce: function getCurrentNonce() {
5615
6031
  return currentNonce;
5616
6032
  },
6033
+ waitForNonce: function waitForNonce(maxWaitMs) {
6034
+ if (currentNonce) return Promise.resolve(currentNonce);
6035
+ var pending = pendingNonce;
6036
+ if (!pending || !(maxWaitMs > 0)) return Promise.resolve("");
6037
+ return new Promise(function(resolve) {
6038
+ var timer = setTimeout(function() {
6039
+ return resolve(currentNonce);
6040
+ }, maxWaitMs);
6041
+ pending.then(function(nonce) {
6042
+ clearTimeout(timer);
6043
+ resolve(nonce);
6044
+ }, function() {
6045
+ clearTimeout(timer);
6046
+ resolve("");
6047
+ });
6048
+ });
6049
+ },
5617
6050
  injectNonce: function injectNonce(vastTagUrl) {
5618
6051
  if (!currentNonce || !vastTagUrl) return vastTagUrl;
5619
6052
  try {
@@ -5650,8 +6083,90 @@ function createPalNonceManager() {
5650
6083
  reset: function reset() {
5651
6084
  currentNonce = "";
5652
6085
  currentNonceManager = void 0;
6086
+ pendingNonce = void 0;
5653
6087
  }
5654
6088
  };
6089
+ function generate(options) {
6090
+ return _async_to_generator(function() {
6091
+ var _options_allowStorage, _options_adWillAutoPlay, _options_adWillPlayMuted, _options_playerVolume, _options_continuousPlayback, loader, goog, request, manager, error;
6092
+ return _ts_generator(this, function(_state) {
6093
+ switch(_state.label){
6094
+ case 0:
6095
+ _state.trys.push([
6096
+ 0,
6097
+ 3,
6098
+ ,
6099
+ 4
6100
+ ]);
6101
+ return [
6102
+ 4,
6103
+ loadPalSdk()
6104
+ ];
6105
+ case 1:
6106
+ _state.sent();
6107
+ loader = getOrCreateNonceLoader((_options_allowStorage = options.allowStorage) !== null && _options_allowStorage !== void 0 ? _options_allowStorage : true);
6108
+ goog = window.goog;
6109
+ request = new goog.pal.NonceRequest();
6110
+ request.adWillAutoPlay = (_options_adWillAutoPlay = options.adWillAutoPlay) !== null && _options_adWillAutoPlay !== void 0 ? _options_adWillAutoPlay : true;
6111
+ request.adWillPlayMuted = (_options_adWillPlayMuted = options.adWillPlayMuted) !== null && _options_adWillPlayMuted !== void 0 ? _options_adWillPlayMuted : false;
6112
+ request.playerVolume = (_options_playerVolume = options.playerVolume) !== null && _options_playerVolume !== void 0 ? _options_playerVolume : request.adWillPlayMuted ? 0 : 1;
6113
+ request.continuousPlayback = (_options_continuousPlayback = options.continuousPlayback) !== null && _options_continuousPlayback !== void 0 ? _options_continuousPlayback : true;
6114
+ request.descriptionUrl = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
6115
+ request.iconsSupported = true;
6116
+ request.playerType = "StormcloudVideoPlayer";
6117
+ request.playerVersion = "1.0";
6118
+ request.supportedApiFrameworks = "2,7,9";
6119
+ request.url = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
6120
+ request.videoWidth = options.videoWidth || 640;
6121
+ request.videoHeight = options.videoHeight || 480;
6122
+ if (options.ppid) request.ppid = options.ppid;
6123
+ if (options.sessionId) request.sessionId = options.sessionId;
6124
+ console.log("[PAL] NonceRequest before generateNonce:", JSON.stringify({
6125
+ adWillAutoPlay: request.adWillAutoPlay,
6126
+ adWillPlayMuted: request.adWillPlayMuted,
6127
+ playerVolume: request.playerVolume,
6128
+ continuousPlayback: request.continuousPlayback,
6129
+ descriptionUrl: request.descriptionUrl,
6130
+ iconsSupported: request.iconsSupported,
6131
+ playerType: request.playerType,
6132
+ playerVersion: request.playerVersion,
6133
+ supportedApiFrameworks: request.supportedApiFrameworks,
6134
+ url: request.url,
6135
+ videoWidth: request.videoWidth,
6136
+ videoHeight: request.videoHeight,
6137
+ ppid: request.ppid,
6138
+ sessionId: request.sessionId
6139
+ }, null, 2));
6140
+ return [
6141
+ 4,
6142
+ loader.loadNonceManager(request)
6143
+ ];
6144
+ case 2:
6145
+ manager = _state.sent();
6146
+ currentNonceManager = manager;
6147
+ currentNonce = manager.getNonce();
6148
+ console.log("[PAL] Nonce generated successfully");
6149
+ return [
6150
+ 2,
6151
+ currentNonce
6152
+ ];
6153
+ case 3:
6154
+ error = _state.sent();
6155
+ console.warn("[PAL] Failed to generate nonce:", error);
6156
+ currentNonce = "";
6157
+ currentNonceManager = void 0;
6158
+ return [
6159
+ 2,
6160
+ ""
6161
+ ];
6162
+ case 4:
6163
+ return [
6164
+ 2
6165
+ ];
6166
+ }
6167
+ });
6168
+ })();
6169
+ }
5655
6170
  }
5656
6171
  // src/utils/trackingIngest.ts
5657
6172
  var DEFAULT_TRACKING_INGEST_CONFIG = {
@@ -5740,7 +6255,14 @@ function ingestPlayerTracking(licenseKey, channel, body) {
5740
6255
  // src/utils/tracking.ts
5741
6256
  var cachedBrowserId = null;
5742
6257
  function buildAnalyticsContext(config) {
6258
+ var _config_contentNetwork, _config_channelName, _config_programTitle;
5743
6259
  var context = {};
6260
+ var contentNetwork = (_config_contentNetwork = config.contentNetwork) === null || _config_contentNetwork === void 0 ? void 0 : _config_contentNetwork.trim();
6261
+ var contentChannel = (_config_channelName = config.channelName) === null || _config_channelName === void 0 ? void 0 : _config_channelName.trim();
6262
+ var contentTitle = (_config_programTitle = config.programTitle) === null || _config_programTitle === void 0 ? void 0 : _config_programTitle.trim();
6263
+ if (contentNetwork) context.contentNetwork = contentNetwork;
6264
+ if (contentChannel) context.contentChannel = contentChannel;
6265
+ if (contentTitle) context.contentTitle = contentTitle;
5744
6266
  if (config.debugAdTiming) {
5745
6267
  context.debugAdTiming = true;
5746
6268
  }
@@ -6231,12 +6753,19 @@ function sendAdImpressionTracking(_0, _1) {
6231
6753
  4,
6232
6754
  ingestPlayerTracking(licenseKey, "impressions", {
6233
6755
  events: [
6234
- {
6756
+ _object_spread({
6235
6757
  player_id: metricEvent.player_id,
6236
6758
  ad_played_count: 1,
6237
6759
  ad_url: adImpressionInfo.adUrl,
6238
- capture_at: adImpressionInfo.timestamp
6239
- }
6760
+ capture_at: adImpressionInfo.timestamp,
6761
+ source: "gam"
6762
+ }, context.contentNetwork ? {
6763
+ content_network: context.contentNetwork
6764
+ } : {}, context.contentChannel ? {
6765
+ content_channel: context.contentChannel
6766
+ } : {}, context.contentTitle ? {
6767
+ content_title: context.contentTitle
6768
+ } : {})
6240
6769
  ]
6241
6770
  })
6242
6771
  ];
@@ -7585,6 +8114,21 @@ var Scte35CueManager = /*#__PURE__*/ function() {
7585
8114
  return Scte35CueManager;
7586
8115
  }();
7587
8116
  // src/player/AdConfigManager.ts
8117
+ function withDeferredPodParams(rawUrl, deferNonce) {
8118
+ try {
8119
+ var url = new URL(rawUrl);
8120
+ url.searchParams.set("pmnd", "[SCVP-PMND]");
8121
+ url.searchParams.set("pmxd", "[SCVP-PMXD]");
8122
+ url.searchParams.set("pmad", "[SCVP-PMAD]");
8123
+ if (deferNonce && !url.searchParams.get("givn")) {
8124
+ url.searchParams.delete("paln");
8125
+ url.searchParams.set("givn", "[SCVP-GIVN]");
8126
+ }
8127
+ return url.toString();
8128
+ } catch (unused) {
8129
+ return rawUrl;
8130
+ }
8131
+ }
7588
8132
  var AdConfigManager = /*#__PURE__*/ function() {
7589
8133
  function AdConfigManager(config, video) {
7590
8134
  _class_call_check(this, AdConfigManager);
@@ -7595,8 +8139,8 @@ var AdConfigManager = /*#__PURE__*/ function() {
7595
8139
  this.podCounter = 0;
7596
8140
  this.podAssignedByPrefetch = false;
7597
8141
  this.lastHeartbeatTime = 0;
7598
- this.defaultPodMaxAds = 6;
7599
- this.defaultPodMaxDurationMs = 12e4;
8142
+ this.defaultEdgePodMaxAds = 6;
8143
+ this.palNonceDispatchWaitMs = 1500;
7600
8144
  this.config = config;
7601
8145
  this.video = video;
7602
8146
  }
@@ -7624,7 +8168,7 @@ var AdConfigManager = /*#__PURE__*/ function() {
7624
8168
  key: "fetchAdConfiguration",
7625
8169
  value: function fetchAdConfiguration() {
7626
8170
  return _async_to_generator(function() {
7627
- var _data_response_ima_publisherdeskima, _data_response_ima, _data_response, _data_response_options_vast_cue_tones, _data_response_options_vast, _data_response_options, _data_response1, vastMode, vastEndpoint, apiUrl, headers, response, data, imaPayload, decodedPayload, numberAds;
8171
+ var _data_response_ima_publisherdeskima, _data_response_ima, _data_response, _data_response_options_vast_cue_tones, _data_response_options_vast, _data_response_options, _data_response1, apiUrl, headers, response, data, imaPayload, decodedPayload, numberAds;
7628
8172
  return _ts_generator(this, function(_state) {
7629
8173
  switch(_state.label){
7630
8174
  case 0:
@@ -7645,28 +8189,6 @@ var AdConfigManager = /*#__PURE__*/ function() {
7645
8189
  2
7646
8190
  ];
7647
8191
  case 2:
7648
- vastMode = this.config.vastMode || "default";
7649
- if (this.debug) {
7650
- console.log("[StormcloudVideoPlayer] VAST mode:", vastMode);
7651
- }
7652
- if (vastMode === "adstorm") {
7653
- if (!this.config.licenseKey) {
7654
- if (this.debug) {
7655
- console.warn("[StormcloudVideoPlayer] AdStorm mode requires a license key");
7656
- }
7657
- return [
7658
- 2
7659
- ];
7660
- }
7661
- vastEndpoint = "https://adstorm.co/api-adstorm-dev/adstorm/vast/".concat(this.config.licenseKey);
7662
- this.apiVastTagUrl = vastEndpoint;
7663
- if (this.debug) {
7664
- console.log("[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):", vastEndpoint);
7665
- }
7666
- return [
7667
- 2
7668
- ];
7669
- }
7670
8192
  if (this.config.vastTagUrl) {
7671
8193
  this.apiVastTagUrl = normalizeVastTagUrl(this.config.vastTagUrl);
7672
8194
  if (this.debug) {
@@ -7676,7 +8198,7 @@ var AdConfigManager = /*#__PURE__*/ function() {
7676
8198
  2
7677
8199
  ];
7678
8200
  }
7679
- apiUrl = "https://adstorm.co/api-adstorm-dev/adstorm/ads/web";
8201
+ apiUrl = "https://edge.stormcloudhub.com/api/v1/adstorm/ads/web";
7680
8202
  if (this.debug) {
7681
8203
  console.log("[StormcloudVideoPlayer] Fetching ad configuration from:", apiUrl);
7682
8204
  }
@@ -8023,16 +8545,16 @@ var AdConfigManager = /*#__PURE__*/ function() {
8023
8545
  }
8024
8546
  },
8025
8547
  {
8026
- key: "resolvePodParams",
8027
- value: function resolvePodParams(breakDurationMs) {
8028
- var maxDurationMs = breakDurationMs != null && breakDurationMs > 0 ? breakDurationMs : this.config.podMaxDurationMs != null && this.config.podMaxDurationMs > 0 ? this.config.podMaxDurationMs : this.defaultPodMaxDurationMs;
8029
- var maxAds = this.config.podMaxAds && this.config.podMaxAds > 0 ? this.config.podMaxAds : this.apiNumberAds && this.apiNumberAds > 0 ? this.apiNumberAds : this.defaultPodMaxAds;
8030
- var minDurationMs = this.config.podExactDuration && maxDurationMs != null ? maxDurationMs : 0;
8031
- return {
8032
- maxAds: maxAds,
8033
- minDurationMs: minDurationMs,
8034
- maxDurationMs: maxDurationMs
8035
- };
8548
+ key: "resolveAdPodConfig",
8549
+ value: function resolveAdPodConfig1() {
8550
+ return resolveAdPodConfig(this.config);
8551
+ }
8552
+ },
8553
+ {
8554
+ key: "resolveEdgeMaxAds",
8555
+ value: function resolveEdgeMaxAds() {
8556
+ var _this_resolveAdPodConfig_maxAdsPerBreak;
8557
+ return (_this_resolveAdPodConfig_maxAdsPerBreak = this.resolveAdPodConfig().maxAdsPerBreak) !== null && _this_resolveAdPodConfig_maxAdsPerBreak !== void 0 ? _this_resolveAdPodConfig_maxAdsPerBreak : this.apiNumberAds && this.apiNumberAds > 0 ? this.apiNumberAds : this.defaultEdgePodMaxAds;
8036
8558
  }
8037
8559
  },
8038
8560
  {
@@ -8049,17 +8571,13 @@ var AdConfigManager = /*#__PURE__*/ function() {
8049
8571
  },
8050
8572
  {
8051
8573
  key: "generatePodVastUrl",
8052
- value: function generatePodVastUrl(baseUrl, podParams, adPlayer, palNonce, inAdBreak) {
8053
- var _podParams_maxDurationMs;
8574
+ value: function generatePodVastUrl(baseUrl, adPlayer, palNonce, inAdBreak) {
8054
8575
  var adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;
8055
8576
  var envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);
8056
- var urlWithMacros = applyVastMacros(baseUrl, _object_spread_props(_object_spread({
8577
+ var macroContext = _object_spread_props(_object_spread({
8057
8578
  correlator: this.viewCorrelator,
8058
8579
  streamCorrelator: this.streamCorrelator,
8059
8580
  pod: this.podCounter > 0 ? this.podCounter : void 0,
8060
- podMaxAds: podParams.maxAds,
8061
- podMinDurationMs: podParams.minDurationMs,
8062
- podMaxDurationMs: podParams.maxDurationMs,
8063
8581
  isCtv: envSignals.isCtv,
8064
8582
  pageUrl: !envSignals.isCtv && typeof window !== "undefined" ? toDevSafeUrl(window.location.href) : void 0,
8065
8583
  adWillPlayMuted: adWillPlayMuted,
@@ -8075,13 +8593,72 @@ var AdConfigManager = /*#__PURE__*/ function() {
8075
8593
  } : {}, this.config.channelName ? {
8076
8594
  channelName: this.config.channelName
8077
8595
  } : {}), {
8078
- consent: this.consentSignals
8079
- }));
8080
- var finalUrl = palNonce.injectNonce(ensureVideoAdType(urlWithMacros));
8081
- console.log("[StormcloudVideoPlayer] Resolved optimized-pod request URL (pod=".concat(this.podCounter, ", pmad=").concat(podParams.maxAds, ", pmnd=").concat(podParams.minDurationMs, ", pmxd=").concat((_podParams_maxDurationMs = podParams.maxDurationMs) !== null && _podParams_maxDurationMs !== void 0 ? _podParams_maxDurationMs : "?", "):"), finalUrl);
8596
+ consent: this.consentSignals,
8597
+ palNonce: palNonce.getCurrentNonce() || void 0
8598
+ });
8599
+ var nonceReady = !!macroContext.palNonce;
8600
+ var finalUrl;
8601
+ if (hasScvpMacros(baseUrl)) {
8602
+ var deferred = new Set(SCVP_POD_MACROS);
8603
+ if (!nonceReady) deferred.add("GIVN");
8604
+ var _applyScvpMacros = applyScvpMacros(baseUrl, macroContext, deferred), url = _applyScvpMacros.url, unresolved = _applyScvpMacros.unresolved;
8605
+ if (unresolved.length > 0) {
8606
+ console.warn("[StormcloudVideoPlayer] Unresolved SCVP macros (removed from request):", unresolved.join(", "));
8607
+ }
8608
+ finalUrl = ensureVideoAdType(url);
8609
+ } else {
8610
+ finalUrl = withDeferredPodParams(palNonce.injectNonce(ensureVideoAdType(applyVastMacros(baseUrl, macroContext))), !nonceReady);
8611
+ }
8612
+ console.log("[StormcloudVideoPlayer] Prepared optimized-pod request URL (pod=".concat(this.podCounter, "; pmnd/pmxd/pmad resolved at dispatch):"), finalUrl);
8082
8613
  return finalUrl;
8083
8614
  }
8084
8615
  },
8616
+ {
8617
+ key: "completeDeferredRequestSignals",
8618
+ value: function completeDeferredRequestSignals(url, palNonce) {
8619
+ return _async_to_generator(function() {
8620
+ var nonce, _tmp;
8621
+ return _ts_generator(this, function(_state) {
8622
+ switch(_state.label){
8623
+ case 0:
8624
+ if (findScvpMacroNames(url).indexOf("GIVN") === -1) return [
8625
+ 2,
8626
+ url
8627
+ ];
8628
+ _tmp = palNonce.getCurrentNonce();
8629
+ if (_tmp) return [
8630
+ 3,
8631
+ 2
8632
+ ];
8633
+ return [
8634
+ 4,
8635
+ palNonce.waitForNonce(this.palNonceDispatchWaitMs)
8636
+ ];
8637
+ case 1:
8638
+ _tmp = _state.sent();
8639
+ _state.label = 2;
8640
+ case 2:
8641
+ nonce = _tmp;
8642
+ if (!nonce) return [
8643
+ 2,
8644
+ url
8645
+ ];
8646
+ return [
8647
+ 2,
8648
+ substituteScvpMacros(url, /* @__PURE__ */ new Map([
8649
+ [
8650
+ "GIVN",
8651
+ nonce
8652
+ ]
8653
+ ]), function(name) {
8654
+ return name !== "GIVN";
8655
+ }).url
8656
+ ];
8657
+ }
8658
+ });
8659
+ }).call(this);
8660
+ }
8661
+ },
8085
8662
  {
8086
8663
  // --- Tracking ---
8087
8664
  key: "initializeTracking",
@@ -8129,6 +8706,9 @@ var AdConfigManager = /*#__PURE__*/ function() {
8129
8706
  return AdConfigManager;
8130
8707
  }();
8131
8708
  // src/player/AdTimingService.ts
8709
+ function monotonicNow() {
8710
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
8711
+ }
8132
8712
  var AdTimingService = /*#__PURE__*/ function() {
8133
8713
  function AdTimingService(config, video, callbacks) {
8134
8714
  _class_call_check(this, AdTimingService);
@@ -8259,6 +8839,21 @@ var AdTimingService = /*#__PURE__*/ function() {
8259
8839
  },
8260
8840
  {
8261
8841
  // --- Duration boundary ---
8842
+ key: "beginBreakTiming",
8843
+ value: function beginBreakTiming(startWallClockMs) {
8844
+ this.currentAdBreakStartWallClockMs = startWallClockMs;
8845
+ this.breakStartMonoMs = monotonicNow() + (startWallClockMs - Date.now());
8846
+ this.breakEndMonoMs = void 0;
8847
+ }
8848
+ },
8849
+ {
8850
+ key: "markBreakEndedNow",
8851
+ value: function markBreakEndedNow() {
8852
+ this.scteAdBreakEndWallClockMs = Date.now();
8853
+ this.breakEndMonoMs = monotonicNow();
8854
+ }
8855
+ },
8856
+ {
8262
8857
  key: "setAdBreakDurationBoundary",
8263
8858
  value: function setAdBreakDurationBoundary(durationMs) {
8264
8859
  this.expectedAdBreakDurationMs = durationMs;
@@ -8267,6 +8862,18 @@ var AdTimingService = /*#__PURE__*/ function() {
8267
8862
  } else {
8268
8863
  this.scteAdBreakEndWallClockMs = void 0;
8269
8864
  }
8865
+ this.breakEndMonoMs = durationMs != null && this.breakStartMonoMs != null ? this.breakStartMonoMs + durationMs : void 0;
8866
+ }
8867
+ },
8868
+ {
8869
+ key: "getBreakTimingSnapshot",
8870
+ value: function getBreakTimingSnapshot() {
8871
+ return {
8872
+ scheduledBreakDurationMs: this.expectedAdBreakDurationMs,
8873
+ breakStartMonoMs: this.breakStartMonoMs,
8874
+ breakEndMonoMs: this.breakEndMonoMs,
8875
+ playedDurationMs: this.adBreakPlayedDurationMs
8876
+ };
8270
8877
  }
8271
8878
  },
8272
8879
  {
@@ -8680,6 +9287,8 @@ var AdTimingService = /*#__PURE__*/ function() {
8680
9287
  this.expectedAdBreakDurationMs = void 0;
8681
9288
  this.currentAdBreakStartWallClockMs = void 0;
8682
9289
  this.scteAdBreakEndWallClockMs = void 0;
9290
+ this.breakStartMonoMs = void 0;
9291
+ this.breakEndMonoMs = void 0;
8683
9292
  this.adBreakPlayedDurationMs = 0;
8684
9293
  this.currentAdIndex = 0;
8685
9294
  this.totalAdsInBreak = 0;
@@ -9693,9 +10302,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9693
10302
  // ───────────────────────────────────────────────────────────────
9694
10303
  key: "nextAdRequestUrl",
9695
10304
  value: function nextAdRequestUrl(baseVastUrl) {
9696
- var remaining = Math.min(this.timing.getWallClockRemainingAdMs(), this.timing.getDurationBudgetRemainingMs());
9697
- var breakDurationMs = remaining > 0 ? remaining : void 0;
9698
- return this.host.generatePodVastUrl(baseVastUrl, breakDurationMs);
10305
+ return this.host.generatePodVastUrl(baseVastUrl);
9699
10306
  }
9700
10307
  },
9701
10308
  {
@@ -9958,7 +10565,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9958
10565
  key: "handleAdStart",
9959
10566
  value: function handleAdStart(marker) {
9960
10567
  return _async_to_generator(function() {
9961
- var baseVastUrl, edgeConfigured, adBreakDurationMs, currentMuted, currentVolume, epoch, hasPrefetchedUrl, mode, edgeUrl, outcome, podPlayed;
10568
+ var baseVastUrl, edgeConfigured, adBreakDurationMs, currentMuted, currentVolume, epoch, mode, edgeUrl, outcome, podPlayed;
9962
10569
  return _ts_generator(this, function(_state) {
9963
10570
  switch(_state.label){
9964
10571
  case 0:
@@ -10010,8 +10617,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10010
10617
  }
10011
10618
  this.noteOpportunity("scte35", this.cueManager.activeScte35BreakKey, "midroll");
10012
10619
  epoch = this.timing.adBreakEpoch;
10013
- hasPrefetchedUrl = !!(this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0);
10014
- if (!(adBreakDurationMs == null && (!hasPrefetchedUrl || edgeConfigured))) return [
10620
+ if (!(adBreakDurationMs == null)) return [
10015
10621
  3,
10016
10622
  2
10017
10623
  ];
@@ -10067,7 +10673,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10067
10673
  }
10068
10674
  return [
10069
10675
  4,
10070
- this.startOptimizedPod(baseVastUrl, adBreakDurationMs)
10676
+ this.startOptimizedPod(baseVastUrl)
10071
10677
  ];
10072
10678
  case 6:
10073
10679
  podPlayed = _state.sent();
@@ -10135,9 +10741,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10135
10741
  value: // ───────────────────────────────────────────────────────────────
10136
10742
  // Optimized pod (single multi-ad request)
10137
10743
  // ───────────────────────────────────────────────────────────────
10138
- function startOptimizedPod(baseVastUrl, breakDurationMs) {
10744
+ function startOptimizedPod(baseVastUrl) {
10139
10745
  return _async_to_generator(function() {
10140
- var podUrl, prefetched, epoch, generation, adPlayer, requestToken, requestUrl, _ref, _adPlayer_getPodAdCount, podCount, error;
10746
+ var podUrl, prefetched, epoch, generation, adPlayer, requestToken, requestUrl, _ref, _this_currentVastUrl, _adPlayer_getPodAdCount, finalizeRequestUrl, podCount, error;
10141
10747
  return _ts_generator(this, function(_state) {
10142
10748
  switch(_state.label){
10143
10749
  case 0:
@@ -10146,7 +10752,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10146
10752
  podUrl = this.pendingAdBreak.vastUrls[0];
10147
10753
  this.clearPendingAdBreak();
10148
10754
  } else {
10149
- podUrl = this.host.generatePodVastUrl(baseVastUrl, breakDurationMs);
10755
+ podUrl = this.host.generatePodVastUrl(baseVastUrl);
10150
10756
  }
10151
10757
  if (!podUrl) {
10152
10758
  return [
@@ -10170,9 +10776,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10170
10776
  case 1:
10171
10777
  _state.trys.push([
10172
10778
  1,
10173
- 5,
10779
+ 9,
10174
10780
  ,
10175
- 6
10781
+ 10
10176
10782
  ]);
10177
10783
  return [
10178
10784
  4,
@@ -10184,15 +10790,46 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10184
10790
  2,
10185
10791
  true
10186
10792
  ];
10793
+ return [
10794
+ 4,
10795
+ this.host.completeGamRequestSignals(requestUrl)
10796
+ ];
10797
+ case 3:
10798
+ requestUrl = _state.sent();
10799
+ if (this.isStale(epoch, generation)) return [
10800
+ 2,
10801
+ true
10802
+ ];
10187
10803
  this.timing.startAdRequestWatchdog(requestToken);
10804
+ finalizeRequestUrl = this.createGamDispatchFinalizer(requestToken);
10805
+ _state.label = 4;
10806
+ case 4:
10807
+ _state.trys.push([
10808
+ 4,
10809
+ ,
10810
+ 6,
10811
+ 7
10812
+ ]);
10188
10813
  return [
10189
10814
  4,
10190
10815
  this.callController(function() {
10191
- return adPlayer.requestAds(requestUrl);
10816
+ return adPlayer.requestAds(requestUrl, {
10817
+ finalizeRequestUrl: finalizeRequestUrl
10818
+ });
10192
10819
  })
10193
10820
  ];
10194
- case 3:
10821
+ case 5:
10195
10822
  _state.sent();
10823
+ return [
10824
+ 3,
10825
+ 7
10826
+ ];
10827
+ case 6:
10828
+ this.recordPodResponseDiagnostics(requestToken, adPlayer);
10829
+ return [
10830
+ 7
10831
+ ];
10832
+ case 7:
10196
10833
  this.timing.clearAdRequestWatchdog();
10197
10834
  if (this.isStale(epoch, generation)) {
10198
10835
  this.logOrchestratorFunnel("stale_request_result_ignored", {
@@ -10220,7 +10857,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10220
10857
  }
10221
10858
  sendAdLoadedTracking(this.host.config.licenseKey, {
10222
10859
  source: "hls",
10223
- vastUrl: requestUrl,
10860
+ vastUrl: (_this_currentVastUrl = this.currentVastUrl) !== null && _this_currentVastUrl !== void 0 ? _this_currentVastUrl : requestUrl,
10224
10861
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
10225
10862
  }, this.analyticsContext).catch(function() {});
10226
10863
  this.timing.startAdFailsafeTimer(requestToken);
@@ -10230,7 +10867,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10230
10867
  return adPlayer.play();
10231
10868
  })
10232
10869
  ];
10233
- case 4:
10870
+ case 8:
10234
10871
  _state.sent();
10235
10872
  if (this.isStale(epoch, generation)) return [
10236
10873
  2,
@@ -10244,7 +10881,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10244
10881
  2,
10245
10882
  true
10246
10883
  ];
10247
- case 5:
10884
+ case 9:
10248
10885
  error = _state.sent();
10249
10886
  this.timing.clearAdRequestWatchdog();
10250
10887
  this.timing.clearAdFailsafeTimer();
@@ -10264,12 +10901,16 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10264
10901
  if (this.debug) {
10265
10902
  console.warn("[POD] Optimized pod request/play failed:", error);
10266
10903
  }
10904
+ if (this.handlePodRequestNotSent(error)) return [
10905
+ 2,
10906
+ false
10907
+ ];
10267
10908
  this.recordRequestFailure(error, podUrl);
10268
10909
  return [
10269
10910
  2,
10270
10911
  false
10271
10912
  ];
10272
- case 6:
10913
+ case 10:
10273
10914
  return [
10274
10915
  2
10275
10916
  ];
@@ -10315,17 +10956,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10315
10956
  }
10316
10957
  },
10317
10958
  {
10318
- /**
10319
- * Builds the next Edge request from the budget left right now, or marks Edge
10320
- * exhausted for this break. Synchronous on purpose: callers must reach the
10321
- * REQUESTING state in the same tick so a second completion event cannot race
10322
- * in a parallel request.
10323
- */ key: "prepareEdgePodRequest",
10959
+ key: "prepareEdgePodRequest",
10324
10960
  value: function prepareEdgePodRequest() {
10325
10961
  var baseUrl = this.host.getEdgePodBaseUrl();
10326
10962
  if (!baseUrl) return void 0;
10327
10963
  var remainingMs = this.timing.getRemainingAdMs();
10328
- var remainingAds = Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak);
10964
+ var remainingAds = Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolveEdgeMaxAds() - this.timing.totalAdsInBreak);
10329
10965
  if (remainingAds < 1) {
10330
10966
  this.markEdgeExhausted("ad_capacity_reached", {
10331
10967
  adsInBreak: this.timing.totalAdsInBreak
@@ -10404,7 +11040,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10404
11040
  ];
10405
11041
  }
10406
11042
  remainingMs = this.timing.getRemainingAdMs();
10407
- remainingAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak));
11043
+ remainingAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolveEdgeMaxAds() - this.timing.totalAdsInBreak));
10408
11044
  overrunAllowanceMs = Math.max(0, (_this_host_config_maxAdBreakExtensionMs = this.host.config.maxAdBreakExtensionMs) !== null && _this_host_config_maxAdBreakExtensionMs !== void 0 ? _this_host_config_maxAdBreakExtensionMs : 0);
10409
11045
  podCount = adPlayer.limitPodToBudget ? adPlayer.limitPodToBudget(remainingMs + overrunAllowanceMs, remainingAds) : (_ref = (_adPlayer_getPodAdCount = adPlayer.getPodAdCount) === null || _adPlayer_getPodAdCount === void 0 ? void 0 : _adPlayer_getPodAdCount.call(adPlayer)) !== null && _ref !== void 0 ? _ref : 0;
10410
11046
  if (classifyEdgeVastResponse({
@@ -10751,7 +11387,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10751
11387
  {
10752
11388
  key: "noteVastUrlGenerated",
10753
11389
  value: function noteVastUrlGenerated(url, source) {
10754
- var _ref, _ref1, _ref2, _ref3, _ref4;
11390
+ var _ref, _ref1;
10755
11391
  var params;
10756
11392
  try {
10757
11393
  params = new URL(url).searchParams;
@@ -10761,9 +11397,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10761
11397
  requestId: void 0,
10762
11398
  source: source,
10763
11399
  pod: (_ref1 = params === null || params === void 0 ? void 0 : params.get("pod")) !== null && _ref1 !== void 0 ? _ref1 : void 0,
10764
- pmad: (_ref2 = params === null || params === void 0 ? void 0 : params.get("pmad")) !== null && _ref2 !== void 0 ? _ref2 : void 0,
10765
- pmnd: (_ref3 = params === null || params === void 0 ? void 0 : params.get("pmnd")) !== null && _ref3 !== void 0 ? _ref3 : void 0,
10766
- pmxd: (_ref4 = params === null || params === void 0 ? void 0 : params.get("pmxd")) !== null && _ref4 !== void 0 ? _ref4 : void 0,
11400
+ podParamsDeferredToDispatch: findScvpMacroNames(url).some(function(name) {
11401
+ return SCVP_POD_MACROS.has(name);
11402
+ }),
10767
11403
  adType: adType
10768
11404
  });
10769
11405
  if (adType === "audio" || adType === "audio_video") {
@@ -10804,10 +11440,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10804
11440
  if (diag && !diag.failureReason) {
10805
11441
  diag.failureReason = "".concat(outcome, ": ").concat(message);
10806
11442
  }
11443
+ var failureKey = (diag === null || diag === void 0 ? void 0 : diag.dispatchedUrl) && findScvpMacroNames(vastTagUrl).some(function(name) {
11444
+ return SCVP_POD_MACROS.has(name);
11445
+ }) ? diag.dispatchedUrl : vastTagUrl;
10807
11446
  if (this.timing.isTemporaryAdError(error)) {
10808
- this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());
11447
+ this.timing.temporaryFailureUrls.set(failureKey, Date.now());
10809
11448
  } else if (outcome !== "discarded_budget") {
10810
- this.timing.failedVastUrls.add(vastTagUrl);
11449
+ this.timing.failedVastUrls.add(failureKey);
10811
11450
  }
10812
11451
  this.countFunnelStage("request_outcome:".concat(outcome));
10813
11452
  this.logOrchestratorFunnel("request_outcome", _object_spread({
@@ -10833,6 +11472,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10833
11472
  switch(payload.stage){
10834
11473
  case "gam_http_request_sent":
10835
11474
  diag.gamRequestSent++;
11475
+ this.logPodDispatch(diag);
10836
11476
  break;
10837
11477
  case "edge_http_request_sent":
10838
11478
  diag.edgeRequestSent++;
@@ -10884,8 +11524,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10884
11524
  if (gamReturnedAdWithoutImpression) {
10885
11525
  this.countFunnelStage("gam_ad_without_impression");
10886
11526
  }
10887
- var startedAt = diag.startedAt, fields = _object_without_properties(diag, [
10888
- "startedAt"
11527
+ var startedAt = diag.startedAt, _dispatchedUrl = diag.dispatchedUrl, _logged = diag.podDispatchLogged, fields = _object_without_properties(diag, [
11528
+ "startedAt",
11529
+ "dispatchedUrl",
11530
+ "podDispatchLogged"
10889
11531
  ]);
10890
11532
  console.log("[AdBreak][REQUEST] summary", _object_spread_props(_object_spread({}, fields), {
10891
11533
  durationMs: Date.now() - startedAt,
@@ -10897,24 +11539,71 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10897
11539
  // ───────────────────────────────────────────────────────────────
10898
11540
  // Single ad playback
10899
11541
  // ───────────────────────────────────────────────────────────────
10900
- key: "withCurrentPodBudget",
10901
- value: function withCurrentPodBudget(rawVastTagUrl) {
10902
- var vastTagUrl = ensureVideoAdType(rawVastTagUrl);
10903
- var remaining = Math.min(this.timing.getWallClockRemainingAdMs(), this.timing.getDurationBudgetRemainingMs());
10904
- if (!(remaining > 0)) return vastTagUrl;
10905
- try {
10906
- var url = new URL(vastTagUrl);
10907
- if (!url.searchParams.has("pmxd")) return vastTagUrl;
10908
- var maxMs = Math.round(remaining);
10909
- url.searchParams.set("pmxd", String(maxMs));
10910
- var minMs = Number(url.searchParams.get("pmnd"));
10911
- if (Number.isFinite(minMs) && minMs > maxMs) {
10912
- url.searchParams.set("pmnd", String(maxMs));
10913
- }
10914
- return url.toString();
10915
- } catch (unused) {
10916
- return vastTagUrl;
10917
- }
11542
+ key: "createGamDispatchFinalizer",
11543
+ value: function createGamDispatchFinalizer(requestToken) {
11544
+ var _this = this;
11545
+ var breakId = this.timing.adBreakEpoch;
11546
+ var config = this.adConfig.resolveAdPodConfig();
11547
+ var minUsablePmxdMs = this.timing.getMinRemainingMsToStartAd();
11548
+ return function(url) {
11549
+ var capacity = measureBreakCapacity(_this.timing.getBreakTimingSnapshot(), monotonicNow());
11550
+ var diag = _this.requestDiagnostics.get(requestToken);
11551
+ try {
11552
+ var result = finalizeGamRequestUrl(url, {
11553
+ breakId: breakId,
11554
+ capacity: capacity,
11555
+ config: config,
11556
+ minUsablePmxdMs: minUsablePmxdMs
11557
+ });
11558
+ if (diag) {
11559
+ diag.pod = result.diagnostics;
11560
+ diag.dispatchedUrl = result.url;
11561
+ diag.podDispatchLogged = false;
11562
+ }
11563
+ _this.currentVastUrl = result.url;
11564
+ return result.url;
11565
+ } catch (error) {
11566
+ if (diag && isPodRequestAbortedError(error)) {
11567
+ diag.failureReason = "pod_request_not_sent:".concat(error.reason);
11568
+ }
11569
+ throw error;
11570
+ }
11571
+ };
11572
+ }
11573
+ },
11574
+ {
11575
+ key: "logPodDispatch",
11576
+ value: function logPodDispatch(diag) {
11577
+ if (!diag.pod || diag.podDispatchLogged) return;
11578
+ diag.podDispatchLogged = true;
11579
+ this.logOrchestratorFunnel(diag.pod.optimizedPod ? "optimized_pod_request_dispatched" : "gam_request_dispatched", _object_spread({}, diag.pod));
11580
+ }
11581
+ },
11582
+ {
11583
+ key: "recordPodResponseDiagnostics",
11584
+ value: function recordPodResponseDiagnostics(requestToken, adPlayer) {
11585
+ var _diag_vastAdCount, _ref;
11586
+ var _adPlayer_getPodTotalDurationMs;
11587
+ var diag = this.requestDiagnostics.get(requestToken);
11588
+ if (!(diag === null || diag === void 0 ? void 0 : diag.pod) || diag.pod.pmxdSent == null || diag.podResponse) return;
11589
+ if (diag.gamRequestSent === 0 && diag.vastHttpStatus == null) return;
11590
+ diag.podResponse = computePodResponseDiagnostics(diag.pod.pmxdSent, (_diag_vastAdCount = diag.vastAdCount) !== null && _diag_vastAdCount !== void 0 ? _diag_vastAdCount : 0, (_ref = (_adPlayer_getPodTotalDurationMs = adPlayer.getPodTotalDurationMs) === null || _adPlayer_getPodTotalDurationMs === void 0 ? void 0 : _adPlayer_getPodTotalDurationMs.call(adPlayer)) !== null && _ref !== void 0 ? _ref : 0);
11591
+ this.logOrchestratorFunnel("optimized_pod_response", _object_spread({
11592
+ pmxdSent: diag.pod.pmxdSent
11593
+ }, diag.podResponse));
11594
+ }
11595
+ },
11596
+ {
11597
+ key: "handlePodRequestNotSent",
11598
+ value: function handlePodRequestNotSent(error) {
11599
+ if (!isPodRequestAbortedError(error) || error.reason === "invalid_url") return false;
11600
+ var aborted = error;
11601
+ this.countFunnelStage("request_outcome:pod_request_not_sent");
11602
+ this.logOrchestratorFunnel("pod_request_not_sent", _object_spread({
11603
+ reason: aborted.reason,
11604
+ errorMessage: aborted.message
11605
+ }, aborted.diagnostics));
11606
+ return true;
10918
11607
  }
10919
11608
  },
10920
11609
  {
@@ -11134,7 +11823,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11134
11823
  value: function playSingleAd(vastTagUrl) {
11135
11824
  var trigger = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "vmap";
11136
11825
  return _async_to_generator(function() {
11137
- var epoch, generation, requestToken, ap, budgetedUrl, requestUrl, _ap_getLoadedAdDuration, adDurationS, remainingMs, error;
11826
+ var epoch, generation, requestToken, ap, requestUrl, _this_currentVastUrl, finalizeRequestUrl, _ap_getLoadedAdDuration, adDurationS, remainingMs, error;
11138
11827
  return _ts_generator(this, function(_state) {
11139
11828
  switch(_state.label){
11140
11829
  case 0:
@@ -11172,19 +11861,18 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11172
11861
  requestToken = ++this.timing.adRequestTokenCounter;
11173
11862
  this.timing.activeAdRequestToken = requestToken;
11174
11863
  ap = this.host.getAdPlayer();
11175
- budgetedUrl = this.withCurrentPodBudget(vastTagUrl);
11176
11864
  this.currentPodSource = "gam";
11177
11865
  this.setSlotState("REQUESTING", trigger);
11178
11866
  this.beginFunnelRequest(ap, requestToken, trigger);
11179
- requestUrl = this.applyOpportunityFloor(budgetedUrl);
11867
+ requestUrl = this.applyOpportunityFloor(ensureVideoAdType(vastTagUrl));
11180
11868
  this.currentVastUrl = requestUrl;
11181
11869
  _state.label = 1;
11182
11870
  case 1:
11183
11871
  _state.trys.push([
11184
11872
  1,
11185
- 5,
11873
+ 9,
11186
11874
  ,
11187
- 6
11875
+ 10
11188
11876
  ]);
11189
11877
  return [
11190
11878
  4,
@@ -11195,15 +11883,45 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11195
11883
  if (this.isStale(epoch, generation)) return [
11196
11884
  2
11197
11885
  ];
11886
+ return [
11887
+ 4,
11888
+ this.host.completeGamRequestSignals(requestUrl)
11889
+ ];
11890
+ case 3:
11891
+ requestUrl = _state.sent();
11892
+ if (this.isStale(epoch, generation)) return [
11893
+ 2
11894
+ ];
11198
11895
  this.timing.startAdRequestWatchdog(requestToken);
11896
+ finalizeRequestUrl = this.createGamDispatchFinalizer(requestToken);
11897
+ _state.label = 4;
11898
+ case 4:
11899
+ _state.trys.push([
11900
+ 4,
11901
+ ,
11902
+ 6,
11903
+ 7
11904
+ ]);
11199
11905
  return [
11200
11906
  4,
11201
11907
  this.callController(function() {
11202
- return ap.requestAds(requestUrl);
11908
+ return ap.requestAds(requestUrl, {
11909
+ finalizeRequestUrl: finalizeRequestUrl
11910
+ });
11203
11911
  })
11204
11912
  ];
11205
- case 3:
11913
+ case 5:
11206
11914
  _state.sent();
11915
+ return [
11916
+ 3,
11917
+ 7
11918
+ ];
11919
+ case 6:
11920
+ this.recordPodResponseDiagnostics(requestToken, ap);
11921
+ return [
11922
+ 7
11923
+ ];
11924
+ case 7:
11207
11925
  this.timing.clearAdRequestWatchdog();
11208
11926
  if (this.isStale(epoch, generation)) {
11209
11927
  this.logOrchestratorFunnel("stale_request_result_ignored", {
@@ -11215,7 +11933,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11215
11933
  }
11216
11934
  sendAdLoadedTracking(this.host.config.licenseKey, {
11217
11935
  source: "hls",
11218
- vastUrl: requestUrl,
11936
+ vastUrl: (_this_currentVastUrl = this.currentVastUrl) !== null && _this_currentVastUrl !== void 0 ? _this_currentVastUrl : requestUrl,
11219
11937
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
11220
11938
  }, this.analyticsContext).catch(function() {});
11221
11939
  if (!this.timing.ensureLoadedAdFitsBudget(ap)) {
@@ -11236,7 +11954,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11236
11954
  return ap.play();
11237
11955
  })
11238
11956
  ];
11239
- case 4:
11957
+ case 8:
11240
11958
  _state.sent();
11241
11959
  if (this.isStale(epoch, generation)) return [
11242
11960
  2
@@ -11248,9 +11966,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11248
11966
  this.timing.temporaryFailureUrls.delete(vastTagUrl);
11249
11967
  return [
11250
11968
  3,
11251
- 6
11969
+ 10
11252
11970
  ];
11253
- case 5:
11971
+ case 9:
11254
11972
  error = _state.sent();
11255
11973
  this.timing.clearAdRequestWatchdog();
11256
11974
  this.timing.clearAdFailsafeTimer();
@@ -11267,12 +11985,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11267
11985
  ];
11268
11986
  }
11269
11987
  if (this.debug) console.error("[AD-ERROR] Ad request failed:", error === null || error === void 0 ? void 0 : error.message);
11988
+ if (this.handlePodRequestNotSent(error)) throw error;
11270
11989
  this.recordRequestFailure(error, vastTagUrl);
11271
11990
  if ((error === null || error === void 0 ? void 0 : error.message) === "ad_duration_exceeds_budget") {
11272
11991
  this.recreateAdController("discarded_budget");
11273
11992
  }
11274
11993
  throw error;
11275
- case 6:
11994
+ case 10:
11276
11995
  return [
11277
11996
  2
11278
11997
  ];
@@ -11334,7 +12053,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11334
12053
  playbackFailedAfterFill: count("request_outcome:playback_failed"),
11335
12054
  requestFailed: count("request_failed"),
11336
12055
  requestAbortedTimeout: count("request_aborted_timeout"),
11337
- credentialsRetries: count("vast_credentials_retry"),
12056
+ credentialsModeChanges: count("gam_credentials_mode_changed"),
11338
12057
  wrapperFailures: count("wrapper_fetch:failure"),
11339
12058
  noSupportedMedia: count("vast_no_supported_media"),
11340
12059
  vpaidOnly: count("vast_no_supported_media:vpaid"),
@@ -11870,8 +12589,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11870
12589
  requiresMediaPipelineResetAfterAds: function requiresMediaPipelineResetAfterAds1() {
11871
12590
  return requiresMediaPipelineResetAfterAds();
11872
12591
  },
11873
- generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
11874
- return _this.generatePodVastUrl(base, breakDurationMs);
12592
+ generatePodVastUrl: function generatePodVastUrl(base) {
12593
+ return _this.generatePodVastUrl(base);
12594
+ },
12595
+ completeGamRequestSignals: function completeGamRequestSignals(url) {
12596
+ return _this.adConfig.completeDeferredRequestSignals(url, _this.palNonce);
11875
12597
  },
11876
12598
  getEdgePodBaseUrl: function getEdgePodBaseUrl() {
11877
12599
  return _this.edgePodBaseUrl;
@@ -11995,9 +12717,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11995
12717
  },
11996
12718
  {
11997
12719
  key: "generatePodVastUrl",
11998
- value: function generatePodVastUrl(baseUrl, breakDurationMs) {
11999
- var podParams = this.adConfig.resolvePodParams(breakDurationMs);
12000
- return this.adConfig.generatePodVastUrl(baseUrl, podParams, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
12720
+ value: function generatePodVastUrl(baseUrl) {
12721
+ return this.adConfig.generatePodVastUrl(baseUrl, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
12001
12722
  }
12002
12723
  },
12003
12724
  {
@@ -12351,7 +13072,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12351
13072
  activeAdRequest: this.timing.activeAdRequestToken !== null
12352
13073
  });
12353
13074
  }
12354
- this.timing.scteAdBreakEndWallClockMs = Date.now();
13075
+ this.timing.markBreakEndedNow();
12355
13076
  this.timing.clearAdStartTimer();
12356
13077
  this.timing.clearAdStopTimer();
12357
13078
  if (adPlaying) {
@@ -12378,7 +13099,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12378
13099
  this.adBreak.inAdBreak = true;
12379
13100
  this.cueManager.activeScte35BreakKey = cueKey !== null && cueKey !== void 0 ? cueKey : this.cueManager.pendingScte35CueKey;
12380
13101
  this.cueManager.scheduledScte35BreakKey = void 0;
12381
- this.timing.currentAdBreakStartWallClockMs = this.timing.resolveScteBreakStartWallClockMs(marker);
13102
+ this.timing.beginBreakTiming(this.timing.resolveScteBreakStartWallClockMs(marker));
12382
13103
  this.timing.setAdBreakDurationBoundary(durationMs);
12383
13104
  this.adBreak.handleAdStart(marker);
12384
13105
  this.timing.scheduleAdStopAtBreakBoundary();
@@ -12424,9 +13145,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12424
13145
  }
12425
13146
  this.adConfig.beginNewAdPod();
12426
13147
  this.adConfig.podAssignedByPrefetch = true;
12427
- var breakDurationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0;
12428
13148
  var generatedUrls = [
12429
- this.generatePodVastUrl(baseVastUrl, breakDurationMs)
13149
+ this.generatePodVastUrl(baseVastUrl)
12430
13150
  ];
12431
13151
  this.adBreak.pendingAdBreak = _object_spread_props(_object_spread({
12432
13152
  marker: marker
@@ -12525,7 +13245,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12525
13245
  this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);
12526
13246
  this.adBreak.showAds = true;
12527
13247
  this.adBreak.inAdBreak = true;
12528
- this.timing.currentAdBreakStartWallClockMs = Date.now();
13248
+ this.timing.beginBreakTiming(Date.now());
12529
13249
  if (durationMs > 0) {
12530
13250
  this.timing.setAdBreakDurationBoundary(durationMs);
12531
13251
  }
@@ -12797,7 +13517,6 @@ var CRITICAL_PROPS = [
12797
13517
  "vmapUrl",
12798
13518
  "lowLatencyMode",
12799
13519
  "driftToleranceMs",
12800
- "vastMode",
12801
13520
  "ctvAdRequest",
12802
13521
  "adFloorMinCents",
12803
13522
  "adFloorMaxCents",
@@ -12806,7 +13525,7 @@ var CRITICAL_PROPS = [
12806
13525
  var CONTROLS_HIDE_DELAY = 3e3;
12807
13526
  var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
12808
13527
  var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12809
- var src = props.src, autoplay = props.autoplay, muted = props.muted, lowLatencyMode = props.lowLatencyMode, allowNativeHls = props.allowNativeHls, isLiveStream = props.isLiveStream, driftToleranceMs = props.driftToleranceMs, immediateManifestAds = props.immediateManifestAds, debugAdTiming = props.debugAdTiming, showCustomControls = props.showCustomControls, hideLoadingIndicator = props.hideLoadingIndicator, onVolumeToggle = props.onVolumeToggle, onFullscreenToggle = props.onFullscreenToggle, onControlClick = props.onControlClick, onReady = props.onReady, wrapperClassName = props.wrapperClassName, wrapperStyle = props.wrapperStyle, className = props.className, style = props.style, controls = props.controls, playsInline = props.playsInline, preload = props.preload, poster = props.poster, children = props.children, licenseKey = props.licenseKey, vastMode = props.vastMode, vastTagUrl = props.vastTagUrl, isVmap = props.isVmap, vmapUrl = props.vmapUrl, minSegmentsBeforePlay = props.minSegmentsBeforePlay, ctvAdRequest = props.ctvAdRequest, programTitle = props.programTitle, channelName = props.channelName, minRemainingMsToStartAd = props.minRemainingMsToStartAd, minRemainingMsToRequestAd = props.minRemainingMsToRequestAd, maxNoFillsPerBreak = props.maxNoFillsPerBreak, maxAdBreakExtensionMs = props.maxAdBreakExtensionMs, adFloorLadderEnabled = props.adFloorLadderEnabled, adFloorLadder = props.adFloorLadder, adFloorMinCents = props.adFloorMinCents, adFloorMaxCents = props.adFloorMaxCents, adFloorStepCents = props.adFloorStepCents, enableEdgePodRequest = props.enableEdgePodRequest, edgePodUrl = props.edgePodUrl, restVideoAttrs = _object_without_properties(props, [
13528
+ var src = props.src, autoplay = props.autoplay, muted = props.muted, lowLatencyMode = props.lowLatencyMode, allowNativeHls = props.allowNativeHls, isLiveStream = props.isLiveStream, driftToleranceMs = props.driftToleranceMs, immediateManifestAds = props.immediateManifestAds, debugAdTiming = props.debugAdTiming, showCustomControls = props.showCustomControls, hideLoadingIndicator = props.hideLoadingIndicator, onVolumeToggle = props.onVolumeToggle, onFullscreenToggle = props.onFullscreenToggle, onControlClick = props.onControlClick, onReady = props.onReady, wrapperClassName = props.wrapperClassName, wrapperStyle = props.wrapperStyle, className = props.className, style = props.style, controls = props.controls, playsInline = props.playsInline, preload = props.preload, poster = props.poster, children = props.children, licenseKey = props.licenseKey, vastTagUrl = props.vastTagUrl, isVmap = props.isVmap, vmapUrl = props.vmapUrl, minSegmentsBeforePlay = props.minSegmentsBeforePlay, ctvAdRequest = props.ctvAdRequest, programTitle = props.programTitle, channelName = props.channelName, contentNetwork = props.contentNetwork, minRemainingMsToStartAd = props.minRemainingMsToStartAd, minRemainingMsToRequestAd = props.minRemainingMsToRequestAd, maxNoFillsPerBreak = props.maxNoFillsPerBreak, maxAdBreakExtensionMs = props.maxAdBreakExtensionMs, adFloorLadderEnabled = props.adFloorLadderEnabled, adFloorLadder = props.adFloorLadder, adFloorMinCents = props.adFloorMinCents, adFloorMaxCents = props.adFloorMaxCents, adFloorStepCents = props.adFloorStepCents, enableEdgePodRequest = props.enableEdgePodRequest, edgePodUrl = props.edgePodUrl, restVideoAttrs = _object_without_properties(props, [
12810
13529
  "src",
12811
13530
  "autoplay",
12812
13531
  "muted",
@@ -12832,7 +13551,6 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12832
13551
  "poster",
12833
13552
  "children",
12834
13553
  "licenseKey",
12835
- "vastMode",
12836
13554
  "vastTagUrl",
12837
13555
  "isVmap",
12838
13556
  "vmapUrl",
@@ -12840,6 +13558,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12840
13558
  "ctvAdRequest",
12841
13559
  "programTitle",
12842
13560
  "channelName",
13561
+ "contentNetwork",
12843
13562
  "minRemainingMsToStartAd",
12844
13563
  "minRemainingMsToRequestAd",
12845
13564
  "maxNoFillsPerBreak",
@@ -12998,7 +13717,6 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12998
13717
  vmapUrl,
12999
13718
  lowLatencyMode,
13000
13719
  driftToleranceMs,
13001
- vastMode,
13002
13720
  adFloorMinCents,
13003
13721
  adFloorMaxCents,
13004
13722
  adFloorStepCents
@@ -13040,7 +13758,6 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
13040
13758
  if (onFullscreenToggle !== void 0) cfg.onFullscreenToggle = onFullscreenToggle;
13041
13759
  if (onControlClick !== void 0) cfg.onControlClick = onControlClick;
13042
13760
  if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
13043
- if (vastMode !== void 0) cfg.vastMode = vastMode;
13044
13761
  if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;
13045
13762
  if (isVmap !== void 0) cfg.isVmap = isVmap;
13046
13763
  if (vmapUrl !== void 0) cfg.vmapUrl = vmapUrl;
@@ -13048,6 +13765,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
13048
13765
  if (ctvAdRequest !== void 0) cfg.ctvAdRequest = ctvAdRequest;
13049
13766
  if (programTitle !== void 0) cfg.programTitle = programTitle;
13050
13767
  if (channelName !== void 0) cfg.channelName = channelName;
13768
+ if (contentNetwork !== void 0) cfg.contentNetwork = contentNetwork;
13051
13769
  if (minRemainingMsToStartAd !== void 0) cfg.minRemainingMsToStartAd = minRemainingMsToStartAd;
13052
13770
  if (minRemainingMsToRequestAd !== void 0) cfg.minRemainingMsToRequestAd = minRemainingMsToRequestAd;
13053
13771
  if (maxNoFillsPerBreak !== void 0) cfg.maxNoFillsPerBreak = maxNoFillsPerBreak;
@@ -15380,8 +16098,10 @@ var StormcloudPlayer_default = StormcloudPlayer;
15380
16098
  // Annotate the CommonJS export names for ESM import in node:
15381
16099
  0 && (module.exports = {
15382
16100
  DEFAULT_FLOOR_LADDER_BOUNDS: DEFAULT_FLOOR_LADDER_BOUNDS,
16101
+ DEFAULT_REQUEST_SAFETY_MS: DEFAULT_REQUEST_SAFETY_MS,
15383
16102
  DEFAULT_TRACKING_INGEST_CONFIG: DEFAULT_TRACKING_INGEST_CONFIG,
15384
16103
  DEFAULT_WEB_FLOOR_LADDER_CONFIG: DEFAULT_WEB_FLOOR_LADDER_CONFIG,
16104
+ GAM_AD_OPPORTUNITY_DURATION_MS: GAM_AD_OPPORTUNITY_DURATION_MS,
15385
16105
  IS_BROWSER: IS_BROWSER,
15386
16106
  IS_GLOBAL: IS_GLOBAL,
15387
16107
  IS_IOS: IS_IOS,