stormcloud-video-player 0.8.18 → 0.8.20

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 (48) hide show
  1. package/README.md +67 -83
  2. package/dist/stormcloud-vp.min.js +1 -1
  3. package/lib/index.cjs +686 -353
  4. package/lib/index.cjs.map +1 -1
  5. package/lib/index.d.cts +1 -1
  6. package/lib/index.d.ts +1 -1
  7. package/lib/index.js +686 -353
  8. package/lib/index.js.map +1 -1
  9. package/lib/player/AdBreakOrchestrator.cjs +11 -11
  10. package/lib/player/AdBreakOrchestrator.cjs.map +1 -1
  11. package/lib/player/AdBreakOrchestrator.d.cts +4 -4
  12. package/lib/player/{VmapManager.cjs → AdConfigManager.cjs} +561 -217
  13. package/lib/player/AdConfigManager.cjs.map +1 -0
  14. package/lib/player/{VmapManager.d.cts → AdConfigManager.d.cts} +3 -3
  15. package/lib/player/AdPreloadPool.d.cts +1 -1
  16. package/lib/player/AdTimingService.d.cts +1 -1
  17. package/lib/player/HlsEngine.d.cts +1 -1
  18. package/lib/player/PlayerControls.d.cts +1 -1
  19. package/lib/player/Scte35CueManager.d.cts +1 -1
  20. package/lib/player/Scte35Parser.d.cts +1 -1
  21. package/lib/player/StormcloudVideoPlayer.cjs +686 -353
  22. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  23. package/lib/player/StormcloudVideoPlayer.d.cts +2 -2
  24. package/lib/player/playerTypes.d.cts +1 -1
  25. package/lib/players/HlsPlayer.cjs +686 -353
  26. package/lib/players/HlsPlayer.cjs.map +1 -1
  27. package/lib/players/HlsPlayer.d.cts +1 -1
  28. package/lib/players/index.cjs +686 -353
  29. package/lib/players/index.cjs.map +1 -1
  30. package/lib/sdk/hlsAdPlayer.cjs +5 -4
  31. package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
  32. package/lib/sdk/hlsAdPlayer.d.cts +1 -1
  33. package/lib/types-BAP8n5mE.d.cts +126 -0
  34. package/lib/ui/StormcloudVideoPlayer.cjs +686 -353
  35. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  36. package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
  37. package/lib/utils/ctvVastSignals.cjs +103 -33
  38. package/lib/utils/ctvVastSignals.cjs.map +1 -1
  39. package/lib/utils/ctvVastSignals.d.cts +1 -13
  40. package/lib/utils/tracking.d.cts +1 -1
  41. package/lib/utils/vastEnvironmentSignals.cjs +450 -0
  42. package/lib/utils/vastEnvironmentSignals.cjs.map +1 -0
  43. package/lib/utils/vastEnvironmentSignals.d.cts +16 -0
  44. package/lib/utils/vastMacros.cjs +347 -25
  45. package/lib/utils/vastMacros.cjs.map +1 -1
  46. package/lib/utils/vastMacros.d.cts +3 -1
  47. package/package.json +1 -1
  48. package/lib/player/VmapManager.cjs.map +0 -1
@@ -776,6 +776,7 @@ function createHlsAdPlayer(contentVideo, options) {
776
776
  handleAdComplete();
777
777
  });
778
778
  adVideoElement.addEventListener("error", function(e) {
779
+ if (!adPlaying) return;
779
780
  console.error("[HlsAdPlayer] Ad video error:", e);
780
781
  if (currentAd) {
781
782
  fireTrackingPixels(currentAd.trackingUrls.error);
@@ -977,15 +978,15 @@ function createHlsAdPlayer(contentVideo, options) {
977
978
  adVideoElement.muted = originalMutedState;
978
979
  console.log("[HlsAdPlayer] Set ad video volume to ".concat(adVideoElement.volume, ", muted: ").concat(adVideoElement.muted, ", originalMutedState: ").concat(originalMutedState, ", contentVolume: ").concat(contentVolume));
979
980
  }
981
+ mediaFile = selectBestMediaFile(currentAd.mediaFiles);
982
+ if (!mediaFile) {
983
+ throw new Error("No media file available for ad");
984
+ }
980
985
  if (adContainerEl) {
981
986
  adContainerEl.style.display = "flex";
982
987
  adContainerEl.style.pointerEvents = "auto";
983
988
  }
984
989
  emit("content_pause");
985
- mediaFile = selectBestMediaFile(currentAd.mediaFiles);
986
- if (!mediaFile) {
987
- throw new Error("No media file available for ad");
988
- }
989
990
  isHlsAd = isHlsMediaFile(mediaFile);
990
991
  console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad from: ").concat(mediaFile.url));
991
992
  if (isHlsAd && import_hls.default.isSupported()) {
@@ -2271,22 +2272,337 @@ function initializePolyfills() {
2271
2272
  polyfillTextEncoder();
2272
2273
  polyfillPromiseFinally();
2273
2274
  }
2274
- // src/utils/vastMacros.ts
2275
- function generateCorrelator() {
2276
- if (typeof crypto !== "undefined" && crypto.getRandomValues) {
2275
+ // src/utils/vastEnvironmentSignals.ts
2276
+ var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
2277
+ var AIRY_WEBOS_APP_ID = "com.freeairytv.webos";
2278
+ var AIRY_TIZEN_APP_ID = "com.freeairytv.samsung";
2279
+ var AIRY_ROKU_APP_ID = "com.freeairytv.roku";
2280
+ var AIRY_APP_NAME = "AiryTV Movies & TV";
2281
+ var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
2282
+ var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
2283
+ function getDefaultAppId() {
2284
+ if (typeof navigator === "undefined") return AIRY_ANDROID_APP_ID;
2285
+ var ua = navigator.userAgent;
2286
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;
2287
+ if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;
2288
+ if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;
2289
+ return AIRY_ANDROID_APP_ID;
2290
+ }
2291
+ var DEVICE_ID_STORAGE_KEYS = [
2292
+ "rdid",
2293
+ "ifa",
2294
+ "advertisingId",
2295
+ "advertising_id",
2296
+ "deviceAdvertisingId",
2297
+ "aaid",
2298
+ "adid",
2299
+ "rida",
2300
+ "tifa",
2301
+ "lgudid"
2302
+ ];
2303
+ var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
2304
+ "aaid",
2305
+ "adid"
2306
+ ]);
2307
+ function resolveVastEnvironmentSignals(isCtv) {
2308
+ var _ref, _bridgeSignals_limitAdTracking;
2309
+ var bridgeSignals = readNativeBridgeSignals();
2310
+ var deviceId = bridgeSignals.deviceId || readStoredDeviceId();
2311
+ var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || inferDeviceIdType();
2312
+ var limitAdTracking = deviceId != null ? (_ref = (_bridgeSignals_limitAdTracking = bridgeSignals.limitAdTracking) !== null && _bridgeSignals_limitAdTracking !== void 0 ? _bridgeSignals_limitAdTracking : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false : void 0;
2313
+ if (isCtv) {
2314
+ return _object_spread_props(_object_spread({
2315
+ isCtv: true,
2316
+ contentUrl: bridgeSignals.contentUrl || readStoredString("contentUrl") || AIRY_DEFAULT_CONTENT_URL,
2317
+ appId: bridgeSignals.appId || readStoredString("appId") || readStoredString("msid") || getDefaultAppId(),
2318
+ appName: bridgeSignals.appName || readStoredString("appName") || readStoredString("an") || AIRY_APP_NAME,
2319
+ sessionId: getOrCreateCtvSessionId()
2320
+ }, deviceId ? {
2321
+ deviceId: deviceId
2322
+ } : {}, deviceIdType ? {
2323
+ deviceIdType: deviceIdType
2324
+ } : {}, limitAdTracking != null ? {
2325
+ limitAdTracking: limitAdTracking
2326
+ } : {}), {
2327
+ deviceTypeHint: 5
2328
+ });
2329
+ }
2330
+ return _object_spread({
2331
+ isCtv: false
2332
+ }, deviceId ? {
2333
+ deviceId: deviceId
2334
+ } : {}, deviceIdType ? {
2335
+ deviceIdType: deviceIdType
2336
+ } : {}, limitAdTracking != null ? {
2337
+ limitAdTracking: limitAdTracking
2338
+ } : {});
2339
+ }
2340
+ function inferDeviceIdType() {
2341
+ if (typeof navigator === "undefined") {
2342
+ return void 0;
2343
+ }
2344
+ var ua = navigator.userAgent;
2345
+ if (/Roku/i.test(ua)) return "rida";
2346
+ if (/Tizen|Samsung/i.test(ua)) return "tifa";
2347
+ if (/AppleTV|Apple TV/i.test(ua)) return "tvOS";
2348
+ if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
2349
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return "lgudid";
2350
+ if (/Android|Google TV/i.test(ua)) return "aaid";
2351
+ if (/iPhone|iPad|iPod/i.test(ua)) return "idfa";
2352
+ return void 0;
2353
+ }
2354
+ function isEquivalentDeviceIdType(tagType, runtimeType) {
2355
+ if (!tagType || !runtimeType) return false;
2356
+ var tag = tagType.toLowerCase();
2357
+ var runtime = runtimeType.toLowerCase();
2358
+ if (tag === runtime) return true;
2359
+ return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
2360
+ }
2361
+ function getOrCreateCtvSessionId() {
2362
+ var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
2363
+ if (existing) {
2364
+ return existing;
2365
+ }
2366
+ var sessionId = createUuid();
2367
+ try {
2368
+ var _window_localStorage;
2369
+ (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
2370
+ } catch (unused) {}
2371
+ return sessionId;
2372
+ }
2373
+ function createUuid() {
2374
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
2375
+ return crypto.randomUUID();
2376
+ }
2377
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
2378
+ var value = Math.floor(Math.random() * 16);
2379
+ var nibble = char === "x" ? value : value & 3 | 8;
2380
+ return nibble.toString(16);
2381
+ });
2382
+ }
2383
+ function readNativeBridgeSignals() {
2384
+ if (typeof window === "undefined") {
2385
+ return {};
2386
+ }
2387
+ var candidates = [
2388
+ window.__STORMCLOUD_CTV_AD_INFO__,
2389
+ window.__STORMCLOUD_CTV__,
2390
+ window.stormcloudCtv,
2391
+ window.AiryTV,
2392
+ window.Android,
2393
+ window.webOS,
2394
+ window.tizen,
2395
+ window.amazon
2396
+ ].filter(Boolean);
2397
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2398
+ try {
2399
+ for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2400
+ var source = _step.value;
2401
+ var contentUrl = readBridgeValue(source, [
2402
+ "contentUrl",
2403
+ "url",
2404
+ "videoUrl",
2405
+ "canonicalUrl"
2406
+ ]) || void 0;
2407
+ var appId = readBridgeValue(source, [
2408
+ "appId",
2409
+ "msid",
2410
+ "applicationId",
2411
+ "packageName"
2412
+ ]) || void 0;
2413
+ var appName = readBridgeValue(source, [
2414
+ "appName",
2415
+ "an",
2416
+ "applicationName"
2417
+ ]) || void 0;
2418
+ var deviceId = readBridgeValue(source, [
2419
+ "rdid",
2420
+ "ifa",
2421
+ "advertisingId",
2422
+ "adId",
2423
+ "deviceId",
2424
+ "lgudid",
2425
+ "LGUDID",
2426
+ "tifa",
2427
+ "rida",
2428
+ "afai",
2429
+ "aaid"
2430
+ ]) || void 0;
2431
+ if (!contentUrl && !deviceId && !appId && !appName) continue;
2432
+ var deviceIdType = readBridgeValue(source, [
2433
+ "idtype",
2434
+ "deviceIdType",
2435
+ "advertisingIdType",
2436
+ "idType"
2437
+ ]) || inferDeviceIdType();
2438
+ var limitAdTracking = readBridgeBoolean(source, [
2439
+ "is_lat",
2440
+ "limitAdTracking",
2441
+ "limitedAdTracking",
2442
+ "lat"
2443
+ ]);
2444
+ return _object_spread({}, contentUrl ? {
2445
+ contentUrl: contentUrl
2446
+ } : {}, appId ? {
2447
+ appId: appId
2448
+ } : {}, appName ? {
2449
+ appName: appName
2450
+ } : {}, deviceId ? {
2451
+ deviceId: deviceId
2452
+ } : {}, deviceId && deviceIdType ? {
2453
+ deviceIdType: deviceIdType
2454
+ } : {}, deviceId && limitAdTracking != null ? {
2455
+ limitAdTracking: limitAdTracking
2456
+ } : {});
2457
+ }
2458
+ } catch (err) {
2459
+ _didIteratorError = true;
2460
+ _iteratorError = err;
2461
+ } finally{
2277
2462
  try {
2278
- var _buf_, _buf_1;
2279
- var buf = new Uint32Array(2);
2280
- crypto.getRandomValues(buf);
2281
- var value = ((_buf_ = buf[0]) !== null && _buf_ !== void 0 ? _buf_ : 0) * 2097152 + (((_buf_1 = buf[1]) !== null && _buf_1 !== void 0 ? _buf_1 : 0) & 2097151);
2282
- if (value > 0) {
2283
- return String(value);
2463
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2464
+ _iterator.return();
2284
2465
  }
2285
- } catch (unused) {}
2466
+ } finally{
2467
+ if (_didIteratorError) {
2468
+ throw _iteratorError;
2469
+ }
2470
+ }
2286
2471
  }
2287
- return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);
2472
+ return {};
2473
+ }
2474
+ function readBridgeValue(source, keys) {
2475
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2476
+ try {
2477
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2478
+ var key = _step.value;
2479
+ var value = source === null || source === void 0 ? void 0 : source[key];
2480
+ if (typeof value === "string" && value) {
2481
+ return value;
2482
+ }
2483
+ if (typeof value === "function") {
2484
+ try {
2485
+ var result = value.call(source);
2486
+ if (typeof result === "string" && result) {
2487
+ return result;
2488
+ }
2489
+ } catch (unused) {}
2490
+ }
2491
+ }
2492
+ } catch (err) {
2493
+ _didIteratorError = true;
2494
+ _iteratorError = err;
2495
+ } finally{
2496
+ try {
2497
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2498
+ _iterator.return();
2499
+ }
2500
+ } finally{
2501
+ if (_didIteratorError) {
2502
+ throw _iteratorError;
2503
+ }
2504
+ }
2505
+ }
2506
+ return void 0;
2507
+ }
2508
+ function readBridgeBoolean(source, keys) {
2509
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2510
+ try {
2511
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2512
+ var key = _step.value;
2513
+ var value = source === null || source === void 0 ? void 0 : source[key];
2514
+ var normalized = normalizeBoolean(value);
2515
+ if (normalized != null) {
2516
+ return normalized;
2517
+ }
2518
+ if (typeof value === "function") {
2519
+ try {
2520
+ var result = normalizeBoolean(value.call(source));
2521
+ if (result != null) {
2522
+ return result;
2523
+ }
2524
+ } catch (unused) {}
2525
+ }
2526
+ }
2527
+ } catch (err) {
2528
+ _didIteratorError = true;
2529
+ _iteratorError = err;
2530
+ } finally{
2531
+ try {
2532
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2533
+ _iterator.return();
2534
+ }
2535
+ } finally{
2536
+ if (_didIteratorError) {
2537
+ throw _iteratorError;
2538
+ }
2539
+ }
2540
+ }
2541
+ return void 0;
2542
+ }
2543
+ function readStoredDeviceId() {
2544
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2545
+ try {
2546
+ for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2547
+ var key = _step.value;
2548
+ var value = readStoredString(key);
2549
+ if (value) {
2550
+ return value;
2551
+ }
2552
+ }
2553
+ } catch (err) {
2554
+ _didIteratorError = true;
2555
+ _iteratorError = err;
2556
+ } finally{
2557
+ try {
2558
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2559
+ _iterator.return();
2560
+ }
2561
+ } finally{
2562
+ if (_didIteratorError) {
2563
+ throw _iteratorError;
2564
+ }
2565
+ }
2566
+ }
2567
+ return void 0;
2568
+ }
2569
+ function readStoredString(key) {
2570
+ if (typeof window === "undefined") {
2571
+ return void 0;
2572
+ }
2573
+ try {
2574
+ var _window_localStorage;
2575
+ var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
2576
+ return value || void 0;
2577
+ } catch (unused) {
2578
+ return void 0;
2579
+ }
2580
+ }
2581
+ function readStoredLimitAdTracking() {
2582
+ return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
2583
+ }
2584
+ function normalizeBoolean(value) {
2585
+ if (typeof value === "boolean") {
2586
+ return value;
2587
+ }
2588
+ if (typeof value === "number") {
2589
+ return value === 1;
2590
+ }
2591
+ if (typeof value === "string") {
2592
+ var normalized = value.toLowerCase();
2593
+ if (normalized === "1" || normalized === "true" || normalized === "yes") {
2594
+ return true;
2595
+ }
2596
+ if (normalized === "0" || normalized === "false" || normalized === "no") {
2597
+ return false;
2598
+ }
2599
+ }
2600
+ return void 0;
2288
2601
  }
2602
+ // src/utils/vastMacros.ts
2289
2603
  var UNEXPANDED_MACRO_PATTERN = /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/;
2604
+ var INVALID_VAST_PARAM_KEY = /^\s|\s$/;
2605
+ var EXAMPLE_COM_URL = /example\.com/i;
2290
2606
  var CTV_UNSUPPORTED_PARAMS = [
2291
2607
  "description_url",
2292
2608
  "tfcd",
@@ -2301,14 +2617,288 @@ var CTV_UNSUPPORTED_PARAMS = [
2301
2617
  "gdpr_consent",
2302
2618
  "us_privacy"
2303
2619
  ];
2620
+ var INLINE_DEVICE_MACRO_REPLACEMENTS = [
2621
+ {
2622
+ pattern: /\[RDID\]/gi,
2623
+ getValue: function getValue(ctx) {
2624
+ return ctx.deviceId;
2625
+ }
2626
+ },
2627
+ {
2628
+ pattern: /\[IFA\]/gi,
2629
+ getValue: function getValue(ctx) {
2630
+ return ctx.deviceId;
2631
+ }
2632
+ },
2633
+ {
2634
+ pattern: /\[ADVERTISING[_-]?ID(?:ENTIFIER)?\]/gi,
2635
+ getValue: function getValue(ctx) {
2636
+ return ctx.deviceId;
2637
+ }
2638
+ },
2639
+ {
2640
+ pattern: /\[DEVICE[_-]?ID\]/gi,
2641
+ getValue: function getValue(ctx) {
2642
+ return ctx.deviceId;
2643
+ }
2644
+ },
2645
+ {
2646
+ pattern: /\[IDTYPE\]/gi,
2647
+ getValue: function getValue(ctx) {
2648
+ return ctx.deviceIdType;
2649
+ }
2650
+ },
2651
+ {
2652
+ pattern: /\{rdid\}/gi,
2653
+ getValue: function getValue(ctx) {
2654
+ return ctx.deviceId;
2655
+ }
2656
+ },
2657
+ {
2658
+ pattern: /\{device[_-]?id\}/gi,
2659
+ getValue: function getValue(ctx) {
2660
+ return ctx.deviceId;
2661
+ }
2662
+ },
2663
+ {
2664
+ pattern: /\{idtype\}/gi,
2665
+ getValue: function getValue(ctx) {
2666
+ return ctx.deviceIdType;
2667
+ }
2668
+ },
2669
+ {
2670
+ pattern: /%%ADVERTISING_IDENTIFIER_PLAIN%%/gi,
2671
+ getValue: function getValue(ctx) {
2672
+ return ctx.deviceId;
2673
+ }
2674
+ },
2675
+ {
2676
+ pattern: /%%ADVERTISING_ID_OPT_OUT%%/gi,
2677
+ getValue: function getValue(ctx) {
2678
+ return ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2679
+ }
2680
+ },
2681
+ {
2682
+ pattern: /%%ADVERTISING_ID_TYPE%%/gi,
2683
+ getValue: function getValue(ctx) {
2684
+ return ctx.deviceIdType;
2685
+ }
2686
+ },
2687
+ {
2688
+ pattern: /%%ADVERTISING_ID%%/gi,
2689
+ getValue: function getValue(ctx) {
2690
+ return ctx.deviceId;
2691
+ }
2692
+ },
2693
+ {
2694
+ pattern: /%%LIMIT_AD_TRACKING%%/gi,
2695
+ getValue: function getValue(ctx) {
2696
+ return ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2697
+ }
2698
+ },
2699
+ {
2700
+ pattern: /%%MSID%%/gi,
2701
+ getValue: function getValue(ctx) {
2702
+ return ctx.appId;
2703
+ }
2704
+ },
2705
+ {
2706
+ pattern: /%%APP_NAME%%/gi,
2707
+ getValue: function getValue(ctx) {
2708
+ return ctx.appName;
2709
+ }
2710
+ },
2711
+ {
2712
+ pattern: /%%SESSION_ID%%/gi,
2713
+ getValue: function getValue(ctx) {
2714
+ return ctx.sessionId;
2715
+ }
2716
+ },
2717
+ {
2718
+ pattern: /%%CORRELATOR%%/gi,
2719
+ getValue: function getValue(ctx) {
2720
+ return ctx.correlator;
2721
+ }
2722
+ }
2723
+ ];
2724
+ function isMacroPlaceholder(value) {
2725
+ if (value == null) return true;
2726
+ var trimmed = value.trim();
2727
+ if (!trimmed) return true;
2728
+ if (UNEXPANDED_MACRO_PATTERN.test(trimmed)) return true;
2729
+ return /^(unknown|null|undefined|none|n\/a|\$\{[^}]+\})$/i.test(trimmed);
2730
+ }
2731
+ function generateCorrelator() {
2732
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
2733
+ try {
2734
+ var _buf_, _buf_1;
2735
+ var buf = new Uint32Array(2);
2736
+ crypto.getRandomValues(buf);
2737
+ var value = ((_buf_ = buf[0]) !== null && _buf_ !== void 0 ? _buf_ : 0) * 2097152 + (((_buf_1 = buf[1]) !== null && _buf_1 !== void 0 ? _buf_1 : 0) & 2097151);
2738
+ if (value > 0) {
2739
+ return String(value);
2740
+ }
2741
+ } catch (unused) {}
2742
+ }
2743
+ return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);
2744
+ }
2745
+ function expandInlineMacroPlaceholders(baseUrl, ctx) {
2746
+ var url = baseUrl;
2747
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2748
+ try {
2749
+ for(var _iterator = INLINE_DEVICE_MACRO_REPLACEMENTS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2750
+ var _step_value = _step.value, pattern = _step_value.pattern, getValue = _step_value.getValue;
2751
+ var value = getValue(ctx);
2752
+ if (value != null && value !== "") {
2753
+ url = url.replace(pattern, encodeURIComponent(value));
2754
+ }
2755
+ }
2756
+ } catch (err) {
2757
+ _didIteratorError = true;
2758
+ _iteratorError = err;
2759
+ } finally{
2760
+ try {
2761
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2762
+ _iterator.return();
2763
+ }
2764
+ } finally{
2765
+ if (_didIteratorError) {
2766
+ throw _iteratorError;
2767
+ }
2768
+ }
2769
+ }
2770
+ return url;
2771
+ }
2772
+ function applyDeviceIdentityParams(params, ctx) {
2773
+ var _ctx_deviceId, _ctx_deviceIdType;
2774
+ var runtimeId = (_ctx_deviceId = ctx.deviceId) === null || _ctx_deviceId === void 0 ? void 0 : _ctx_deviceId.trim();
2775
+ var runtimeType = ((_ctx_deviceIdType = ctx.deviceIdType) === null || _ctx_deviceIdType === void 0 ? void 0 : _ctx_deviceIdType.trim()) || inferDeviceIdType();
2776
+ var tagRdid = params.get("rdid");
2777
+ var tagType = params.get("idtype");
2778
+ var tagLat = params.get("is_lat");
2779
+ var latValue = ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2780
+ if (runtimeId) {
2781
+ params.set("rdid", runtimeId);
2782
+ params.set("idtype", runtimeType || tagType || "aaid");
2783
+ params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder(tagLat) ? "0" : tagLat);
2784
+ return;
2785
+ }
2786
+ var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));
2787
+ var tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));
2788
+ if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {
2789
+ params.delete("rdid");
2790
+ params.delete("idtype");
2791
+ params.delete("is_lat");
2792
+ return;
2793
+ }
2794
+ if (tagRdidValid) {
2795
+ if (isMacroPlaceholder(tagType) && runtimeType) {
2796
+ params.set("idtype", runtimeType);
2797
+ }
2798
+ if (isMacroPlaceholder(tagLat)) {
2799
+ params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : "0");
2800
+ }
2801
+ return;
2802
+ }
2803
+ params.delete("rdid");
2804
+ params.delete("idtype");
2805
+ params.delete("is_lat");
2806
+ }
2807
+ function removeBrokenAppNameOrphans(params, appName) {
2808
+ var toDelete = [];
2809
+ params.forEach(function(_value, key) {
2810
+ if (!key || INVALID_VAST_PARAM_KEY.test(key)) {
2811
+ toDelete.push(key);
2812
+ }
2813
+ });
2814
+ if (appName && appName.includes("&")) {
2815
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2816
+ try {
2817
+ for(var _iterator = appName.split("&").slice(1)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2818
+ var suffix = _step.value;
2819
+ var trimmed = suffix.trimStart();
2820
+ if (!trimmed) continue;
2821
+ toDelete.push(suffix, " ".concat(trimmed), trimmed);
2822
+ }
2823
+ } catch (err) {
2824
+ _didIteratorError = true;
2825
+ _iteratorError = err;
2826
+ } finally{
2827
+ try {
2828
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2829
+ _iterator.return();
2830
+ }
2831
+ } finally{
2832
+ if (_didIteratorError) {
2833
+ throw _iteratorError;
2834
+ }
2835
+ }
2836
+ }
2837
+ }
2838
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
2839
+ try {
2840
+ for(var _iterator1 = new Set(toDelete)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
2841
+ var key = _step1.value;
2842
+ if (key) params.delete(key);
2843
+ }
2844
+ } catch (err) {
2845
+ _didIteratorError1 = true;
2846
+ _iteratorError1 = err;
2847
+ } finally{
2848
+ try {
2849
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2850
+ _iterator1.return();
2851
+ }
2852
+ } finally{
2853
+ if (_didIteratorError1) {
2854
+ throw _iteratorError1;
2855
+ }
2856
+ }
2857
+ }
2858
+ }
2859
+ function normalizeVastTagUrl(raw) {
2860
+ if (!raw) return raw;
2861
+ try {
2862
+ var url = new URL(raw);
2863
+ var anValue = url.searchParams.get("an");
2864
+ if (anValue !== null) {
2865
+ var orphanFragments = [];
2866
+ url.searchParams.forEach(function(_value, key) {
2867
+ if (key && INVALID_VAST_PARAM_KEY.test(key)) {
2868
+ orphanFragments.push(key.trim());
2869
+ }
2870
+ });
2871
+ if (orphanFragments.length > 0) {
2872
+ var reconstructed = [
2873
+ anValue.trimEnd()
2874
+ ].concat(_to_consumable_array(orphanFragments)).filter(Boolean).join(" & ");
2875
+ url.searchParams.forEach(function(_value, key) {
2876
+ if (key && INVALID_VAST_PARAM_KEY.test(key)) {
2877
+ url.searchParams.delete(key);
2878
+ }
2879
+ });
2880
+ url.searchParams.set("an", reconstructed);
2881
+ return url.toString().replace(/([?&]an=)([^&]*)/, function(_match, prefix, val) {
2882
+ return prefix + val.replace(/\+/g, "%20");
2883
+ });
2884
+ }
2885
+ }
2886
+ removeBrokenAppNameOrphans(url.searchParams);
2887
+ return url.toString();
2888
+ } catch (unused) {
2889
+ return raw;
2890
+ }
2891
+ }
2304
2892
  function applyVastMacros(baseUrl, ctx) {
2893
+ var expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);
2305
2894
  var url;
2306
2895
  try {
2307
- url = new URL(baseUrl);
2896
+ url = new URL(normalizeVastTagUrl(expandedUrl));
2308
2897
  } catch (unused) {
2309
- return replaceCorrelatorFallback(baseUrl, ctx.correlator);
2898
+ return replaceCorrelatorFallback(expandedUrl, ctx.correlator);
2310
2899
  }
2311
2900
  var params = url.searchParams;
2901
+ removeBrokenAppNameOrphans(params, ctx.appName);
2312
2902
  params.set("correlator", ctx.correlator);
2313
2903
  if (ctx.isCtv) {
2314
2904
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
@@ -2346,6 +2936,12 @@ function applyVastMacros(baseUrl, ctx) {
2346
2936
  if (!ctx.isCtv) {
2347
2937
  params.set("description_url", requestUrl);
2348
2938
  }
2939
+ } else {
2940
+ var existingUrl = params.get("url") || "";
2941
+ if (EXAMPLE_COM_URL.test(existingUrl)) {
2942
+ params.delete("url");
2943
+ params.delete("description_url");
2944
+ }
2349
2945
  }
2350
2946
  if (ctx.adWillPlayMuted != null) {
2351
2947
  params.set("vpmute", ctx.adWillPlayMuted ? "1" : "0");
@@ -2357,6 +2953,7 @@ function applyVastMacros(baseUrl, ctx) {
2357
2953
  params.set("msid", ctx.appId);
2358
2954
  }
2359
2955
  if (ctx.appName) {
2956
+ removeBrokenAppNameOrphans(params, ctx.appName);
2360
2957
  params.set("an", ctx.appName);
2361
2958
  }
2362
2959
  if (ctx.sessionId) {
@@ -2367,15 +2964,7 @@ function applyVastMacros(baseUrl, ctx) {
2367
2964
  } else if (ctx.isCtv) {
2368
2965
  params.set("dth", "5");
2369
2966
  }
2370
- if (ctx.deviceId && ctx.deviceIdType) {
2371
- params.set("rdid", ctx.deviceId);
2372
- params.set("idtype", ctx.deviceIdType);
2373
- params.set("is_lat", ctx.limitAdTracking ? "1" : "0");
2374
- } else {
2375
- params.delete("rdid");
2376
- params.delete("idtype");
2377
- params.delete("is_lat");
2378
- }
2967
+ applyDeviceIdentityParams(params, ctx);
2379
2968
  if (!ctx.isCtv) {
2380
2969
  var consent = ctx.consent;
2381
2970
  if ((consent === null || consent === void 0 ? void 0 : consent.gdpr) != null) {
@@ -2393,7 +2982,7 @@ function applyVastMacros(baseUrl, ctx) {
2393
2982
  }
2394
2983
  var staleKeys = [];
2395
2984
  params.forEach(function(value, key) {
2396
- if (UNEXPANDED_MACRO_PATTERN.test(value)) {
2985
+ if (isMacroPlaceholder(value)) {
2397
2986
  staleKeys.push(key);
2398
2987
  }
2399
2988
  });
@@ -2417,6 +3006,7 @@ function applyVastMacros(baseUrl, ctx) {
2417
3006
  }
2418
3007
  }
2419
3008
  }
3009
+ removeBrokenAppNameOrphans(params, ctx.appName);
2420
3010
  return url.toString();
2421
3011
  }
2422
3012
  function replaceCorrelatorFallback(baseUrl, correlator) {
@@ -3667,276 +4257,10 @@ var Scte35CueManager = /*#__PURE__*/ function() {
3667
4257
  ]);
3668
4258
  return Scte35CueManager;
3669
4259
  }();
3670
- // src/utils/ctvVastSignals.ts
3671
- var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
3672
- var AIRY_APP_NAME = "AiryTV Movies & TV";
3673
- var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
3674
- var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
3675
- var DEVICE_ID_STORAGE_KEYS = [
3676
- "rdid",
3677
- "ifa",
3678
- "advertisingId",
3679
- "advertising_id",
3680
- "deviceAdvertisingId",
3681
- "aaid",
3682
- "adid",
3683
- "rida",
3684
- "tifa"
3685
- ];
3686
- function resolveCtvVastSignals() {
3687
- var _ref, _bridgeSignals_limitAdTracking;
3688
- var bridgeSignals = readNativeBridgeSignals();
3689
- var deviceId = bridgeSignals.deviceId || readStoredDeviceId();
3690
- var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || inferDeviceIdType();
3691
- var contentUrl = bridgeSignals.contentUrl || readStoredString("contentUrl") || AIRY_DEFAULT_CONTENT_URL;
3692
- return _object_spread_props(_object_spread({
3693
- contentUrl: contentUrl,
3694
- appId: AIRY_ANDROID_APP_ID,
3695
- appName: AIRY_APP_NAME,
3696
- sessionId: getOrCreateCtvSessionId()
3697
- }, deviceId ? {
3698
- deviceId: deviceId
3699
- } : {}, deviceId && deviceIdType ? {
3700
- deviceIdType: deviceIdType
3701
- } : {}, deviceId ? {
3702
- limitAdTracking: (_ref = (_bridgeSignals_limitAdTracking = bridgeSignals.limitAdTracking) !== null && _bridgeSignals_limitAdTracking !== void 0 ? _bridgeSignals_limitAdTracking : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false
3703
- } : {}), {
3704
- deviceTypeHint: 5
3705
- });
3706
- }
3707
- function getOrCreateCtvSessionId() {
3708
- var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
3709
- if (existing) {
3710
- return existing;
3711
- }
3712
- var sessionId = createUuid();
3713
- try {
3714
- var _window_localStorage;
3715
- (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
3716
- } catch (unused) {}
3717
- return sessionId;
3718
- }
3719
- function createUuid() {
3720
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
3721
- return crypto.randomUUID();
3722
- }
3723
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
3724
- var value = Math.floor(Math.random() * 16);
3725
- var nibble = char === "x" ? value : value & 3 | 8;
3726
- return nibble.toString(16);
3727
- });
3728
- }
3729
- function readNativeBridgeSignals() {
3730
- if (typeof window === "undefined") {
3731
- return {};
3732
- }
3733
- var candidates = [
3734
- window.__STORMCLOUD_CTV_AD_INFO__,
3735
- window.__STORMCLOUD_CTV__,
3736
- window.stormcloudCtv,
3737
- window.AiryTV,
3738
- window.Android
3739
- ].filter(Boolean);
3740
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3741
- try {
3742
- for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3743
- var source = _step.value;
3744
- var contentUrl = readBridgeValue(source, [
3745
- "contentUrl",
3746
- "url",
3747
- "videoUrl",
3748
- "canonicalUrl"
3749
- ]) || void 0;
3750
- var deviceId = readBridgeValue(source, [
3751
- "rdid",
3752
- "ifa",
3753
- "advertisingId",
3754
- "adId",
3755
- "deviceId"
3756
- ]) || void 0;
3757
- if (!contentUrl && !deviceId) continue;
3758
- var deviceIdType = readBridgeValue(source, [
3759
- "idtype",
3760
- "deviceIdType",
3761
- "advertisingIdType"
3762
- ]) || inferDeviceIdType();
3763
- var limitAdTracking = readBridgeBoolean(source, [
3764
- "is_lat",
3765
- "limitAdTracking",
3766
- "limitedAdTracking",
3767
- "lat"
3768
- ]);
3769
- return _object_spread({}, contentUrl ? {
3770
- contentUrl: contentUrl
3771
- } : {}, deviceId ? {
3772
- deviceId: deviceId
3773
- } : {}, deviceId && deviceIdType ? {
3774
- deviceIdType: deviceIdType
3775
- } : {}, deviceId && limitAdTracking != null ? {
3776
- limitAdTracking: limitAdTracking
3777
- } : {});
3778
- }
3779
- } catch (err) {
3780
- _didIteratorError = true;
3781
- _iteratorError = err;
3782
- } finally{
3783
- try {
3784
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3785
- _iterator.return();
3786
- }
3787
- } finally{
3788
- if (_didIteratorError) {
3789
- throw _iteratorError;
3790
- }
3791
- }
3792
- }
3793
- return {};
3794
- }
3795
- function readBridgeValue(source, keys) {
3796
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3797
- try {
3798
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3799
- var key = _step.value;
3800
- var value = source === null || source === void 0 ? void 0 : source[key];
3801
- if (typeof value === "string" && value) {
3802
- return value;
3803
- }
3804
- if (typeof value === "function") {
3805
- try {
3806
- var result = value.call(source);
3807
- if (typeof result === "string" && result) {
3808
- return result;
3809
- }
3810
- } catch (unused) {}
3811
- }
3812
- }
3813
- } catch (err) {
3814
- _didIteratorError = true;
3815
- _iteratorError = err;
3816
- } finally{
3817
- try {
3818
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3819
- _iterator.return();
3820
- }
3821
- } finally{
3822
- if (_didIteratorError) {
3823
- throw _iteratorError;
3824
- }
3825
- }
3826
- }
3827
- return void 0;
3828
- }
3829
- function readBridgeBoolean(source, keys) {
3830
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3831
- try {
3832
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3833
- var key = _step.value;
3834
- var value = source === null || source === void 0 ? void 0 : source[key];
3835
- var normalized = normalizeBoolean(value);
3836
- if (normalized != null) {
3837
- return normalized;
3838
- }
3839
- if (typeof value === "function") {
3840
- try {
3841
- var result = normalizeBoolean(value.call(source));
3842
- if (result != null) {
3843
- return result;
3844
- }
3845
- } catch (unused) {}
3846
- }
3847
- }
3848
- } catch (err) {
3849
- _didIteratorError = true;
3850
- _iteratorError = err;
3851
- } finally{
3852
- try {
3853
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3854
- _iterator.return();
3855
- }
3856
- } finally{
3857
- if (_didIteratorError) {
3858
- throw _iteratorError;
3859
- }
3860
- }
3861
- }
3862
- return void 0;
3863
- }
3864
- function readStoredDeviceId() {
3865
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3866
- try {
3867
- for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3868
- var key = _step.value;
3869
- var value = readStoredString(key);
3870
- if (value) {
3871
- return value;
3872
- }
3873
- }
3874
- } catch (err) {
3875
- _didIteratorError = true;
3876
- _iteratorError = err;
3877
- } finally{
3878
- try {
3879
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3880
- _iterator.return();
3881
- }
3882
- } finally{
3883
- if (_didIteratorError) {
3884
- throw _iteratorError;
3885
- }
3886
- }
3887
- }
3888
- return void 0;
3889
- }
3890
- function readStoredString(key) {
3891
- if (typeof window === "undefined") {
3892
- return void 0;
3893
- }
3894
- try {
3895
- var _window_localStorage;
3896
- var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
3897
- return value || void 0;
3898
- } catch (unused) {
3899
- return void 0;
3900
- }
3901
- }
3902
- function readStoredLimitAdTracking() {
3903
- return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
3904
- }
3905
- function normalizeBoolean(value) {
3906
- if (typeof value === "boolean") {
3907
- return value;
3908
- }
3909
- if (typeof value === "number") {
3910
- return value === 1;
3911
- }
3912
- if (typeof value === "string") {
3913
- var normalized = value.toLowerCase();
3914
- if (normalized === "1" || normalized === "true" || normalized === "yes") {
3915
- return true;
3916
- }
3917
- if (normalized === "0" || normalized === "false" || normalized === "no") {
3918
- return false;
3919
- }
3920
- }
3921
- return void 0;
3922
- }
3923
- function inferDeviceIdType() {
3924
- if (typeof navigator === "undefined") {
3925
- return void 0;
3926
- }
3927
- var ua = navigator.userAgent;
3928
- if (/Roku/i.test(ua)) return "rida";
3929
- if (/Tizen|Samsung/i.test(ua)) return "tifa";
3930
- if (/AppleTV/i.test(ua)) return "tvOS";
3931
- if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
3932
- if (/Web0S|webOS|LG/i.test(ua)) return "lgudid";
3933
- if (/Android|Google TV/i.test(ua)) return "aaid";
3934
- return void 0;
3935
- }
3936
- // src/player/VmapManager.ts
3937
- var VmapManager = /*#__PURE__*/ function() {
3938
- function VmapManager(config, video) {
3939
- _class_call_check(this, VmapManager);
4260
+ // src/player/AdConfigManager.ts
4261
+ var AdConfigManager = /*#__PURE__*/ function() {
4262
+ function AdConfigManager(config, video) {
4263
+ _class_call_check(this, AdConfigManager);
3940
4264
  this.vmapBreaks = [];
3941
4265
  this.consumedVmapBreakIds = /* @__PURE__ */ new Set();
3942
4266
  this.streamCorrelator = generateCorrelator();
@@ -3948,7 +4272,7 @@ var VmapManager = /*#__PURE__*/ function() {
3948
4272
  this.config = config;
3949
4273
  this.video = video;
3950
4274
  }
3951
- _create_class(VmapManager, [
4275
+ _create_class(AdConfigManager, [
3952
4276
  {
3953
4277
  key: "debug",
3954
4278
  get: function get() {
@@ -3966,7 +4290,7 @@ var VmapManager = /*#__PURE__*/ function() {
3966
4290
  key: "fetchAdConfiguration",
3967
4291
  value: function fetchAdConfiguration() {
3968
4292
  return _async_to_generator(function() {
3969
- 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, numberAds;
4293
+ 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;
3970
4294
  return _ts_generator(this, function(_state) {
3971
4295
  switch(_state.label){
3972
4296
  case 0:
@@ -4010,7 +4334,7 @@ var VmapManager = /*#__PURE__*/ function() {
4010
4334
  ];
4011
4335
  }
4012
4336
  if (this.config.vastTagUrl) {
4013
- this.apiVastTagUrl = this.config.vastTagUrl;
4337
+ this.apiVastTagUrl = normalizeVastTagUrl(this.config.vastTagUrl);
4014
4338
  if (this.debug) {
4015
4339
  console.log("[StormcloudVideoPlayer] Using custom VAST tag URL:", this.apiVastTagUrl);
4016
4340
  }
@@ -4050,9 +4374,16 @@ var VmapManager = /*#__PURE__*/ function() {
4050
4374
  data = _state.sent();
4051
4375
  imaPayload = (_data_response = data.response) === null || _data_response === void 0 ? void 0 : (_data_response_ima = _data_response.ima) === null || _data_response_ima === void 0 ? void 0 : (_data_response_ima_publisherdeskima = _data_response_ima["publisherdesk.ima"]) === null || _data_response_ima_publisherdeskima === void 0 ? void 0 : _data_response_ima_publisherdeskima.payload;
4052
4376
  if (imaPayload) {
4053
- this.apiVastTagUrl = decodeURIComponent(imaPayload);
4377
+ decodedPayload = imaPayload;
4378
+ try {
4379
+ decodedPayload = decodeURIComponent(imaPayload);
4380
+ } catch (unused) {
4381
+ console.warn("[StormcloudVideoPlayer] imaPayload was not URI-encoded; using as-is:", imaPayload);
4382
+ }
4383
+ console.log("[StormcloudVideoPlayer] Raw VAST tag URL (from API):", decodedPayload);
4384
+ this.apiVastTagUrl = normalizeVastTagUrl(decodedPayload);
4054
4385
  if (this.debug) {
4055
- console.log("[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:", this.apiVastTagUrl);
4386
+ console.log("[StormcloudVideoPlayer] Normalized VAST tag URL:", this.apiVastTagUrl);
4056
4387
  }
4057
4388
  } else {
4058
4389
  if (this.debug) {
@@ -4365,28 +4696,30 @@ var VmapManager = /*#__PURE__*/ function() {
4365
4696
  for(var i = 0; i < count; i++){
4366
4697
  this.adRequestPositionInBreak++;
4367
4698
  var adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;
4368
- var ctvSignals = this.config.ctvAdRequest ? resolveCtvVastSignals() : void 0;
4699
+ var envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);
4369
4700
  var urlWithMacros = applyVastMacros(baseUrl, {
4370
4701
  correlator: generateCorrelator(),
4371
4702
  streamCorrelator: this.streamCorrelator,
4372
4703
  pod: this.podCounter > 0 ? this.podCounter : void 0,
4373
4704
  adPosition: this.adRequestPositionInBreak,
4374
- isCtv: this.config.ctvAdRequest,
4375
- contentUrl: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.contentUrl,
4376
- pageUrl: !this.config.ctvAdRequest && typeof window !== "undefined" ? window.location.href : void 0,
4705
+ isCtv: envSignals.isCtv,
4706
+ contentUrl: envSignals.contentUrl,
4707
+ pageUrl: !envSignals.isCtv && typeof window !== "undefined" ? window.location.href : void 0,
4377
4708
  adWillPlayMuted: adWillPlayMuted,
4378
4709
  adWillAutoPlay: !!this.config.autoplay,
4379
- appId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.appId,
4380
- appName: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.appName,
4381
- sessionId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.sessionId,
4382
- deviceId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceId,
4383
- deviceIdType: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceIdType,
4384
- limitAdTracking: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.limitAdTracking,
4385
- deviceTypeHint: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceTypeHint,
4710
+ appId: envSignals.appId,
4711
+ appName: envSignals.appName,
4712
+ sessionId: envSignals.sessionId,
4713
+ deviceId: envSignals.deviceId,
4714
+ deviceIdType: envSignals.deviceIdType,
4715
+ limitAdTracking: envSignals.limitAdTracking,
4716
+ deviceTypeHint: envSignals.deviceTypeHint,
4386
4717
  adTest: this.config.adTest,
4387
4718
  consent: this.consentSignals
4388
4719
  });
4389
- urls.push(palNonce.injectNonce(urlWithMacros));
4720
+ var finalUrl = palNonce.injectNonce(urlWithMacros);
4721
+ console.log("[StormcloudVideoPlayer] Resolved ad request URL (pod=".concat(this.podCounter, ", pos=").concat(this.adRequestPositionInBreak, "):"), finalUrl);
4722
+ urls.push(finalUrl);
4390
4723
  }
4391
4724
  return urls;
4392
4725
  }
@@ -4435,7 +4768,7 @@ var VmapManager = /*#__PURE__*/ function() {
4435
4768
  }
4436
4769
  }
4437
4770
  ]);
4438
- return VmapManager;
4771
+ return AdConfigManager;
4439
4772
  }();
4440
4773
  // src/player/AdTimingService.ts
4441
4774
  var AdTimingService = /*#__PURE__*/ function() {
@@ -6162,7 +6495,7 @@ function resizePlayer(video, adPlayer, debug) {
6162
6495
  }
6163
6496
  // src/player/AdBreakOrchestrator.ts
6164
6497
  var AdBreakOrchestrator = /*#__PURE__*/ function() {
6165
- function AdBreakOrchestrator(host, timing, preloadPool, vmap, cueManager, placeholder) {
6498
+ function AdBreakOrchestrator(host, timing, preloadPool, adConfig, cueManager, placeholder) {
6166
6499
  _class_call_check(this, AdBreakOrchestrator);
6167
6500
  this.inAdBreak = false;
6168
6501
  this.showAds = false;
@@ -6177,7 +6510,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6177
6510
  this.host = host;
6178
6511
  this.timing = timing;
6179
6512
  this.preloadPool = preloadPool;
6180
- this.vmap = vmap;
6513
+ this.adConfig = adConfig;
6181
6514
  this.cueManager = cueManager;
6182
6515
  this.placeholder = placeholder;
6183
6516
  }
@@ -6343,7 +6676,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6343
6676
  }
6344
6677
  this.pendingAdBreak = null;
6345
6678
  this.cueManager.pendingScte35CueKey = void 0;
6346
- this.vmap.podAssignedByPrefetch = false;
6679
+ this.adConfig.podAssignedByPrefetch = false;
6347
6680
  }
6348
6681
  },
6349
6682
  {
@@ -6357,15 +6690,15 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6357
6690
  return _ts_generator(this, function(_state) {
6358
6691
  switch(_state.label){
6359
6692
  case 0:
6360
- scheduled = this.vmap.findCurrentOrNextBreak(this.host.video.currentTime * 1e3);
6693
+ scheduled = this.adConfig.findCurrentOrNextBreak(this.host.video.currentTime * 1e3);
6361
6694
  if (scheduled) {
6362
- this.vmap.consumedVmapBreakIds.add(this.vmap.getAdBreakKey(scheduled));
6695
+ this.adConfig.consumedVmapBreakIds.add(this.adConfig.getAdBreakKey(scheduled));
6363
6696
  }
6364
- tags = this.vmap.selectVastTagsForBreak(scheduled);
6697
+ tags = this.adConfig.selectVastTagsForBreak(scheduled);
6365
6698
  if (tags && tags.length > 0 && tags[0]) {
6366
6699
  baseVastUrl = tags[0];
6367
- } else if (this.vmap.apiVastTagUrl) {
6368
- baseVastUrl = this.vmap.apiVastTagUrl;
6700
+ } else if (this.adConfig.apiVastTagUrl) {
6701
+ baseVastUrl = this.adConfig.apiVastTagUrl;
6369
6702
  } else {
6370
6703
  this.clearPendingAdBreak();
6371
6704
  return [
@@ -6383,10 +6716,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6383
6716
  this.continuousFetchingActive = true;
6384
6717
  this.isShowingPlaceholder = false;
6385
6718
  this.timing.totalAdRequestsInBreak = 0;
6386
- if (this.vmap.podAssignedByPrefetch) {
6387
- this.vmap.podAssignedByPrefetch = false;
6719
+ if (this.adConfig.podAssignedByPrefetch) {
6720
+ this.adConfig.podAssignedByPrefetch = false;
6388
6721
  } else {
6389
- this.vmap.beginNewAdPod();
6722
+ this.adConfig.beginNewAdPod();
6390
6723
  }
6391
6724
  currentMuted = this.host.video.muted;
6392
6725
  currentVolume = this.host.video.volume;
@@ -7658,7 +7991,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7658
7991
  return _this.adBreak.inAdBreak;
7659
7992
  }
7660
7993
  });
7661
- this.vmap = new VmapManager(this.config, this.video);
7994
+ this.adConfig = new AdConfigManager(this.config, this.video);
7662
7995
  this.timing = new AdTimingService(this.config, this.video, {
7663
7996
  onAdStopTimerFired: function onAdStopTimerFired() {
7664
7997
  return _this.onAdStopTimerFired();
@@ -7738,7 +8071,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7738
8071
  generateVastUrls: function generateVastUrls(base, count) {
7739
8072
  return _this.generateVastUrls(base, count);
7740
8073
  }
7741
- }, this.timing, this.preloadPool, this.vmap, this.cueManager, this.placeholder);
8074
+ }, this.timing, this.preloadPool, this.adConfig, this.cueManager, this.placeholder);
7742
8075
  }
7743
8076
  _create_class(StormcloudVideoPlayer, [
7744
8077
  {
@@ -7766,7 +8099,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7766
8099
  {
7767
8100
  key: "generateVastUrls",
7768
8101
  value: function generateVastUrls(baseUrl, count) {
7769
- return this.vmap.generateVastUrlsWithCorrelators(baseUrl, count, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
8102
+ return this.adConfig.generateVastUrlsWithCorrelators(baseUrl, count, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
7770
8103
  }
7771
8104
  },
7772
8105
  {
@@ -7794,7 +8127,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7794
8127
  ]);
7795
8128
  return [
7796
8129
  4,
7797
- this.vmap.fetchAdConfiguration()
8130
+ this.adConfig.fetchAdConfiguration()
7798
8131
  ];
7799
8132
  case 2:
7800
8133
  _state.sent();
@@ -7821,9 +8154,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7821
8154
  continuousPlayback: (_this_config_lowLatencyMode = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false
7822
8155
  }).catch(function() {});
7823
8156
  fetchConsentSignals().then(function(signals) {
7824
- _this.vmap.consentSignals = signals;
8157
+ _this.adConfig.consentSignals = signals;
7825
8158
  }).catch(function() {});
7826
- this.vmap.initializeTracking();
8159
+ this.adConfig.initializeTracking();
7827
8160
  if (!this.hlsEngine.shouldUseNativeHls(function() {
7828
8161
  return _this.getStreamType();
7829
8162
  })) return [
@@ -7858,14 +8191,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7858
8191
  return _async_to_generator(function() {
7859
8192
  var prerollKey, adBehavior;
7860
8193
  return _ts_generator(this, function(_state) {
7861
- if (!this.vmap.isVmapEnabled() && !isLive && this.vmap.vmapBreaks.length === 0 && this.vmap.apiVastTagUrl) {
8194
+ if (!this.adConfig.isVmapEnabled() && !isLive && this.adConfig.vmapBreaks.length === 0 && this.adConfig.apiVastTagUrl) {
7862
8195
  prerollKey = "synthetic-vod-preroll";
7863
- if (!this.vmap.consumedVmapBreakIds.has(prerollKey)) {
7864
- this.vmap.vmapBreaks = [
8196
+ if (!this.adConfig.consumedVmapBreakIds.has(prerollKey)) {
8197
+ this.adConfig.vmapBreaks = [
7865
8198
  {
7866
8199
  id: prerollKey,
7867
8200
  startTimeMs: 0,
7868
- vastTagUrl: this.vmap.apiVastTagUrl
8201
+ vastTagUrl: this.adConfig.apiVastTagUrl
7869
8202
  }
7870
8203
  ];
7871
8204
  if (this.debug) {
@@ -8132,19 +8465,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8132
8465
  key: "startAdPrefetch",
8133
8466
  value: function startAdPrefetch(marker, fragmentSn, cueKey) {
8134
8467
  if (this.adBreak.pendingAdBreak || this.adBreak.inAdBreak) return;
8135
- var scheduled = this.vmap.findCurrentOrNextBreak(this.video.currentTime * 1e3);
8136
- var tags = this.vmap.selectVastTagsForBreak(scheduled);
8468
+ var scheduled = this.adConfig.findCurrentOrNextBreak(this.video.currentTime * 1e3);
8469
+ var tags = this.adConfig.selectVastTagsForBreak(scheduled);
8137
8470
  var baseVastUrl;
8138
8471
  if (tags && tags.length > 0 && tags[0]) {
8139
8472
  baseVastUrl = tags[0];
8140
- } else if (this.vmap.apiVastTagUrl) {
8141
- baseVastUrl = this.vmap.apiVastTagUrl;
8473
+ } else if (this.adConfig.apiVastTagUrl) {
8474
+ baseVastUrl = this.adConfig.apiVastTagUrl;
8142
8475
  } else {
8143
8476
  if (this.debug) console.warn("[StormcloudVideoPlayer] No VAST URL available for prefetch");
8144
8477
  return;
8145
8478
  }
8146
- this.vmap.beginNewAdPod();
8147
- this.vmap.podAssignedByPrefetch = true;
8479
+ this.adConfig.beginNewAdPod();
8480
+ this.adConfig.podAssignedByPrefetch = true;
8148
8481
  var generatedUrls = this.generateVastUrls(baseVastUrl, 1);
8149
8482
  this.adBreak.pendingAdBreak = _object_spread_props(_object_spread({
8150
8483
  marker: marker
@@ -8179,10 +8512,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8179
8512
  key: "onTimeUpdate",
8180
8513
  value: function onTimeUpdate(currentTimeSec) {
8181
8514
  var _this = this;
8182
- if (!this.vmap.isVmapEnabled() || this.vmap.vmapBreaks.length === 0) return;
8515
+ if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;
8183
8516
  if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;
8184
8517
  var nowMs = currentTimeSec * 1e3;
8185
- var breakToPlay = this.vmap.findBreakForTime(nowMs);
8518
+ var breakToPlay = this.adConfig.findBreakForTime(nowMs);
8186
8519
  if (breakToPlay) {
8187
8520
  void this.handleVmapAdBreak(breakToPlay, nowMs).catch(function(error) {
8188
8521
  if (_this.debug) {
@@ -8196,11 +8529,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8196
8529
  key: "onVideoEnded",
8197
8530
  value: function onVideoEnded() {
8198
8531
  var _this = this;
8199
- if (!this.vmap.isVmapEnabled() || this.vmap.vmapBreaks.length === 0) return;
8532
+ if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;
8200
8533
  if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;
8201
8534
  var durationMs = Number.isFinite(this.video.duration) ? Math.floor(this.video.duration * 1e3) : 0;
8202
- var postroll = this.vmap.vmapBreaks.find(function(b) {
8203
- return b.startTimeMs === -1 && !_this.vmap.consumedVmapBreakIds.has(_this.vmap.getAdBreakKey(b));
8535
+ var postroll = this.adConfig.vmapBreaks.find(function(b) {
8536
+ return b.startTimeMs === -1 && !_this.adConfig.consumedVmapBreakIds.has(_this.adConfig.getAdBreakKey(b));
8204
8537
  });
8205
8538
  if (postroll) {
8206
8539
  void this.handleVmapAdBreak(postroll, durationMs).catch(function(error) {
@@ -8219,11 +8552,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8219
8552
  return _ts_generator(this, function(_state) {
8220
8553
  switch(_state.label){
8221
8554
  case 0:
8222
- key = this.vmap.getAdBreakKey(adBreak);
8223
- if (this.vmap.consumedVmapBreakIds.has(key)) return [
8555
+ key = this.adConfig.getAdBreakKey(adBreak);
8556
+ if (this.adConfig.consumedVmapBreakIds.has(key)) return [
8224
8557
  2
8225
8558
  ];
8226
- breakStartMs = this.vmap.resolveBreakStartMs(adBreak);
8559
+ breakStartMs = this.adConfig.resolveBreakStartMs(adBreak);
8227
8560
  if (breakStartMs == null) return [
8228
8561
  2
8229
8562
  ];
@@ -8234,8 +8567,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8234
8567
  3,
8235
8568
  4
8236
8569
  ];
8237
- this.vmap.consumedVmapBreakIds.add(key);
8238
- tags = this.vmap.selectVastTagsForBreak(adBreak);
8570
+ this.adConfig.consumedVmapBreakIds.add(key);
8571
+ tags = this.adConfig.selectVastTagsForBreak(adBreak);
8239
8572
  if (!tags || tags.length === 0) return [
8240
8573
  2
8241
8574
  ];
@@ -8427,7 +8760,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8427
8760
  this.video.removeEventListener("emptied", this.emptiedHandler);
8428
8761
  delete this.emptiedHandler;
8429
8762
  }
8430
- this.vmap.destroyTracking();
8763
+ this.adConfig.destroyTracking();
8431
8764
  this.hlsEngine.destroy();
8432
8765
  (_this_adPlayer = this.adPlayer) === null || _this_adPlayer === void 0 ? void 0 : _this_adPlayer.destroy();
8433
8766
  if (this.palPlaybackStarted) {