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
package/lib/index.js CHANGED
@@ -797,6 +797,7 @@ function createHlsAdPlayer(contentVideo, options) {
797
797
  handleAdComplete();
798
798
  });
799
799
  adVideoElement.addEventListener("error", function(e) {
800
+ if (!adPlaying) return;
800
801
  console.error("[HlsAdPlayer] Ad video error:", e);
801
802
  if (currentAd) {
802
803
  fireTrackingPixels(currentAd.trackingUrls.error);
@@ -998,15 +999,15 @@ function createHlsAdPlayer(contentVideo, options) {
998
999
  adVideoElement.muted = originalMutedState;
999
1000
  console.log("[HlsAdPlayer] Set ad video volume to ".concat(adVideoElement.volume, ", muted: ").concat(adVideoElement.muted, ", originalMutedState: ").concat(originalMutedState, ", contentVolume: ").concat(contentVolume));
1000
1001
  }
1002
+ mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1003
+ if (!mediaFile) {
1004
+ throw new Error("No media file available for ad");
1005
+ }
1001
1006
  if (adContainerEl) {
1002
1007
  adContainerEl.style.display = "flex";
1003
1008
  adContainerEl.style.pointerEvents = "auto";
1004
1009
  }
1005
1010
  emit("content_pause");
1006
- mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1007
- if (!mediaFile) {
1008
- throw new Error("No media file available for ad");
1009
- }
1010
1011
  isHlsAd = isHlsMediaFile(mediaFile);
1011
1012
  console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad from: ").concat(mediaFile.url));
1012
1013
  if (isHlsAd && Hls.isSupported()) {
@@ -2318,22 +2319,337 @@ function initializePolyfills() {
2318
2319
  polyfillTextEncoder();
2319
2320
  polyfillPromiseFinally();
2320
2321
  }
2321
- // src/utils/vastMacros.ts
2322
- function generateCorrelator() {
2323
- if (typeof crypto !== "undefined" && crypto.getRandomValues) {
2322
+ // src/utils/vastEnvironmentSignals.ts
2323
+ var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
2324
+ var AIRY_WEBOS_APP_ID = "com.freeairytv.webos";
2325
+ var AIRY_TIZEN_APP_ID = "com.freeairytv.samsung";
2326
+ var AIRY_ROKU_APP_ID = "com.freeairytv.roku";
2327
+ var AIRY_APP_NAME = "AiryTV Movies & TV";
2328
+ var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
2329
+ var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
2330
+ function getDefaultAppId() {
2331
+ if (typeof navigator === "undefined") return AIRY_ANDROID_APP_ID;
2332
+ var ua = navigator.userAgent;
2333
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;
2334
+ if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;
2335
+ if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;
2336
+ return AIRY_ANDROID_APP_ID;
2337
+ }
2338
+ var DEVICE_ID_STORAGE_KEYS = [
2339
+ "rdid",
2340
+ "ifa",
2341
+ "advertisingId",
2342
+ "advertising_id",
2343
+ "deviceAdvertisingId",
2344
+ "aaid",
2345
+ "adid",
2346
+ "rida",
2347
+ "tifa",
2348
+ "lgudid"
2349
+ ];
2350
+ var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
2351
+ "aaid",
2352
+ "adid"
2353
+ ]);
2354
+ function resolveVastEnvironmentSignals(isCtv) {
2355
+ var _ref, _bridgeSignals_limitAdTracking;
2356
+ var bridgeSignals = readNativeBridgeSignals();
2357
+ var deviceId = bridgeSignals.deviceId || readStoredDeviceId();
2358
+ var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || inferDeviceIdType();
2359
+ 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;
2360
+ if (isCtv) {
2361
+ return _object_spread_props(_object_spread({
2362
+ isCtv: true,
2363
+ contentUrl: bridgeSignals.contentUrl || readStoredString("contentUrl") || AIRY_DEFAULT_CONTENT_URL,
2364
+ appId: bridgeSignals.appId || readStoredString("appId") || readStoredString("msid") || getDefaultAppId(),
2365
+ appName: bridgeSignals.appName || readStoredString("appName") || readStoredString("an") || AIRY_APP_NAME,
2366
+ sessionId: getOrCreateCtvSessionId()
2367
+ }, deviceId ? {
2368
+ deviceId: deviceId
2369
+ } : {}, deviceIdType ? {
2370
+ deviceIdType: deviceIdType
2371
+ } : {}, limitAdTracking != null ? {
2372
+ limitAdTracking: limitAdTracking
2373
+ } : {}), {
2374
+ deviceTypeHint: 5
2375
+ });
2376
+ }
2377
+ return _object_spread({
2378
+ isCtv: false
2379
+ }, deviceId ? {
2380
+ deviceId: deviceId
2381
+ } : {}, deviceIdType ? {
2382
+ deviceIdType: deviceIdType
2383
+ } : {}, limitAdTracking != null ? {
2384
+ limitAdTracking: limitAdTracking
2385
+ } : {});
2386
+ }
2387
+ function inferDeviceIdType() {
2388
+ if (typeof navigator === "undefined") {
2389
+ return void 0;
2390
+ }
2391
+ var ua = navigator.userAgent;
2392
+ if (/Roku/i.test(ua)) return "rida";
2393
+ if (/Tizen|Samsung/i.test(ua)) return "tifa";
2394
+ if (/AppleTV|Apple TV/i.test(ua)) return "tvOS";
2395
+ if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
2396
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return "lgudid";
2397
+ if (/Android|Google TV/i.test(ua)) return "aaid";
2398
+ if (/iPhone|iPad|iPod/i.test(ua)) return "idfa";
2399
+ return void 0;
2400
+ }
2401
+ function isEquivalentDeviceIdType(tagType, runtimeType) {
2402
+ if (!tagType || !runtimeType) return false;
2403
+ var tag = tagType.toLowerCase();
2404
+ var runtime = runtimeType.toLowerCase();
2405
+ if (tag === runtime) return true;
2406
+ return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
2407
+ }
2408
+ function getOrCreateCtvSessionId() {
2409
+ var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
2410
+ if (existing) {
2411
+ return existing;
2412
+ }
2413
+ var sessionId = createUuid();
2414
+ try {
2415
+ var _window_localStorage;
2416
+ (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
2417
+ } catch (unused) {}
2418
+ return sessionId;
2419
+ }
2420
+ function createUuid() {
2421
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
2422
+ return crypto.randomUUID();
2423
+ }
2424
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
2425
+ var value = Math.floor(Math.random() * 16);
2426
+ var nibble = char === "x" ? value : value & 3 | 8;
2427
+ return nibble.toString(16);
2428
+ });
2429
+ }
2430
+ function readNativeBridgeSignals() {
2431
+ if (typeof window === "undefined") {
2432
+ return {};
2433
+ }
2434
+ var candidates = [
2435
+ window.__STORMCLOUD_CTV_AD_INFO__,
2436
+ window.__STORMCLOUD_CTV__,
2437
+ window.stormcloudCtv,
2438
+ window.AiryTV,
2439
+ window.Android,
2440
+ window.webOS,
2441
+ window.tizen,
2442
+ window.amazon
2443
+ ].filter(Boolean);
2444
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2445
+ try {
2446
+ for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2447
+ var source = _step.value;
2448
+ var contentUrl = readBridgeValue(source, [
2449
+ "contentUrl",
2450
+ "url",
2451
+ "videoUrl",
2452
+ "canonicalUrl"
2453
+ ]) || void 0;
2454
+ var appId = readBridgeValue(source, [
2455
+ "appId",
2456
+ "msid",
2457
+ "applicationId",
2458
+ "packageName"
2459
+ ]) || void 0;
2460
+ var appName = readBridgeValue(source, [
2461
+ "appName",
2462
+ "an",
2463
+ "applicationName"
2464
+ ]) || void 0;
2465
+ var deviceId = readBridgeValue(source, [
2466
+ "rdid",
2467
+ "ifa",
2468
+ "advertisingId",
2469
+ "adId",
2470
+ "deviceId",
2471
+ "lgudid",
2472
+ "LGUDID",
2473
+ "tifa",
2474
+ "rida",
2475
+ "afai",
2476
+ "aaid"
2477
+ ]) || void 0;
2478
+ if (!contentUrl && !deviceId && !appId && !appName) continue;
2479
+ var deviceIdType = readBridgeValue(source, [
2480
+ "idtype",
2481
+ "deviceIdType",
2482
+ "advertisingIdType",
2483
+ "idType"
2484
+ ]) || inferDeviceIdType();
2485
+ var limitAdTracking = readBridgeBoolean(source, [
2486
+ "is_lat",
2487
+ "limitAdTracking",
2488
+ "limitedAdTracking",
2489
+ "lat"
2490
+ ]);
2491
+ return _object_spread({}, contentUrl ? {
2492
+ contentUrl: contentUrl
2493
+ } : {}, appId ? {
2494
+ appId: appId
2495
+ } : {}, appName ? {
2496
+ appName: appName
2497
+ } : {}, deviceId ? {
2498
+ deviceId: deviceId
2499
+ } : {}, deviceId && deviceIdType ? {
2500
+ deviceIdType: deviceIdType
2501
+ } : {}, deviceId && limitAdTracking != null ? {
2502
+ limitAdTracking: limitAdTracking
2503
+ } : {});
2504
+ }
2505
+ } catch (err) {
2506
+ _didIteratorError = true;
2507
+ _iteratorError = err;
2508
+ } finally{
2324
2509
  try {
2325
- var _buf_, _buf_1;
2326
- var buf = new Uint32Array(2);
2327
- crypto.getRandomValues(buf);
2328
- 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);
2329
- if (value > 0) {
2330
- return String(value);
2510
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2511
+ _iterator.return();
2331
2512
  }
2332
- } catch (unused) {}
2513
+ } finally{
2514
+ if (_didIteratorError) {
2515
+ throw _iteratorError;
2516
+ }
2517
+ }
2333
2518
  }
2334
- return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);
2519
+ return {};
2520
+ }
2521
+ function readBridgeValue(source, keys) {
2522
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2523
+ try {
2524
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2525
+ var key = _step.value;
2526
+ var value = source === null || source === void 0 ? void 0 : source[key];
2527
+ if (typeof value === "string" && value) {
2528
+ return value;
2529
+ }
2530
+ if (typeof value === "function") {
2531
+ try {
2532
+ var result = value.call(source);
2533
+ if (typeof result === "string" && result) {
2534
+ return result;
2535
+ }
2536
+ } catch (unused) {}
2537
+ }
2538
+ }
2539
+ } catch (err) {
2540
+ _didIteratorError = true;
2541
+ _iteratorError = err;
2542
+ } finally{
2543
+ try {
2544
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2545
+ _iterator.return();
2546
+ }
2547
+ } finally{
2548
+ if (_didIteratorError) {
2549
+ throw _iteratorError;
2550
+ }
2551
+ }
2552
+ }
2553
+ return void 0;
2335
2554
  }
2555
+ function readBridgeBoolean(source, keys) {
2556
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2557
+ try {
2558
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2559
+ var key = _step.value;
2560
+ var value = source === null || source === void 0 ? void 0 : source[key];
2561
+ var normalized = normalizeBoolean(value);
2562
+ if (normalized != null) {
2563
+ return normalized;
2564
+ }
2565
+ if (typeof value === "function") {
2566
+ try {
2567
+ var result = normalizeBoolean(value.call(source));
2568
+ if (result != null) {
2569
+ return result;
2570
+ }
2571
+ } catch (unused) {}
2572
+ }
2573
+ }
2574
+ } catch (err) {
2575
+ _didIteratorError = true;
2576
+ _iteratorError = err;
2577
+ } finally{
2578
+ try {
2579
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2580
+ _iterator.return();
2581
+ }
2582
+ } finally{
2583
+ if (_didIteratorError) {
2584
+ throw _iteratorError;
2585
+ }
2586
+ }
2587
+ }
2588
+ return void 0;
2589
+ }
2590
+ function readStoredDeviceId() {
2591
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2592
+ try {
2593
+ for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2594
+ var key = _step.value;
2595
+ var value = readStoredString(key);
2596
+ if (value) {
2597
+ return value;
2598
+ }
2599
+ }
2600
+ } catch (err) {
2601
+ _didIteratorError = true;
2602
+ _iteratorError = err;
2603
+ } finally{
2604
+ try {
2605
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2606
+ _iterator.return();
2607
+ }
2608
+ } finally{
2609
+ if (_didIteratorError) {
2610
+ throw _iteratorError;
2611
+ }
2612
+ }
2613
+ }
2614
+ return void 0;
2615
+ }
2616
+ function readStoredString(key) {
2617
+ if (typeof window === "undefined") {
2618
+ return void 0;
2619
+ }
2620
+ try {
2621
+ var _window_localStorage;
2622
+ var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
2623
+ return value || void 0;
2624
+ } catch (unused) {
2625
+ return void 0;
2626
+ }
2627
+ }
2628
+ function readStoredLimitAdTracking() {
2629
+ return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
2630
+ }
2631
+ function normalizeBoolean(value) {
2632
+ if (typeof value === "boolean") {
2633
+ return value;
2634
+ }
2635
+ if (typeof value === "number") {
2636
+ return value === 1;
2637
+ }
2638
+ if (typeof value === "string") {
2639
+ var normalized = value.toLowerCase();
2640
+ if (normalized === "1" || normalized === "true" || normalized === "yes") {
2641
+ return true;
2642
+ }
2643
+ if (normalized === "0" || normalized === "false" || normalized === "no") {
2644
+ return false;
2645
+ }
2646
+ }
2647
+ return void 0;
2648
+ }
2649
+ // src/utils/vastMacros.ts
2336
2650
  var UNEXPANDED_MACRO_PATTERN = /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/;
2651
+ var INVALID_VAST_PARAM_KEY = /^\s|\s$/;
2652
+ var EXAMPLE_COM_URL = /example\.com/i;
2337
2653
  var CTV_UNSUPPORTED_PARAMS = [
2338
2654
  "description_url",
2339
2655
  "tfcd",
@@ -2348,14 +2664,288 @@ var CTV_UNSUPPORTED_PARAMS = [
2348
2664
  "gdpr_consent",
2349
2665
  "us_privacy"
2350
2666
  ];
2667
+ var INLINE_DEVICE_MACRO_REPLACEMENTS = [
2668
+ {
2669
+ pattern: /\[RDID\]/gi,
2670
+ getValue: function getValue(ctx) {
2671
+ return ctx.deviceId;
2672
+ }
2673
+ },
2674
+ {
2675
+ pattern: /\[IFA\]/gi,
2676
+ getValue: function getValue(ctx) {
2677
+ return ctx.deviceId;
2678
+ }
2679
+ },
2680
+ {
2681
+ pattern: /\[ADVERTISING[_-]?ID(?:ENTIFIER)?\]/gi,
2682
+ getValue: function getValue(ctx) {
2683
+ return ctx.deviceId;
2684
+ }
2685
+ },
2686
+ {
2687
+ pattern: /\[DEVICE[_-]?ID\]/gi,
2688
+ getValue: function getValue(ctx) {
2689
+ return ctx.deviceId;
2690
+ }
2691
+ },
2692
+ {
2693
+ pattern: /\[IDTYPE\]/gi,
2694
+ getValue: function getValue(ctx) {
2695
+ return ctx.deviceIdType;
2696
+ }
2697
+ },
2698
+ {
2699
+ pattern: /\{rdid\}/gi,
2700
+ getValue: function getValue(ctx) {
2701
+ return ctx.deviceId;
2702
+ }
2703
+ },
2704
+ {
2705
+ pattern: /\{device[_-]?id\}/gi,
2706
+ getValue: function getValue(ctx) {
2707
+ return ctx.deviceId;
2708
+ }
2709
+ },
2710
+ {
2711
+ pattern: /\{idtype\}/gi,
2712
+ getValue: function getValue(ctx) {
2713
+ return ctx.deviceIdType;
2714
+ }
2715
+ },
2716
+ {
2717
+ pattern: /%%ADVERTISING_IDENTIFIER_PLAIN%%/gi,
2718
+ getValue: function getValue(ctx) {
2719
+ return ctx.deviceId;
2720
+ }
2721
+ },
2722
+ {
2723
+ pattern: /%%ADVERTISING_ID_OPT_OUT%%/gi,
2724
+ getValue: function getValue(ctx) {
2725
+ return ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2726
+ }
2727
+ },
2728
+ {
2729
+ pattern: /%%ADVERTISING_ID_TYPE%%/gi,
2730
+ getValue: function getValue(ctx) {
2731
+ return ctx.deviceIdType;
2732
+ }
2733
+ },
2734
+ {
2735
+ pattern: /%%ADVERTISING_ID%%/gi,
2736
+ getValue: function getValue(ctx) {
2737
+ return ctx.deviceId;
2738
+ }
2739
+ },
2740
+ {
2741
+ pattern: /%%LIMIT_AD_TRACKING%%/gi,
2742
+ getValue: function getValue(ctx) {
2743
+ return ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2744
+ }
2745
+ },
2746
+ {
2747
+ pattern: /%%MSID%%/gi,
2748
+ getValue: function getValue(ctx) {
2749
+ return ctx.appId;
2750
+ }
2751
+ },
2752
+ {
2753
+ pattern: /%%APP_NAME%%/gi,
2754
+ getValue: function getValue(ctx) {
2755
+ return ctx.appName;
2756
+ }
2757
+ },
2758
+ {
2759
+ pattern: /%%SESSION_ID%%/gi,
2760
+ getValue: function getValue(ctx) {
2761
+ return ctx.sessionId;
2762
+ }
2763
+ },
2764
+ {
2765
+ pattern: /%%CORRELATOR%%/gi,
2766
+ getValue: function getValue(ctx) {
2767
+ return ctx.correlator;
2768
+ }
2769
+ }
2770
+ ];
2771
+ function isMacroPlaceholder(value) {
2772
+ if (value == null) return true;
2773
+ var trimmed = value.trim();
2774
+ if (!trimmed) return true;
2775
+ if (UNEXPANDED_MACRO_PATTERN.test(trimmed)) return true;
2776
+ return /^(unknown|null|undefined|none|n\/a|\$\{[^}]+\})$/i.test(trimmed);
2777
+ }
2778
+ function generateCorrelator() {
2779
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
2780
+ try {
2781
+ var _buf_, _buf_1;
2782
+ var buf = new Uint32Array(2);
2783
+ crypto.getRandomValues(buf);
2784
+ 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);
2785
+ if (value > 0) {
2786
+ return String(value);
2787
+ }
2788
+ } catch (unused) {}
2789
+ }
2790
+ return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);
2791
+ }
2792
+ function expandInlineMacroPlaceholders(baseUrl, ctx) {
2793
+ var url = baseUrl;
2794
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2795
+ try {
2796
+ for(var _iterator = INLINE_DEVICE_MACRO_REPLACEMENTS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2797
+ var _step_value = _step.value, pattern = _step_value.pattern, getValue = _step_value.getValue;
2798
+ var value = getValue(ctx);
2799
+ if (value != null && value !== "") {
2800
+ url = url.replace(pattern, encodeURIComponent(value));
2801
+ }
2802
+ }
2803
+ } catch (err) {
2804
+ _didIteratorError = true;
2805
+ _iteratorError = err;
2806
+ } finally{
2807
+ try {
2808
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2809
+ _iterator.return();
2810
+ }
2811
+ } finally{
2812
+ if (_didIteratorError) {
2813
+ throw _iteratorError;
2814
+ }
2815
+ }
2816
+ }
2817
+ return url;
2818
+ }
2819
+ function applyDeviceIdentityParams(params, ctx) {
2820
+ var _ctx_deviceId, _ctx_deviceIdType;
2821
+ var runtimeId = (_ctx_deviceId = ctx.deviceId) === null || _ctx_deviceId === void 0 ? void 0 : _ctx_deviceId.trim();
2822
+ var runtimeType = ((_ctx_deviceIdType = ctx.deviceIdType) === null || _ctx_deviceIdType === void 0 ? void 0 : _ctx_deviceIdType.trim()) || inferDeviceIdType();
2823
+ var tagRdid = params.get("rdid");
2824
+ var tagType = params.get("idtype");
2825
+ var tagLat = params.get("is_lat");
2826
+ var latValue = ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2827
+ if (runtimeId) {
2828
+ params.set("rdid", runtimeId);
2829
+ params.set("idtype", runtimeType || tagType || "aaid");
2830
+ params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder(tagLat) ? "0" : tagLat);
2831
+ return;
2832
+ }
2833
+ var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));
2834
+ var tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));
2835
+ if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {
2836
+ params.delete("rdid");
2837
+ params.delete("idtype");
2838
+ params.delete("is_lat");
2839
+ return;
2840
+ }
2841
+ if (tagRdidValid) {
2842
+ if (isMacroPlaceholder(tagType) && runtimeType) {
2843
+ params.set("idtype", runtimeType);
2844
+ }
2845
+ if (isMacroPlaceholder(tagLat)) {
2846
+ params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : "0");
2847
+ }
2848
+ return;
2849
+ }
2850
+ params.delete("rdid");
2851
+ params.delete("idtype");
2852
+ params.delete("is_lat");
2853
+ }
2854
+ function removeBrokenAppNameOrphans(params, appName) {
2855
+ var toDelete = [];
2856
+ params.forEach(function(_value, key) {
2857
+ if (!key || INVALID_VAST_PARAM_KEY.test(key)) {
2858
+ toDelete.push(key);
2859
+ }
2860
+ });
2861
+ if (appName && appName.includes("&")) {
2862
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2863
+ try {
2864
+ for(var _iterator = appName.split("&").slice(1)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2865
+ var suffix = _step.value;
2866
+ var trimmed = suffix.trimStart();
2867
+ if (!trimmed) continue;
2868
+ toDelete.push(suffix, " ".concat(trimmed), trimmed);
2869
+ }
2870
+ } catch (err) {
2871
+ _didIteratorError = true;
2872
+ _iteratorError = err;
2873
+ } finally{
2874
+ try {
2875
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2876
+ _iterator.return();
2877
+ }
2878
+ } finally{
2879
+ if (_didIteratorError) {
2880
+ throw _iteratorError;
2881
+ }
2882
+ }
2883
+ }
2884
+ }
2885
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
2886
+ try {
2887
+ for(var _iterator1 = new Set(toDelete)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
2888
+ var key = _step1.value;
2889
+ if (key) params.delete(key);
2890
+ }
2891
+ } catch (err) {
2892
+ _didIteratorError1 = true;
2893
+ _iteratorError1 = err;
2894
+ } finally{
2895
+ try {
2896
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2897
+ _iterator1.return();
2898
+ }
2899
+ } finally{
2900
+ if (_didIteratorError1) {
2901
+ throw _iteratorError1;
2902
+ }
2903
+ }
2904
+ }
2905
+ }
2906
+ function normalizeVastTagUrl(raw) {
2907
+ if (!raw) return raw;
2908
+ try {
2909
+ var url = new URL(raw);
2910
+ var anValue = url.searchParams.get("an");
2911
+ if (anValue !== null) {
2912
+ var orphanFragments = [];
2913
+ url.searchParams.forEach(function(_value, key) {
2914
+ if (key && INVALID_VAST_PARAM_KEY.test(key)) {
2915
+ orphanFragments.push(key.trim());
2916
+ }
2917
+ });
2918
+ if (orphanFragments.length > 0) {
2919
+ var reconstructed = [
2920
+ anValue.trimEnd()
2921
+ ].concat(_to_consumable_array(orphanFragments)).filter(Boolean).join(" & ");
2922
+ url.searchParams.forEach(function(_value, key) {
2923
+ if (key && INVALID_VAST_PARAM_KEY.test(key)) {
2924
+ url.searchParams.delete(key);
2925
+ }
2926
+ });
2927
+ url.searchParams.set("an", reconstructed);
2928
+ return url.toString().replace(/([?&]an=)([^&]*)/, function(_match, prefix, val) {
2929
+ return prefix + val.replace(/\+/g, "%20");
2930
+ });
2931
+ }
2932
+ }
2933
+ removeBrokenAppNameOrphans(url.searchParams);
2934
+ return url.toString();
2935
+ } catch (unused) {
2936
+ return raw;
2937
+ }
2938
+ }
2351
2939
  function applyVastMacros(baseUrl, ctx) {
2940
+ var expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);
2352
2941
  var url;
2353
2942
  try {
2354
- url = new URL(baseUrl);
2943
+ url = new URL(normalizeVastTagUrl(expandedUrl));
2355
2944
  } catch (unused) {
2356
- return replaceCorrelatorFallback(baseUrl, ctx.correlator);
2945
+ return replaceCorrelatorFallback(expandedUrl, ctx.correlator);
2357
2946
  }
2358
2947
  var params = url.searchParams;
2948
+ removeBrokenAppNameOrphans(params, ctx.appName);
2359
2949
  params.set("correlator", ctx.correlator);
2360
2950
  if (ctx.isCtv) {
2361
2951
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
@@ -2393,6 +2983,12 @@ function applyVastMacros(baseUrl, ctx) {
2393
2983
  if (!ctx.isCtv) {
2394
2984
  params.set("description_url", requestUrl);
2395
2985
  }
2986
+ } else {
2987
+ var existingUrl = params.get("url") || "";
2988
+ if (EXAMPLE_COM_URL.test(existingUrl)) {
2989
+ params.delete("url");
2990
+ params.delete("description_url");
2991
+ }
2396
2992
  }
2397
2993
  if (ctx.adWillPlayMuted != null) {
2398
2994
  params.set("vpmute", ctx.adWillPlayMuted ? "1" : "0");
@@ -2404,6 +3000,7 @@ function applyVastMacros(baseUrl, ctx) {
2404
3000
  params.set("msid", ctx.appId);
2405
3001
  }
2406
3002
  if (ctx.appName) {
3003
+ removeBrokenAppNameOrphans(params, ctx.appName);
2407
3004
  params.set("an", ctx.appName);
2408
3005
  }
2409
3006
  if (ctx.sessionId) {
@@ -2414,15 +3011,7 @@ function applyVastMacros(baseUrl, ctx) {
2414
3011
  } else if (ctx.isCtv) {
2415
3012
  params.set("dth", "5");
2416
3013
  }
2417
- if (ctx.deviceId && ctx.deviceIdType) {
2418
- params.set("rdid", ctx.deviceId);
2419
- params.set("idtype", ctx.deviceIdType);
2420
- params.set("is_lat", ctx.limitAdTracking ? "1" : "0");
2421
- } else {
2422
- params.delete("rdid");
2423
- params.delete("idtype");
2424
- params.delete("is_lat");
2425
- }
3014
+ applyDeviceIdentityParams(params, ctx);
2426
3015
  if (!ctx.isCtv) {
2427
3016
  var consent = ctx.consent;
2428
3017
  if ((consent === null || consent === void 0 ? void 0 : consent.gdpr) != null) {
@@ -2440,7 +3029,7 @@ function applyVastMacros(baseUrl, ctx) {
2440
3029
  }
2441
3030
  var staleKeys = [];
2442
3031
  params.forEach(function(value, key) {
2443
- if (UNEXPANDED_MACRO_PATTERN.test(value)) {
3032
+ if (isMacroPlaceholder(value)) {
2444
3033
  staleKeys.push(key);
2445
3034
  }
2446
3035
  });
@@ -2464,6 +3053,7 @@ function applyVastMacros(baseUrl, ctx) {
2464
3053
  }
2465
3054
  }
2466
3055
  }
3056
+ removeBrokenAppNameOrphans(params, ctx.appName);
2467
3057
  return url.toString();
2468
3058
  }
2469
3059
  function replaceCorrelatorFallback(baseUrl, correlator) {
@@ -3739,277 +4329,11 @@ var Scte35CueManager = /*#__PURE__*/ function() {
3739
4329
  ]);
3740
4330
  return Scte35CueManager;
3741
4331
  }();
3742
- // src/utils/ctvVastSignals.ts
3743
- var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
3744
- var AIRY_APP_NAME = "AiryTV Movies & TV";
3745
- var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
3746
- var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
3747
- var DEVICE_ID_STORAGE_KEYS = [
3748
- "rdid",
3749
- "ifa",
3750
- "advertisingId",
3751
- "advertising_id",
3752
- "deviceAdvertisingId",
3753
- "aaid",
3754
- "adid",
3755
- "rida",
3756
- "tifa"
3757
- ];
3758
- function resolveCtvVastSignals() {
3759
- var _ref, _bridgeSignals_limitAdTracking;
3760
- var bridgeSignals = readNativeBridgeSignals();
3761
- var deviceId = bridgeSignals.deviceId || readStoredDeviceId();
3762
- var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || inferDeviceIdType();
3763
- var contentUrl = bridgeSignals.contentUrl || readStoredString("contentUrl") || AIRY_DEFAULT_CONTENT_URL;
3764
- return _object_spread_props(_object_spread({
3765
- contentUrl: contentUrl,
3766
- appId: AIRY_ANDROID_APP_ID,
3767
- appName: AIRY_APP_NAME,
3768
- sessionId: getOrCreateCtvSessionId()
3769
- }, deviceId ? {
3770
- deviceId: deviceId
3771
- } : {}, deviceId && deviceIdType ? {
3772
- deviceIdType: deviceIdType
3773
- } : {}, deviceId ? {
3774
- limitAdTracking: (_ref = (_bridgeSignals_limitAdTracking = bridgeSignals.limitAdTracking) !== null && _bridgeSignals_limitAdTracking !== void 0 ? _bridgeSignals_limitAdTracking : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false
3775
- } : {}), {
3776
- deviceTypeHint: 5
3777
- });
3778
- }
3779
- function getOrCreateCtvSessionId() {
3780
- var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
3781
- if (existing) {
3782
- return existing;
3783
- }
3784
- var sessionId = createUuid();
3785
- try {
3786
- var _window_localStorage;
3787
- (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
3788
- } catch (unused) {}
3789
- return sessionId;
3790
- }
3791
- function createUuid() {
3792
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
3793
- return crypto.randomUUID();
3794
- }
3795
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
3796
- var value = Math.floor(Math.random() * 16);
3797
- var nibble = char === "x" ? value : value & 3 | 8;
3798
- return nibble.toString(16);
3799
- });
3800
- }
3801
- function readNativeBridgeSignals() {
3802
- if (typeof window === "undefined") {
3803
- return {};
3804
- }
3805
- var candidates = [
3806
- window.__STORMCLOUD_CTV_AD_INFO__,
3807
- window.__STORMCLOUD_CTV__,
3808
- window.stormcloudCtv,
3809
- window.AiryTV,
3810
- window.Android
3811
- ].filter(Boolean);
3812
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3813
- try {
3814
- for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3815
- var source = _step.value;
3816
- var contentUrl = readBridgeValue(source, [
3817
- "contentUrl",
3818
- "url",
3819
- "videoUrl",
3820
- "canonicalUrl"
3821
- ]) || void 0;
3822
- var deviceId = readBridgeValue(source, [
3823
- "rdid",
3824
- "ifa",
3825
- "advertisingId",
3826
- "adId",
3827
- "deviceId"
3828
- ]) || void 0;
3829
- if (!contentUrl && !deviceId) continue;
3830
- var deviceIdType = readBridgeValue(source, [
3831
- "idtype",
3832
- "deviceIdType",
3833
- "advertisingIdType"
3834
- ]) || inferDeviceIdType();
3835
- var limitAdTracking = readBridgeBoolean(source, [
3836
- "is_lat",
3837
- "limitAdTracking",
3838
- "limitedAdTracking",
3839
- "lat"
3840
- ]);
3841
- return _object_spread({}, contentUrl ? {
3842
- contentUrl: contentUrl
3843
- } : {}, deviceId ? {
3844
- deviceId: deviceId
3845
- } : {}, deviceId && deviceIdType ? {
3846
- deviceIdType: deviceIdType
3847
- } : {}, deviceId && limitAdTracking != null ? {
3848
- limitAdTracking: limitAdTracking
3849
- } : {});
3850
- }
3851
- } catch (err) {
3852
- _didIteratorError = true;
3853
- _iteratorError = err;
3854
- } finally{
3855
- try {
3856
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3857
- _iterator.return();
3858
- }
3859
- } finally{
3860
- if (_didIteratorError) {
3861
- throw _iteratorError;
3862
- }
3863
- }
3864
- }
3865
- return {};
3866
- }
3867
- function readBridgeValue(source, keys) {
3868
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3869
- try {
3870
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3871
- var key = _step.value;
3872
- var value = source === null || source === void 0 ? void 0 : source[key];
3873
- if (typeof value === "string" && value) {
3874
- return value;
3875
- }
3876
- if (typeof value === "function") {
3877
- try {
3878
- var result = value.call(source);
3879
- if (typeof result === "string" && result) {
3880
- return result;
3881
- }
3882
- } catch (unused) {}
3883
- }
3884
- }
3885
- } catch (err) {
3886
- _didIteratorError = true;
3887
- _iteratorError = err;
3888
- } finally{
3889
- try {
3890
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3891
- _iterator.return();
3892
- }
3893
- } finally{
3894
- if (_didIteratorError) {
3895
- throw _iteratorError;
3896
- }
3897
- }
3898
- }
3899
- return void 0;
3900
- }
3901
- function readBridgeBoolean(source, keys) {
3902
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3903
- try {
3904
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3905
- var key = _step.value;
3906
- var value = source === null || source === void 0 ? void 0 : source[key];
3907
- var normalized = normalizeBoolean(value);
3908
- if (normalized != null) {
3909
- return normalized;
3910
- }
3911
- if (typeof value === "function") {
3912
- try {
3913
- var result = normalizeBoolean(value.call(source));
3914
- if (result != null) {
3915
- return result;
3916
- }
3917
- } catch (unused) {}
3918
- }
3919
- }
3920
- } catch (err) {
3921
- _didIteratorError = true;
3922
- _iteratorError = err;
3923
- } finally{
3924
- try {
3925
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3926
- _iterator.return();
3927
- }
3928
- } finally{
3929
- if (_didIteratorError) {
3930
- throw _iteratorError;
3931
- }
3932
- }
3933
- }
3934
- return void 0;
3935
- }
3936
- function readStoredDeviceId() {
3937
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3938
- try {
3939
- for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3940
- var key = _step.value;
3941
- var value = readStoredString(key);
3942
- if (value) {
3943
- return value;
3944
- }
3945
- }
3946
- } catch (err) {
3947
- _didIteratorError = true;
3948
- _iteratorError = err;
3949
- } finally{
3950
- try {
3951
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3952
- _iterator.return();
3953
- }
3954
- } finally{
3955
- if (_didIteratorError) {
3956
- throw _iteratorError;
3957
- }
3958
- }
3959
- }
3960
- return void 0;
3961
- }
3962
- function readStoredString(key) {
3963
- if (typeof window === "undefined") {
3964
- return void 0;
3965
- }
3966
- try {
3967
- var _window_localStorage;
3968
- var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
3969
- return value || void 0;
3970
- } catch (unused) {
3971
- return void 0;
3972
- }
3973
- }
3974
- function readStoredLimitAdTracking() {
3975
- return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
3976
- }
3977
- function normalizeBoolean(value) {
3978
- if (typeof value === "boolean") {
3979
- return value;
3980
- }
3981
- if (typeof value === "number") {
3982
- return value === 1;
3983
- }
3984
- if (typeof value === "string") {
3985
- var normalized = value.toLowerCase();
3986
- if (normalized === "1" || normalized === "true" || normalized === "yes") {
3987
- return true;
3988
- }
3989
- if (normalized === "0" || normalized === "false" || normalized === "no") {
3990
- return false;
3991
- }
3992
- }
3993
- return void 0;
3994
- }
3995
- function inferDeviceIdType() {
3996
- if (typeof navigator === "undefined") {
3997
- return void 0;
3998
- }
3999
- var ua = navigator.userAgent;
4000
- if (/Roku/i.test(ua)) return "rida";
4001
- if (/Tizen|Samsung/i.test(ua)) return "tifa";
4002
- if (/AppleTV/i.test(ua)) return "tvOS";
4003
- if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
4004
- if (/Web0S|webOS|LG/i.test(ua)) return "lgudid";
4005
- if (/Android|Google TV/i.test(ua)) return "aaid";
4006
- return void 0;
4007
- }
4008
- // src/player/VmapManager.ts
4009
- var VmapManager = /*#__PURE__*/ function() {
4332
+ // src/player/AdConfigManager.ts
4333
+ var AdConfigManager = /*#__PURE__*/ function() {
4010
4334
  "use strict";
4011
- function VmapManager(config, video) {
4012
- _class_call_check(this, VmapManager);
4335
+ function AdConfigManager(config, video) {
4336
+ _class_call_check(this, AdConfigManager);
4013
4337
  this.vmapBreaks = [];
4014
4338
  this.consumedVmapBreakIds = /* @__PURE__ */ new Set();
4015
4339
  this.streamCorrelator = generateCorrelator();
@@ -4021,7 +4345,7 @@ var VmapManager = /*#__PURE__*/ function() {
4021
4345
  this.config = config;
4022
4346
  this.video = video;
4023
4347
  }
4024
- _create_class(VmapManager, [
4348
+ _create_class(AdConfigManager, [
4025
4349
  {
4026
4350
  key: "debug",
4027
4351
  get: function get() {
@@ -4039,7 +4363,7 @@ var VmapManager = /*#__PURE__*/ function() {
4039
4363
  key: "fetchAdConfiguration",
4040
4364
  value: function fetchAdConfiguration() {
4041
4365
  return _async_to_generator(function() {
4042
- 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;
4366
+ 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;
4043
4367
  return _ts_generator(this, function(_state) {
4044
4368
  switch(_state.label){
4045
4369
  case 0:
@@ -4083,7 +4407,7 @@ var VmapManager = /*#__PURE__*/ function() {
4083
4407
  ];
4084
4408
  }
4085
4409
  if (this.config.vastTagUrl) {
4086
- this.apiVastTagUrl = this.config.vastTagUrl;
4410
+ this.apiVastTagUrl = normalizeVastTagUrl(this.config.vastTagUrl);
4087
4411
  if (this.debug) {
4088
4412
  console.log("[StormcloudVideoPlayer] Using custom VAST tag URL:", this.apiVastTagUrl);
4089
4413
  }
@@ -4123,9 +4447,16 @@ var VmapManager = /*#__PURE__*/ function() {
4123
4447
  data = _state.sent();
4124
4448
  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;
4125
4449
  if (imaPayload) {
4126
- this.apiVastTagUrl = decodeURIComponent(imaPayload);
4450
+ decodedPayload = imaPayload;
4451
+ try {
4452
+ decodedPayload = decodeURIComponent(imaPayload);
4453
+ } catch (unused) {
4454
+ console.warn("[StormcloudVideoPlayer] imaPayload was not URI-encoded; using as-is:", imaPayload);
4455
+ }
4456
+ console.log("[StormcloudVideoPlayer] Raw VAST tag URL (from API):", decodedPayload);
4457
+ this.apiVastTagUrl = normalizeVastTagUrl(decodedPayload);
4127
4458
  if (this.debug) {
4128
- console.log("[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:", this.apiVastTagUrl);
4459
+ console.log("[StormcloudVideoPlayer] Normalized VAST tag URL:", this.apiVastTagUrl);
4129
4460
  }
4130
4461
  } else {
4131
4462
  if (this.debug) {
@@ -4438,28 +4769,30 @@ var VmapManager = /*#__PURE__*/ function() {
4438
4769
  for(var i = 0; i < count; i++){
4439
4770
  this.adRequestPositionInBreak++;
4440
4771
  var adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;
4441
- var ctvSignals = this.config.ctvAdRequest ? resolveCtvVastSignals() : void 0;
4772
+ var envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);
4442
4773
  var urlWithMacros = applyVastMacros(baseUrl, {
4443
4774
  correlator: generateCorrelator(),
4444
4775
  streamCorrelator: this.streamCorrelator,
4445
4776
  pod: this.podCounter > 0 ? this.podCounter : void 0,
4446
4777
  adPosition: this.adRequestPositionInBreak,
4447
- isCtv: this.config.ctvAdRequest,
4448
- contentUrl: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.contentUrl,
4449
- pageUrl: !this.config.ctvAdRequest && typeof window !== "undefined" ? window.location.href : void 0,
4778
+ isCtv: envSignals.isCtv,
4779
+ contentUrl: envSignals.contentUrl,
4780
+ pageUrl: !envSignals.isCtv && typeof window !== "undefined" ? window.location.href : void 0,
4450
4781
  adWillPlayMuted: adWillPlayMuted,
4451
4782
  adWillAutoPlay: !!this.config.autoplay,
4452
- appId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.appId,
4453
- appName: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.appName,
4454
- sessionId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.sessionId,
4455
- deviceId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceId,
4456
- deviceIdType: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceIdType,
4457
- limitAdTracking: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.limitAdTracking,
4458
- deviceTypeHint: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceTypeHint,
4783
+ appId: envSignals.appId,
4784
+ appName: envSignals.appName,
4785
+ sessionId: envSignals.sessionId,
4786
+ deviceId: envSignals.deviceId,
4787
+ deviceIdType: envSignals.deviceIdType,
4788
+ limitAdTracking: envSignals.limitAdTracking,
4789
+ deviceTypeHint: envSignals.deviceTypeHint,
4459
4790
  adTest: this.config.adTest,
4460
4791
  consent: this.consentSignals
4461
4792
  });
4462
- urls.push(palNonce.injectNonce(urlWithMacros));
4793
+ var finalUrl = palNonce.injectNonce(urlWithMacros);
4794
+ console.log("[StormcloudVideoPlayer] Resolved ad request URL (pod=".concat(this.podCounter, ", pos=").concat(this.adRequestPositionInBreak, "):"), finalUrl);
4795
+ urls.push(finalUrl);
4463
4796
  }
4464
4797
  return urls;
4465
4798
  }
@@ -4508,7 +4841,7 @@ var VmapManager = /*#__PURE__*/ function() {
4508
4841
  }
4509
4842
  }
4510
4843
  ]);
4511
- return VmapManager;
4844
+ return AdConfigManager;
4512
4845
  }();
4513
4846
  // src/player/AdTimingService.ts
4514
4847
  var AdTimingService = /*#__PURE__*/ function() {
@@ -6240,7 +6573,7 @@ function resizePlayer(video, adPlayer, debug) {
6240
6573
  // src/player/AdBreakOrchestrator.ts
6241
6574
  var AdBreakOrchestrator = /*#__PURE__*/ function() {
6242
6575
  "use strict";
6243
- function AdBreakOrchestrator(host, timing, preloadPool, vmap, cueManager, placeholder) {
6576
+ function AdBreakOrchestrator(host, timing, preloadPool, adConfig, cueManager, placeholder) {
6244
6577
  _class_call_check(this, AdBreakOrchestrator);
6245
6578
  this.inAdBreak = false;
6246
6579
  this.showAds = false;
@@ -6255,7 +6588,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6255
6588
  this.host = host;
6256
6589
  this.timing = timing;
6257
6590
  this.preloadPool = preloadPool;
6258
- this.vmap = vmap;
6591
+ this.adConfig = adConfig;
6259
6592
  this.cueManager = cueManager;
6260
6593
  this.placeholder = placeholder;
6261
6594
  }
@@ -6421,7 +6754,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6421
6754
  }
6422
6755
  this.pendingAdBreak = null;
6423
6756
  this.cueManager.pendingScte35CueKey = void 0;
6424
- this.vmap.podAssignedByPrefetch = false;
6757
+ this.adConfig.podAssignedByPrefetch = false;
6425
6758
  }
6426
6759
  },
6427
6760
  {
@@ -6435,15 +6768,15 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6435
6768
  return _ts_generator(this, function(_state) {
6436
6769
  switch(_state.label){
6437
6770
  case 0:
6438
- scheduled = this.vmap.findCurrentOrNextBreak(this.host.video.currentTime * 1e3);
6771
+ scheduled = this.adConfig.findCurrentOrNextBreak(this.host.video.currentTime * 1e3);
6439
6772
  if (scheduled) {
6440
- this.vmap.consumedVmapBreakIds.add(this.vmap.getAdBreakKey(scheduled));
6773
+ this.adConfig.consumedVmapBreakIds.add(this.adConfig.getAdBreakKey(scheduled));
6441
6774
  }
6442
- tags = this.vmap.selectVastTagsForBreak(scheduled);
6775
+ tags = this.adConfig.selectVastTagsForBreak(scheduled);
6443
6776
  if (tags && tags.length > 0 && tags[0]) {
6444
6777
  baseVastUrl = tags[0];
6445
- } else if (this.vmap.apiVastTagUrl) {
6446
- baseVastUrl = this.vmap.apiVastTagUrl;
6778
+ } else if (this.adConfig.apiVastTagUrl) {
6779
+ baseVastUrl = this.adConfig.apiVastTagUrl;
6447
6780
  } else {
6448
6781
  this.clearPendingAdBreak();
6449
6782
  return [
@@ -6461,10 +6794,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6461
6794
  this.continuousFetchingActive = true;
6462
6795
  this.isShowingPlaceholder = false;
6463
6796
  this.timing.totalAdRequestsInBreak = 0;
6464
- if (this.vmap.podAssignedByPrefetch) {
6465
- this.vmap.podAssignedByPrefetch = false;
6797
+ if (this.adConfig.podAssignedByPrefetch) {
6798
+ this.adConfig.podAssignedByPrefetch = false;
6466
6799
  } else {
6467
- this.vmap.beginNewAdPod();
6800
+ this.adConfig.beginNewAdPod();
6468
6801
  }
6469
6802
  currentMuted = this.host.video.muted;
6470
6803
  currentVolume = this.host.video.volume;
@@ -7737,7 +8070,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7737
8070
  return _this.adBreak.inAdBreak;
7738
8071
  }
7739
8072
  });
7740
- this.vmap = new VmapManager(this.config, this.video);
8073
+ this.adConfig = new AdConfigManager(this.config, this.video);
7741
8074
  this.timing = new AdTimingService(this.config, this.video, {
7742
8075
  onAdStopTimerFired: function onAdStopTimerFired() {
7743
8076
  return _this.onAdStopTimerFired();
@@ -7817,7 +8150,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7817
8150
  generateVastUrls: function generateVastUrls(base, count) {
7818
8151
  return _this.generateVastUrls(base, count);
7819
8152
  }
7820
- }, this.timing, this.preloadPool, this.vmap, this.cueManager, this.placeholder);
8153
+ }, this.timing, this.preloadPool, this.adConfig, this.cueManager, this.placeholder);
7821
8154
  }
7822
8155
  _create_class(StormcloudVideoPlayer, [
7823
8156
  {
@@ -7845,7 +8178,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7845
8178
  {
7846
8179
  key: "generateVastUrls",
7847
8180
  value: function generateVastUrls(baseUrl, count) {
7848
- return this.vmap.generateVastUrlsWithCorrelators(baseUrl, count, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
8181
+ return this.adConfig.generateVastUrlsWithCorrelators(baseUrl, count, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
7849
8182
  }
7850
8183
  },
7851
8184
  {
@@ -7873,7 +8206,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7873
8206
  ]);
7874
8207
  return [
7875
8208
  4,
7876
- this.vmap.fetchAdConfiguration()
8209
+ this.adConfig.fetchAdConfiguration()
7877
8210
  ];
7878
8211
  case 2:
7879
8212
  _state.sent();
@@ -7900,9 +8233,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7900
8233
  continuousPlayback: (_this_config_lowLatencyMode = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false
7901
8234
  }).catch(function() {});
7902
8235
  fetchConsentSignals().then(function(signals) {
7903
- _this.vmap.consentSignals = signals;
8236
+ _this.adConfig.consentSignals = signals;
7904
8237
  }).catch(function() {});
7905
- this.vmap.initializeTracking();
8238
+ this.adConfig.initializeTracking();
7906
8239
  if (!this.hlsEngine.shouldUseNativeHls(function() {
7907
8240
  return _this.getStreamType();
7908
8241
  })) return [
@@ -7937,14 +8270,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7937
8270
  return _async_to_generator(function() {
7938
8271
  var prerollKey, adBehavior;
7939
8272
  return _ts_generator(this, function(_state) {
7940
- if (!this.vmap.isVmapEnabled() && !isLive && this.vmap.vmapBreaks.length === 0 && this.vmap.apiVastTagUrl) {
8273
+ if (!this.adConfig.isVmapEnabled() && !isLive && this.adConfig.vmapBreaks.length === 0 && this.adConfig.apiVastTagUrl) {
7941
8274
  prerollKey = "synthetic-vod-preroll";
7942
- if (!this.vmap.consumedVmapBreakIds.has(prerollKey)) {
7943
- this.vmap.vmapBreaks = [
8275
+ if (!this.adConfig.consumedVmapBreakIds.has(prerollKey)) {
8276
+ this.adConfig.vmapBreaks = [
7944
8277
  {
7945
8278
  id: prerollKey,
7946
8279
  startTimeMs: 0,
7947
- vastTagUrl: this.vmap.apiVastTagUrl
8280
+ vastTagUrl: this.adConfig.apiVastTagUrl
7948
8281
  }
7949
8282
  ];
7950
8283
  if (this.debug) {
@@ -8211,19 +8544,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8211
8544
  key: "startAdPrefetch",
8212
8545
  value: function startAdPrefetch(marker, fragmentSn, cueKey) {
8213
8546
  if (this.adBreak.pendingAdBreak || this.adBreak.inAdBreak) return;
8214
- var scheduled = this.vmap.findCurrentOrNextBreak(this.video.currentTime * 1e3);
8215
- var tags = this.vmap.selectVastTagsForBreak(scheduled);
8547
+ var scheduled = this.adConfig.findCurrentOrNextBreak(this.video.currentTime * 1e3);
8548
+ var tags = this.adConfig.selectVastTagsForBreak(scheduled);
8216
8549
  var baseVastUrl;
8217
8550
  if (tags && tags.length > 0 && tags[0]) {
8218
8551
  baseVastUrl = tags[0];
8219
- } else if (this.vmap.apiVastTagUrl) {
8220
- baseVastUrl = this.vmap.apiVastTagUrl;
8552
+ } else if (this.adConfig.apiVastTagUrl) {
8553
+ baseVastUrl = this.adConfig.apiVastTagUrl;
8221
8554
  } else {
8222
8555
  if (this.debug) console.warn("[StormcloudVideoPlayer] No VAST URL available for prefetch");
8223
8556
  return;
8224
8557
  }
8225
- this.vmap.beginNewAdPod();
8226
- this.vmap.podAssignedByPrefetch = true;
8558
+ this.adConfig.beginNewAdPod();
8559
+ this.adConfig.podAssignedByPrefetch = true;
8227
8560
  var generatedUrls = this.generateVastUrls(baseVastUrl, 1);
8228
8561
  this.adBreak.pendingAdBreak = _object_spread_props(_object_spread({
8229
8562
  marker: marker
@@ -8258,10 +8591,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8258
8591
  key: "onTimeUpdate",
8259
8592
  value: function onTimeUpdate(currentTimeSec) {
8260
8593
  var _this = this;
8261
- if (!this.vmap.isVmapEnabled() || this.vmap.vmapBreaks.length === 0) return;
8594
+ if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;
8262
8595
  if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;
8263
8596
  var nowMs = currentTimeSec * 1e3;
8264
- var breakToPlay = this.vmap.findBreakForTime(nowMs);
8597
+ var breakToPlay = this.adConfig.findBreakForTime(nowMs);
8265
8598
  if (breakToPlay) {
8266
8599
  void this.handleVmapAdBreak(breakToPlay, nowMs).catch(function(error) {
8267
8600
  if (_this.debug) {
@@ -8275,11 +8608,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8275
8608
  key: "onVideoEnded",
8276
8609
  value: function onVideoEnded() {
8277
8610
  var _this = this;
8278
- if (!this.vmap.isVmapEnabled() || this.vmap.vmapBreaks.length === 0) return;
8611
+ if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;
8279
8612
  if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;
8280
8613
  var durationMs = Number.isFinite(this.video.duration) ? Math.floor(this.video.duration * 1e3) : 0;
8281
- var postroll = this.vmap.vmapBreaks.find(function(b) {
8282
- return b.startTimeMs === -1 && !_this.vmap.consumedVmapBreakIds.has(_this.vmap.getAdBreakKey(b));
8614
+ var postroll = this.adConfig.vmapBreaks.find(function(b) {
8615
+ return b.startTimeMs === -1 && !_this.adConfig.consumedVmapBreakIds.has(_this.adConfig.getAdBreakKey(b));
8283
8616
  });
8284
8617
  if (postroll) {
8285
8618
  void this.handleVmapAdBreak(postroll, durationMs).catch(function(error) {
@@ -8298,11 +8631,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8298
8631
  return _ts_generator(this, function(_state) {
8299
8632
  switch(_state.label){
8300
8633
  case 0:
8301
- key = this.vmap.getAdBreakKey(adBreak);
8302
- if (this.vmap.consumedVmapBreakIds.has(key)) return [
8634
+ key = this.adConfig.getAdBreakKey(adBreak);
8635
+ if (this.adConfig.consumedVmapBreakIds.has(key)) return [
8303
8636
  2
8304
8637
  ];
8305
- breakStartMs = this.vmap.resolveBreakStartMs(adBreak);
8638
+ breakStartMs = this.adConfig.resolveBreakStartMs(adBreak);
8306
8639
  if (breakStartMs == null) return [
8307
8640
  2
8308
8641
  ];
@@ -8313,8 +8646,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8313
8646
  3,
8314
8647
  4
8315
8648
  ];
8316
- this.vmap.consumedVmapBreakIds.add(key);
8317
- tags = this.vmap.selectVastTagsForBreak(adBreak);
8649
+ this.adConfig.consumedVmapBreakIds.add(key);
8650
+ tags = this.adConfig.selectVastTagsForBreak(adBreak);
8318
8651
  if (!tags || tags.length === 0) return [
8319
8652
  2
8320
8653
  ];
@@ -8506,7 +8839,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8506
8839
  this.video.removeEventListener("emptied", this.emptiedHandler);
8507
8840
  delete this.emptiedHandler;
8508
8841
  }
8509
- this.vmap.destroyTracking();
8842
+ this.adConfig.destroyTracking();
8510
8843
  this.hlsEngine.destroy();
8511
8844
  (_this_adPlayer = this.adPlayer) === null || _this_adPlayer === void 0 ? void 0 : _this_adPlayer.destroy();
8512
8845
  if (this.palPlaybackStarted) {