stormcloud-video-player 0.8.72 → 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 +992 -276
  5. package/lib/StormcloudPlayer.cjs.map +1 -1
  6. package/lib/StormcloudPlayer.d.cts +1 -0
  7. package/lib/index.cjs +1005 -281
  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 +998 -282
  12. package/lib/index.js.map +1 -1
  13. package/lib/player/AdBreakOrchestrator.cjs +772 -70
  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 +992 -276
  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 +992 -276
  36. package/lib/players/HlsPlayer.cjs.map +1 -1
  37. package/lib/players/HlsPlayer.d.cts +1 -0
  38. package/lib/players/index.cjs +992 -276
  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 +997 -281
  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
@@ -382,21 +382,20 @@ var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
382
382
  "adid"
383
383
  ]);
384
384
  function resolveVastEnvironmentSignals(isCtv) {
385
- var _ref;
386
385
  var bridgeSignals = readNativeBridgeSignals();
387
386
  var platformDevice = readPlatformNativeDeviceId();
388
- var realDeviceId = bridgeSignals.deviceId || (isCtv ? readStoredDeviceId() : void 0) || platformDevice.deviceId;
387
+ var bridgeDeviceId = validDeviceId(bridgeSignals.deviceId);
388
+ var realDeviceId = bridgeDeviceId || (isCtv ? validDeviceId(readStoredDeviceId()) : void 0) || validDeviceId(platformDevice.deviceId);
389
389
  var deviceId = realDeviceId;
390
- var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || platformDevice.deviceIdType || inferDeviceIdType();
391
- var platformLat = bridgeSignals.deviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;
392
- var limitAdTracking = deviceId != null ? (_ref = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false : void 0;
390
+ var deviceIdType = (bridgeDeviceId ? bridgeSignals.deviceIdType : void 0) || readStoredString("deviceIdType") || readStoredString("idtype") || platformDevice.deviceIdType || inferDeviceIdType();
391
+ var platformLat = bridgeDeviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;
392
+ var limitAdTracking = deviceId != null ? platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking() : void 0;
393
393
  if (!deviceId && isCtv) {
394
394
  var dpid = getOrCreateStoredUuid(PLAYER_ID_STORAGE_KEY);
395
395
  if (dpid) {
396
- var _ref1;
397
396
  deviceId = dpid;
398
397
  deviceIdType = "dpid";
399
- limitAdTracking = (_ref1 = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking()) !== null && _ref1 !== void 0 ? _ref1 : false;
398
+ limitAdTracking = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking();
400
399
  }
401
400
  }
402
401
  var deviceTypeHint = resolveDeviceTypeHint(isCtv);
@@ -761,6 +760,9 @@ function isMacroPlaceholder(value) {
761
760
  var t = value.trim();
762
761
  return !t || /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/.test(t) || /^(unknown|null|undefined|none|n\/a|\$\{[^}]+\})$/i.test(t) || ZEROED_AD_ID_PATTERNS.has(t.toLowerCase());
763
762
  }
763
+ function validDeviceId(value) {
764
+ return value && !isMacroPlaceholder(value) ? value : void 0;
765
+ }
764
766
  function isZeroedAdId(value) {
765
767
  return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());
766
768
  }
@@ -1293,6 +1295,198 @@ function ensureVideoAdType(rawUrl) {
1293
1295
  return rawUrl;
1294
1296
  }
1295
1297
  }
1298
+ var SCVP_MACRO_DETECT = /\[SCVP-|%5BSCVP-|\(SCVP-|%28SCVP-/i;
1299
+ var SCVP_MACRO_PATTERN = /\[SCVP-([A-Z0-9-]+)\]|\(SCVP-([A-Z0-9-]+)\)/gi;
1300
+ var SCVP_WHOLE_VALUE_PATTERN = /^\s*(?:\[SCVP-([A-Z0-9-]+)\]|\(SCVP-([A-Z0-9-]+)\))\s*$/i;
1301
+ var NESTED_QUERY_PARAM_KEYS = /* @__PURE__ */ new Set([
1302
+ "cust_params"
1303
+ ]);
1304
+ var SCVP_POD_MACROS = /* @__PURE__ */ new Set([
1305
+ "PMND",
1306
+ "PMXD",
1307
+ "PMAD"
1308
+ ]);
1309
+ function hasScvpMacros(url) {
1310
+ return !!url && SCVP_MACRO_DETECT.test(url);
1311
+ }
1312
+ function safeDecode(value) {
1313
+ try {
1314
+ return decodeURIComponent(value.replace(/\+/g, " "));
1315
+ } catch (unused) {
1316
+ return value;
1317
+ }
1318
+ }
1319
+ function findScvpMacroNames(url) {
1320
+ if (!url) return [];
1321
+ var names = /* @__PURE__ */ new Set();
1322
+ var text = url;
1323
+ for(var pass = 0; pass < 3; pass++){
1324
+ text.replace(SCVP_MACRO_PATTERN, function(_m, bracketName, parenName) {
1325
+ names.add(String(bracketName || parenName).toUpperCase());
1326
+ return "";
1327
+ });
1328
+ var decoded = safeDecode(text);
1329
+ if (decoded === text) break;
1330
+ text = decoded;
1331
+ }
1332
+ return Array.from(names);
1333
+ }
1334
+ function resolveScvpMacroValues(ctx) {
1335
+ var _ctx_deviceId, _ctx_deviceIdType, _ctx_consent, _ctx_consent1, _ctx_consent2;
1336
+ var values = /* @__PURE__ */ new Map();
1337
+ var set = function set(name, value) {
1338
+ if (value == null) return;
1339
+ var str = String(value).trim();
1340
+ if (str) values.set(name, str);
1341
+ };
1342
+ var toFlag = function toFlag(value) {
1343
+ return value == null ? void 0 : value ? "1" : "0";
1344
+ };
1345
+ var deviceId = (_ctx_deviceId = ctx.deviceId) === null || _ctx_deviceId === void 0 ? void 0 : _ctx_deviceId.trim();
1346
+ var deviceIdType = deviceId ? ((_ctx_deviceIdType = ctx.deviceIdType) === null || _ctx_deviceIdType === void 0 ? void 0 : _ctx_deviceIdType.trim()) || inferDeviceIdType() : void 0;
1347
+ if (deviceId && deviceIdType) {
1348
+ set("RDID", deviceId);
1349
+ set("IDTYPE", deviceIdType);
1350
+ set("IS-LAT", toFlag(ctx.limitAdTracking));
1351
+ }
1352
+ set("SID", ctx.sessionId);
1353
+ set("DTH", ctx.deviceTypeHint);
1354
+ set("GIVN", ctx.palNonce);
1355
+ set("CT-TI", ctx.programTitle);
1356
+ set("CT-CH", ctx.channelName);
1357
+ set("POD", ctx.pod);
1358
+ set("CORRELATOR", ctx.correlator);
1359
+ set("SCOR", ctx.streamCorrelator);
1360
+ set("VPMUTE", toFlag(ctx.adWillPlayMuted));
1361
+ if (ctx.adWillAutoPlay != null) {
1362
+ set("VPA", ctx.adWillAutoPlay ? "auto" : "click");
1363
+ }
1364
+ set("GDPR", (_ctx_consent = ctx.consent) === null || _ctx_consent === void 0 ? void 0 : _ctx_consent.gdpr);
1365
+ set("GDPR-CONSENT", (_ctx_consent1 = ctx.consent) === null || _ctx_consent1 === void 0 ? void 0 : _ctx_consent1.gdprConsent);
1366
+ set("US-PRIVACY", (_ctx_consent2 = ctx.consent) === null || _ctx_consent2 === void 0 ? void 0 : _ctx_consent2.usPrivacy);
1367
+ return values;
1368
+ }
1369
+ var keepNone = function keepNone() {
1370
+ return false;
1371
+ };
1372
+ function substituteScvpParams(params, values, unresolved, keep, nested) {
1373
+ var out = [];
1374
+ var replaceMacro = function replaceMacro(match, bracketName, parenName) {
1375
+ var name = String(bracketName || parenName).toUpperCase();
1376
+ var value = values.get(name);
1377
+ if (value != null) return value;
1378
+ if (keep(name)) return match;
1379
+ unresolved.add(name);
1380
+ return "";
1381
+ };
1382
+ params.forEach(function(value, key) {
1383
+ var whole = value.match(SCVP_WHOLE_VALUE_PATTERN);
1384
+ if (whole) {
1385
+ var name = String(whole[1] || whole[2]).toUpperCase();
1386
+ var resolved = values.get(name);
1387
+ if (resolved != null) {
1388
+ out.push([
1389
+ key,
1390
+ resolved
1391
+ ]);
1392
+ } else if (keep(name)) {
1393
+ out.push([
1394
+ key,
1395
+ value
1396
+ ]);
1397
+ } else {
1398
+ unresolved.add(name);
1399
+ }
1400
+ return;
1401
+ }
1402
+ if (!SCVP_MACRO_DETECT.test(value)) {
1403
+ out.push([
1404
+ key,
1405
+ value
1406
+ ]);
1407
+ return;
1408
+ }
1409
+ if (!nested && NESTED_QUERY_PARAM_KEYS.has(key)) {
1410
+ var inner = substituteScvpParams(new URLSearchParams(value), values, unresolved, keep, true);
1411
+ if (inner.length > 0) {
1412
+ out.push([
1413
+ key,
1414
+ inner.map(function(param) {
1415
+ var _param = _sliced_to_array(param, 2), k = _param[0], v = _param[1];
1416
+ return "".concat(encodeURIComponent(k), "=").concat(encodeURIComponent(v));
1417
+ }).join("&")
1418
+ ]);
1419
+ }
1420
+ return;
1421
+ }
1422
+ out.push([
1423
+ key,
1424
+ value.replace(SCVP_MACRO_PATTERN, replaceMacro)
1425
+ ]);
1426
+ });
1427
+ return out;
1428
+ }
1429
+ function substituteScvpMacros(baseUrl, values) {
1430
+ var keep = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : keepNone;
1431
+ var unresolved = /* @__PURE__ */ new Set();
1432
+ var url;
1433
+ try {
1434
+ url = new URL(normalizeVastTagUrl(baseUrl));
1435
+ } catch (unused) {
1436
+ var replaced = baseUrl.replace(SCVP_MACRO_PATTERN, function(match, bracketName, parenName) {
1437
+ var name = String(bracketName || parenName).toUpperCase();
1438
+ var value = values.get(name);
1439
+ if (value != null) return encodeURIComponent(value);
1440
+ if (keep(name)) return match;
1441
+ unresolved.add(name);
1442
+ return "";
1443
+ });
1444
+ return {
1445
+ url: replaced,
1446
+ unresolved: Array.from(unresolved)
1447
+ };
1448
+ }
1449
+ var entries = substituteScvpParams(url.searchParams, values, unresolved, keep, false);
1450
+ var search = new URLSearchParams();
1451
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1452
+ try {
1453
+ for(var _iterator = entries[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1454
+ var _step_value = _sliced_to_array(_step.value, 2), key = _step_value[0], value = _step_value[1];
1455
+ search.append(key, value);
1456
+ }
1457
+ } catch (err) {
1458
+ _didIteratorError = true;
1459
+ _iteratorError = err;
1460
+ } finally{
1461
+ try {
1462
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1463
+ _iterator.return();
1464
+ }
1465
+ } finally{
1466
+ if (_didIteratorError) {
1467
+ throw _iteratorError;
1468
+ }
1469
+ }
1470
+ }
1471
+ url.search = search.toString();
1472
+ return {
1473
+ url: url.toString(),
1474
+ unresolved: Array.from(unresolved)
1475
+ };
1476
+ }
1477
+ function applyScvpMacros(baseUrl, ctx) {
1478
+ var deferred = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : /* @__PURE__ */ new Set();
1479
+ return substituteScvpMacros(baseUrl, resolveScvpMacroValues(ctx), function(name) {
1480
+ return deferred.has(name);
1481
+ });
1482
+ }
1483
+ function stripScvpMacros(url) {
1484
+ if (findScvpMacroNames(url).length === 0) return {
1485
+ url: url,
1486
+ unresolved: []
1487
+ };
1488
+ return substituteScvpMacros(url, /* @__PURE__ */ new Map());
1489
+ }
1296
1490
  function applyVastMacros(baseUrl, ctx) {
1297
1491
  var expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);
1298
1492
  var url;
@@ -1334,15 +1528,6 @@ function applyVastMacros(baseUrl, ctx) {
1334
1528
  }
1335
1529
  params.delete("ppos");
1336
1530
  params.delete("lip");
1337
- if (ctx.podMinDurationMs != null) {
1338
- params.set("pmnd", String(Math.max(0, Math.round(ctx.podMinDurationMs))));
1339
- }
1340
- if (ctx.podMaxDurationMs != null) {
1341
- params.set("pmxd", String(Math.max(0, Math.round(ctx.podMaxDurationMs))));
1342
- }
1343
- if (ctx.podMaxAds != null) {
1344
- params.set("pmad", String(Math.max(1, Math.round(ctx.podMaxAds))));
1345
- }
1346
1531
  var existingUrl = params.get("url") || "";
1347
1532
  if (EXAMPLE_COM_URL.test(existingUrl)) {
1348
1533
  params.delete("url");
@@ -2172,6 +2357,309 @@ function substituteVastTrackingMacros(url) {
2172
2357
  return KNOWN_VAST_MACROS.has(name) ? "" : match;
2173
2358
  });
2174
2359
  }
2360
+ // src/player/OptimizedPodRequest.ts
2361
+ var DEFAULT_REQUEST_SAFETY_MS = 1500;
2362
+ var GAM_AD_OPPORTUNITY_DURATION_MS = 3e4;
2363
+ var POD_PARAM_KEYS = [
2364
+ "pmnd",
2365
+ "pmxd",
2366
+ "pmad"
2367
+ ];
2368
+ var POSITIVE_INT = /^[1-9]\d*$/;
2369
+ var NON_NEGATIVE_INT = /^(0|[1-9]\d*)$/;
2370
+ function nonNegativeInt(value) {
2371
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : void 0;
2372
+ }
2373
+ function positiveInt(value) {
2374
+ return typeof value === "number" && Number.isFinite(value) && value >= 1 ? Math.floor(value) : void 0;
2375
+ }
2376
+ function resolveAdPodConfig(config) {
2377
+ var _config_adPodConfig, _nonNegativeInt, _nonNegativeInt1, _positiveInt;
2378
+ var pod = (_config_adPodConfig = config.adPodConfig) !== null && _config_adPodConfig !== void 0 ? _config_adPodConfig : {};
2379
+ return {
2380
+ requestSafetyMs: (_nonNegativeInt = nonNegativeInt(pod.requestSafetyMs)) !== null && _nonNegativeInt !== void 0 ? _nonNegativeInt : DEFAULT_REQUEST_SAFETY_MS,
2381
+ minPodDurationMs: (_nonNegativeInt1 = nonNegativeInt(pod.minPodDurationMs)) !== null && _nonNegativeInt1 !== void 0 ? _nonNegativeInt1 : 0,
2382
+ maxAdsPerBreak: pod.maxAdsPerBreak === void 0 ? positiveInt(config.podMaxAds) : positiveInt(pod.maxAdsPerBreak),
2383
+ maxPodDurationMs: (_positiveInt = positiveInt(pod.maxPodDurationMs)) !== null && _positiveInt !== void 0 ? _positiveInt : positiveInt(config.podMaxDurationMs),
2384
+ exactDuration: config.podExactDuration === true
2385
+ };
2386
+ }
2387
+ function measureBreakCapacity(timing, nowMonoMs) {
2388
+ var _timing_breakEndMonoMs;
2389
+ var scheduled = timing.scheduledBreakDurationMs;
2390
+ if (scheduled == null || !(scheduled > 0) || timing.breakStartMonoMs == null) {
2391
+ return void 0;
2392
+ }
2393
+ var endMonoMs = (_timing_breakEndMonoMs = timing.breakEndMonoMs) !== null && _timing_breakEndMonoMs !== void 0 ? _timing_breakEndMonoMs : timing.breakStartMonoMs + scheduled;
2394
+ var untilEnd = Math.min(scheduled, endMonoMs - nowMonoMs);
2395
+ var unplayed = scheduled - Math.max(0, timing.playedDurationMs);
2396
+ return {
2397
+ scheduledBreakDurationMs: scheduled,
2398
+ elapsedBeforeGamRequestMs: Math.max(0, nowMonoMs - timing.breakStartMonoMs),
2399
+ remainingAtGamDispatchMs: Math.max(0, Math.min(untilEnd, unplayed))
2400
+ };
2401
+ }
2402
+ function resolvePodParams(input) {
2403
+ var capacity = input.capacity, config = input.config;
2404
+ var pmxd;
2405
+ var source;
2406
+ if (capacity) {
2407
+ pmxd = Math.floor(capacity.remainingAtGamDispatchMs - config.requestSafetyMs);
2408
+ source = "break_remaining";
2409
+ } else if (config.maxPodDurationMs != null) {
2410
+ pmxd = config.maxPodDurationMs;
2411
+ source = "configured_cap";
2412
+ } else if (input.tagMaxDurationMs != null) {
2413
+ pmxd = input.tagMaxDurationMs;
2414
+ source = "tag_cap";
2415
+ } else {
2416
+ return {
2417
+ kind: "omit"
2418
+ };
2419
+ }
2420
+ var minUsable = Math.max(1, Math.floor(input.minUsablePmxdMs));
2421
+ if (!Number.isFinite(pmxd) || pmxd < minUsable) {
2422
+ return {
2423
+ kind: "abort",
2424
+ reason: capacity ? "insufficient_break_capacity" : "invalid_pod_cap",
2425
+ pmxdCandidateMs: Number.isFinite(pmxd) ? pmxd : 0
2426
+ };
2427
+ }
2428
+ var pmnd = config.exactDuration ? pmxd : Math.min(config.minPodDurationMs, pmxd);
2429
+ return {
2430
+ kind: "send",
2431
+ params: {
2432
+ pmnd: pmnd,
2433
+ pmxd: pmxd,
2434
+ pmad: config.maxAdsPerBreak
2435
+ },
2436
+ source: source
2437
+ };
2438
+ }
2439
+ function podRequestAborted(reason, message, diagnostics) {
2440
+ var error = new Error("Optimized pod request not sent (".concat(reason, "): ").concat(message));
2441
+ error.podRequestAborted = true;
2442
+ error.reason = reason;
2443
+ error.diagnostics = diagnostics;
2444
+ return error;
2445
+ }
2446
+ function isPodRequestAbortedError(error) {
2447
+ return !!error && error.podRequestAborted === true;
2448
+ }
2449
+ function firstPositiveIntParam(params, key) {
2450
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2451
+ try {
2452
+ for(var _iterator = params.getAll(key)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2453
+ var value = _step.value;
2454
+ if (POSITIVE_INT.test(value.trim())) return Number(value.trim());
2455
+ }
2456
+ } catch (err) {
2457
+ _didIteratorError = true;
2458
+ _iteratorError = err;
2459
+ } finally{
2460
+ try {
2461
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2462
+ _iterator.return();
2463
+ }
2464
+ } finally{
2465
+ if (_didIteratorError) {
2466
+ throw _iteratorError;
2467
+ }
2468
+ }
2469
+ }
2470
+ return void 0;
2471
+ }
2472
+ function isOptimizedPodUrl(url) {
2473
+ if (findScvpMacroNames(url).some(function(name) {
2474
+ return SCVP_POD_MACROS.has(name);
2475
+ })) return true;
2476
+ try {
2477
+ var params = new URL(url).searchParams;
2478
+ return POD_PARAM_KEYS.some(function(key) {
2479
+ return params.has(key);
2480
+ });
2481
+ } catch (unused) {
2482
+ return false;
2483
+ }
2484
+ }
2485
+ function finalizeGamRequestUrl(rawUrl, ctx) {
2486
+ var nowEpochMs = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : Date.now();
2487
+ var optimizedPod = isOptimizedPodUrl(rawUrl);
2488
+ var capacity = ctx.capacity;
2489
+ var base = {
2490
+ breakId: ctx.breakId,
2491
+ optimizedPod: optimizedPod,
2492
+ scteBreakDurationMs: capacity === null || capacity === void 0 ? void 0 : capacity.scheduledBreakDurationMs,
2493
+ elapsedBeforeGamRequestMs: capacity === null || capacity === void 0 ? void 0 : capacity.elapsedBeforeGamRequestMs,
2494
+ remainingAtGamDispatchMs: capacity === null || capacity === void 0 ? void 0 : capacity.remainingAtGamDispatchMs,
2495
+ safetyReserveMs: ctx.config.requestSafetyMs
2496
+ };
2497
+ var decision = {
2498
+ kind: "omit"
2499
+ };
2500
+ if (optimizedPod) {
2501
+ var tagMaxDurationMs;
2502
+ try {
2503
+ tagMaxDurationMs = firstPositiveIntParam(new URL(rawUrl).searchParams, "pmxd");
2504
+ } catch (unused) {}
2505
+ decision = resolvePodParams({
2506
+ capacity: capacity,
2507
+ config: ctx.config,
2508
+ minUsablePmxdMs: ctx.minUsablePmxdMs,
2509
+ tagMaxDurationMs: tagMaxDurationMs
2510
+ });
2511
+ if (decision.kind === "abort") {
2512
+ throw podRequestAborted(decision.reason, "pmxd would be ".concat(decision.pmxdCandidateMs, "ms (minimum ").concat(ctx.minUsablePmxdMs, "ms)"), base);
2513
+ }
2514
+ }
2515
+ var pod = decision.kind === "send" ? decision.params : void 0;
2516
+ var values = /* @__PURE__ */ new Map();
2517
+ if (pod) {
2518
+ values.set("PMND", String(pod.pmnd));
2519
+ values.set("PMXD", String(pod.pmxd));
2520
+ if (pod.pmad != null) values.set("PMAD", String(pod.pmad));
2521
+ }
2522
+ var substituted = substituteScvpMacros(rawUrl, values);
2523
+ var finalUrl;
2524
+ try {
2525
+ var url = new URL(normalizeVastTagUrl(substituted.url));
2526
+ if (pod) {
2527
+ url.searchParams.set("pmnd", String(pod.pmnd));
2528
+ url.searchParams.set("pmxd", String(pod.pmxd));
2529
+ if (pod.pmad != null) url.searchParams.set("pmad", String(pod.pmad));
2530
+ else url.searchParams.delete("pmad");
2531
+ } else {
2532
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2533
+ try {
2534
+ for(var _iterator = POD_PARAM_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2535
+ var key = _step.value;
2536
+ url.searchParams.delete(key);
2537
+ }
2538
+ } catch (err) {
2539
+ _didIteratorError = true;
2540
+ _iteratorError = err;
2541
+ } finally{
2542
+ try {
2543
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2544
+ _iterator.return();
2545
+ }
2546
+ } finally{
2547
+ if (_didIteratorError) {
2548
+ throw _iteratorError;
2549
+ }
2550
+ }
2551
+ }
2552
+ }
2553
+ finalUrl = url.toString();
2554
+ } catch (unused) {
2555
+ throw podRequestAborted("invalid_url", "GAM request URL could not be parsed", base);
2556
+ }
2557
+ var problems = validateGamRequestUrl(finalUrl, {
2558
+ optimizedPod: !!pod,
2559
+ remainingMs: decision.kind === "send" && decision.source === "break_remaining" ? capacity === null || capacity === void 0 ? void 0 : capacity.remainingAtGamDispatchMs : void 0
2560
+ });
2561
+ if (problems.length > 0) {
2562
+ throw podRequestAborted("invalid_url", problems.join("; "), base);
2563
+ }
2564
+ var givn = null;
2565
+ try {
2566
+ givn = new URL(finalUrl).searchParams.get("givn");
2567
+ } catch (unused) {}
2568
+ return {
2569
+ url: finalUrl,
2570
+ diagnostics: {
2571
+ breakId: ctx.breakId,
2572
+ optimizedPod: !!pod,
2573
+ pmxdSource: decision.kind === "send" ? decision.source : void 0,
2574
+ scteBreakDurationMs: capacity === null || capacity === void 0 ? void 0 : capacity.scheduledBreakDurationMs,
2575
+ elapsedBeforeGamRequestMs: capacity === null || capacity === void 0 ? void 0 : capacity.elapsedBeforeGamRequestMs,
2576
+ remainingAtGamDispatchMs: capacity === null || capacity === void 0 ? void 0 : capacity.remainingAtGamDispatchMs,
2577
+ safetyReserveMs: ctx.config.requestSafetyMs,
2578
+ pmndSent: pod === null || pod === void 0 ? void 0 : pod.pmnd,
2579
+ pmxdSent: pod === null || pod === void 0 ? void 0 : pod.pmxd,
2580
+ pmadSent: pod === null || pod === void 0 ? void 0 : pod.pmad,
2581
+ palNoncePresent: !!givn,
2582
+ gamRequestDispatchTimestamp: new Date(nowEpochMs).toISOString(),
2583
+ strippedMacros: substituted.unresolved.filter(function(name) {
2584
+ return !SCVP_POD_MACROS.has(name);
2585
+ })
2586
+ }
2587
+ };
2588
+ }
2589
+ function validateGamRequestUrl(url, expect) {
2590
+ var problems = [];
2591
+ var leftover = findScvpMacroNames(url);
2592
+ if (leftover.length > 0) problems.push("unresolved SCVP macros: ".concat(leftover.join(", ")));
2593
+ var params;
2594
+ try {
2595
+ params = new URL(url).searchParams;
2596
+ } catch (unused) {
2597
+ return problems.concat("URL could not be parsed");
2598
+ }
2599
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2600
+ try {
2601
+ for(var _iterator = POD_PARAM_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2602
+ var key = _step.value;
2603
+ if (params.getAll(key).length > 1) problems.push("duplicate ".concat(key));
2604
+ }
2605
+ } catch (err) {
2606
+ _didIteratorError = true;
2607
+ _iteratorError = err;
2608
+ } finally{
2609
+ try {
2610
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2611
+ _iterator.return();
2612
+ }
2613
+ } finally{
2614
+ if (_didIteratorError) {
2615
+ throw _iteratorError;
2616
+ }
2617
+ }
2618
+ }
2619
+ if (!expect.optimizedPod) {
2620
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
2621
+ try {
2622
+ for(var _iterator1 = POD_PARAM_KEYS[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
2623
+ var key1 = _step1.value;
2624
+ if (params.has(key1)) problems.push("".concat(key1, " present on a non-pod request"));
2625
+ }
2626
+ } catch (err) {
2627
+ _didIteratorError1 = true;
2628
+ _iteratorError1 = err;
2629
+ } finally{
2630
+ try {
2631
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2632
+ _iterator1.return();
2633
+ }
2634
+ } finally{
2635
+ if (_didIteratorError1) {
2636
+ throw _iteratorError1;
2637
+ }
2638
+ }
2639
+ }
2640
+ return problems;
2641
+ }
2642
+ var pmxd = params.get("pmxd");
2643
+ var pmnd = params.get("pmnd");
2644
+ var pmad = params.get("pmad");
2645
+ if (pmxd == null || !POSITIVE_INT.test(pmxd)) problems.push("pmxd must be a positive integer (got ".concat(pmxd, ")"));
2646
+ if (pmnd == null || !NON_NEGATIVE_INT.test(pmnd)) problems.push("pmnd must be a non-negative integer (got ".concat(pmnd, ")"));
2647
+ if (pmxd != null && pmnd != null && Number(pmnd) > Number(pmxd)) problems.push("pmnd exceeds pmxd");
2648
+ if (pmad != null && !POSITIVE_INT.test(pmad)) problems.push("pmad must be a positive integer or absent (got ".concat(pmad, ")"));
2649
+ if (expect.remainingMs != null && pmxd != null && Number(pmxd) > expect.remainingMs) {
2650
+ problems.push("pmxd ".concat(pmxd, " exceeds remaining break ").concat(expect.remainingMs, "ms"));
2651
+ }
2652
+ return problems;
2653
+ }
2654
+ function computePodResponseDiagnostics(pmxdSent, vastAdCount, totalVastCreativeDurationMs) {
2655
+ var estimatedUnusedPodMs = Math.max(0, pmxdSent - totalVastCreativeDurationMs);
2656
+ return {
2657
+ vastAdCount: vastAdCount,
2658
+ totalVastCreativeDurationMs: totalVastCreativeDurationMs,
2659
+ estimatedUnusedPodMs: estimatedUnusedPodMs,
2660
+ estimatedUnmatchedCount: Math.floor(estimatedUnusedPodMs / GAM_AD_OPPORTUNITY_DURATION_MS)
2661
+ };
2662
+ }
2175
2663
  // src/sdk/hlsAdPlayer.ts
2176
2664
  var LINEAR_TRACKING_EVENTS = [
2177
2665
  "creativeView",
@@ -2252,6 +2740,7 @@ function toVastMediaErrorCode(error) {
2252
2740
  return VAST_ERROR_MEDIA_DISPLAY;
2253
2741
  }
2254
2742
  }
2743
+ var gamCredentialsMode = "include";
2255
2744
  function createHlsAdPlayer(contentVideo, options) {
2256
2745
  var _contentVideo_AD_VIDEO_PROP, _contentVideo_AD_CONTAINER_PROP, _ref;
2257
2746
  var adPlaying = false;
@@ -3123,9 +3612,9 @@ function createHlsAdPlayer(contentVideo, options) {
3123
3612
  }
3124
3613
  }
3125
3614
  function fetchVastXml(vastTagUrl) {
3126
- var credentials = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "include", kind = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "gam";
3615
+ 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;
3127
3616
  return _async_to_generator(function() {
3128
- var controller, timeoutId, startedAt, attempt, requestVast, response, error, error1;
3617
+ var controller, timeoutId, startedAt, attempt, resolveDispatchUrl, requestVast, response, error, error1;
3129
3618
  return _ts_generator(this, function(_state) {
3130
3619
  switch(_state.label){
3131
3620
  case 0:
@@ -3139,13 +3628,32 @@ function createHlsAdPlayer(contentVideo, options) {
3139
3628
  }, VAST_REQUEST_TIMEOUT_MS) : void 0;
3140
3629
  startedAt = Date.now();
3141
3630
  attempt = 0;
3631
+ resolveDispatchUrl = function resolveDispatchUrl() {
3632
+ if (kind === "wrapper") return vastTagUrl;
3633
+ if (finalizeRequestUrl) return finalizeRequestUrl(vastTagUrl, attempt);
3634
+ var _stripScvpMacros = stripScvpMacros(vastTagUrl), url = _stripScvpMacros.url, unresolved = _stripScvpMacros.unresolved;
3635
+ if (unresolved.length > 0) {
3636
+ console.warn("[HlsAdPlayer] Removed unresolved SCVP macros before dispatch:", unresolved.join(", "));
3637
+ }
3638
+ return url;
3639
+ };
3142
3640
  requestVast = function requestVast(creds) {
3143
3641
  return _async_to_generator(function() {
3144
- var response;
3642
+ var pending, response;
3145
3643
  return _ts_generator(this, function(_state) {
3146
3644
  switch(_state.label){
3147
3645
  case 0:
3148
3646
  attempt++;
3647
+ pending = fetch(resolveDispatchUrl(), _object_spread({
3648
+ mode: "cors",
3649
+ credentials: creds,
3650
+ headers: {
3651
+ "Accept": "application/xml, text/xml, */*"
3652
+ },
3653
+ referrerPolicy: "no-referrer-when-downgrade"
3654
+ }, controller ? {
3655
+ signal: controller.signal
3656
+ } : {}));
3149
3657
  if (kind !== "wrapper") {
3150
3658
  logFunnel("".concat(kind, "_http_request_sent"), {
3151
3659
  attempt: attempt,
@@ -3154,16 +3662,7 @@ function createHlsAdPlayer(contentVideo, options) {
3154
3662
  }
3155
3663
  return [
3156
3664
  4,
3157
- fetch(vastTagUrl, _object_spread({
3158
- mode: "cors",
3159
- credentials: creds,
3160
- headers: {
3161
- "Accept": "application/xml, text/xml, */*"
3162
- },
3163
- referrerPolicy: "no-referrer-when-downgrade"
3164
- }, controller ? {
3165
- signal: controller.signal
3166
- } : {}))
3665
+ pending
3167
3666
  ];
3168
3667
  case 1:
3169
3668
  response = _state.sent();
@@ -3187,9 +3686,9 @@ function createHlsAdPlayer(contentVideo, options) {
3187
3686
  case 1:
3188
3687
  _state.trys.push([
3189
3688
  1,
3190
- 10,
3191
- 11,
3192
- 12
3689
+ 7,
3690
+ 8,
3691
+ 9
3193
3692
  ]);
3194
3693
  _state.label = 2;
3195
3694
  case 2:
@@ -3197,7 +3696,7 @@ function createHlsAdPlayer(contentVideo, options) {
3197
3696
  2,
3198
3697
  4,
3199
3698
  ,
3200
- 8
3699
+ 5
3201
3700
  ]);
3202
3701
  return [
3203
3702
  4,
@@ -3207,36 +3706,21 @@ function createHlsAdPlayer(contentVideo, options) {
3207
3706
  response = _state.sent();
3208
3707
  return [
3209
3708
  3,
3210
- 8
3709
+ 5
3211
3710
  ];
3212
3711
  case 4:
3213
3712
  error = _state.sent();
3214
- if (!(credentials !== "omit" && !(controller === null || controller === void 0 ? void 0 : controller.signal.aborted))) return [
3215
- 3,
3216
- 6
3217
- ];
3218
- console.warn('[HlsAdPlayer] VAST fetch failed with credentials="'.concat(credentials, '", retrying without credentials:'), error);
3219
- logFunnel("vast_credentials_retry", {
3220
- errorMessage: error === null || error === void 0 ? void 0 : error.message
3221
- });
3222
- return [
3223
- 4,
3224
- requestVast("omit")
3225
- ];
3226
- case 5:
3227
- response = _state.sent();
3228
- return [
3229
- 3,
3230
- 7
3231
- ];
3232
- case 6:
3713
+ if (kind === "gam" && !(controller === null || controller === void 0 ? void 0 : controller.signal.aborted) && !isPodRequestAbortedError(error)) {
3714
+ gamCredentialsMode = credentials === "include" ? "omit" : "include";
3715
+ console.warn('[HlsAdPlayer] GAM fetch failed with credentials="'.concat(credentials, '"; next GAM request will use credentials="').concat(gamCredentialsMode, '":'), error);
3716
+ logFunnel("gam_credentials_mode_changed", {
3717
+ from: credentials,
3718
+ to: gamCredentialsMode,
3719
+ errorMessage: error === null || error === void 0 ? void 0 : error.message
3720
+ });
3721
+ }
3233
3722
  throw error;
3234
- case 7:
3235
- return [
3236
- 3,
3237
- 8
3238
- ];
3239
- case 8:
3723
+ case 5:
3240
3724
  if (!response.ok) {
3241
3725
  throw new Error("Failed to fetch VAST: HTTP ".concat(response.status, " ").concat(response.statusText));
3242
3726
  }
@@ -3244,12 +3728,12 @@ function createHlsAdPlayer(contentVideo, options) {
3244
3728
  4,
3245
3729
  response.text()
3246
3730
  ];
3247
- case 9:
3731
+ case 6:
3248
3732
  return [
3249
3733
  2,
3250
3734
  _state.sent()
3251
3735
  ];
3252
- case 10:
3736
+ case 7:
3253
3737
  error1 = _state.sent();
3254
3738
  if (controller === null || controller === void 0 ? void 0 : controller.signal.aborted) {
3255
3739
  if (pendingRequestAbortReason) {
@@ -3258,13 +3742,13 @@ function createHlsAdPlayer(contentVideo, options) {
3258
3742
  throw new Error("VAST request timeout after ".concat(VAST_REQUEST_TIMEOUT_MS, "ms: ").concat(vastTagUrl));
3259
3743
  }
3260
3744
  throw error1;
3261
- case 11:
3745
+ case 8:
3262
3746
  if (timeoutId !== void 0) clearTimeout(timeoutId);
3263
3747
  if (controller) pendingVastRequests.delete(controller);
3264
3748
  return [
3265
3749
  7
3266
3750
  ];
3267
- case 12:
3751
+ case 9:
3268
3752
  return [
3269
3753
  2
3270
3754
  ];
@@ -3397,7 +3881,7 @@ function createHlsAdPlayer(contentVideo, options) {
3397
3881
  });
3398
3882
  }
3399
3883
  function fetchAndParsePod(vastTagUrl) {
3400
- var source = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "gam";
3884
+ var source = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "gam", finalizeRequestUrl = arguments.length > 2 ? arguments[2] : void 0;
3401
3885
  return _async_to_generator(function() {
3402
3886
  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;
3403
3887
  return _ts_generator(this, function(_state) {
@@ -3407,7 +3891,7 @@ function createHlsAdPlayer(contentVideo, options) {
3407
3891
  isEdge = source === "edge";
3408
3892
  return [
3409
3893
  4,
3410
- fetchVastXml(vastTagUrl, isEdge ? "omit" : "include", source)
3894
+ fetchVastXml(vastTagUrl, isEdge ? "omit" : gamCredentialsMode, source, finalizeRequestUrl)
3411
3895
  ];
3412
3896
  case 1:
3413
3897
  vastXml = _state.sent();
@@ -4730,7 +5214,7 @@ function createHlsAdPlayer(contentVideo, options) {
4730
5214
  case 2:
4731
5215
  return [
4732
5216
  4,
4733
- fetchAndParsePod(vastTagUrl, source)
5217
+ fetchAndParsePod(vastTagUrl, source, requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.finalizeRequestUrl)
4734
5218
  ];
4735
5219
  case 3:
4736
5220
  ads = _state.sent();
@@ -5307,95 +5791,38 @@ function getOrCreateNonceLoader(allowStorage) {
5307
5791
  function createPalNonceManager() {
5308
5792
  var currentNonce = "";
5309
5793
  var currentNonceManager;
5794
+ var pendingNonce;
5310
5795
  return {
5311
5796
  generateNonce: function generateNonce() {
5312
- return _async_to_generator(function() {
5313
- var options, _options_allowStorage, _options_adWillAutoPlay, _options_adWillPlayMuted, _options_playerVolume, _options_continuousPlayback, loader, goog, request, manager, error;
5314
- var _arguments = arguments;
5315
- return _ts_generator(this, function(_state) {
5316
- switch(_state.label){
5317
- case 0:
5318
- options = _arguments.length > 0 && _arguments[0] !== void 0 ? _arguments[0] : {};
5319
- _state.label = 1;
5320
- case 1:
5321
- _state.trys.push([
5322
- 1,
5323
- 4,
5324
- ,
5325
- 5
5326
- ]);
5327
- return [
5328
- 4,
5329
- loadPalSdk()
5330
- ];
5331
- case 2:
5332
- _state.sent();
5333
- loader = getOrCreateNonceLoader((_options_allowStorage = options.allowStorage) !== null && _options_allowStorage !== void 0 ? _options_allowStorage : true);
5334
- goog = window.goog;
5335
- request = new goog.pal.NonceRequest();
5336
- request.adWillAutoPlay = (_options_adWillAutoPlay = options.adWillAutoPlay) !== null && _options_adWillAutoPlay !== void 0 ? _options_adWillAutoPlay : true;
5337
- request.adWillPlayMuted = (_options_adWillPlayMuted = options.adWillPlayMuted) !== null && _options_adWillPlayMuted !== void 0 ? _options_adWillPlayMuted : false;
5338
- request.playerVolume = (_options_playerVolume = options.playerVolume) !== null && _options_playerVolume !== void 0 ? _options_playerVolume : request.adWillPlayMuted ? 0 : 1;
5339
- request.continuousPlayback = (_options_continuousPlayback = options.continuousPlayback) !== null && _options_continuousPlayback !== void 0 ? _options_continuousPlayback : true;
5340
- request.descriptionUrl = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
5341
- request.iconsSupported = true;
5342
- request.playerType = "StormcloudVideoPlayer";
5343
- request.playerVersion = "1.0";
5344
- request.supportedApiFrameworks = "2,7,9";
5345
- request.url = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
5346
- request.videoWidth = options.videoWidth || 640;
5347
- request.videoHeight = options.videoHeight || 480;
5348
- if (options.ppid) request.ppid = options.ppid;
5349
- if (options.sessionId) request.sessionId = options.sessionId;
5350
- console.log("[PAL] NonceRequest before generateNonce:", JSON.stringify({
5351
- adWillAutoPlay: request.adWillAutoPlay,
5352
- adWillPlayMuted: request.adWillPlayMuted,
5353
- playerVolume: request.playerVolume,
5354
- continuousPlayback: request.continuousPlayback,
5355
- descriptionUrl: request.descriptionUrl,
5356
- iconsSupported: request.iconsSupported,
5357
- playerType: request.playerType,
5358
- playerVersion: request.playerVersion,
5359
- supportedApiFrameworks: request.supportedApiFrameworks,
5360
- url: request.url,
5361
- videoWidth: request.videoWidth,
5362
- videoHeight: request.videoHeight,
5363
- ppid: request.ppid,
5364
- sessionId: request.sessionId
5365
- }, null, 2));
5366
- return [
5367
- 4,
5368
- loader.loadNonceManager(request)
5369
- ];
5370
- case 3:
5371
- manager = _state.sent();
5372
- currentNonceManager = manager;
5373
- currentNonce = manager.getNonce();
5374
- console.log("[PAL] Nonce generated successfully");
5375
- return [
5376
- 2,
5377
- currentNonce
5378
- ];
5379
- case 4:
5380
- error = _state.sent();
5381
- console.warn("[PAL] Failed to generate nonce:", error);
5382
- currentNonce = "";
5383
- currentNonceManager = void 0;
5384
- return [
5385
- 2,
5386
- ""
5387
- ];
5388
- case 5:
5389
- return [
5390
- 2
5391
- ];
5392
- }
5393
- });
5394
- }).apply(this, arguments);
5797
+ var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
5798
+ var run = generate(options);
5799
+ pendingNonce = run;
5800
+ var settle = function settle() {
5801
+ if (pendingNonce === run) pendingNonce = void 0;
5802
+ };
5803
+ run.then(settle, settle);
5804
+ return run;
5395
5805
  },
5396
5806
  getCurrentNonce: function getCurrentNonce() {
5397
5807
  return currentNonce;
5398
5808
  },
5809
+ waitForNonce: function waitForNonce(maxWaitMs) {
5810
+ if (currentNonce) return Promise.resolve(currentNonce);
5811
+ var pending = pendingNonce;
5812
+ if (!pending || !(maxWaitMs > 0)) return Promise.resolve("");
5813
+ return new Promise(function(resolve) {
5814
+ var timer = setTimeout(function() {
5815
+ return resolve(currentNonce);
5816
+ }, maxWaitMs);
5817
+ pending.then(function(nonce) {
5818
+ clearTimeout(timer);
5819
+ resolve(nonce);
5820
+ }, function() {
5821
+ clearTimeout(timer);
5822
+ resolve("");
5823
+ });
5824
+ });
5825
+ },
5399
5826
  injectNonce: function injectNonce(vastTagUrl) {
5400
5827
  if (!currentNonce || !vastTagUrl) return vastTagUrl;
5401
5828
  try {
@@ -5432,8 +5859,90 @@ function createPalNonceManager() {
5432
5859
  reset: function reset() {
5433
5860
  currentNonce = "";
5434
5861
  currentNonceManager = void 0;
5862
+ pendingNonce = void 0;
5435
5863
  }
5436
5864
  };
5865
+ function generate(options) {
5866
+ return _async_to_generator(function() {
5867
+ var _options_allowStorage, _options_adWillAutoPlay, _options_adWillPlayMuted, _options_playerVolume, _options_continuousPlayback, loader, goog, request, manager, error;
5868
+ return _ts_generator(this, function(_state) {
5869
+ switch(_state.label){
5870
+ case 0:
5871
+ _state.trys.push([
5872
+ 0,
5873
+ 3,
5874
+ ,
5875
+ 4
5876
+ ]);
5877
+ return [
5878
+ 4,
5879
+ loadPalSdk()
5880
+ ];
5881
+ case 1:
5882
+ _state.sent();
5883
+ loader = getOrCreateNonceLoader((_options_allowStorage = options.allowStorage) !== null && _options_allowStorage !== void 0 ? _options_allowStorage : true);
5884
+ goog = window.goog;
5885
+ request = new goog.pal.NonceRequest();
5886
+ request.adWillAutoPlay = (_options_adWillAutoPlay = options.adWillAutoPlay) !== null && _options_adWillAutoPlay !== void 0 ? _options_adWillAutoPlay : true;
5887
+ request.adWillPlayMuted = (_options_adWillPlayMuted = options.adWillPlayMuted) !== null && _options_adWillPlayMuted !== void 0 ? _options_adWillPlayMuted : false;
5888
+ request.playerVolume = (_options_playerVolume = options.playerVolume) !== null && _options_playerVolume !== void 0 ? _options_playerVolume : request.adWillPlayMuted ? 0 : 1;
5889
+ request.continuousPlayback = (_options_continuousPlayback = options.continuousPlayback) !== null && _options_continuousPlayback !== void 0 ? _options_continuousPlayback : true;
5890
+ request.descriptionUrl = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
5891
+ request.iconsSupported = true;
5892
+ request.playerType = "StormcloudVideoPlayer";
5893
+ request.playerVersion = "1.0";
5894
+ request.supportedApiFrameworks = "2,7,9";
5895
+ request.url = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
5896
+ request.videoWidth = options.videoWidth || 640;
5897
+ request.videoHeight = options.videoHeight || 480;
5898
+ if (options.ppid) request.ppid = options.ppid;
5899
+ if (options.sessionId) request.sessionId = options.sessionId;
5900
+ console.log("[PAL] NonceRequest before generateNonce:", JSON.stringify({
5901
+ adWillAutoPlay: request.adWillAutoPlay,
5902
+ adWillPlayMuted: request.adWillPlayMuted,
5903
+ playerVolume: request.playerVolume,
5904
+ continuousPlayback: request.continuousPlayback,
5905
+ descriptionUrl: request.descriptionUrl,
5906
+ iconsSupported: request.iconsSupported,
5907
+ playerType: request.playerType,
5908
+ playerVersion: request.playerVersion,
5909
+ supportedApiFrameworks: request.supportedApiFrameworks,
5910
+ url: request.url,
5911
+ videoWidth: request.videoWidth,
5912
+ videoHeight: request.videoHeight,
5913
+ ppid: request.ppid,
5914
+ sessionId: request.sessionId
5915
+ }, null, 2));
5916
+ return [
5917
+ 4,
5918
+ loader.loadNonceManager(request)
5919
+ ];
5920
+ case 2:
5921
+ manager = _state.sent();
5922
+ currentNonceManager = manager;
5923
+ currentNonce = manager.getNonce();
5924
+ console.log("[PAL] Nonce generated successfully");
5925
+ return [
5926
+ 2,
5927
+ currentNonce
5928
+ ];
5929
+ case 3:
5930
+ error = _state.sent();
5931
+ console.warn("[PAL] Failed to generate nonce:", error);
5932
+ currentNonce = "";
5933
+ currentNonceManager = void 0;
5934
+ return [
5935
+ 2,
5936
+ ""
5937
+ ];
5938
+ case 4:
5939
+ return [
5940
+ 2
5941
+ ];
5942
+ }
5943
+ });
5944
+ })();
5945
+ }
5437
5946
  }
5438
5947
  // src/utils/trackingIngest.ts
5439
5948
  var DEFAULT_TRACKING_INGEST_CONFIG = {
@@ -5516,7 +6025,14 @@ function ingestPlayerTracking(licenseKey, channel, body) {
5516
6025
  // src/utils/tracking.ts
5517
6026
  var cachedBrowserId = null;
5518
6027
  function buildAnalyticsContext(config) {
6028
+ var _config_contentNetwork, _config_channelName, _config_programTitle;
5519
6029
  var context = {};
6030
+ var contentNetwork = (_config_contentNetwork = config.contentNetwork) === null || _config_contentNetwork === void 0 ? void 0 : _config_contentNetwork.trim();
6031
+ var contentChannel = (_config_channelName = config.channelName) === null || _config_channelName === void 0 ? void 0 : _config_channelName.trim();
6032
+ var contentTitle = (_config_programTitle = config.programTitle) === null || _config_programTitle === void 0 ? void 0 : _config_programTitle.trim();
6033
+ if (contentNetwork) context.contentNetwork = contentNetwork;
6034
+ if (contentChannel) context.contentChannel = contentChannel;
6035
+ if (contentTitle) context.contentTitle = contentTitle;
5520
6036
  if (config.debugAdTiming) {
5521
6037
  context.debugAdTiming = true;
5522
6038
  }
@@ -6007,12 +6523,19 @@ function sendAdImpressionTracking(_0, _1) {
6007
6523
  4,
6008
6524
  ingestPlayerTracking(licenseKey, "impressions", {
6009
6525
  events: [
6010
- {
6526
+ _object_spread({
6011
6527
  player_id: metricEvent.player_id,
6012
6528
  ad_played_count: 1,
6013
6529
  ad_url: adImpressionInfo.adUrl,
6014
- capture_at: adImpressionInfo.timestamp
6015
- }
6530
+ capture_at: adImpressionInfo.timestamp,
6531
+ source: "gam"
6532
+ }, context.contentNetwork ? {
6533
+ content_network: context.contentNetwork
6534
+ } : {}, context.contentChannel ? {
6535
+ content_channel: context.contentChannel
6536
+ } : {}, context.contentTitle ? {
6537
+ content_title: context.contentTitle
6538
+ } : {})
6016
6539
  ]
6017
6540
  })
6018
6541
  ];
@@ -7361,6 +7884,21 @@ var Scte35CueManager = /*#__PURE__*/ function() {
7361
7884
  return Scte35CueManager;
7362
7885
  }();
7363
7886
  // src/player/AdConfigManager.ts
7887
+ function withDeferredPodParams(rawUrl, deferNonce) {
7888
+ try {
7889
+ var url = new URL(rawUrl);
7890
+ url.searchParams.set("pmnd", "[SCVP-PMND]");
7891
+ url.searchParams.set("pmxd", "[SCVP-PMXD]");
7892
+ url.searchParams.set("pmad", "[SCVP-PMAD]");
7893
+ if (deferNonce && !url.searchParams.get("givn")) {
7894
+ url.searchParams.delete("paln");
7895
+ url.searchParams.set("givn", "[SCVP-GIVN]");
7896
+ }
7897
+ return url.toString();
7898
+ } catch (unused) {
7899
+ return rawUrl;
7900
+ }
7901
+ }
7364
7902
  var AdConfigManager = /*#__PURE__*/ function() {
7365
7903
  function AdConfigManager(config, video) {
7366
7904
  _class_call_check(this, AdConfigManager);
@@ -7371,8 +7909,8 @@ var AdConfigManager = /*#__PURE__*/ function() {
7371
7909
  this.podCounter = 0;
7372
7910
  this.podAssignedByPrefetch = false;
7373
7911
  this.lastHeartbeatTime = 0;
7374
- this.defaultPodMaxAds = 6;
7375
- this.defaultPodMaxDurationMs = 12e4;
7912
+ this.defaultEdgePodMaxAds = 6;
7913
+ this.palNonceDispatchWaitMs = 1500;
7376
7914
  this.config = config;
7377
7915
  this.video = video;
7378
7916
  }
@@ -7400,7 +7938,7 @@ var AdConfigManager = /*#__PURE__*/ function() {
7400
7938
  key: "fetchAdConfiguration",
7401
7939
  value: function fetchAdConfiguration() {
7402
7940
  return _async_to_generator(function() {
7403
- 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;
7941
+ 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;
7404
7942
  return _ts_generator(this, function(_state) {
7405
7943
  switch(_state.label){
7406
7944
  case 0:
@@ -7421,28 +7959,6 @@ var AdConfigManager = /*#__PURE__*/ function() {
7421
7959
  2
7422
7960
  ];
7423
7961
  case 2:
7424
- vastMode = this.config.vastMode || "default";
7425
- if (this.debug) {
7426
- console.log("[StormcloudVideoPlayer] VAST mode:", vastMode);
7427
- }
7428
- if (vastMode === "adstorm") {
7429
- if (!this.config.licenseKey) {
7430
- if (this.debug) {
7431
- console.warn("[StormcloudVideoPlayer] AdStorm mode requires a license key");
7432
- }
7433
- return [
7434
- 2
7435
- ];
7436
- }
7437
- vastEndpoint = "https://adstorm.co/api-adstorm-dev/adstorm/vast/".concat(this.config.licenseKey);
7438
- this.apiVastTagUrl = vastEndpoint;
7439
- if (this.debug) {
7440
- console.log("[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):", vastEndpoint);
7441
- }
7442
- return [
7443
- 2
7444
- ];
7445
- }
7446
7962
  if (this.config.vastTagUrl) {
7447
7963
  this.apiVastTagUrl = normalizeVastTagUrl(this.config.vastTagUrl);
7448
7964
  if (this.debug) {
@@ -7452,7 +7968,7 @@ var AdConfigManager = /*#__PURE__*/ function() {
7452
7968
  2
7453
7969
  ];
7454
7970
  }
7455
- apiUrl = "https://adstorm.co/api-adstorm-dev/adstorm/ads/web";
7971
+ apiUrl = "https://edge.stormcloudhub.com/api/v1/adstorm/ads/web";
7456
7972
  if (this.debug) {
7457
7973
  console.log("[StormcloudVideoPlayer] Fetching ad configuration from:", apiUrl);
7458
7974
  }
@@ -7799,16 +8315,16 @@ var AdConfigManager = /*#__PURE__*/ function() {
7799
8315
  }
7800
8316
  },
7801
8317
  {
7802
- key: "resolvePodParams",
7803
- value: function resolvePodParams(breakDurationMs) {
7804
- var maxDurationMs = breakDurationMs != null && breakDurationMs > 0 ? breakDurationMs : this.config.podMaxDurationMs != null && this.config.podMaxDurationMs > 0 ? this.config.podMaxDurationMs : this.defaultPodMaxDurationMs;
7805
- var maxAds = this.config.podMaxAds && this.config.podMaxAds > 0 ? this.config.podMaxAds : this.apiNumberAds && this.apiNumberAds > 0 ? this.apiNumberAds : this.defaultPodMaxAds;
7806
- var minDurationMs = this.config.podExactDuration && maxDurationMs != null ? maxDurationMs : 0;
7807
- return {
7808
- maxAds: maxAds,
7809
- minDurationMs: minDurationMs,
7810
- maxDurationMs: maxDurationMs
7811
- };
8318
+ key: "resolveAdPodConfig",
8319
+ value: function resolveAdPodConfig1() {
8320
+ return resolveAdPodConfig(this.config);
8321
+ }
8322
+ },
8323
+ {
8324
+ key: "resolveEdgeMaxAds",
8325
+ value: function resolveEdgeMaxAds() {
8326
+ var _this_resolveAdPodConfig_maxAdsPerBreak;
8327
+ 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;
7812
8328
  }
7813
8329
  },
7814
8330
  {
@@ -7825,17 +8341,13 @@ var AdConfigManager = /*#__PURE__*/ function() {
7825
8341
  },
7826
8342
  {
7827
8343
  key: "generatePodVastUrl",
7828
- value: function generatePodVastUrl(baseUrl, podParams, adPlayer, palNonce, inAdBreak) {
7829
- var _podParams_maxDurationMs;
8344
+ value: function generatePodVastUrl(baseUrl, adPlayer, palNonce, inAdBreak) {
7830
8345
  var adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;
7831
8346
  var envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);
7832
- var urlWithMacros = applyVastMacros(baseUrl, _object_spread_props(_object_spread({
8347
+ var macroContext = _object_spread_props(_object_spread({
7833
8348
  correlator: this.viewCorrelator,
7834
8349
  streamCorrelator: this.streamCorrelator,
7835
8350
  pod: this.podCounter > 0 ? this.podCounter : void 0,
7836
- podMaxAds: podParams.maxAds,
7837
- podMinDurationMs: podParams.minDurationMs,
7838
- podMaxDurationMs: podParams.maxDurationMs,
7839
8351
  isCtv: envSignals.isCtv,
7840
8352
  pageUrl: !envSignals.isCtv && typeof window !== "undefined" ? toDevSafeUrl(window.location.href) : void 0,
7841
8353
  adWillPlayMuted: adWillPlayMuted,
@@ -7851,13 +8363,72 @@ var AdConfigManager = /*#__PURE__*/ function() {
7851
8363
  } : {}, this.config.channelName ? {
7852
8364
  channelName: this.config.channelName
7853
8365
  } : {}), {
7854
- consent: this.consentSignals
7855
- }));
7856
- var finalUrl = palNonce.injectNonce(ensureVideoAdType(urlWithMacros));
7857
- 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);
8366
+ consent: this.consentSignals,
8367
+ palNonce: palNonce.getCurrentNonce() || void 0
8368
+ });
8369
+ var nonceReady = !!macroContext.palNonce;
8370
+ var finalUrl;
8371
+ if (hasScvpMacros(baseUrl)) {
8372
+ var deferred = new Set(SCVP_POD_MACROS);
8373
+ if (!nonceReady) deferred.add("GIVN");
8374
+ var _applyScvpMacros = applyScvpMacros(baseUrl, macroContext, deferred), url = _applyScvpMacros.url, unresolved = _applyScvpMacros.unresolved;
8375
+ if (unresolved.length > 0) {
8376
+ console.warn("[StormcloudVideoPlayer] Unresolved SCVP macros (removed from request):", unresolved.join(", "));
8377
+ }
8378
+ finalUrl = ensureVideoAdType(url);
8379
+ } else {
8380
+ finalUrl = withDeferredPodParams(palNonce.injectNonce(ensureVideoAdType(applyVastMacros(baseUrl, macroContext))), !nonceReady);
8381
+ }
8382
+ console.log("[StormcloudVideoPlayer] Prepared optimized-pod request URL (pod=".concat(this.podCounter, "; pmnd/pmxd/pmad resolved at dispatch):"), finalUrl);
7858
8383
  return finalUrl;
7859
8384
  }
7860
8385
  },
8386
+ {
8387
+ key: "completeDeferredRequestSignals",
8388
+ value: function completeDeferredRequestSignals(url, palNonce) {
8389
+ return _async_to_generator(function() {
8390
+ var nonce, _tmp;
8391
+ return _ts_generator(this, function(_state) {
8392
+ switch(_state.label){
8393
+ case 0:
8394
+ if (findScvpMacroNames(url).indexOf("GIVN") === -1) return [
8395
+ 2,
8396
+ url
8397
+ ];
8398
+ _tmp = palNonce.getCurrentNonce();
8399
+ if (_tmp) return [
8400
+ 3,
8401
+ 2
8402
+ ];
8403
+ return [
8404
+ 4,
8405
+ palNonce.waitForNonce(this.palNonceDispatchWaitMs)
8406
+ ];
8407
+ case 1:
8408
+ _tmp = _state.sent();
8409
+ _state.label = 2;
8410
+ case 2:
8411
+ nonce = _tmp;
8412
+ if (!nonce) return [
8413
+ 2,
8414
+ url
8415
+ ];
8416
+ return [
8417
+ 2,
8418
+ substituteScvpMacros(url, /* @__PURE__ */ new Map([
8419
+ [
8420
+ "GIVN",
8421
+ nonce
8422
+ ]
8423
+ ]), function(name) {
8424
+ return name !== "GIVN";
8425
+ }).url
8426
+ ];
8427
+ }
8428
+ });
8429
+ }).call(this);
8430
+ }
8431
+ },
7861
8432
  {
7862
8433
  // --- Tracking ---
7863
8434
  key: "initializeTracking",
@@ -7905,6 +8476,9 @@ var AdConfigManager = /*#__PURE__*/ function() {
7905
8476
  return AdConfigManager;
7906
8477
  }();
7907
8478
  // src/player/AdTimingService.ts
8479
+ function monotonicNow() {
8480
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
8481
+ }
7908
8482
  var AdTimingService = /*#__PURE__*/ function() {
7909
8483
  function AdTimingService(config, video, callbacks) {
7910
8484
  _class_call_check(this, AdTimingService);
@@ -8035,6 +8609,21 @@ var AdTimingService = /*#__PURE__*/ function() {
8035
8609
  },
8036
8610
  {
8037
8611
  // --- Duration boundary ---
8612
+ key: "beginBreakTiming",
8613
+ value: function beginBreakTiming(startWallClockMs) {
8614
+ this.currentAdBreakStartWallClockMs = startWallClockMs;
8615
+ this.breakStartMonoMs = monotonicNow() + (startWallClockMs - Date.now());
8616
+ this.breakEndMonoMs = void 0;
8617
+ }
8618
+ },
8619
+ {
8620
+ key: "markBreakEndedNow",
8621
+ value: function markBreakEndedNow() {
8622
+ this.scteAdBreakEndWallClockMs = Date.now();
8623
+ this.breakEndMonoMs = monotonicNow();
8624
+ }
8625
+ },
8626
+ {
8038
8627
  key: "setAdBreakDurationBoundary",
8039
8628
  value: function setAdBreakDurationBoundary(durationMs) {
8040
8629
  this.expectedAdBreakDurationMs = durationMs;
@@ -8043,6 +8632,18 @@ var AdTimingService = /*#__PURE__*/ function() {
8043
8632
  } else {
8044
8633
  this.scteAdBreakEndWallClockMs = void 0;
8045
8634
  }
8635
+ this.breakEndMonoMs = durationMs != null && this.breakStartMonoMs != null ? this.breakStartMonoMs + durationMs : void 0;
8636
+ }
8637
+ },
8638
+ {
8639
+ key: "getBreakTimingSnapshot",
8640
+ value: function getBreakTimingSnapshot() {
8641
+ return {
8642
+ scheduledBreakDurationMs: this.expectedAdBreakDurationMs,
8643
+ breakStartMonoMs: this.breakStartMonoMs,
8644
+ breakEndMonoMs: this.breakEndMonoMs,
8645
+ playedDurationMs: this.adBreakPlayedDurationMs
8646
+ };
8046
8647
  }
8047
8648
  },
8048
8649
  {
@@ -8456,6 +9057,8 @@ var AdTimingService = /*#__PURE__*/ function() {
8456
9057
  this.expectedAdBreakDurationMs = void 0;
8457
9058
  this.currentAdBreakStartWallClockMs = void 0;
8458
9059
  this.scteAdBreakEndWallClockMs = void 0;
9060
+ this.breakStartMonoMs = void 0;
9061
+ this.breakEndMonoMs = void 0;
8459
9062
  this.adBreakPlayedDurationMs = 0;
8460
9063
  this.currentAdIndex = 0;
8461
9064
  this.totalAdsInBreak = 0;
@@ -9469,9 +10072,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9469
10072
  // ───────────────────────────────────────────────────────────────
9470
10073
  key: "nextAdRequestUrl",
9471
10074
  value: function nextAdRequestUrl(baseVastUrl) {
9472
- var remaining = Math.min(this.timing.getWallClockRemainingAdMs(), this.timing.getDurationBudgetRemainingMs());
9473
- var breakDurationMs = remaining > 0 ? remaining : void 0;
9474
- return this.host.generatePodVastUrl(baseVastUrl, breakDurationMs);
10075
+ return this.host.generatePodVastUrl(baseVastUrl);
9475
10076
  }
9476
10077
  },
9477
10078
  {
@@ -9734,7 +10335,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9734
10335
  key: "handleAdStart",
9735
10336
  value: function handleAdStart(marker) {
9736
10337
  return _async_to_generator(function() {
9737
- var baseVastUrl, edgeConfigured, adBreakDurationMs, currentMuted, currentVolume, epoch, hasPrefetchedUrl, mode, edgeUrl, outcome, podPlayed;
10338
+ var baseVastUrl, edgeConfigured, adBreakDurationMs, currentMuted, currentVolume, epoch, mode, edgeUrl, outcome, podPlayed;
9738
10339
  return _ts_generator(this, function(_state) {
9739
10340
  switch(_state.label){
9740
10341
  case 0:
@@ -9786,8 +10387,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9786
10387
  }
9787
10388
  this.noteOpportunity("scte35", this.cueManager.activeScte35BreakKey, "midroll");
9788
10389
  epoch = this.timing.adBreakEpoch;
9789
- hasPrefetchedUrl = !!(this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0);
9790
- if (!(adBreakDurationMs == null && (!hasPrefetchedUrl || edgeConfigured))) return [
10390
+ if (!(adBreakDurationMs == null)) return [
9791
10391
  3,
9792
10392
  2
9793
10393
  ];
@@ -9843,7 +10443,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9843
10443
  }
9844
10444
  return [
9845
10445
  4,
9846
- this.startOptimizedPod(baseVastUrl, adBreakDurationMs)
10446
+ this.startOptimizedPod(baseVastUrl)
9847
10447
  ];
9848
10448
  case 6:
9849
10449
  podPlayed = _state.sent();
@@ -9911,9 +10511,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9911
10511
  value: // ───────────────────────────────────────────────────────────────
9912
10512
  // Optimized pod (single multi-ad request)
9913
10513
  // ───────────────────────────────────────────────────────────────
9914
- function startOptimizedPod(baseVastUrl, breakDurationMs) {
10514
+ function startOptimizedPod(baseVastUrl) {
9915
10515
  return _async_to_generator(function() {
9916
- var podUrl, prefetched, epoch, generation, adPlayer, requestToken, requestUrl, _ref, _adPlayer_getPodAdCount, podCount, error;
10516
+ var podUrl, prefetched, epoch, generation, adPlayer, requestToken, requestUrl, _ref, _this_currentVastUrl, _adPlayer_getPodAdCount, finalizeRequestUrl, podCount, error;
9917
10517
  return _ts_generator(this, function(_state) {
9918
10518
  switch(_state.label){
9919
10519
  case 0:
@@ -9922,7 +10522,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9922
10522
  podUrl = this.pendingAdBreak.vastUrls[0];
9923
10523
  this.clearPendingAdBreak();
9924
10524
  } else {
9925
- podUrl = this.host.generatePodVastUrl(baseVastUrl, breakDurationMs);
10525
+ podUrl = this.host.generatePodVastUrl(baseVastUrl);
9926
10526
  }
9927
10527
  if (!podUrl) {
9928
10528
  return [
@@ -9946,9 +10546,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9946
10546
  case 1:
9947
10547
  _state.trys.push([
9948
10548
  1,
9949
- 5,
10549
+ 9,
9950
10550
  ,
9951
- 6
10551
+ 10
9952
10552
  ]);
9953
10553
  return [
9954
10554
  4,
@@ -9960,15 +10560,46 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9960
10560
  2,
9961
10561
  true
9962
10562
  ];
10563
+ return [
10564
+ 4,
10565
+ this.host.completeGamRequestSignals(requestUrl)
10566
+ ];
10567
+ case 3:
10568
+ requestUrl = _state.sent();
10569
+ if (this.isStale(epoch, generation)) return [
10570
+ 2,
10571
+ true
10572
+ ];
9963
10573
  this.timing.startAdRequestWatchdog(requestToken);
10574
+ finalizeRequestUrl = this.createGamDispatchFinalizer(requestToken);
10575
+ _state.label = 4;
10576
+ case 4:
10577
+ _state.trys.push([
10578
+ 4,
10579
+ ,
10580
+ 6,
10581
+ 7
10582
+ ]);
9964
10583
  return [
9965
10584
  4,
9966
10585
  this.callController(function() {
9967
- return adPlayer.requestAds(requestUrl);
10586
+ return adPlayer.requestAds(requestUrl, {
10587
+ finalizeRequestUrl: finalizeRequestUrl
10588
+ });
9968
10589
  })
9969
10590
  ];
9970
- case 3:
10591
+ case 5:
9971
10592
  _state.sent();
10593
+ return [
10594
+ 3,
10595
+ 7
10596
+ ];
10597
+ case 6:
10598
+ this.recordPodResponseDiagnostics(requestToken, adPlayer);
10599
+ return [
10600
+ 7
10601
+ ];
10602
+ case 7:
9972
10603
  this.timing.clearAdRequestWatchdog();
9973
10604
  if (this.isStale(epoch, generation)) {
9974
10605
  this.logOrchestratorFunnel("stale_request_result_ignored", {
@@ -9996,7 +10627,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9996
10627
  }
9997
10628
  sendAdLoadedTracking(this.host.config.licenseKey, {
9998
10629
  source: "hls",
9999
- vastUrl: requestUrl,
10630
+ vastUrl: (_this_currentVastUrl = this.currentVastUrl) !== null && _this_currentVastUrl !== void 0 ? _this_currentVastUrl : requestUrl,
10000
10631
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
10001
10632
  }, this.analyticsContext).catch(function() {});
10002
10633
  this.timing.startAdFailsafeTimer(requestToken);
@@ -10006,7 +10637,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10006
10637
  return adPlayer.play();
10007
10638
  })
10008
10639
  ];
10009
- case 4:
10640
+ case 8:
10010
10641
  _state.sent();
10011
10642
  if (this.isStale(epoch, generation)) return [
10012
10643
  2,
@@ -10020,7 +10651,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10020
10651
  2,
10021
10652
  true
10022
10653
  ];
10023
- case 5:
10654
+ case 9:
10024
10655
  error = _state.sent();
10025
10656
  this.timing.clearAdRequestWatchdog();
10026
10657
  this.timing.clearAdFailsafeTimer();
@@ -10040,12 +10671,16 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10040
10671
  if (this.debug) {
10041
10672
  console.warn("[POD] Optimized pod request/play failed:", error);
10042
10673
  }
10674
+ if (this.handlePodRequestNotSent(error)) return [
10675
+ 2,
10676
+ false
10677
+ ];
10043
10678
  this.recordRequestFailure(error, podUrl);
10044
10679
  return [
10045
10680
  2,
10046
10681
  false
10047
10682
  ];
10048
- case 6:
10683
+ case 10:
10049
10684
  return [
10050
10685
  2
10051
10686
  ];
@@ -10091,17 +10726,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10091
10726
  }
10092
10727
  },
10093
10728
  {
10094
- /**
10095
- * Builds the next Edge request from the budget left right now, or marks Edge
10096
- * exhausted for this break. Synchronous on purpose: callers must reach the
10097
- * REQUESTING state in the same tick so a second completion event cannot race
10098
- * in a parallel request.
10099
- */ key: "prepareEdgePodRequest",
10729
+ key: "prepareEdgePodRequest",
10100
10730
  value: function prepareEdgePodRequest() {
10101
10731
  var baseUrl = this.host.getEdgePodBaseUrl();
10102
10732
  if (!baseUrl) return void 0;
10103
10733
  var remainingMs = this.timing.getRemainingAdMs();
10104
- var remainingAds = Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak);
10734
+ var remainingAds = Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolveEdgeMaxAds() - this.timing.totalAdsInBreak);
10105
10735
  if (remainingAds < 1) {
10106
10736
  this.markEdgeExhausted("ad_capacity_reached", {
10107
10737
  adsInBreak: this.timing.totalAdsInBreak
@@ -10126,7 +10756,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10126
10756
  key: "runEdgePod",
10127
10757
  value: function runEdgePod(requestUrl, trigger) {
10128
10758
  return _async_to_generator(function() {
10129
- var _params_get, _params_get1, epoch, generation, adPlayer, requestToken, params, _ref, _adPlayer_getPodAdCount, _adPlayer_getPodTotalDurationMs, remainingMs, remainingAds, podCount, error, errorMessage, classification, diag;
10759
+ var _params_get, _params_get1, epoch, generation, adPlayer, requestToken, params, _this_host_config_maxAdBreakExtensionMs, _ref, _adPlayer_getPodAdCount, _adPlayer_getPodTotalDurationMs, remainingMs, remainingAds, overrunAllowanceMs, podCount, error, errorMessage, classification, diag;
10130
10760
  return _ts_generator(this, function(_state) {
10131
10761
  switch(_state.label){
10132
10762
  case 0:
@@ -10180,8 +10810,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10180
10810
  ];
10181
10811
  }
10182
10812
  remainingMs = this.timing.getRemainingAdMs();
10183
- remainingAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak));
10184
- podCount = adPlayer.limitPodToBudget ? adPlayer.limitPodToBudget(remainingMs, remainingAds) : (_ref = (_adPlayer_getPodAdCount = adPlayer.getPodAdCount) === null || _adPlayer_getPodAdCount === void 0 ? void 0 : _adPlayer_getPodAdCount.call(adPlayer)) !== null && _ref !== void 0 ? _ref : 0;
10813
+ remainingAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolveEdgeMaxAds() - this.timing.totalAdsInBreak));
10814
+ overrunAllowanceMs = Math.max(0, (_this_host_config_maxAdBreakExtensionMs = this.host.config.maxAdBreakExtensionMs) !== null && _this_host_config_maxAdBreakExtensionMs !== void 0 ? _this_host_config_maxAdBreakExtensionMs : 0);
10815
+ 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;
10185
10816
  if (classifyEdgeVastResponse({
10186
10817
  podAdCount: podCount
10187
10818
  }) !== "fill") {
@@ -10191,7 +10822,8 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10191
10822
  this.logOrchestratorFunnel("edge_fill", {
10192
10823
  podAdCount: podCount,
10193
10824
  podDurationMs: (_adPlayer_getPodTotalDurationMs = adPlayer.getPodTotalDurationMs) === null || _adPlayer_getPodTotalDurationMs === void 0 ? void 0 : _adPlayer_getPodTotalDurationMs.call(adPlayer),
10194
- remainingMs: remainingMs
10825
+ remainingMs: remainingMs,
10826
+ overrunAllowanceMs: overrunAllowanceMs
10195
10827
  });
10196
10828
  sendAdLoadedTracking(this.host.config.licenseKey, {
10197
10829
  source: "hls",
@@ -10525,7 +11157,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10525
11157
  {
10526
11158
  key: "noteVastUrlGenerated",
10527
11159
  value: function noteVastUrlGenerated(url, source) {
10528
- var _ref, _ref1, _ref2, _ref3, _ref4;
11160
+ var _ref, _ref1;
10529
11161
  var params;
10530
11162
  try {
10531
11163
  params = new URL(url).searchParams;
@@ -10535,9 +11167,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10535
11167
  requestId: void 0,
10536
11168
  source: source,
10537
11169
  pod: (_ref1 = params === null || params === void 0 ? void 0 : params.get("pod")) !== null && _ref1 !== void 0 ? _ref1 : void 0,
10538
- pmad: (_ref2 = params === null || params === void 0 ? void 0 : params.get("pmad")) !== null && _ref2 !== void 0 ? _ref2 : void 0,
10539
- pmnd: (_ref3 = params === null || params === void 0 ? void 0 : params.get("pmnd")) !== null && _ref3 !== void 0 ? _ref3 : void 0,
10540
- pmxd: (_ref4 = params === null || params === void 0 ? void 0 : params.get("pmxd")) !== null && _ref4 !== void 0 ? _ref4 : void 0,
11170
+ podParamsDeferredToDispatch: findScvpMacroNames(url).some(function(name) {
11171
+ return SCVP_POD_MACROS.has(name);
11172
+ }),
10541
11173
  adType: adType
10542
11174
  });
10543
11175
  if (adType === "audio" || adType === "audio_video") {
@@ -10578,10 +11210,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10578
11210
  if (diag && !diag.failureReason) {
10579
11211
  diag.failureReason = "".concat(outcome, ": ").concat(message);
10580
11212
  }
11213
+ var failureKey = (diag === null || diag === void 0 ? void 0 : diag.dispatchedUrl) && findScvpMacroNames(vastTagUrl).some(function(name) {
11214
+ return SCVP_POD_MACROS.has(name);
11215
+ }) ? diag.dispatchedUrl : vastTagUrl;
10581
11216
  if (this.timing.isTemporaryAdError(error)) {
10582
- this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());
11217
+ this.timing.temporaryFailureUrls.set(failureKey, Date.now());
10583
11218
  } else if (outcome !== "discarded_budget") {
10584
- this.timing.failedVastUrls.add(vastTagUrl);
11219
+ this.timing.failedVastUrls.add(failureKey);
10585
11220
  }
10586
11221
  this.countFunnelStage("request_outcome:".concat(outcome));
10587
11222
  this.logOrchestratorFunnel("request_outcome", _object_spread({
@@ -10607,6 +11242,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10607
11242
  switch(payload.stage){
10608
11243
  case "gam_http_request_sent":
10609
11244
  diag.gamRequestSent++;
11245
+ this.logPodDispatch(diag);
10610
11246
  break;
10611
11247
  case "edge_http_request_sent":
10612
11248
  diag.edgeRequestSent++;
@@ -10658,8 +11294,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10658
11294
  if (gamReturnedAdWithoutImpression) {
10659
11295
  this.countFunnelStage("gam_ad_without_impression");
10660
11296
  }
10661
- var startedAt = diag.startedAt, fields = _object_without_properties(diag, [
10662
- "startedAt"
11297
+ var startedAt = diag.startedAt, _dispatchedUrl = diag.dispatchedUrl, _logged = diag.podDispatchLogged, fields = _object_without_properties(diag, [
11298
+ "startedAt",
11299
+ "dispatchedUrl",
11300
+ "podDispatchLogged"
10663
11301
  ]);
10664
11302
  console.log("[AdBreak][REQUEST] summary", _object_spread_props(_object_spread({}, fields), {
10665
11303
  durationMs: Date.now() - startedAt,
@@ -10671,24 +11309,71 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10671
11309
  // ───────────────────────────────────────────────────────────────
10672
11310
  // Single ad playback
10673
11311
  // ───────────────────────────────────────────────────────────────
10674
- key: "withCurrentPodBudget",
10675
- value: function withCurrentPodBudget(rawVastTagUrl) {
10676
- var vastTagUrl = ensureVideoAdType(rawVastTagUrl);
10677
- var remaining = Math.min(this.timing.getWallClockRemainingAdMs(), this.timing.getDurationBudgetRemainingMs());
10678
- if (!(remaining > 0)) return vastTagUrl;
10679
- try {
10680
- var url = new URL(vastTagUrl);
10681
- if (!url.searchParams.has("pmxd")) return vastTagUrl;
10682
- var maxMs = Math.round(remaining);
10683
- url.searchParams.set("pmxd", String(maxMs));
10684
- var minMs = Number(url.searchParams.get("pmnd"));
10685
- if (Number.isFinite(minMs) && minMs > maxMs) {
10686
- url.searchParams.set("pmnd", String(maxMs));
10687
- }
10688
- return url.toString();
10689
- } catch (unused) {
10690
- return vastTagUrl;
10691
- }
11312
+ key: "createGamDispatchFinalizer",
11313
+ value: function createGamDispatchFinalizer(requestToken) {
11314
+ var _this = this;
11315
+ var breakId = this.timing.adBreakEpoch;
11316
+ var config = this.adConfig.resolveAdPodConfig();
11317
+ var minUsablePmxdMs = this.timing.getMinRemainingMsToStartAd();
11318
+ return function(url) {
11319
+ var capacity = measureBreakCapacity(_this.timing.getBreakTimingSnapshot(), monotonicNow());
11320
+ var diag = _this.requestDiagnostics.get(requestToken);
11321
+ try {
11322
+ var result = finalizeGamRequestUrl(url, {
11323
+ breakId: breakId,
11324
+ capacity: capacity,
11325
+ config: config,
11326
+ minUsablePmxdMs: minUsablePmxdMs
11327
+ });
11328
+ if (diag) {
11329
+ diag.pod = result.diagnostics;
11330
+ diag.dispatchedUrl = result.url;
11331
+ diag.podDispatchLogged = false;
11332
+ }
11333
+ _this.currentVastUrl = result.url;
11334
+ return result.url;
11335
+ } catch (error) {
11336
+ if (diag && isPodRequestAbortedError(error)) {
11337
+ diag.failureReason = "pod_request_not_sent:".concat(error.reason);
11338
+ }
11339
+ throw error;
11340
+ }
11341
+ };
11342
+ }
11343
+ },
11344
+ {
11345
+ key: "logPodDispatch",
11346
+ value: function logPodDispatch(diag) {
11347
+ if (!diag.pod || diag.podDispatchLogged) return;
11348
+ diag.podDispatchLogged = true;
11349
+ this.logOrchestratorFunnel(diag.pod.optimizedPod ? "optimized_pod_request_dispatched" : "gam_request_dispatched", _object_spread({}, diag.pod));
11350
+ }
11351
+ },
11352
+ {
11353
+ key: "recordPodResponseDiagnostics",
11354
+ value: function recordPodResponseDiagnostics(requestToken, adPlayer) {
11355
+ var _diag_vastAdCount, _ref;
11356
+ var _adPlayer_getPodTotalDurationMs;
11357
+ var diag = this.requestDiagnostics.get(requestToken);
11358
+ if (!(diag === null || diag === void 0 ? void 0 : diag.pod) || diag.pod.pmxdSent == null || diag.podResponse) return;
11359
+ if (diag.gamRequestSent === 0 && diag.vastHttpStatus == null) return;
11360
+ 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);
11361
+ this.logOrchestratorFunnel("optimized_pod_response", _object_spread({
11362
+ pmxdSent: diag.pod.pmxdSent
11363
+ }, diag.podResponse));
11364
+ }
11365
+ },
11366
+ {
11367
+ key: "handlePodRequestNotSent",
11368
+ value: function handlePodRequestNotSent(error) {
11369
+ if (!isPodRequestAbortedError(error) || error.reason === "invalid_url") return false;
11370
+ var aborted = error;
11371
+ this.countFunnelStage("request_outcome:pod_request_not_sent");
11372
+ this.logOrchestratorFunnel("pod_request_not_sent", _object_spread({
11373
+ reason: aborted.reason,
11374
+ errorMessage: aborted.message
11375
+ }, aborted.diagnostics));
11376
+ return true;
10692
11377
  }
10693
11378
  },
10694
11379
  {
@@ -10908,7 +11593,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10908
11593
  value: function playSingleAd(vastTagUrl) {
10909
11594
  var trigger = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "vmap";
10910
11595
  return _async_to_generator(function() {
10911
- var epoch, generation, requestToken, ap, budgetedUrl, requestUrl, _ap_getLoadedAdDuration, adDurationS, remainingMs, error;
11596
+ var epoch, generation, requestToken, ap, requestUrl, _this_currentVastUrl, finalizeRequestUrl, _ap_getLoadedAdDuration, adDurationS, remainingMs, error;
10912
11597
  return _ts_generator(this, function(_state) {
10913
11598
  switch(_state.label){
10914
11599
  case 0:
@@ -10946,19 +11631,18 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10946
11631
  requestToken = ++this.timing.adRequestTokenCounter;
10947
11632
  this.timing.activeAdRequestToken = requestToken;
10948
11633
  ap = this.host.getAdPlayer();
10949
- budgetedUrl = this.withCurrentPodBudget(vastTagUrl);
10950
11634
  this.currentPodSource = "gam";
10951
11635
  this.setSlotState("REQUESTING", trigger);
10952
11636
  this.beginFunnelRequest(ap, requestToken, trigger);
10953
- requestUrl = this.applyOpportunityFloor(budgetedUrl);
11637
+ requestUrl = this.applyOpportunityFloor(ensureVideoAdType(vastTagUrl));
10954
11638
  this.currentVastUrl = requestUrl;
10955
11639
  _state.label = 1;
10956
11640
  case 1:
10957
11641
  _state.trys.push([
10958
11642
  1,
10959
- 5,
11643
+ 9,
10960
11644
  ,
10961
- 6
11645
+ 10
10962
11646
  ]);
10963
11647
  return [
10964
11648
  4,
@@ -10969,15 +11653,45 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10969
11653
  if (this.isStale(epoch, generation)) return [
10970
11654
  2
10971
11655
  ];
11656
+ return [
11657
+ 4,
11658
+ this.host.completeGamRequestSignals(requestUrl)
11659
+ ];
11660
+ case 3:
11661
+ requestUrl = _state.sent();
11662
+ if (this.isStale(epoch, generation)) return [
11663
+ 2
11664
+ ];
10972
11665
  this.timing.startAdRequestWatchdog(requestToken);
11666
+ finalizeRequestUrl = this.createGamDispatchFinalizer(requestToken);
11667
+ _state.label = 4;
11668
+ case 4:
11669
+ _state.trys.push([
11670
+ 4,
11671
+ ,
11672
+ 6,
11673
+ 7
11674
+ ]);
10973
11675
  return [
10974
11676
  4,
10975
11677
  this.callController(function() {
10976
- return ap.requestAds(requestUrl);
11678
+ return ap.requestAds(requestUrl, {
11679
+ finalizeRequestUrl: finalizeRequestUrl
11680
+ });
10977
11681
  })
10978
11682
  ];
10979
- case 3:
11683
+ case 5:
10980
11684
  _state.sent();
11685
+ return [
11686
+ 3,
11687
+ 7
11688
+ ];
11689
+ case 6:
11690
+ this.recordPodResponseDiagnostics(requestToken, ap);
11691
+ return [
11692
+ 7
11693
+ ];
11694
+ case 7:
10981
11695
  this.timing.clearAdRequestWatchdog();
10982
11696
  if (this.isStale(epoch, generation)) {
10983
11697
  this.logOrchestratorFunnel("stale_request_result_ignored", {
@@ -10989,7 +11703,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10989
11703
  }
10990
11704
  sendAdLoadedTracking(this.host.config.licenseKey, {
10991
11705
  source: "hls",
10992
- vastUrl: requestUrl,
11706
+ vastUrl: (_this_currentVastUrl = this.currentVastUrl) !== null && _this_currentVastUrl !== void 0 ? _this_currentVastUrl : requestUrl,
10993
11707
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
10994
11708
  }, this.analyticsContext).catch(function() {});
10995
11709
  if (!this.timing.ensureLoadedAdFitsBudget(ap)) {
@@ -11010,7 +11724,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11010
11724
  return ap.play();
11011
11725
  })
11012
11726
  ];
11013
- case 4:
11727
+ case 8:
11014
11728
  _state.sent();
11015
11729
  if (this.isStale(epoch, generation)) return [
11016
11730
  2
@@ -11022,9 +11736,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11022
11736
  this.timing.temporaryFailureUrls.delete(vastTagUrl);
11023
11737
  return [
11024
11738
  3,
11025
- 6
11739
+ 10
11026
11740
  ];
11027
- case 5:
11741
+ case 9:
11028
11742
  error = _state.sent();
11029
11743
  this.timing.clearAdRequestWatchdog();
11030
11744
  this.timing.clearAdFailsafeTimer();
@@ -11041,12 +11755,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11041
11755
  ];
11042
11756
  }
11043
11757
  if (this.debug) console.error("[AD-ERROR] Ad request failed:", error === null || error === void 0 ? void 0 : error.message);
11758
+ if (this.handlePodRequestNotSent(error)) throw error;
11044
11759
  this.recordRequestFailure(error, vastTagUrl);
11045
11760
  if ((error === null || error === void 0 ? void 0 : error.message) === "ad_duration_exceeds_budget") {
11046
11761
  this.recreateAdController("discarded_budget");
11047
11762
  }
11048
11763
  throw error;
11049
- case 6:
11764
+ case 10:
11050
11765
  return [
11051
11766
  2
11052
11767
  ];
@@ -11108,7 +11823,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11108
11823
  playbackFailedAfterFill: count("request_outcome:playback_failed"),
11109
11824
  requestFailed: count("request_failed"),
11110
11825
  requestAbortedTimeout: count("request_aborted_timeout"),
11111
- credentialsRetries: count("vast_credentials_retry"),
11826
+ credentialsModeChanges: count("gam_credentials_mode_changed"),
11112
11827
  wrapperFailures: count("wrapper_fetch:failure"),
11113
11828
  noSupportedMedia: count("vast_no_supported_media"),
11114
11829
  vpaidOnly: count("vast_no_supported_media:vpaid"),
@@ -11644,8 +12359,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11644
12359
  requiresMediaPipelineResetAfterAds: function requiresMediaPipelineResetAfterAds1() {
11645
12360
  return requiresMediaPipelineResetAfterAds();
11646
12361
  },
11647
- generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
11648
- return _this.generatePodVastUrl(base, breakDurationMs);
12362
+ generatePodVastUrl: function generatePodVastUrl(base) {
12363
+ return _this.generatePodVastUrl(base);
12364
+ },
12365
+ completeGamRequestSignals: function completeGamRequestSignals(url) {
12366
+ return _this.adConfig.completeDeferredRequestSignals(url, _this.palNonce);
11649
12367
  },
11650
12368
  getEdgePodBaseUrl: function getEdgePodBaseUrl() {
11651
12369
  return _this.edgePodBaseUrl;
@@ -11769,9 +12487,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11769
12487
  },
11770
12488
  {
11771
12489
  key: "generatePodVastUrl",
11772
- value: function generatePodVastUrl(baseUrl, breakDurationMs) {
11773
- var podParams = this.adConfig.resolvePodParams(breakDurationMs);
11774
- return this.adConfig.generatePodVastUrl(baseUrl, podParams, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
12490
+ value: function generatePodVastUrl(baseUrl) {
12491
+ return this.adConfig.generatePodVastUrl(baseUrl, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
11775
12492
  }
11776
12493
  },
11777
12494
  {
@@ -12125,7 +12842,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12125
12842
  activeAdRequest: this.timing.activeAdRequestToken !== null
12126
12843
  });
12127
12844
  }
12128
- this.timing.scteAdBreakEndWallClockMs = Date.now();
12845
+ this.timing.markBreakEndedNow();
12129
12846
  this.timing.clearAdStartTimer();
12130
12847
  this.timing.clearAdStopTimer();
12131
12848
  if (adPlaying) {
@@ -12152,7 +12869,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12152
12869
  this.adBreak.inAdBreak = true;
12153
12870
  this.cueManager.activeScte35BreakKey = cueKey !== null && cueKey !== void 0 ? cueKey : this.cueManager.pendingScte35CueKey;
12154
12871
  this.cueManager.scheduledScte35BreakKey = void 0;
12155
- this.timing.currentAdBreakStartWallClockMs = this.timing.resolveScteBreakStartWallClockMs(marker);
12872
+ this.timing.beginBreakTiming(this.timing.resolveScteBreakStartWallClockMs(marker));
12156
12873
  this.timing.setAdBreakDurationBoundary(durationMs);
12157
12874
  this.adBreak.handleAdStart(marker);
12158
12875
  this.timing.scheduleAdStopAtBreakBoundary();
@@ -12198,9 +12915,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12198
12915
  }
12199
12916
  this.adConfig.beginNewAdPod();
12200
12917
  this.adConfig.podAssignedByPrefetch = true;
12201
- var breakDurationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0;
12202
12918
  var generatedUrls = [
12203
- this.generatePodVastUrl(baseVastUrl, breakDurationMs)
12919
+ this.generatePodVastUrl(baseVastUrl)
12204
12920
  ];
12205
12921
  this.adBreak.pendingAdBreak = _object_spread_props(_object_spread({
12206
12922
  marker: marker
@@ -12299,7 +13015,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12299
13015
  this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);
12300
13016
  this.adBreak.showAds = true;
12301
13017
  this.adBreak.inAdBreak = true;
12302
- this.timing.currentAdBreakStartWallClockMs = Date.now();
13018
+ this.timing.beginBreakTiming(Date.now());
12303
13019
  if (durationMs > 0) {
12304
13020
  this.timing.setAdBreakDurationBoundary(durationMs);
12305
13021
  }