stormcloud-video-player 0.8.73 → 0.8.75

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 +2 -1
  4. package/lib/StormcloudPlayer.cjs +988 -273
  5. package/lib/StormcloudPlayer.cjs.map +1 -1
  6. package/lib/StormcloudPlayer.d.cts +1 -0
  7. package/lib/index.cjs +999 -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 +992 -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 +315 -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 +988 -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 +988 -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 +988 -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 +991 -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 +251 -10
  59. package/lib/utils/vastMacros.cjs.map +1 -1
  60. package/lib/utils/vastMacros.d.cts +13 -4
  61. package/package.json +5 -3
package/lib/index.js CHANGED
@@ -363,21 +363,20 @@ var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
363
363
  "adid"
364
364
  ]);
365
365
  function resolveVastEnvironmentSignals(isCtv) {
366
- var _ref;
367
366
  var bridgeSignals = readNativeBridgeSignals();
368
367
  var platformDevice = readPlatformNativeDeviceId();
369
- var realDeviceId = bridgeSignals.deviceId || (isCtv ? readStoredDeviceId() : void 0) || platformDevice.deviceId;
368
+ var bridgeDeviceId = validDeviceId(bridgeSignals.deviceId);
369
+ var realDeviceId = bridgeDeviceId || (isCtv ? validDeviceId(readStoredDeviceId()) : void 0) || validDeviceId(platformDevice.deviceId);
370
370
  var deviceId = realDeviceId;
371
- var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || platformDevice.deviceIdType || inferDeviceIdType();
372
- var platformLat = bridgeSignals.deviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;
373
- var limitAdTracking = deviceId != null ? (_ref = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false : void 0;
371
+ var deviceIdType = (bridgeDeviceId ? bridgeSignals.deviceIdType : void 0) || readStoredString("deviceIdType") || readStoredString("idtype") || platformDevice.deviceIdType || inferDeviceIdType();
372
+ var platformLat = bridgeDeviceId ? bridgeSignals.limitAdTracking : platformDevice.limitAdTracking;
373
+ var limitAdTracking = deviceId != null ? platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking() : void 0;
374
374
  if (!deviceId && isCtv) {
375
375
  var dpid = getOrCreateStoredUuid(PLAYER_ID_STORAGE_KEY);
376
376
  if (dpid) {
377
- var _ref1;
378
377
  deviceId = dpid;
379
378
  deviceIdType = "dpid";
380
- limitAdTracking = (_ref1 = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking()) !== null && _ref1 !== void 0 ? _ref1 : false;
379
+ limitAdTracking = platformLat !== null && platformLat !== void 0 ? platformLat : readStoredLimitAdTracking();
381
380
  }
382
381
  }
383
382
  var deviceTypeHint = resolveDeviceTypeHint(isCtv);
@@ -742,6 +741,9 @@ function isMacroPlaceholder(value) {
742
741
  var t = value.trim();
743
742
  return !t || /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/.test(t) || /^(unknown|null|undefined|none|n\/a|\$\{[^}]+\})$/i.test(t) || ZEROED_AD_ID_PATTERNS.has(t.toLowerCase());
744
743
  }
744
+ function validDeviceId(value) {
745
+ return value && !isMacroPlaceholder(value) ? value : void 0;
746
+ }
745
747
  function isZeroedAdId(value) {
746
748
  return ZEROED_AD_ID_PATTERNS.has(value.trim().toLowerCase());
747
749
  }
@@ -1274,6 +1276,199 @@ function ensureVideoAdType(rawUrl) {
1274
1276
  return rawUrl;
1275
1277
  }
1276
1278
  }
1279
+ var SCVP_MACRO_DETECT = /\[SCVP-|%5BSCVP-|\(SCVP-|%28SCVP-/i;
1280
+ var SCVP_MACRO_PATTERN = /\[SCVP-([A-Z0-9-]+)\]|\(SCVP-([A-Z0-9-]+)\)/gi;
1281
+ var SCVP_WHOLE_VALUE_PATTERN = /^\s*(?:\[SCVP-([A-Z0-9-]+)\]|\(SCVP-([A-Z0-9-]+)\))\s*$/i;
1282
+ var NESTED_QUERY_PARAM_KEYS = /* @__PURE__ */ new Set([
1283
+ "cust_params"
1284
+ ]);
1285
+ var SCVP_POD_MACROS = /* @__PURE__ */ new Set([
1286
+ "PMND",
1287
+ "PMXD",
1288
+ "PMAD"
1289
+ ]);
1290
+ function hasScvpMacros(url) {
1291
+ return !!url && SCVP_MACRO_DETECT.test(url);
1292
+ }
1293
+ function safeDecode(value) {
1294
+ try {
1295
+ return decodeURIComponent(value.replace(/\+/g, " "));
1296
+ } catch (unused) {
1297
+ return value;
1298
+ }
1299
+ }
1300
+ function findScvpMacroNames(url) {
1301
+ if (!url) return [];
1302
+ var names = /* @__PURE__ */ new Set();
1303
+ var text = url;
1304
+ for(var pass = 0; pass < 3; pass++){
1305
+ text.replace(SCVP_MACRO_PATTERN, function(_m, bracketName, parenName) {
1306
+ names.add(String(bracketName || parenName).toUpperCase());
1307
+ return "";
1308
+ });
1309
+ var decoded = safeDecode(text);
1310
+ if (decoded === text) break;
1311
+ text = decoded;
1312
+ }
1313
+ return Array.from(names);
1314
+ }
1315
+ function resolveScvpMacroValues(ctx) {
1316
+ var _ctx_deviceId, _ctx_deviceIdType, _ctx_consent, _ctx_consent1, _ctx_consent2;
1317
+ var values = /* @__PURE__ */ new Map();
1318
+ var set = function set(name, value) {
1319
+ if (value == null) return;
1320
+ var str = String(value).trim();
1321
+ if (str) values.set(name, str);
1322
+ };
1323
+ var toFlag = function toFlag(value) {
1324
+ return value == null ? void 0 : value ? "1" : "0";
1325
+ };
1326
+ var deviceId = (_ctx_deviceId = ctx.deviceId) === null || _ctx_deviceId === void 0 ? void 0 : _ctx_deviceId.trim();
1327
+ var deviceIdType = deviceId ? ((_ctx_deviceIdType = ctx.deviceIdType) === null || _ctx_deviceIdType === void 0 ? void 0 : _ctx_deviceIdType.trim()) || inferDeviceIdType() : void 0;
1328
+ if (deviceId && deviceIdType) {
1329
+ var _toFlag;
1330
+ set("RDID", deviceId);
1331
+ set("IDTYPE", deviceIdType);
1332
+ set("IS-LAT", (_toFlag = toFlag(ctx.limitAdTracking)) !== null && _toFlag !== void 0 ? _toFlag : "0");
1333
+ }
1334
+ set("SID", ctx.sessionId);
1335
+ set("DTH", ctx.deviceTypeHint);
1336
+ set("GIVN", ctx.palNonce);
1337
+ set("CT-TI", ctx.programTitle);
1338
+ set("CT-CH", ctx.channelName);
1339
+ set("POD", ctx.pod);
1340
+ set("CORRELATOR", ctx.correlator);
1341
+ set("SCOR", ctx.streamCorrelator);
1342
+ set("VPMUTE", toFlag(ctx.adWillPlayMuted));
1343
+ if (ctx.adWillAutoPlay != null) {
1344
+ set("VPA", ctx.adWillAutoPlay ? "auto" : "click");
1345
+ }
1346
+ set("GDPR", (_ctx_consent = ctx.consent) === null || _ctx_consent === void 0 ? void 0 : _ctx_consent.gdpr);
1347
+ set("GDPR-CONSENT", (_ctx_consent1 = ctx.consent) === null || _ctx_consent1 === void 0 ? void 0 : _ctx_consent1.gdprConsent);
1348
+ set("US-PRIVACY", (_ctx_consent2 = ctx.consent) === null || _ctx_consent2 === void 0 ? void 0 : _ctx_consent2.usPrivacy);
1349
+ return values;
1350
+ }
1351
+ var keepNone = function keepNone() {
1352
+ return false;
1353
+ };
1354
+ function substituteScvpParams(params, values, unresolved, keep, nested) {
1355
+ var out = [];
1356
+ var replaceMacro = function replaceMacro(match, bracketName, parenName) {
1357
+ var name = String(bracketName || parenName).toUpperCase();
1358
+ var value = values.get(name);
1359
+ if (value != null) return value;
1360
+ if (keep(name)) return match;
1361
+ unresolved.add(name);
1362
+ return "";
1363
+ };
1364
+ params.forEach(function(value, key) {
1365
+ var whole = value.match(SCVP_WHOLE_VALUE_PATTERN);
1366
+ if (whole) {
1367
+ var name = String(whole[1] || whole[2]).toUpperCase();
1368
+ var resolved = values.get(name);
1369
+ if (resolved != null) {
1370
+ out.push([
1371
+ key,
1372
+ resolved
1373
+ ]);
1374
+ } else if (keep(name)) {
1375
+ out.push([
1376
+ key,
1377
+ value
1378
+ ]);
1379
+ } else {
1380
+ unresolved.add(name);
1381
+ }
1382
+ return;
1383
+ }
1384
+ if (!SCVP_MACRO_DETECT.test(value)) {
1385
+ out.push([
1386
+ key,
1387
+ value
1388
+ ]);
1389
+ return;
1390
+ }
1391
+ if (!nested && NESTED_QUERY_PARAM_KEYS.has(key)) {
1392
+ var inner = substituteScvpParams(new URLSearchParams(value), values, unresolved, keep, true);
1393
+ if (inner.length > 0) {
1394
+ out.push([
1395
+ key,
1396
+ inner.map(function(param) {
1397
+ var _param = _sliced_to_array(param, 2), k = _param[0], v = _param[1];
1398
+ return "".concat(encodeURIComponent(k), "=").concat(encodeURIComponent(v));
1399
+ }).join("&")
1400
+ ]);
1401
+ }
1402
+ return;
1403
+ }
1404
+ out.push([
1405
+ key,
1406
+ value.replace(SCVP_MACRO_PATTERN, replaceMacro)
1407
+ ]);
1408
+ });
1409
+ return out;
1410
+ }
1411
+ function substituteScvpMacros(baseUrl, values) {
1412
+ var keep = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : keepNone;
1413
+ var unresolved = /* @__PURE__ */ new Set();
1414
+ var url;
1415
+ try {
1416
+ url = new URL(normalizeVastTagUrl(baseUrl));
1417
+ } catch (unused) {
1418
+ var replaced = baseUrl.replace(SCVP_MACRO_PATTERN, function(match, bracketName, parenName) {
1419
+ var name = String(bracketName || parenName).toUpperCase();
1420
+ var value = values.get(name);
1421
+ if (value != null) return encodeURIComponent(value);
1422
+ if (keep(name)) return match;
1423
+ unresolved.add(name);
1424
+ return "";
1425
+ });
1426
+ return {
1427
+ url: replaced,
1428
+ unresolved: Array.from(unresolved)
1429
+ };
1430
+ }
1431
+ var entries = substituteScvpParams(url.searchParams, values, unresolved, keep, false);
1432
+ var search = new URLSearchParams();
1433
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1434
+ try {
1435
+ for(var _iterator = entries[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1436
+ var _step_value = _sliced_to_array(_step.value, 2), key = _step_value[0], value = _step_value[1];
1437
+ search.append(key, value);
1438
+ }
1439
+ } catch (err) {
1440
+ _didIteratorError = true;
1441
+ _iteratorError = err;
1442
+ } finally{
1443
+ try {
1444
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1445
+ _iterator.return();
1446
+ }
1447
+ } finally{
1448
+ if (_didIteratorError) {
1449
+ throw _iteratorError;
1450
+ }
1451
+ }
1452
+ }
1453
+ url.search = search.toString();
1454
+ return {
1455
+ url: url.toString(),
1456
+ unresolved: Array.from(unresolved)
1457
+ };
1458
+ }
1459
+ function applyScvpMacros(baseUrl, ctx) {
1460
+ var deferred = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : /* @__PURE__ */ new Set();
1461
+ return substituteScvpMacros(baseUrl, resolveScvpMacroValues(ctx), function(name) {
1462
+ return deferred.has(name);
1463
+ });
1464
+ }
1465
+ function stripScvpMacros(url) {
1466
+ if (findScvpMacroNames(url).length === 0) return {
1467
+ url: url,
1468
+ unresolved: []
1469
+ };
1470
+ return substituteScvpMacros(url, /* @__PURE__ */ new Map());
1471
+ }
1277
1472
  function applyVastMacros(baseUrl, ctx) {
1278
1473
  var expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);
1279
1474
  var url;
@@ -1315,15 +1510,6 @@ function applyVastMacros(baseUrl, ctx) {
1315
1510
  }
1316
1511
  params.delete("ppos");
1317
1512
  params.delete("lip");
1318
- if (ctx.podMinDurationMs != null) {
1319
- params.set("pmnd", String(Math.max(0, Math.round(ctx.podMinDurationMs))));
1320
- }
1321
- if (ctx.podMaxDurationMs != null) {
1322
- params.set("pmxd", String(Math.max(0, Math.round(ctx.podMaxDurationMs))));
1323
- }
1324
- if (ctx.podMaxAds != null) {
1325
- params.set("pmad", String(Math.max(1, Math.round(ctx.podMaxAds))));
1326
- }
1327
1513
  var existingUrl = params.get("url") || "";
1328
1514
  if (EXAMPLE_COM_URL.test(existingUrl)) {
1329
1515
  params.delete("url");
@@ -2177,6 +2363,309 @@ function substituteVastTrackingMacros(url) {
2177
2363
  return KNOWN_VAST_MACROS.has(name) ? "" : match;
2178
2364
  });
2179
2365
  }
2366
+ // src/player/OptimizedPodRequest.ts
2367
+ var DEFAULT_REQUEST_SAFETY_MS = 1500;
2368
+ var GAM_AD_OPPORTUNITY_DURATION_MS = 3e4;
2369
+ var POD_PARAM_KEYS = [
2370
+ "pmnd",
2371
+ "pmxd",
2372
+ "pmad"
2373
+ ];
2374
+ var POSITIVE_INT = /^[1-9]\d*$/;
2375
+ var NON_NEGATIVE_INT = /^(0|[1-9]\d*)$/;
2376
+ function nonNegativeInt(value) {
2377
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : void 0;
2378
+ }
2379
+ function positiveInt(value) {
2380
+ return typeof value === "number" && Number.isFinite(value) && value >= 1 ? Math.floor(value) : void 0;
2381
+ }
2382
+ function resolveAdPodConfig(config) {
2383
+ var _config_adPodConfig, _nonNegativeInt, _nonNegativeInt1, _positiveInt;
2384
+ var pod = (_config_adPodConfig = config.adPodConfig) !== null && _config_adPodConfig !== void 0 ? _config_adPodConfig : {};
2385
+ return {
2386
+ requestSafetyMs: (_nonNegativeInt = nonNegativeInt(pod.requestSafetyMs)) !== null && _nonNegativeInt !== void 0 ? _nonNegativeInt : DEFAULT_REQUEST_SAFETY_MS,
2387
+ minPodDurationMs: (_nonNegativeInt1 = nonNegativeInt(pod.minPodDurationMs)) !== null && _nonNegativeInt1 !== void 0 ? _nonNegativeInt1 : 0,
2388
+ maxAdsPerBreak: pod.maxAdsPerBreak === void 0 ? positiveInt(config.podMaxAds) : positiveInt(pod.maxAdsPerBreak),
2389
+ maxPodDurationMs: (_positiveInt = positiveInt(pod.maxPodDurationMs)) !== null && _positiveInt !== void 0 ? _positiveInt : positiveInt(config.podMaxDurationMs),
2390
+ exactDuration: config.podExactDuration === true
2391
+ };
2392
+ }
2393
+ function measureBreakCapacity(timing, nowMonoMs) {
2394
+ var _timing_breakEndMonoMs;
2395
+ var scheduled = timing.scheduledBreakDurationMs;
2396
+ if (scheduled == null || !(scheduled > 0) || timing.breakStartMonoMs == null) {
2397
+ return void 0;
2398
+ }
2399
+ var endMonoMs = (_timing_breakEndMonoMs = timing.breakEndMonoMs) !== null && _timing_breakEndMonoMs !== void 0 ? _timing_breakEndMonoMs : timing.breakStartMonoMs + scheduled;
2400
+ var untilEnd = Math.min(scheduled, endMonoMs - nowMonoMs);
2401
+ var unplayed = scheduled - Math.max(0, timing.playedDurationMs);
2402
+ return {
2403
+ scheduledBreakDurationMs: scheduled,
2404
+ elapsedBeforeGamRequestMs: Math.max(0, nowMonoMs - timing.breakStartMonoMs),
2405
+ remainingAtGamDispatchMs: Math.max(0, Math.min(untilEnd, unplayed))
2406
+ };
2407
+ }
2408
+ function resolvePodParams(input) {
2409
+ var capacity = input.capacity, config = input.config;
2410
+ var pmxd;
2411
+ var source;
2412
+ if (capacity) {
2413
+ pmxd = Math.floor(capacity.remainingAtGamDispatchMs - config.requestSafetyMs);
2414
+ source = "break_remaining";
2415
+ } else if (config.maxPodDurationMs != null) {
2416
+ pmxd = config.maxPodDurationMs;
2417
+ source = "configured_cap";
2418
+ } else if (input.tagMaxDurationMs != null) {
2419
+ pmxd = input.tagMaxDurationMs;
2420
+ source = "tag_cap";
2421
+ } else {
2422
+ return {
2423
+ kind: "omit"
2424
+ };
2425
+ }
2426
+ var minUsable = Math.max(1, Math.floor(input.minUsablePmxdMs));
2427
+ if (!Number.isFinite(pmxd) || pmxd < minUsable) {
2428
+ return {
2429
+ kind: "abort",
2430
+ reason: capacity ? "insufficient_break_capacity" : "invalid_pod_cap",
2431
+ pmxdCandidateMs: Number.isFinite(pmxd) ? pmxd : 0
2432
+ };
2433
+ }
2434
+ var pmnd = config.exactDuration ? pmxd : Math.min(config.minPodDurationMs, pmxd);
2435
+ return {
2436
+ kind: "send",
2437
+ params: {
2438
+ pmnd: pmnd,
2439
+ pmxd: pmxd,
2440
+ pmad: config.maxAdsPerBreak
2441
+ },
2442
+ source: source
2443
+ };
2444
+ }
2445
+ function podRequestAborted(reason, message, diagnostics) {
2446
+ var error = new Error("Optimized pod request not sent (".concat(reason, "): ").concat(message));
2447
+ error.podRequestAborted = true;
2448
+ error.reason = reason;
2449
+ error.diagnostics = diagnostics;
2450
+ return error;
2451
+ }
2452
+ function isPodRequestAbortedError(error) {
2453
+ return !!error && error.podRequestAborted === true;
2454
+ }
2455
+ function firstPositiveIntParam(params, key) {
2456
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2457
+ try {
2458
+ for(var _iterator = params.getAll(key)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2459
+ var value = _step.value;
2460
+ if (POSITIVE_INT.test(value.trim())) return Number(value.trim());
2461
+ }
2462
+ } catch (err) {
2463
+ _didIteratorError = true;
2464
+ _iteratorError = err;
2465
+ } finally{
2466
+ try {
2467
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2468
+ _iterator.return();
2469
+ }
2470
+ } finally{
2471
+ if (_didIteratorError) {
2472
+ throw _iteratorError;
2473
+ }
2474
+ }
2475
+ }
2476
+ return void 0;
2477
+ }
2478
+ function isOptimizedPodUrl(url) {
2479
+ if (findScvpMacroNames(url).some(function(name) {
2480
+ return SCVP_POD_MACROS.has(name);
2481
+ })) return true;
2482
+ try {
2483
+ var params = new URL(url).searchParams;
2484
+ return POD_PARAM_KEYS.some(function(key) {
2485
+ return params.has(key);
2486
+ });
2487
+ } catch (unused) {
2488
+ return false;
2489
+ }
2490
+ }
2491
+ function finalizeGamRequestUrl(rawUrl, ctx) {
2492
+ var nowEpochMs = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : Date.now();
2493
+ var optimizedPod = isOptimizedPodUrl(rawUrl);
2494
+ var capacity = ctx.capacity;
2495
+ var base = {
2496
+ breakId: ctx.breakId,
2497
+ optimizedPod: optimizedPod,
2498
+ scteBreakDurationMs: capacity === null || capacity === void 0 ? void 0 : capacity.scheduledBreakDurationMs,
2499
+ elapsedBeforeGamRequestMs: capacity === null || capacity === void 0 ? void 0 : capacity.elapsedBeforeGamRequestMs,
2500
+ remainingAtGamDispatchMs: capacity === null || capacity === void 0 ? void 0 : capacity.remainingAtGamDispatchMs,
2501
+ safetyReserveMs: ctx.config.requestSafetyMs
2502
+ };
2503
+ var decision = {
2504
+ kind: "omit"
2505
+ };
2506
+ if (optimizedPod) {
2507
+ var tagMaxDurationMs;
2508
+ try {
2509
+ tagMaxDurationMs = firstPositiveIntParam(new URL(rawUrl).searchParams, "pmxd");
2510
+ } catch (unused) {}
2511
+ decision = resolvePodParams({
2512
+ capacity: capacity,
2513
+ config: ctx.config,
2514
+ minUsablePmxdMs: ctx.minUsablePmxdMs,
2515
+ tagMaxDurationMs: tagMaxDurationMs
2516
+ });
2517
+ if (decision.kind === "abort") {
2518
+ throw podRequestAborted(decision.reason, "pmxd would be ".concat(decision.pmxdCandidateMs, "ms (minimum ").concat(ctx.minUsablePmxdMs, "ms)"), base);
2519
+ }
2520
+ }
2521
+ var pod = decision.kind === "send" ? decision.params : void 0;
2522
+ var values = /* @__PURE__ */ new Map();
2523
+ if (pod) {
2524
+ values.set("PMND", String(pod.pmnd));
2525
+ values.set("PMXD", String(pod.pmxd));
2526
+ if (pod.pmad != null) values.set("PMAD", String(pod.pmad));
2527
+ }
2528
+ var substituted = substituteScvpMacros(rawUrl, values);
2529
+ var finalUrl;
2530
+ try {
2531
+ var url = new URL(normalizeVastTagUrl(substituted.url));
2532
+ if (pod) {
2533
+ url.searchParams.set("pmnd", String(pod.pmnd));
2534
+ url.searchParams.set("pmxd", String(pod.pmxd));
2535
+ if (pod.pmad != null) url.searchParams.set("pmad", String(pod.pmad));
2536
+ else url.searchParams.delete("pmad");
2537
+ } else {
2538
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2539
+ try {
2540
+ for(var _iterator = POD_PARAM_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2541
+ var key = _step.value;
2542
+ url.searchParams.delete(key);
2543
+ }
2544
+ } catch (err) {
2545
+ _didIteratorError = true;
2546
+ _iteratorError = err;
2547
+ } finally{
2548
+ try {
2549
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2550
+ _iterator.return();
2551
+ }
2552
+ } finally{
2553
+ if (_didIteratorError) {
2554
+ throw _iteratorError;
2555
+ }
2556
+ }
2557
+ }
2558
+ }
2559
+ finalUrl = url.toString();
2560
+ } catch (unused) {
2561
+ throw podRequestAborted("invalid_url", "GAM request URL could not be parsed", base);
2562
+ }
2563
+ var problems = validateGamRequestUrl(finalUrl, {
2564
+ optimizedPod: !!pod,
2565
+ remainingMs: decision.kind === "send" && decision.source === "break_remaining" ? capacity === null || capacity === void 0 ? void 0 : capacity.remainingAtGamDispatchMs : void 0
2566
+ });
2567
+ if (problems.length > 0) {
2568
+ throw podRequestAborted("invalid_url", problems.join("; "), base);
2569
+ }
2570
+ var givn = null;
2571
+ try {
2572
+ givn = new URL(finalUrl).searchParams.get("givn");
2573
+ } catch (unused) {}
2574
+ return {
2575
+ url: finalUrl,
2576
+ diagnostics: {
2577
+ breakId: ctx.breakId,
2578
+ optimizedPod: !!pod,
2579
+ pmxdSource: decision.kind === "send" ? decision.source : void 0,
2580
+ scteBreakDurationMs: capacity === null || capacity === void 0 ? void 0 : capacity.scheduledBreakDurationMs,
2581
+ elapsedBeforeGamRequestMs: capacity === null || capacity === void 0 ? void 0 : capacity.elapsedBeforeGamRequestMs,
2582
+ remainingAtGamDispatchMs: capacity === null || capacity === void 0 ? void 0 : capacity.remainingAtGamDispatchMs,
2583
+ safetyReserveMs: ctx.config.requestSafetyMs,
2584
+ pmndSent: pod === null || pod === void 0 ? void 0 : pod.pmnd,
2585
+ pmxdSent: pod === null || pod === void 0 ? void 0 : pod.pmxd,
2586
+ pmadSent: pod === null || pod === void 0 ? void 0 : pod.pmad,
2587
+ palNoncePresent: !!givn,
2588
+ gamRequestDispatchTimestamp: new Date(nowEpochMs).toISOString(),
2589
+ strippedMacros: substituted.unresolved.filter(function(name) {
2590
+ return !SCVP_POD_MACROS.has(name);
2591
+ })
2592
+ }
2593
+ };
2594
+ }
2595
+ function validateGamRequestUrl(url, expect) {
2596
+ var problems = [];
2597
+ var leftover = findScvpMacroNames(url);
2598
+ if (leftover.length > 0) problems.push("unresolved SCVP macros: ".concat(leftover.join(", ")));
2599
+ var params;
2600
+ try {
2601
+ params = new URL(url).searchParams;
2602
+ } catch (unused) {
2603
+ return problems.concat("URL could not be parsed");
2604
+ }
2605
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2606
+ try {
2607
+ for(var _iterator = POD_PARAM_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2608
+ var key = _step.value;
2609
+ if (params.getAll(key).length > 1) problems.push("duplicate ".concat(key));
2610
+ }
2611
+ } catch (err) {
2612
+ _didIteratorError = true;
2613
+ _iteratorError = err;
2614
+ } finally{
2615
+ try {
2616
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2617
+ _iterator.return();
2618
+ }
2619
+ } finally{
2620
+ if (_didIteratorError) {
2621
+ throw _iteratorError;
2622
+ }
2623
+ }
2624
+ }
2625
+ if (!expect.optimizedPod) {
2626
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
2627
+ try {
2628
+ for(var _iterator1 = POD_PARAM_KEYS[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
2629
+ var key1 = _step1.value;
2630
+ if (params.has(key1)) problems.push("".concat(key1, " present on a non-pod request"));
2631
+ }
2632
+ } catch (err) {
2633
+ _didIteratorError1 = true;
2634
+ _iteratorError1 = err;
2635
+ } finally{
2636
+ try {
2637
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2638
+ _iterator1.return();
2639
+ }
2640
+ } finally{
2641
+ if (_didIteratorError1) {
2642
+ throw _iteratorError1;
2643
+ }
2644
+ }
2645
+ }
2646
+ return problems;
2647
+ }
2648
+ var pmxd = params.get("pmxd");
2649
+ var pmnd = params.get("pmnd");
2650
+ var pmad = params.get("pmad");
2651
+ if (pmxd == null || !POSITIVE_INT.test(pmxd)) problems.push("pmxd must be a positive integer (got ".concat(pmxd, ")"));
2652
+ if (pmnd == null || !NON_NEGATIVE_INT.test(pmnd)) problems.push("pmnd must be a non-negative integer (got ".concat(pmnd, ")"));
2653
+ if (pmxd != null && pmnd != null && Number(pmnd) > Number(pmxd)) problems.push("pmnd exceeds pmxd");
2654
+ if (pmad != null && !POSITIVE_INT.test(pmad)) problems.push("pmad must be a positive integer or absent (got ".concat(pmad, ")"));
2655
+ if (expect.remainingMs != null && pmxd != null && Number(pmxd) > expect.remainingMs) {
2656
+ problems.push("pmxd ".concat(pmxd, " exceeds remaining break ").concat(expect.remainingMs, "ms"));
2657
+ }
2658
+ return problems;
2659
+ }
2660
+ function computePodResponseDiagnostics(pmxdSent, vastAdCount, totalVastCreativeDurationMs) {
2661
+ var estimatedUnusedPodMs = Math.max(0, pmxdSent - totalVastCreativeDurationMs);
2662
+ return {
2663
+ vastAdCount: vastAdCount,
2664
+ totalVastCreativeDurationMs: totalVastCreativeDurationMs,
2665
+ estimatedUnusedPodMs: estimatedUnusedPodMs,
2666
+ estimatedUnmatchedCount: Math.floor(estimatedUnusedPodMs / GAM_AD_OPPORTUNITY_DURATION_MS)
2667
+ };
2668
+ }
2180
2669
  // src/sdk/hlsAdPlayer.ts
2181
2670
  var LINEAR_TRACKING_EVENTS = [
2182
2671
  "creativeView",
@@ -2257,6 +2746,7 @@ function toVastMediaErrorCode(error) {
2257
2746
  return VAST_ERROR_MEDIA_DISPLAY;
2258
2747
  }
2259
2748
  }
2749
+ var gamCredentialsMode = "include";
2260
2750
  function createHlsAdPlayer(contentVideo, options) {
2261
2751
  var _contentVideo_AD_VIDEO_PROP, _contentVideo_AD_CONTAINER_PROP, _ref;
2262
2752
  var adPlaying = false;
@@ -3128,9 +3618,9 @@ function createHlsAdPlayer(contentVideo, options) {
3128
3618
  }
3129
3619
  }
3130
3620
  function fetchVastXml(vastTagUrl) {
3131
- var credentials = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "include", kind = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "gam";
3621
+ 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;
3132
3622
  return _async_to_generator(function() {
3133
- var controller, timeoutId, startedAt, attempt, requestVast, response, error, error1;
3623
+ var controller, timeoutId, startedAt, attempt, resolveDispatchUrl, requestVast, response, error, error1;
3134
3624
  return _ts_generator(this, function(_state) {
3135
3625
  switch(_state.label){
3136
3626
  case 0:
@@ -3144,13 +3634,32 @@ function createHlsAdPlayer(contentVideo, options) {
3144
3634
  }, VAST_REQUEST_TIMEOUT_MS) : void 0;
3145
3635
  startedAt = Date.now();
3146
3636
  attempt = 0;
3637
+ resolveDispatchUrl = function resolveDispatchUrl() {
3638
+ if (kind === "wrapper") return vastTagUrl;
3639
+ if (finalizeRequestUrl) return finalizeRequestUrl(vastTagUrl, attempt);
3640
+ var _stripScvpMacros = stripScvpMacros(vastTagUrl), url = _stripScvpMacros.url, unresolved = _stripScvpMacros.unresolved;
3641
+ if (unresolved.length > 0) {
3642
+ console.warn("[HlsAdPlayer] Removed unresolved SCVP macros before dispatch:", unresolved.join(", "));
3643
+ }
3644
+ return url;
3645
+ };
3147
3646
  requestVast = function requestVast(creds) {
3148
3647
  return _async_to_generator(function() {
3149
- var response;
3648
+ var pending, response;
3150
3649
  return _ts_generator(this, function(_state) {
3151
3650
  switch(_state.label){
3152
3651
  case 0:
3153
3652
  attempt++;
3653
+ pending = fetch(resolveDispatchUrl(), _object_spread({
3654
+ mode: "cors",
3655
+ credentials: creds,
3656
+ headers: {
3657
+ "Accept": "application/xml, text/xml, */*"
3658
+ },
3659
+ referrerPolicy: "no-referrer-when-downgrade"
3660
+ }, controller ? {
3661
+ signal: controller.signal
3662
+ } : {}));
3154
3663
  if (kind !== "wrapper") {
3155
3664
  logFunnel("".concat(kind, "_http_request_sent"), {
3156
3665
  attempt: attempt,
@@ -3159,16 +3668,7 @@ function createHlsAdPlayer(contentVideo, options) {
3159
3668
  }
3160
3669
  return [
3161
3670
  4,
3162
- fetch(vastTagUrl, _object_spread({
3163
- mode: "cors",
3164
- credentials: creds,
3165
- headers: {
3166
- "Accept": "application/xml, text/xml, */*"
3167
- },
3168
- referrerPolicy: "no-referrer-when-downgrade"
3169
- }, controller ? {
3170
- signal: controller.signal
3171
- } : {}))
3671
+ pending
3172
3672
  ];
3173
3673
  case 1:
3174
3674
  response = _state.sent();
@@ -3192,9 +3692,9 @@ function createHlsAdPlayer(contentVideo, options) {
3192
3692
  case 1:
3193
3693
  _state.trys.push([
3194
3694
  1,
3195
- 10,
3196
- 11,
3197
- 12
3695
+ 7,
3696
+ 8,
3697
+ 9
3198
3698
  ]);
3199
3699
  _state.label = 2;
3200
3700
  case 2:
@@ -3202,7 +3702,7 @@ function createHlsAdPlayer(contentVideo, options) {
3202
3702
  2,
3203
3703
  4,
3204
3704
  ,
3205
- 8
3705
+ 5
3206
3706
  ]);
3207
3707
  return [
3208
3708
  4,
@@ -3212,36 +3712,21 @@ function createHlsAdPlayer(contentVideo, options) {
3212
3712
  response = _state.sent();
3213
3713
  return [
3214
3714
  3,
3215
- 8
3715
+ 5
3216
3716
  ];
3217
3717
  case 4:
3218
3718
  error = _state.sent();
3219
- if (!(credentials !== "omit" && !(controller === null || controller === void 0 ? void 0 : controller.signal.aborted))) return [
3220
- 3,
3221
- 6
3222
- ];
3223
- console.warn('[HlsAdPlayer] VAST fetch failed with credentials="'.concat(credentials, '", retrying without credentials:'), error);
3224
- logFunnel("vast_credentials_retry", {
3225
- errorMessage: error === null || error === void 0 ? void 0 : error.message
3226
- });
3227
- return [
3228
- 4,
3229
- requestVast("omit")
3230
- ];
3231
- case 5:
3232
- response = _state.sent();
3233
- return [
3234
- 3,
3235
- 7
3236
- ];
3237
- case 6:
3719
+ if (kind === "gam" && !(controller === null || controller === void 0 ? void 0 : controller.signal.aborted) && !isPodRequestAbortedError(error)) {
3720
+ gamCredentialsMode = credentials === "include" ? "omit" : "include";
3721
+ console.warn('[HlsAdPlayer] GAM fetch failed with credentials="'.concat(credentials, '"; next GAM request will use credentials="').concat(gamCredentialsMode, '":'), error);
3722
+ logFunnel("gam_credentials_mode_changed", {
3723
+ from: credentials,
3724
+ to: gamCredentialsMode,
3725
+ errorMessage: error === null || error === void 0 ? void 0 : error.message
3726
+ });
3727
+ }
3238
3728
  throw error;
3239
- case 7:
3240
- return [
3241
- 3,
3242
- 8
3243
- ];
3244
- case 8:
3729
+ case 5:
3245
3730
  if (!response.ok) {
3246
3731
  throw new Error("Failed to fetch VAST: HTTP ".concat(response.status, " ").concat(response.statusText));
3247
3732
  }
@@ -3249,12 +3734,12 @@ function createHlsAdPlayer(contentVideo, options) {
3249
3734
  4,
3250
3735
  response.text()
3251
3736
  ];
3252
- case 9:
3737
+ case 6:
3253
3738
  return [
3254
3739
  2,
3255
3740
  _state.sent()
3256
3741
  ];
3257
- case 10:
3742
+ case 7:
3258
3743
  error1 = _state.sent();
3259
3744
  if (controller === null || controller === void 0 ? void 0 : controller.signal.aborted) {
3260
3745
  if (pendingRequestAbortReason) {
@@ -3263,13 +3748,13 @@ function createHlsAdPlayer(contentVideo, options) {
3263
3748
  throw new Error("VAST request timeout after ".concat(VAST_REQUEST_TIMEOUT_MS, "ms: ").concat(vastTagUrl));
3264
3749
  }
3265
3750
  throw error1;
3266
- case 11:
3751
+ case 8:
3267
3752
  if (timeoutId !== void 0) clearTimeout(timeoutId);
3268
3753
  if (controller) pendingVastRequests.delete(controller);
3269
3754
  return [
3270
3755
  7
3271
3756
  ];
3272
- case 12:
3757
+ case 9:
3273
3758
  return [
3274
3759
  2
3275
3760
  ];
@@ -3402,7 +3887,7 @@ function createHlsAdPlayer(contentVideo, options) {
3402
3887
  });
3403
3888
  }
3404
3889
  function fetchAndParsePod(vastTagUrl) {
3405
- var source = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "gam";
3890
+ var source = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "gam", finalizeRequestUrl = arguments.length > 2 ? arguments[2] : void 0;
3406
3891
  return _async_to_generator(function() {
3407
3892
  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;
3408
3893
  return _ts_generator(this, function(_state) {
@@ -3412,7 +3897,7 @@ function createHlsAdPlayer(contentVideo, options) {
3412
3897
  isEdge = source === "edge";
3413
3898
  return [
3414
3899
  4,
3415
- fetchVastXml(vastTagUrl, isEdge ? "omit" : "include", source)
3900
+ fetchVastXml(vastTagUrl, isEdge ? "omit" : gamCredentialsMode, source, finalizeRequestUrl)
3416
3901
  ];
3417
3902
  case 1:
3418
3903
  vastXml = _state.sent();
@@ -4735,7 +5220,7 @@ function createHlsAdPlayer(contentVideo, options) {
4735
5220
  case 2:
4736
5221
  return [
4737
5222
  4,
4738
- fetchAndParsePod(vastTagUrl, source)
5223
+ fetchAndParsePod(vastTagUrl, source, requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.finalizeRequestUrl)
4739
5224
  ];
4740
5225
  case 3:
4741
5226
  ads = _state.sent();
@@ -5312,95 +5797,38 @@ function getOrCreateNonceLoader(allowStorage) {
5312
5797
  function createPalNonceManager() {
5313
5798
  var currentNonce = "";
5314
5799
  var currentNonceManager;
5800
+ var pendingNonce;
5315
5801
  return {
5316
5802
  generateNonce: function generateNonce() {
5317
- return _async_to_generator(function() {
5318
- var options, _options_allowStorage, _options_adWillAutoPlay, _options_adWillPlayMuted, _options_playerVolume, _options_continuousPlayback, loader, goog, request, manager, error;
5319
- var _arguments = arguments;
5320
- return _ts_generator(this, function(_state) {
5321
- switch(_state.label){
5322
- case 0:
5323
- options = _arguments.length > 0 && _arguments[0] !== void 0 ? _arguments[0] : {};
5324
- _state.label = 1;
5325
- case 1:
5326
- _state.trys.push([
5327
- 1,
5328
- 4,
5329
- ,
5330
- 5
5331
- ]);
5332
- return [
5333
- 4,
5334
- loadPalSdk()
5335
- ];
5336
- case 2:
5337
- _state.sent();
5338
- loader = getOrCreateNonceLoader((_options_allowStorage = options.allowStorage) !== null && _options_allowStorage !== void 0 ? _options_allowStorage : true);
5339
- goog = window.goog;
5340
- request = new goog.pal.NonceRequest();
5341
- request.adWillAutoPlay = (_options_adWillAutoPlay = options.adWillAutoPlay) !== null && _options_adWillAutoPlay !== void 0 ? _options_adWillAutoPlay : true;
5342
- request.adWillPlayMuted = (_options_adWillPlayMuted = options.adWillPlayMuted) !== null && _options_adWillPlayMuted !== void 0 ? _options_adWillPlayMuted : false;
5343
- request.playerVolume = (_options_playerVolume = options.playerVolume) !== null && _options_playerVolume !== void 0 ? _options_playerVolume : request.adWillPlayMuted ? 0 : 1;
5344
- request.continuousPlayback = (_options_continuousPlayback = options.continuousPlayback) !== null && _options_continuousPlayback !== void 0 ? _options_continuousPlayback : true;
5345
- request.descriptionUrl = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
5346
- request.iconsSupported = true;
5347
- request.playerType = "StormcloudVideoPlayer";
5348
- request.playerVersion = "1.0";
5349
- request.supportedApiFrameworks = "2,7,9";
5350
- request.url = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
5351
- request.videoWidth = options.videoWidth || 640;
5352
- request.videoHeight = options.videoHeight || 480;
5353
- if (options.ppid) request.ppid = options.ppid;
5354
- if (options.sessionId) request.sessionId = options.sessionId;
5355
- console.log("[PAL] NonceRequest before generateNonce:", JSON.stringify({
5356
- adWillAutoPlay: request.adWillAutoPlay,
5357
- adWillPlayMuted: request.adWillPlayMuted,
5358
- playerVolume: request.playerVolume,
5359
- continuousPlayback: request.continuousPlayback,
5360
- descriptionUrl: request.descriptionUrl,
5361
- iconsSupported: request.iconsSupported,
5362
- playerType: request.playerType,
5363
- playerVersion: request.playerVersion,
5364
- supportedApiFrameworks: request.supportedApiFrameworks,
5365
- url: request.url,
5366
- videoWidth: request.videoWidth,
5367
- videoHeight: request.videoHeight,
5368
- ppid: request.ppid,
5369
- sessionId: request.sessionId
5370
- }, null, 2));
5371
- return [
5372
- 4,
5373
- loader.loadNonceManager(request)
5374
- ];
5375
- case 3:
5376
- manager = _state.sent();
5377
- currentNonceManager = manager;
5378
- currentNonce = manager.getNonce();
5379
- console.log("[PAL] Nonce generated successfully");
5380
- return [
5381
- 2,
5382
- currentNonce
5383
- ];
5384
- case 4:
5385
- error = _state.sent();
5386
- console.warn("[PAL] Failed to generate nonce:", error);
5387
- currentNonce = "";
5388
- currentNonceManager = void 0;
5389
- return [
5390
- 2,
5391
- ""
5392
- ];
5393
- case 5:
5394
- return [
5395
- 2
5396
- ];
5397
- }
5398
- });
5399
- }).apply(this, arguments);
5803
+ var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
5804
+ var run = generate(options);
5805
+ pendingNonce = run;
5806
+ var settle = function settle() {
5807
+ if (pendingNonce === run) pendingNonce = void 0;
5808
+ };
5809
+ run.then(settle, settle);
5810
+ return run;
5400
5811
  },
5401
5812
  getCurrentNonce: function getCurrentNonce() {
5402
5813
  return currentNonce;
5403
5814
  },
5815
+ waitForNonce: function waitForNonce(maxWaitMs) {
5816
+ if (currentNonce) return Promise.resolve(currentNonce);
5817
+ var pending = pendingNonce;
5818
+ if (!pending || !(maxWaitMs > 0)) return Promise.resolve("");
5819
+ return new Promise(function(resolve) {
5820
+ var timer = setTimeout(function() {
5821
+ return resolve(currentNonce);
5822
+ }, maxWaitMs);
5823
+ pending.then(function(nonce) {
5824
+ clearTimeout(timer);
5825
+ resolve(nonce);
5826
+ }, function() {
5827
+ clearTimeout(timer);
5828
+ resolve("");
5829
+ });
5830
+ });
5831
+ },
5404
5832
  injectNonce: function injectNonce(vastTagUrl) {
5405
5833
  if (!currentNonce || !vastTagUrl) return vastTagUrl;
5406
5834
  try {
@@ -5437,8 +5865,90 @@ function createPalNonceManager() {
5437
5865
  reset: function reset() {
5438
5866
  currentNonce = "";
5439
5867
  currentNonceManager = void 0;
5868
+ pendingNonce = void 0;
5440
5869
  }
5441
5870
  };
5871
+ function generate(options) {
5872
+ return _async_to_generator(function() {
5873
+ var _options_allowStorage, _options_adWillAutoPlay, _options_adWillPlayMuted, _options_playerVolume, _options_continuousPlayback, loader, goog, request, manager, error;
5874
+ return _ts_generator(this, function(_state) {
5875
+ switch(_state.label){
5876
+ case 0:
5877
+ _state.trys.push([
5878
+ 0,
5879
+ 3,
5880
+ ,
5881
+ 4
5882
+ ]);
5883
+ return [
5884
+ 4,
5885
+ loadPalSdk()
5886
+ ];
5887
+ case 1:
5888
+ _state.sent();
5889
+ loader = getOrCreateNonceLoader((_options_allowStorage = options.allowStorage) !== null && _options_allowStorage !== void 0 ? _options_allowStorage : true);
5890
+ goog = window.goog;
5891
+ request = new goog.pal.NonceRequest();
5892
+ request.adWillAutoPlay = (_options_adWillAutoPlay = options.adWillAutoPlay) !== null && _options_adWillAutoPlay !== void 0 ? _options_adWillAutoPlay : true;
5893
+ request.adWillPlayMuted = (_options_adWillPlayMuted = options.adWillPlayMuted) !== null && _options_adWillPlayMuted !== void 0 ? _options_adWillPlayMuted : false;
5894
+ request.playerVolume = (_options_playerVolume = options.playerVolume) !== null && _options_playerVolume !== void 0 ? _options_playerVolume : request.adWillPlayMuted ? 0 : 1;
5895
+ request.continuousPlayback = (_options_continuousPlayback = options.continuousPlayback) !== null && _options_continuousPlayback !== void 0 ? _options_continuousPlayback : true;
5896
+ request.descriptionUrl = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
5897
+ request.iconsSupported = true;
5898
+ request.playerType = "StormcloudVideoPlayer";
5899
+ request.playerVersion = "1.0";
5900
+ request.supportedApiFrameworks = "2,7,9";
5901
+ request.url = toDevSafeUrl(options.descriptionUrl || (typeof window !== "undefined" ? window.location.href : ""));
5902
+ request.videoWidth = options.videoWidth || 640;
5903
+ request.videoHeight = options.videoHeight || 480;
5904
+ if (options.ppid) request.ppid = options.ppid;
5905
+ if (options.sessionId) request.sessionId = options.sessionId;
5906
+ console.log("[PAL] NonceRequest before generateNonce:", JSON.stringify({
5907
+ adWillAutoPlay: request.adWillAutoPlay,
5908
+ adWillPlayMuted: request.adWillPlayMuted,
5909
+ playerVolume: request.playerVolume,
5910
+ continuousPlayback: request.continuousPlayback,
5911
+ descriptionUrl: request.descriptionUrl,
5912
+ iconsSupported: request.iconsSupported,
5913
+ playerType: request.playerType,
5914
+ playerVersion: request.playerVersion,
5915
+ supportedApiFrameworks: request.supportedApiFrameworks,
5916
+ url: request.url,
5917
+ videoWidth: request.videoWidth,
5918
+ videoHeight: request.videoHeight,
5919
+ ppid: request.ppid,
5920
+ sessionId: request.sessionId
5921
+ }, null, 2));
5922
+ return [
5923
+ 4,
5924
+ loader.loadNonceManager(request)
5925
+ ];
5926
+ case 2:
5927
+ manager = _state.sent();
5928
+ currentNonceManager = manager;
5929
+ currentNonce = manager.getNonce();
5930
+ console.log("[PAL] Nonce generated successfully");
5931
+ return [
5932
+ 2,
5933
+ currentNonce
5934
+ ];
5935
+ case 3:
5936
+ error = _state.sent();
5937
+ console.warn("[PAL] Failed to generate nonce:", error);
5938
+ currentNonce = "";
5939
+ currentNonceManager = void 0;
5940
+ return [
5941
+ 2,
5942
+ ""
5943
+ ];
5944
+ case 4:
5945
+ return [
5946
+ 2
5947
+ ];
5948
+ }
5949
+ });
5950
+ })();
5951
+ }
5442
5952
  }
5443
5953
  // src/utils/trackingIngest.ts
5444
5954
  var DEFAULT_TRACKING_INGEST_CONFIG = {
@@ -5527,7 +6037,14 @@ function ingestPlayerTracking(licenseKey, channel, body) {
5527
6037
  // src/utils/tracking.ts
5528
6038
  var cachedBrowserId = null;
5529
6039
  function buildAnalyticsContext(config) {
6040
+ var _config_contentNetwork, _config_channelName, _config_programTitle;
5530
6041
  var context = {};
6042
+ var contentNetwork = (_config_contentNetwork = config.contentNetwork) === null || _config_contentNetwork === void 0 ? void 0 : _config_contentNetwork.trim();
6043
+ var contentChannel = (_config_channelName = config.channelName) === null || _config_channelName === void 0 ? void 0 : _config_channelName.trim();
6044
+ var contentTitle = (_config_programTitle = config.programTitle) === null || _config_programTitle === void 0 ? void 0 : _config_programTitle.trim();
6045
+ if (contentNetwork) context.contentNetwork = contentNetwork;
6046
+ if (contentChannel) context.contentChannel = contentChannel;
6047
+ if (contentTitle) context.contentTitle = contentTitle;
5531
6048
  if (config.debugAdTiming) {
5532
6049
  context.debugAdTiming = true;
5533
6050
  }
@@ -6018,12 +6535,19 @@ function sendAdImpressionTracking(_0, _1) {
6018
6535
  4,
6019
6536
  ingestPlayerTracking(licenseKey, "impressions", {
6020
6537
  events: [
6021
- {
6538
+ _object_spread({
6022
6539
  player_id: metricEvent.player_id,
6023
6540
  ad_played_count: 1,
6024
6541
  ad_url: adImpressionInfo.adUrl,
6025
- capture_at: adImpressionInfo.timestamp
6026
- }
6542
+ capture_at: adImpressionInfo.timestamp,
6543
+ source: "gam"
6544
+ }, context.contentNetwork ? {
6545
+ content_network: context.contentNetwork
6546
+ } : {}, context.contentChannel ? {
6547
+ content_channel: context.contentChannel
6548
+ } : {}, context.contentTitle ? {
6549
+ content_title: context.contentTitle
6550
+ } : {})
6027
6551
  ]
6028
6552
  })
6029
6553
  ];
@@ -7376,6 +7900,21 @@ var Scte35CueManager = /*#__PURE__*/ function() {
7376
7900
  return Scte35CueManager;
7377
7901
  }();
7378
7902
  // src/player/AdConfigManager.ts
7903
+ function withDeferredPodParams(rawUrl, deferNonce) {
7904
+ try {
7905
+ var url = new URL(rawUrl);
7906
+ url.searchParams.set("pmnd", "[SCVP-PMND]");
7907
+ url.searchParams.set("pmxd", "[SCVP-PMXD]");
7908
+ url.searchParams.set("pmad", "[SCVP-PMAD]");
7909
+ if (deferNonce && !url.searchParams.get("givn")) {
7910
+ url.searchParams.delete("paln");
7911
+ url.searchParams.set("givn", "[SCVP-GIVN]");
7912
+ }
7913
+ return url.toString();
7914
+ } catch (unused) {
7915
+ return rawUrl;
7916
+ }
7917
+ }
7379
7918
  var AdConfigManager = /*#__PURE__*/ function() {
7380
7919
  "use strict";
7381
7920
  function AdConfigManager(config, video) {
@@ -7387,8 +7926,8 @@ var AdConfigManager = /*#__PURE__*/ function() {
7387
7926
  this.podCounter = 0;
7388
7927
  this.podAssignedByPrefetch = false;
7389
7928
  this.lastHeartbeatTime = 0;
7390
- this.defaultPodMaxAds = 6;
7391
- this.defaultPodMaxDurationMs = 12e4;
7929
+ this.defaultEdgePodMaxAds = 6;
7930
+ this.palNonceDispatchWaitMs = 1500;
7392
7931
  this.config = config;
7393
7932
  this.video = video;
7394
7933
  }
@@ -7416,7 +7955,7 @@ var AdConfigManager = /*#__PURE__*/ function() {
7416
7955
  key: "fetchAdConfiguration",
7417
7956
  value: function fetchAdConfiguration() {
7418
7957
  return _async_to_generator(function() {
7419
- 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;
7958
+ 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;
7420
7959
  return _ts_generator(this, function(_state) {
7421
7960
  switch(_state.label){
7422
7961
  case 0:
@@ -7437,28 +7976,6 @@ var AdConfigManager = /*#__PURE__*/ function() {
7437
7976
  2
7438
7977
  ];
7439
7978
  case 2:
7440
- vastMode = this.config.vastMode || "default";
7441
- if (this.debug) {
7442
- console.log("[StormcloudVideoPlayer] VAST mode:", vastMode);
7443
- }
7444
- if (vastMode === "adstorm") {
7445
- if (!this.config.licenseKey) {
7446
- if (this.debug) {
7447
- console.warn("[StormcloudVideoPlayer] AdStorm mode requires a license key");
7448
- }
7449
- return [
7450
- 2
7451
- ];
7452
- }
7453
- vastEndpoint = "https://adstorm.co/api-adstorm-dev/adstorm/vast/".concat(this.config.licenseKey);
7454
- this.apiVastTagUrl = vastEndpoint;
7455
- if (this.debug) {
7456
- console.log("[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):", vastEndpoint);
7457
- }
7458
- return [
7459
- 2
7460
- ];
7461
- }
7462
7979
  if (this.config.vastTagUrl) {
7463
7980
  this.apiVastTagUrl = normalizeVastTagUrl(this.config.vastTagUrl);
7464
7981
  if (this.debug) {
@@ -7468,7 +7985,7 @@ var AdConfigManager = /*#__PURE__*/ function() {
7468
7985
  2
7469
7986
  ];
7470
7987
  }
7471
- apiUrl = "https://adstorm.co/api-adstorm-dev/adstorm/ads/web";
7988
+ apiUrl = "https://edge.stormcloudhub.com/api/v1/adstorm/ads/web";
7472
7989
  if (this.debug) {
7473
7990
  console.log("[StormcloudVideoPlayer] Fetching ad configuration from:", apiUrl);
7474
7991
  }
@@ -7815,16 +8332,16 @@ var AdConfigManager = /*#__PURE__*/ function() {
7815
8332
  }
7816
8333
  },
7817
8334
  {
7818
- key: "resolvePodParams",
7819
- value: function resolvePodParams(breakDurationMs) {
7820
- var maxDurationMs = breakDurationMs != null && breakDurationMs > 0 ? breakDurationMs : this.config.podMaxDurationMs != null && this.config.podMaxDurationMs > 0 ? this.config.podMaxDurationMs : this.defaultPodMaxDurationMs;
7821
- var maxAds = this.config.podMaxAds && this.config.podMaxAds > 0 ? this.config.podMaxAds : this.apiNumberAds && this.apiNumberAds > 0 ? this.apiNumberAds : this.defaultPodMaxAds;
7822
- var minDurationMs = this.config.podExactDuration && maxDurationMs != null ? maxDurationMs : 0;
7823
- return {
7824
- maxAds: maxAds,
7825
- minDurationMs: minDurationMs,
7826
- maxDurationMs: maxDurationMs
7827
- };
8335
+ key: "resolveAdPodConfig",
8336
+ value: function resolveAdPodConfig1() {
8337
+ return resolveAdPodConfig(this.config);
8338
+ }
8339
+ },
8340
+ {
8341
+ key: "resolveEdgeMaxAds",
8342
+ value: function resolveEdgeMaxAds() {
8343
+ var _this_resolveAdPodConfig_maxAdsPerBreak;
8344
+ 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;
7828
8345
  }
7829
8346
  },
7830
8347
  {
@@ -7841,17 +8358,13 @@ var AdConfigManager = /*#__PURE__*/ function() {
7841
8358
  },
7842
8359
  {
7843
8360
  key: "generatePodVastUrl",
7844
- value: function generatePodVastUrl(baseUrl, podParams, adPlayer, palNonce, inAdBreak) {
7845
- var _podParams_maxDurationMs;
8361
+ value: function generatePodVastUrl(baseUrl, adPlayer, palNonce, inAdBreak) {
7846
8362
  var adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;
7847
8363
  var envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);
7848
- var urlWithMacros = applyVastMacros(baseUrl, _object_spread_props(_object_spread({
8364
+ var macroContext = _object_spread_props(_object_spread({
7849
8365
  correlator: this.viewCorrelator,
7850
8366
  streamCorrelator: this.streamCorrelator,
7851
8367
  pod: this.podCounter > 0 ? this.podCounter : void 0,
7852
- podMaxAds: podParams.maxAds,
7853
- podMinDurationMs: podParams.minDurationMs,
7854
- podMaxDurationMs: podParams.maxDurationMs,
7855
8368
  isCtv: envSignals.isCtv,
7856
8369
  pageUrl: !envSignals.isCtv && typeof window !== "undefined" ? toDevSafeUrl(window.location.href) : void 0,
7857
8370
  adWillPlayMuted: adWillPlayMuted,
@@ -7867,13 +8380,72 @@ var AdConfigManager = /*#__PURE__*/ function() {
7867
8380
  } : {}, this.config.channelName ? {
7868
8381
  channelName: this.config.channelName
7869
8382
  } : {}), {
7870
- consent: this.consentSignals
7871
- }));
7872
- var finalUrl = palNonce.injectNonce(ensureVideoAdType(urlWithMacros));
7873
- 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);
8383
+ consent: this.consentSignals,
8384
+ palNonce: palNonce.getCurrentNonce() || void 0
8385
+ });
8386
+ var nonceReady = !!macroContext.palNonce;
8387
+ var finalUrl;
8388
+ if (hasScvpMacros(baseUrl)) {
8389
+ var deferred = new Set(SCVP_POD_MACROS);
8390
+ if (!nonceReady) deferred.add("GIVN");
8391
+ var _applyScvpMacros = applyScvpMacros(baseUrl, macroContext, deferred), url = _applyScvpMacros.url, unresolved = _applyScvpMacros.unresolved;
8392
+ if (unresolved.length > 0) {
8393
+ console.warn("[StormcloudVideoPlayer] Unresolved SCVP macros (removed from request):", unresolved.join(", "));
8394
+ }
8395
+ finalUrl = ensureVideoAdType(url);
8396
+ } else {
8397
+ finalUrl = withDeferredPodParams(palNonce.injectNonce(ensureVideoAdType(applyVastMacros(baseUrl, macroContext))), !nonceReady);
8398
+ }
8399
+ console.log("[StormcloudVideoPlayer] Prepared optimized-pod request URL (pod=".concat(this.podCounter, "; pmnd/pmxd/pmad resolved at dispatch):"), finalUrl);
7874
8400
  return finalUrl;
7875
8401
  }
7876
8402
  },
8403
+ {
8404
+ key: "completeDeferredRequestSignals",
8405
+ value: function completeDeferredRequestSignals(url, palNonce) {
8406
+ return _async_to_generator(function() {
8407
+ var nonce, _tmp;
8408
+ return _ts_generator(this, function(_state) {
8409
+ switch(_state.label){
8410
+ case 0:
8411
+ if (findScvpMacroNames(url).indexOf("GIVN") === -1) return [
8412
+ 2,
8413
+ url
8414
+ ];
8415
+ _tmp = palNonce.getCurrentNonce();
8416
+ if (_tmp) return [
8417
+ 3,
8418
+ 2
8419
+ ];
8420
+ return [
8421
+ 4,
8422
+ palNonce.waitForNonce(this.palNonceDispatchWaitMs)
8423
+ ];
8424
+ case 1:
8425
+ _tmp = _state.sent();
8426
+ _state.label = 2;
8427
+ case 2:
8428
+ nonce = _tmp;
8429
+ if (!nonce) return [
8430
+ 2,
8431
+ url
8432
+ ];
8433
+ return [
8434
+ 2,
8435
+ substituteScvpMacros(url, /* @__PURE__ */ new Map([
8436
+ [
8437
+ "GIVN",
8438
+ nonce
8439
+ ]
8440
+ ]), function(name) {
8441
+ return name !== "GIVN";
8442
+ }).url
8443
+ ];
8444
+ }
8445
+ });
8446
+ }).call(this);
8447
+ }
8448
+ },
7877
8449
  {
7878
8450
  // --- Tracking ---
7879
8451
  key: "initializeTracking",
@@ -7921,6 +8493,9 @@ var AdConfigManager = /*#__PURE__*/ function() {
7921
8493
  return AdConfigManager;
7922
8494
  }();
7923
8495
  // src/player/AdTimingService.ts
8496
+ function monotonicNow() {
8497
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
8498
+ }
7924
8499
  var AdTimingService = /*#__PURE__*/ function() {
7925
8500
  "use strict";
7926
8501
  function AdTimingService(config, video, callbacks) {
@@ -8052,6 +8627,21 @@ var AdTimingService = /*#__PURE__*/ function() {
8052
8627
  },
8053
8628
  {
8054
8629
  // --- Duration boundary ---
8630
+ key: "beginBreakTiming",
8631
+ value: function beginBreakTiming(startWallClockMs) {
8632
+ this.currentAdBreakStartWallClockMs = startWallClockMs;
8633
+ this.breakStartMonoMs = monotonicNow() + (startWallClockMs - Date.now());
8634
+ this.breakEndMonoMs = void 0;
8635
+ }
8636
+ },
8637
+ {
8638
+ key: "markBreakEndedNow",
8639
+ value: function markBreakEndedNow() {
8640
+ this.scteAdBreakEndWallClockMs = Date.now();
8641
+ this.breakEndMonoMs = monotonicNow();
8642
+ }
8643
+ },
8644
+ {
8055
8645
  key: "setAdBreakDurationBoundary",
8056
8646
  value: function setAdBreakDurationBoundary(durationMs) {
8057
8647
  this.expectedAdBreakDurationMs = durationMs;
@@ -8060,6 +8650,18 @@ var AdTimingService = /*#__PURE__*/ function() {
8060
8650
  } else {
8061
8651
  this.scteAdBreakEndWallClockMs = void 0;
8062
8652
  }
8653
+ this.breakEndMonoMs = durationMs != null && this.breakStartMonoMs != null ? this.breakStartMonoMs + durationMs : void 0;
8654
+ }
8655
+ },
8656
+ {
8657
+ key: "getBreakTimingSnapshot",
8658
+ value: function getBreakTimingSnapshot() {
8659
+ return {
8660
+ scheduledBreakDurationMs: this.expectedAdBreakDurationMs,
8661
+ breakStartMonoMs: this.breakStartMonoMs,
8662
+ breakEndMonoMs: this.breakEndMonoMs,
8663
+ playedDurationMs: this.adBreakPlayedDurationMs
8664
+ };
8063
8665
  }
8064
8666
  },
8065
8667
  {
@@ -8473,6 +9075,8 @@ var AdTimingService = /*#__PURE__*/ function() {
8473
9075
  this.expectedAdBreakDurationMs = void 0;
8474
9076
  this.currentAdBreakStartWallClockMs = void 0;
8475
9077
  this.scteAdBreakEndWallClockMs = void 0;
9078
+ this.breakStartMonoMs = void 0;
9079
+ this.breakEndMonoMs = void 0;
8476
9080
  this.adBreakPlayedDurationMs = 0;
8477
9081
  this.currentAdIndex = 0;
8478
9082
  this.totalAdsInBreak = 0;
@@ -9489,9 +10093,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9489
10093
  // ───────────────────────────────────────────────────────────────
9490
10094
  key: "nextAdRequestUrl",
9491
10095
  value: function nextAdRequestUrl(baseVastUrl) {
9492
- var remaining = Math.min(this.timing.getWallClockRemainingAdMs(), this.timing.getDurationBudgetRemainingMs());
9493
- var breakDurationMs = remaining > 0 ? remaining : void 0;
9494
- return this.host.generatePodVastUrl(baseVastUrl, breakDurationMs);
10096
+ return this.host.generatePodVastUrl(baseVastUrl);
9495
10097
  }
9496
10098
  },
9497
10099
  {
@@ -9754,7 +10356,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9754
10356
  key: "handleAdStart",
9755
10357
  value: function handleAdStart(marker) {
9756
10358
  return _async_to_generator(function() {
9757
- var baseVastUrl, edgeConfigured, adBreakDurationMs, currentMuted, currentVolume, epoch, hasPrefetchedUrl, mode, edgeUrl, outcome, podPlayed;
10359
+ var baseVastUrl, edgeConfigured, adBreakDurationMs, currentMuted, currentVolume, epoch, mode, edgeUrl, outcome, podPlayed;
9758
10360
  return _ts_generator(this, function(_state) {
9759
10361
  switch(_state.label){
9760
10362
  case 0:
@@ -9806,8 +10408,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9806
10408
  }
9807
10409
  this.noteOpportunity("scte35", this.cueManager.activeScte35BreakKey, "midroll");
9808
10410
  epoch = this.timing.adBreakEpoch;
9809
- hasPrefetchedUrl = !!(this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0);
9810
- if (!(adBreakDurationMs == null && (!hasPrefetchedUrl || edgeConfigured))) return [
10411
+ if (!(adBreakDurationMs == null)) return [
9811
10412
  3,
9812
10413
  2
9813
10414
  ];
@@ -9863,7 +10464,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9863
10464
  }
9864
10465
  return [
9865
10466
  4,
9866
- this.startOptimizedPod(baseVastUrl, adBreakDurationMs)
10467
+ this.startOptimizedPod(baseVastUrl)
9867
10468
  ];
9868
10469
  case 6:
9869
10470
  podPlayed = _state.sent();
@@ -9931,9 +10532,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9931
10532
  value: // ───────────────────────────────────────────────────────────────
9932
10533
  // Optimized pod (single multi-ad request)
9933
10534
  // ───────────────────────────────────────────────────────────────
9934
- function startOptimizedPod(baseVastUrl, breakDurationMs) {
10535
+ function startOptimizedPod(baseVastUrl) {
9935
10536
  return _async_to_generator(function() {
9936
- var podUrl, prefetched, epoch, generation, adPlayer, requestToken, requestUrl, _ref, _adPlayer_getPodAdCount, podCount, error;
10537
+ var podUrl, prefetched, epoch, generation, adPlayer, requestToken, requestUrl, _ref, _this_currentVastUrl, _adPlayer_getPodAdCount, finalizeRequestUrl, podCount, error;
9937
10538
  return _ts_generator(this, function(_state) {
9938
10539
  switch(_state.label){
9939
10540
  case 0:
@@ -9942,7 +10543,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9942
10543
  podUrl = this.pendingAdBreak.vastUrls[0];
9943
10544
  this.clearPendingAdBreak();
9944
10545
  } else {
9945
- podUrl = this.host.generatePodVastUrl(baseVastUrl, breakDurationMs);
10546
+ podUrl = this.host.generatePodVastUrl(baseVastUrl);
9946
10547
  }
9947
10548
  if (!podUrl) {
9948
10549
  return [
@@ -9966,9 +10567,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9966
10567
  case 1:
9967
10568
  _state.trys.push([
9968
10569
  1,
9969
- 5,
10570
+ 9,
9970
10571
  ,
9971
- 6
10572
+ 10
9972
10573
  ]);
9973
10574
  return [
9974
10575
  4,
@@ -9980,15 +10581,46 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9980
10581
  2,
9981
10582
  true
9982
10583
  ];
10584
+ return [
10585
+ 4,
10586
+ this.host.completeGamRequestSignals(requestUrl)
10587
+ ];
10588
+ case 3:
10589
+ requestUrl = _state.sent();
10590
+ if (this.isStale(epoch, generation)) return [
10591
+ 2,
10592
+ true
10593
+ ];
9983
10594
  this.timing.startAdRequestWatchdog(requestToken);
10595
+ finalizeRequestUrl = this.createGamDispatchFinalizer(requestToken);
10596
+ _state.label = 4;
10597
+ case 4:
10598
+ _state.trys.push([
10599
+ 4,
10600
+ ,
10601
+ 6,
10602
+ 7
10603
+ ]);
9984
10604
  return [
9985
10605
  4,
9986
10606
  this.callController(function() {
9987
- return adPlayer.requestAds(requestUrl);
10607
+ return adPlayer.requestAds(requestUrl, {
10608
+ finalizeRequestUrl: finalizeRequestUrl
10609
+ });
9988
10610
  })
9989
10611
  ];
9990
- case 3:
10612
+ case 5:
9991
10613
  _state.sent();
10614
+ return [
10615
+ 3,
10616
+ 7
10617
+ ];
10618
+ case 6:
10619
+ this.recordPodResponseDiagnostics(requestToken, adPlayer);
10620
+ return [
10621
+ 7
10622
+ ];
10623
+ case 7:
9992
10624
  this.timing.clearAdRequestWatchdog();
9993
10625
  if (this.isStale(epoch, generation)) {
9994
10626
  this.logOrchestratorFunnel("stale_request_result_ignored", {
@@ -10016,7 +10648,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10016
10648
  }
10017
10649
  sendAdLoadedTracking(this.host.config.licenseKey, {
10018
10650
  source: "hls",
10019
- vastUrl: requestUrl,
10651
+ vastUrl: (_this_currentVastUrl = this.currentVastUrl) !== null && _this_currentVastUrl !== void 0 ? _this_currentVastUrl : requestUrl,
10020
10652
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
10021
10653
  }, this.analyticsContext).catch(function() {});
10022
10654
  this.timing.startAdFailsafeTimer(requestToken);
@@ -10026,7 +10658,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10026
10658
  return adPlayer.play();
10027
10659
  })
10028
10660
  ];
10029
- case 4:
10661
+ case 8:
10030
10662
  _state.sent();
10031
10663
  if (this.isStale(epoch, generation)) return [
10032
10664
  2,
@@ -10040,7 +10672,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10040
10672
  2,
10041
10673
  true
10042
10674
  ];
10043
- case 5:
10675
+ case 9:
10044
10676
  error = _state.sent();
10045
10677
  this.timing.clearAdRequestWatchdog();
10046
10678
  this.timing.clearAdFailsafeTimer();
@@ -10060,12 +10692,16 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10060
10692
  if (this.debug) {
10061
10693
  console.warn("[POD] Optimized pod request/play failed:", error);
10062
10694
  }
10695
+ if (this.handlePodRequestNotSent(error)) return [
10696
+ 2,
10697
+ false
10698
+ ];
10063
10699
  this.recordRequestFailure(error, podUrl);
10064
10700
  return [
10065
10701
  2,
10066
10702
  false
10067
10703
  ];
10068
- case 6:
10704
+ case 10:
10069
10705
  return [
10070
10706
  2
10071
10707
  ];
@@ -10111,17 +10747,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10111
10747
  }
10112
10748
  },
10113
10749
  {
10114
- /**
10115
- * Builds the next Edge request from the budget left right now, or marks Edge
10116
- * exhausted for this break. Synchronous on purpose: callers must reach the
10117
- * REQUESTING state in the same tick so a second completion event cannot race
10118
- * in a parallel request.
10119
- */ key: "prepareEdgePodRequest",
10750
+ key: "prepareEdgePodRequest",
10120
10751
  value: function prepareEdgePodRequest() {
10121
10752
  var baseUrl = this.host.getEdgePodBaseUrl();
10122
10753
  if (!baseUrl) return void 0;
10123
10754
  var remainingMs = this.timing.getRemainingAdMs();
10124
- var remainingAds = Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak);
10755
+ var remainingAds = Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolveEdgeMaxAds() - this.timing.totalAdsInBreak);
10125
10756
  if (remainingAds < 1) {
10126
10757
  this.markEdgeExhausted("ad_capacity_reached", {
10127
10758
  adsInBreak: this.timing.totalAdsInBreak
@@ -10200,7 +10831,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10200
10831
  ];
10201
10832
  }
10202
10833
  remainingMs = this.timing.getRemainingAdMs();
10203
- remainingAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak));
10834
+ remainingAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolveEdgeMaxAds() - this.timing.totalAdsInBreak));
10204
10835
  overrunAllowanceMs = Math.max(0, (_this_host_config_maxAdBreakExtensionMs = this.host.config.maxAdBreakExtensionMs) !== null && _this_host_config_maxAdBreakExtensionMs !== void 0 ? _this_host_config_maxAdBreakExtensionMs : 0);
10205
10836
  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;
10206
10837
  if (classifyEdgeVastResponse({
@@ -10547,7 +11178,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10547
11178
  {
10548
11179
  key: "noteVastUrlGenerated",
10549
11180
  value: function noteVastUrlGenerated(url, source) {
10550
- var _ref, _ref1, _ref2, _ref3, _ref4;
11181
+ var _ref, _ref1;
10551
11182
  var params;
10552
11183
  try {
10553
11184
  params = new URL(url).searchParams;
@@ -10557,9 +11188,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10557
11188
  requestId: void 0,
10558
11189
  source: source,
10559
11190
  pod: (_ref1 = params === null || params === void 0 ? void 0 : params.get("pod")) !== null && _ref1 !== void 0 ? _ref1 : void 0,
10560
- pmad: (_ref2 = params === null || params === void 0 ? void 0 : params.get("pmad")) !== null && _ref2 !== void 0 ? _ref2 : void 0,
10561
- pmnd: (_ref3 = params === null || params === void 0 ? void 0 : params.get("pmnd")) !== null && _ref3 !== void 0 ? _ref3 : void 0,
10562
- pmxd: (_ref4 = params === null || params === void 0 ? void 0 : params.get("pmxd")) !== null && _ref4 !== void 0 ? _ref4 : void 0,
11191
+ podParamsDeferredToDispatch: findScvpMacroNames(url).some(function(name) {
11192
+ return SCVP_POD_MACROS.has(name);
11193
+ }),
10563
11194
  adType: adType
10564
11195
  });
10565
11196
  if (adType === "audio" || adType === "audio_video") {
@@ -10600,10 +11231,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10600
11231
  if (diag && !diag.failureReason) {
10601
11232
  diag.failureReason = "".concat(outcome, ": ").concat(message);
10602
11233
  }
11234
+ var failureKey = (diag === null || diag === void 0 ? void 0 : diag.dispatchedUrl) && findScvpMacroNames(vastTagUrl).some(function(name) {
11235
+ return SCVP_POD_MACROS.has(name);
11236
+ }) ? diag.dispatchedUrl : vastTagUrl;
10603
11237
  if (this.timing.isTemporaryAdError(error)) {
10604
- this.timing.temporaryFailureUrls.set(vastTagUrl, Date.now());
11238
+ this.timing.temporaryFailureUrls.set(failureKey, Date.now());
10605
11239
  } else if (outcome !== "discarded_budget") {
10606
- this.timing.failedVastUrls.add(vastTagUrl);
11240
+ this.timing.failedVastUrls.add(failureKey);
10607
11241
  }
10608
11242
  this.countFunnelStage("request_outcome:".concat(outcome));
10609
11243
  this.logOrchestratorFunnel("request_outcome", _object_spread({
@@ -10629,6 +11263,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10629
11263
  switch(payload.stage){
10630
11264
  case "gam_http_request_sent":
10631
11265
  diag.gamRequestSent++;
11266
+ this.logPodDispatch(diag);
10632
11267
  break;
10633
11268
  case "edge_http_request_sent":
10634
11269
  diag.edgeRequestSent++;
@@ -10680,8 +11315,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10680
11315
  if (gamReturnedAdWithoutImpression) {
10681
11316
  this.countFunnelStage("gam_ad_without_impression");
10682
11317
  }
10683
- var startedAt = diag.startedAt, fields = _object_without_properties(diag, [
10684
- "startedAt"
11318
+ var startedAt = diag.startedAt, _dispatchedUrl = diag.dispatchedUrl, _logged = diag.podDispatchLogged, fields = _object_without_properties(diag, [
11319
+ "startedAt",
11320
+ "dispatchedUrl",
11321
+ "podDispatchLogged"
10685
11322
  ]);
10686
11323
  console.log("[AdBreak][REQUEST] summary", _object_spread_props(_object_spread({}, fields), {
10687
11324
  durationMs: Date.now() - startedAt,
@@ -10693,24 +11330,71 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10693
11330
  // ───────────────────────────────────────────────────────────────
10694
11331
  // Single ad playback
10695
11332
  // ───────────────────────────────────────────────────────────────
10696
- key: "withCurrentPodBudget",
10697
- value: function withCurrentPodBudget(rawVastTagUrl) {
10698
- var vastTagUrl = ensureVideoAdType(rawVastTagUrl);
10699
- var remaining = Math.min(this.timing.getWallClockRemainingAdMs(), this.timing.getDurationBudgetRemainingMs());
10700
- if (!(remaining > 0)) return vastTagUrl;
10701
- try {
10702
- var url = new URL(vastTagUrl);
10703
- if (!url.searchParams.has("pmxd")) return vastTagUrl;
10704
- var maxMs = Math.round(remaining);
10705
- url.searchParams.set("pmxd", String(maxMs));
10706
- var minMs = Number(url.searchParams.get("pmnd"));
10707
- if (Number.isFinite(minMs) && minMs > maxMs) {
10708
- url.searchParams.set("pmnd", String(maxMs));
10709
- }
10710
- return url.toString();
10711
- } catch (unused) {
10712
- return vastTagUrl;
10713
- }
11333
+ key: "createGamDispatchFinalizer",
11334
+ value: function createGamDispatchFinalizer(requestToken) {
11335
+ var _this = this;
11336
+ var breakId = this.timing.adBreakEpoch;
11337
+ var config = this.adConfig.resolveAdPodConfig();
11338
+ var minUsablePmxdMs = this.timing.getMinRemainingMsToStartAd();
11339
+ return function(url) {
11340
+ var capacity = measureBreakCapacity(_this.timing.getBreakTimingSnapshot(), monotonicNow());
11341
+ var diag = _this.requestDiagnostics.get(requestToken);
11342
+ try {
11343
+ var result = finalizeGamRequestUrl(url, {
11344
+ breakId: breakId,
11345
+ capacity: capacity,
11346
+ config: config,
11347
+ minUsablePmxdMs: minUsablePmxdMs
11348
+ });
11349
+ if (diag) {
11350
+ diag.pod = result.diagnostics;
11351
+ diag.dispatchedUrl = result.url;
11352
+ diag.podDispatchLogged = false;
11353
+ }
11354
+ _this.currentVastUrl = result.url;
11355
+ return result.url;
11356
+ } catch (error) {
11357
+ if (diag && isPodRequestAbortedError(error)) {
11358
+ diag.failureReason = "pod_request_not_sent:".concat(error.reason);
11359
+ }
11360
+ throw error;
11361
+ }
11362
+ };
11363
+ }
11364
+ },
11365
+ {
11366
+ key: "logPodDispatch",
11367
+ value: function logPodDispatch(diag) {
11368
+ if (!diag.pod || diag.podDispatchLogged) return;
11369
+ diag.podDispatchLogged = true;
11370
+ this.logOrchestratorFunnel(diag.pod.optimizedPod ? "optimized_pod_request_dispatched" : "gam_request_dispatched", _object_spread({}, diag.pod));
11371
+ }
11372
+ },
11373
+ {
11374
+ key: "recordPodResponseDiagnostics",
11375
+ value: function recordPodResponseDiagnostics(requestToken, adPlayer) {
11376
+ var _diag_vastAdCount, _ref;
11377
+ var _adPlayer_getPodTotalDurationMs;
11378
+ var diag = this.requestDiagnostics.get(requestToken);
11379
+ if (!(diag === null || diag === void 0 ? void 0 : diag.pod) || diag.pod.pmxdSent == null || diag.podResponse) return;
11380
+ if (diag.gamRequestSent === 0 && diag.vastHttpStatus == null) return;
11381
+ 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);
11382
+ this.logOrchestratorFunnel("optimized_pod_response", _object_spread({
11383
+ pmxdSent: diag.pod.pmxdSent
11384
+ }, diag.podResponse));
11385
+ }
11386
+ },
11387
+ {
11388
+ key: "handlePodRequestNotSent",
11389
+ value: function handlePodRequestNotSent(error) {
11390
+ if (!isPodRequestAbortedError(error) || error.reason === "invalid_url") return false;
11391
+ var aborted = error;
11392
+ this.countFunnelStage("request_outcome:pod_request_not_sent");
11393
+ this.logOrchestratorFunnel("pod_request_not_sent", _object_spread({
11394
+ reason: aborted.reason,
11395
+ errorMessage: aborted.message
11396
+ }, aborted.diagnostics));
11397
+ return true;
10714
11398
  }
10715
11399
  },
10716
11400
  {
@@ -10930,7 +11614,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10930
11614
  value: function playSingleAd(vastTagUrl) {
10931
11615
  var trigger = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "vmap";
10932
11616
  return _async_to_generator(function() {
10933
- var epoch, generation, requestToken, ap, budgetedUrl, requestUrl, _ap_getLoadedAdDuration, adDurationS, remainingMs, error;
11617
+ var epoch, generation, requestToken, ap, requestUrl, _this_currentVastUrl, finalizeRequestUrl, _ap_getLoadedAdDuration, adDurationS, remainingMs, error;
10934
11618
  return _ts_generator(this, function(_state) {
10935
11619
  switch(_state.label){
10936
11620
  case 0:
@@ -10968,19 +11652,18 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10968
11652
  requestToken = ++this.timing.adRequestTokenCounter;
10969
11653
  this.timing.activeAdRequestToken = requestToken;
10970
11654
  ap = this.host.getAdPlayer();
10971
- budgetedUrl = this.withCurrentPodBudget(vastTagUrl);
10972
11655
  this.currentPodSource = "gam";
10973
11656
  this.setSlotState("REQUESTING", trigger);
10974
11657
  this.beginFunnelRequest(ap, requestToken, trigger);
10975
- requestUrl = this.applyOpportunityFloor(budgetedUrl);
11658
+ requestUrl = this.applyOpportunityFloor(ensureVideoAdType(vastTagUrl));
10976
11659
  this.currentVastUrl = requestUrl;
10977
11660
  _state.label = 1;
10978
11661
  case 1:
10979
11662
  _state.trys.push([
10980
11663
  1,
10981
- 5,
11664
+ 9,
10982
11665
  ,
10983
- 6
11666
+ 10
10984
11667
  ]);
10985
11668
  return [
10986
11669
  4,
@@ -10991,15 +11674,45 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10991
11674
  if (this.isStale(epoch, generation)) return [
10992
11675
  2
10993
11676
  ];
11677
+ return [
11678
+ 4,
11679
+ this.host.completeGamRequestSignals(requestUrl)
11680
+ ];
11681
+ case 3:
11682
+ requestUrl = _state.sent();
11683
+ if (this.isStale(epoch, generation)) return [
11684
+ 2
11685
+ ];
10994
11686
  this.timing.startAdRequestWatchdog(requestToken);
11687
+ finalizeRequestUrl = this.createGamDispatchFinalizer(requestToken);
11688
+ _state.label = 4;
11689
+ case 4:
11690
+ _state.trys.push([
11691
+ 4,
11692
+ ,
11693
+ 6,
11694
+ 7
11695
+ ]);
10995
11696
  return [
10996
11697
  4,
10997
11698
  this.callController(function() {
10998
- return ap.requestAds(requestUrl);
11699
+ return ap.requestAds(requestUrl, {
11700
+ finalizeRequestUrl: finalizeRequestUrl
11701
+ });
10999
11702
  })
11000
11703
  ];
11001
- case 3:
11704
+ case 5:
11002
11705
  _state.sent();
11706
+ return [
11707
+ 3,
11708
+ 7
11709
+ ];
11710
+ case 6:
11711
+ this.recordPodResponseDiagnostics(requestToken, ap);
11712
+ return [
11713
+ 7
11714
+ ];
11715
+ case 7:
11003
11716
  this.timing.clearAdRequestWatchdog();
11004
11717
  if (this.isStale(epoch, generation)) {
11005
11718
  this.logOrchestratorFunnel("stale_request_result_ignored", {
@@ -11011,7 +11724,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11011
11724
  }
11012
11725
  sendAdLoadedTracking(this.host.config.licenseKey, {
11013
11726
  source: "hls",
11014
- vastUrl: requestUrl,
11727
+ vastUrl: (_this_currentVastUrl = this.currentVastUrl) !== null && _this_currentVastUrl !== void 0 ? _this_currentVastUrl : requestUrl,
11015
11728
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
11016
11729
  }, this.analyticsContext).catch(function() {});
11017
11730
  if (!this.timing.ensureLoadedAdFitsBudget(ap)) {
@@ -11032,7 +11745,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11032
11745
  return ap.play();
11033
11746
  })
11034
11747
  ];
11035
- case 4:
11748
+ case 8:
11036
11749
  _state.sent();
11037
11750
  if (this.isStale(epoch, generation)) return [
11038
11751
  2
@@ -11044,9 +11757,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11044
11757
  this.timing.temporaryFailureUrls.delete(vastTagUrl);
11045
11758
  return [
11046
11759
  3,
11047
- 6
11760
+ 10
11048
11761
  ];
11049
- case 5:
11762
+ case 9:
11050
11763
  error = _state.sent();
11051
11764
  this.timing.clearAdRequestWatchdog();
11052
11765
  this.timing.clearAdFailsafeTimer();
@@ -11063,12 +11776,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11063
11776
  ];
11064
11777
  }
11065
11778
  if (this.debug) console.error("[AD-ERROR] Ad request failed:", error === null || error === void 0 ? void 0 : error.message);
11779
+ if (this.handlePodRequestNotSent(error)) throw error;
11066
11780
  this.recordRequestFailure(error, vastTagUrl);
11067
11781
  if ((error === null || error === void 0 ? void 0 : error.message) === "ad_duration_exceeds_budget") {
11068
11782
  this.recreateAdController("discarded_budget");
11069
11783
  }
11070
11784
  throw error;
11071
- case 6:
11785
+ case 10:
11072
11786
  return [
11073
11787
  2
11074
11788
  ];
@@ -11130,7 +11844,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11130
11844
  playbackFailedAfterFill: count("request_outcome:playback_failed"),
11131
11845
  requestFailed: count("request_failed"),
11132
11846
  requestAbortedTimeout: count("request_aborted_timeout"),
11133
- credentialsRetries: count("vast_credentials_retry"),
11847
+ credentialsModeChanges: count("gam_credentials_mode_changed"),
11134
11848
  wrapperFailures: count("wrapper_fetch:failure"),
11135
11849
  noSupportedMedia: count("vast_no_supported_media"),
11136
11850
  vpaidOnly: count("vast_no_supported_media:vpaid"),
@@ -11667,8 +12381,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11667
12381
  requiresMediaPipelineResetAfterAds: function requiresMediaPipelineResetAfterAds1() {
11668
12382
  return requiresMediaPipelineResetAfterAds();
11669
12383
  },
11670
- generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
11671
- return _this.generatePodVastUrl(base, breakDurationMs);
12384
+ generatePodVastUrl: function generatePodVastUrl(base) {
12385
+ return _this.generatePodVastUrl(base);
12386
+ },
12387
+ completeGamRequestSignals: function completeGamRequestSignals(url) {
12388
+ return _this.adConfig.completeDeferredRequestSignals(url, _this.palNonce);
11672
12389
  },
11673
12390
  getEdgePodBaseUrl: function getEdgePodBaseUrl() {
11674
12391
  return _this.edgePodBaseUrl;
@@ -11792,9 +12509,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11792
12509
  },
11793
12510
  {
11794
12511
  key: "generatePodVastUrl",
11795
- value: function generatePodVastUrl(baseUrl, breakDurationMs) {
11796
- var podParams = this.adConfig.resolvePodParams(breakDurationMs);
11797
- return this.adConfig.generatePodVastUrl(baseUrl, podParams, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
12512
+ value: function generatePodVastUrl(baseUrl) {
12513
+ return this.adConfig.generatePodVastUrl(baseUrl, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
11798
12514
  }
11799
12515
  },
11800
12516
  {
@@ -12148,7 +12864,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12148
12864
  activeAdRequest: this.timing.activeAdRequestToken !== null
12149
12865
  });
12150
12866
  }
12151
- this.timing.scteAdBreakEndWallClockMs = Date.now();
12867
+ this.timing.markBreakEndedNow();
12152
12868
  this.timing.clearAdStartTimer();
12153
12869
  this.timing.clearAdStopTimer();
12154
12870
  if (adPlaying) {
@@ -12175,7 +12891,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12175
12891
  this.adBreak.inAdBreak = true;
12176
12892
  this.cueManager.activeScte35BreakKey = cueKey !== null && cueKey !== void 0 ? cueKey : this.cueManager.pendingScte35CueKey;
12177
12893
  this.cueManager.scheduledScte35BreakKey = void 0;
12178
- this.timing.currentAdBreakStartWallClockMs = this.timing.resolveScteBreakStartWallClockMs(marker);
12894
+ this.timing.beginBreakTiming(this.timing.resolveScteBreakStartWallClockMs(marker));
12179
12895
  this.timing.setAdBreakDurationBoundary(durationMs);
12180
12896
  this.adBreak.handleAdStart(marker);
12181
12897
  this.timing.scheduleAdStopAtBreakBoundary();
@@ -12221,9 +12937,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12221
12937
  }
12222
12938
  this.adConfig.beginNewAdPod();
12223
12939
  this.adConfig.podAssignedByPrefetch = true;
12224
- var breakDurationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0;
12225
12940
  var generatedUrls = [
12226
- this.generatePodVastUrl(baseVastUrl, breakDurationMs)
12941
+ this.generatePodVastUrl(baseVastUrl)
12227
12942
  ];
12228
12943
  this.adBreak.pendingAdBreak = _object_spread_props(_object_spread({
12229
12944
  marker: marker
@@ -12322,7 +13037,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12322
13037
  this.adPlayer.updateOriginalMutedState(this.video.muted, this.video.volume);
12323
13038
  this.adBreak.showAds = true;
12324
13039
  this.adBreak.inAdBreak = true;
12325
- this.timing.currentAdBreakStartWallClockMs = Date.now();
13040
+ this.timing.beginBreakTiming(Date.now());
12326
13041
  if (durationMs > 0) {
12327
13042
  this.timing.setAdBreakDurationBoundary(durationMs);
12328
13043
  }
@@ -12594,7 +13309,6 @@ var CRITICAL_PROPS = [
12594
13309
  "vmapUrl",
12595
13310
  "lowLatencyMode",
12596
13311
  "driftToleranceMs",
12597
- "vastMode",
12598
13312
  "ctvAdRequest",
12599
13313
  "adFloorMinCents",
12600
13314
  "adFloorMaxCents",
@@ -12603,7 +13317,7 @@ var CRITICAL_PROPS = [
12603
13317
  var CONTROLS_HIDE_DELAY = 3e3;
12604
13318
  var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
12605
13319
  var StormcloudVideoPlayerComponent = React.memo(function(props) {
12606
- 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, [
13320
+ 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, [
12607
13321
  "src",
12608
13322
  "autoplay",
12609
13323
  "muted",
@@ -12629,7 +13343,6 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
12629
13343
  "poster",
12630
13344
  "children",
12631
13345
  "licenseKey",
12632
- "vastMode",
12633
13346
  "vastTagUrl",
12634
13347
  "isVmap",
12635
13348
  "vmapUrl",
@@ -12637,6 +13350,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
12637
13350
  "ctvAdRequest",
12638
13351
  "programTitle",
12639
13352
  "channelName",
13353
+ "contentNetwork",
12640
13354
  "minRemainingMsToStartAd",
12641
13355
  "minRemainingMsToRequestAd",
12642
13356
  "maxNoFillsPerBreak",
@@ -12795,7 +13509,6 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
12795
13509
  vmapUrl,
12796
13510
  lowLatencyMode,
12797
13511
  driftToleranceMs,
12798
- vastMode,
12799
13512
  adFloorMinCents,
12800
13513
  adFloorMaxCents,
12801
13514
  adFloorStepCents
@@ -12837,7 +13550,6 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
12837
13550
  if (onFullscreenToggle !== void 0) cfg.onFullscreenToggle = onFullscreenToggle;
12838
13551
  if (onControlClick !== void 0) cfg.onControlClick = onControlClick;
12839
13552
  if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
12840
- if (vastMode !== void 0) cfg.vastMode = vastMode;
12841
13553
  if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;
12842
13554
  if (isVmap !== void 0) cfg.isVmap = isVmap;
12843
13555
  if (vmapUrl !== void 0) cfg.vmapUrl = vmapUrl;
@@ -12845,6 +13557,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
12845
13557
  if (ctvAdRequest !== void 0) cfg.ctvAdRequest = ctvAdRequest;
12846
13558
  if (programTitle !== void 0) cfg.programTitle = programTitle;
12847
13559
  if (channelName !== void 0) cfg.channelName = channelName;
13560
+ if (contentNetwork !== void 0) cfg.contentNetwork = contentNetwork;
12848
13561
  if (minRemainingMsToStartAd !== void 0) cfg.minRemainingMsToStartAd = minRemainingMsToStartAd;
12849
13562
  if (minRemainingMsToRequestAd !== void 0) cfg.minRemainingMsToRequestAd = minRemainingMsToRequestAd;
12850
13563
  if (maxNoFillsPerBreak !== void 0) cfg.maxNoFillsPerBreak = maxNoFillsPerBreak;
@@ -15178,5 +15891,5 @@ var createStormcloudPlayer = function createStormcloudPlayer(playerList, fallbac
15178
15891
  };
15179
15892
  var StormcloudPlayer = createStormcloudPlayer(players_default, players_default[players_default.length - 1]);
15180
15893
  var StormcloudPlayer_default = StormcloudPlayer;
15181
- export { DEFAULT_FLOOR_LADDER_BOUNDS, DEFAULT_TRACKING_INGEST_CONFIG, DEFAULT_WEB_FLOOR_LADDER_CONFIG, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer_default as StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, applyTrackingIngestConfig, buildAnalyticsContext, canPlay, configureTrackingIngest, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, fixedFloorSelector, generateFloorLevels, getBrowserConfigOverrides, getBrowserID, getClientInfo, ingestPlayerTracking, initializePolyfills, isMediaStream, isTrackingIngestEnabled, lazy, logBrowserInfo, merge, omit, parseQuery, players_default as players, randomString, requiresMediaPipelineResetAfterAds, resolveFloorLadderBounds, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode, trackingIngestConfig, validateFloorCents, validateFloorLadderConfig };
15894
+ export { DEFAULT_FLOOR_LADDER_BOUNDS, DEFAULT_REQUEST_SAFETY_MS, DEFAULT_TRACKING_INGEST_CONFIG, DEFAULT_WEB_FLOOR_LADDER_CONFIG, GAM_AD_OPPORTUNITY_DURATION_MS, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer_default as StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, applyTrackingIngestConfig, buildAnalyticsContext, canPlay, configureTrackingIngest, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, fixedFloorSelector, generateFloorLevels, getBrowserConfigOverrides, getBrowserID, getClientInfo, ingestPlayerTracking, initializePolyfills, isMediaStream, isTrackingIngestEnabled, lazy, logBrowserInfo, merge, omit, parseQuery, players_default as players, randomString, requiresMediaPipelineResetAfterAds, resolveFloorLadderBounds, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode, trackingIngestConfig, validateFloorCents, validateFloorLadderConfig };
15182
15895
  //# sourceMappingURL=index.js.map