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