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.cjs CHANGED
@@ -1011,6 +1011,7 @@ function createHlsAdPlayer(contentVideo, options) {
1011
1011
  handleAdComplete();
1012
1012
  });
1013
1013
  adVideoElement.addEventListener("error", function(e) {
1014
+ if (!adPlaying) return;
1014
1015
  console.error("[HlsAdPlayer] Ad video error:", e);
1015
1016
  if (currentAd) {
1016
1017
  fireTrackingPixels(currentAd.trackingUrls.error);
@@ -1212,15 +1213,15 @@ function createHlsAdPlayer(contentVideo, options) {
1212
1213
  adVideoElement.muted = originalMutedState;
1213
1214
  console.log("[HlsAdPlayer] Set ad video volume to ".concat(adVideoElement.volume, ", muted: ").concat(adVideoElement.muted, ", originalMutedState: ").concat(originalMutedState, ", contentVolume: ").concat(contentVolume));
1214
1215
  }
1216
+ mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1217
+ if (!mediaFile) {
1218
+ throw new Error("No media file available for ad");
1219
+ }
1215
1220
  if (adContainerEl) {
1216
1221
  adContainerEl.style.display = "flex";
1217
1222
  adContainerEl.style.pointerEvents = "auto";
1218
1223
  }
1219
1224
  emit("content_pause");
1220
- mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1221
- if (!mediaFile) {
1222
- throw new Error("No media file available for ad");
1223
- }
1224
1225
  isHlsAd = isHlsMediaFile(mediaFile);
1225
1226
  console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad from: ").concat(mediaFile.url));
1226
1227
  if (isHlsAd && import_hls.default.isSupported()) {
@@ -2530,22 +2531,337 @@ function initializePolyfills() {
2530
2531
  polyfillTextEncoder();
2531
2532
  polyfillPromiseFinally();
2532
2533
  }
2533
- // src/utils/vastMacros.ts
2534
- function generateCorrelator() {
2535
- if (typeof crypto !== "undefined" && crypto.getRandomValues) {
2534
+ // src/utils/vastEnvironmentSignals.ts
2535
+ var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
2536
+ var AIRY_WEBOS_APP_ID = "com.freeairytv.webos";
2537
+ var AIRY_TIZEN_APP_ID = "com.freeairytv.samsung";
2538
+ var AIRY_ROKU_APP_ID = "com.freeairytv.roku";
2539
+ var AIRY_APP_NAME = "AiryTV Movies & TV";
2540
+ var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
2541
+ var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
2542
+ function getDefaultAppId() {
2543
+ if (typeof navigator === "undefined") return AIRY_ANDROID_APP_ID;
2544
+ var ua = navigator.userAgent;
2545
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;
2546
+ if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;
2547
+ if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;
2548
+ return AIRY_ANDROID_APP_ID;
2549
+ }
2550
+ var DEVICE_ID_STORAGE_KEYS = [
2551
+ "rdid",
2552
+ "ifa",
2553
+ "advertisingId",
2554
+ "advertising_id",
2555
+ "deviceAdvertisingId",
2556
+ "aaid",
2557
+ "adid",
2558
+ "rida",
2559
+ "tifa",
2560
+ "lgudid"
2561
+ ];
2562
+ var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
2563
+ "aaid",
2564
+ "adid"
2565
+ ]);
2566
+ function resolveVastEnvironmentSignals(isCtv) {
2567
+ var _ref, _bridgeSignals_limitAdTracking;
2568
+ var bridgeSignals = readNativeBridgeSignals();
2569
+ var deviceId = bridgeSignals.deviceId || readStoredDeviceId();
2570
+ var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || inferDeviceIdType();
2571
+ 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;
2572
+ if (isCtv) {
2573
+ return _object_spread_props(_object_spread({
2574
+ isCtv: true,
2575
+ contentUrl: bridgeSignals.contentUrl || readStoredString("contentUrl") || AIRY_DEFAULT_CONTENT_URL,
2576
+ appId: bridgeSignals.appId || readStoredString("appId") || readStoredString("msid") || getDefaultAppId(),
2577
+ appName: bridgeSignals.appName || readStoredString("appName") || readStoredString("an") || AIRY_APP_NAME,
2578
+ sessionId: getOrCreateCtvSessionId()
2579
+ }, deviceId ? {
2580
+ deviceId: deviceId
2581
+ } : {}, deviceIdType ? {
2582
+ deviceIdType: deviceIdType
2583
+ } : {}, limitAdTracking != null ? {
2584
+ limitAdTracking: limitAdTracking
2585
+ } : {}), {
2586
+ deviceTypeHint: 5
2587
+ });
2588
+ }
2589
+ return _object_spread({
2590
+ isCtv: false
2591
+ }, deviceId ? {
2592
+ deviceId: deviceId
2593
+ } : {}, deviceIdType ? {
2594
+ deviceIdType: deviceIdType
2595
+ } : {}, limitAdTracking != null ? {
2596
+ limitAdTracking: limitAdTracking
2597
+ } : {});
2598
+ }
2599
+ function inferDeviceIdType() {
2600
+ if (typeof navigator === "undefined") {
2601
+ return void 0;
2602
+ }
2603
+ var ua = navigator.userAgent;
2604
+ if (/Roku/i.test(ua)) return "rida";
2605
+ if (/Tizen|Samsung/i.test(ua)) return "tifa";
2606
+ if (/AppleTV|Apple TV/i.test(ua)) return "tvOS";
2607
+ if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
2608
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return "lgudid";
2609
+ if (/Android|Google TV/i.test(ua)) return "aaid";
2610
+ if (/iPhone|iPad|iPod/i.test(ua)) return "idfa";
2611
+ return void 0;
2612
+ }
2613
+ function isEquivalentDeviceIdType(tagType, runtimeType) {
2614
+ if (!tagType || !runtimeType) return false;
2615
+ var tag = tagType.toLowerCase();
2616
+ var runtime = runtimeType.toLowerCase();
2617
+ if (tag === runtime) return true;
2618
+ return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
2619
+ }
2620
+ function getOrCreateCtvSessionId() {
2621
+ var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
2622
+ if (existing) {
2623
+ return existing;
2624
+ }
2625
+ var sessionId = createUuid();
2626
+ try {
2627
+ var _window_localStorage;
2628
+ (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
2629
+ } catch (unused) {}
2630
+ return sessionId;
2631
+ }
2632
+ function createUuid() {
2633
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
2634
+ return crypto.randomUUID();
2635
+ }
2636
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
2637
+ var value = Math.floor(Math.random() * 16);
2638
+ var nibble = char === "x" ? value : value & 3 | 8;
2639
+ return nibble.toString(16);
2640
+ });
2641
+ }
2642
+ function readNativeBridgeSignals() {
2643
+ if (typeof window === "undefined") {
2644
+ return {};
2645
+ }
2646
+ var candidates = [
2647
+ window.__STORMCLOUD_CTV_AD_INFO__,
2648
+ window.__STORMCLOUD_CTV__,
2649
+ window.stormcloudCtv,
2650
+ window.AiryTV,
2651
+ window.Android,
2652
+ window.webOS,
2653
+ window.tizen,
2654
+ window.amazon
2655
+ ].filter(Boolean);
2656
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2657
+ try {
2658
+ for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2659
+ var source = _step.value;
2660
+ var contentUrl = readBridgeValue(source, [
2661
+ "contentUrl",
2662
+ "url",
2663
+ "videoUrl",
2664
+ "canonicalUrl"
2665
+ ]) || void 0;
2666
+ var appId = readBridgeValue(source, [
2667
+ "appId",
2668
+ "msid",
2669
+ "applicationId",
2670
+ "packageName"
2671
+ ]) || void 0;
2672
+ var appName = readBridgeValue(source, [
2673
+ "appName",
2674
+ "an",
2675
+ "applicationName"
2676
+ ]) || void 0;
2677
+ var deviceId = readBridgeValue(source, [
2678
+ "rdid",
2679
+ "ifa",
2680
+ "advertisingId",
2681
+ "adId",
2682
+ "deviceId",
2683
+ "lgudid",
2684
+ "LGUDID",
2685
+ "tifa",
2686
+ "rida",
2687
+ "afai",
2688
+ "aaid"
2689
+ ]) || void 0;
2690
+ if (!contentUrl && !deviceId && !appId && !appName) continue;
2691
+ var deviceIdType = readBridgeValue(source, [
2692
+ "idtype",
2693
+ "deviceIdType",
2694
+ "advertisingIdType",
2695
+ "idType"
2696
+ ]) || inferDeviceIdType();
2697
+ var limitAdTracking = readBridgeBoolean(source, [
2698
+ "is_lat",
2699
+ "limitAdTracking",
2700
+ "limitedAdTracking",
2701
+ "lat"
2702
+ ]);
2703
+ return _object_spread({}, contentUrl ? {
2704
+ contentUrl: contentUrl
2705
+ } : {}, appId ? {
2706
+ appId: appId
2707
+ } : {}, appName ? {
2708
+ appName: appName
2709
+ } : {}, deviceId ? {
2710
+ deviceId: deviceId
2711
+ } : {}, deviceId && deviceIdType ? {
2712
+ deviceIdType: deviceIdType
2713
+ } : {}, deviceId && limitAdTracking != null ? {
2714
+ limitAdTracking: limitAdTracking
2715
+ } : {});
2716
+ }
2717
+ } catch (err) {
2718
+ _didIteratorError = true;
2719
+ _iteratorError = err;
2720
+ } finally{
2536
2721
  try {
2537
- var _buf_, _buf_1;
2538
- var buf = new Uint32Array(2);
2539
- crypto.getRandomValues(buf);
2540
- 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);
2541
- if (value > 0) {
2542
- return String(value);
2722
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2723
+ _iterator.return();
2543
2724
  }
2544
- } catch (unused) {}
2725
+ } finally{
2726
+ if (_didIteratorError) {
2727
+ throw _iteratorError;
2728
+ }
2729
+ }
2545
2730
  }
2546
- return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);
2731
+ return {};
2732
+ }
2733
+ function readBridgeValue(source, keys) {
2734
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2735
+ try {
2736
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2737
+ var key = _step.value;
2738
+ var value = source === null || source === void 0 ? void 0 : source[key];
2739
+ if (typeof value === "string" && value) {
2740
+ return value;
2741
+ }
2742
+ if (typeof value === "function") {
2743
+ try {
2744
+ var result = value.call(source);
2745
+ if (typeof result === "string" && result) {
2746
+ return result;
2747
+ }
2748
+ } catch (unused) {}
2749
+ }
2750
+ }
2751
+ } catch (err) {
2752
+ _didIteratorError = true;
2753
+ _iteratorError = err;
2754
+ } finally{
2755
+ try {
2756
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2757
+ _iterator.return();
2758
+ }
2759
+ } finally{
2760
+ if (_didIteratorError) {
2761
+ throw _iteratorError;
2762
+ }
2763
+ }
2764
+ }
2765
+ return void 0;
2547
2766
  }
2767
+ function readBridgeBoolean(source, keys) {
2768
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2769
+ try {
2770
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2771
+ var key = _step.value;
2772
+ var value = source === null || source === void 0 ? void 0 : source[key];
2773
+ var normalized = normalizeBoolean(value);
2774
+ if (normalized != null) {
2775
+ return normalized;
2776
+ }
2777
+ if (typeof value === "function") {
2778
+ try {
2779
+ var result = normalizeBoolean(value.call(source));
2780
+ if (result != null) {
2781
+ return result;
2782
+ }
2783
+ } catch (unused) {}
2784
+ }
2785
+ }
2786
+ } catch (err) {
2787
+ _didIteratorError = true;
2788
+ _iteratorError = err;
2789
+ } finally{
2790
+ try {
2791
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2792
+ _iterator.return();
2793
+ }
2794
+ } finally{
2795
+ if (_didIteratorError) {
2796
+ throw _iteratorError;
2797
+ }
2798
+ }
2799
+ }
2800
+ return void 0;
2801
+ }
2802
+ function readStoredDeviceId() {
2803
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2804
+ try {
2805
+ for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2806
+ var key = _step.value;
2807
+ var value = readStoredString(key);
2808
+ if (value) {
2809
+ return value;
2810
+ }
2811
+ }
2812
+ } catch (err) {
2813
+ _didIteratorError = true;
2814
+ _iteratorError = err;
2815
+ } finally{
2816
+ try {
2817
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2818
+ _iterator.return();
2819
+ }
2820
+ } finally{
2821
+ if (_didIteratorError) {
2822
+ throw _iteratorError;
2823
+ }
2824
+ }
2825
+ }
2826
+ return void 0;
2827
+ }
2828
+ function readStoredString(key) {
2829
+ if (typeof window === "undefined") {
2830
+ return void 0;
2831
+ }
2832
+ try {
2833
+ var _window_localStorage;
2834
+ var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
2835
+ return value || void 0;
2836
+ } catch (unused) {
2837
+ return void 0;
2838
+ }
2839
+ }
2840
+ function readStoredLimitAdTracking() {
2841
+ return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
2842
+ }
2843
+ function normalizeBoolean(value) {
2844
+ if (typeof value === "boolean") {
2845
+ return value;
2846
+ }
2847
+ if (typeof value === "number") {
2848
+ return value === 1;
2849
+ }
2850
+ if (typeof value === "string") {
2851
+ var normalized = value.toLowerCase();
2852
+ if (normalized === "1" || normalized === "true" || normalized === "yes") {
2853
+ return true;
2854
+ }
2855
+ if (normalized === "0" || normalized === "false" || normalized === "no") {
2856
+ return false;
2857
+ }
2858
+ }
2859
+ return void 0;
2860
+ }
2861
+ // src/utils/vastMacros.ts
2548
2862
  var UNEXPANDED_MACRO_PATTERN = /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/;
2863
+ var INVALID_VAST_PARAM_KEY = /^\s|\s$/;
2864
+ var EXAMPLE_COM_URL = /example\.com/i;
2549
2865
  var CTV_UNSUPPORTED_PARAMS = [
2550
2866
  "description_url",
2551
2867
  "tfcd",
@@ -2560,14 +2876,288 @@ var CTV_UNSUPPORTED_PARAMS = [
2560
2876
  "gdpr_consent",
2561
2877
  "us_privacy"
2562
2878
  ];
2879
+ var INLINE_DEVICE_MACRO_REPLACEMENTS = [
2880
+ {
2881
+ pattern: /\[RDID\]/gi,
2882
+ getValue: function getValue(ctx) {
2883
+ return ctx.deviceId;
2884
+ }
2885
+ },
2886
+ {
2887
+ pattern: /\[IFA\]/gi,
2888
+ getValue: function getValue(ctx) {
2889
+ return ctx.deviceId;
2890
+ }
2891
+ },
2892
+ {
2893
+ pattern: /\[ADVERTISING[_-]?ID(?:ENTIFIER)?\]/gi,
2894
+ getValue: function getValue(ctx) {
2895
+ return ctx.deviceId;
2896
+ }
2897
+ },
2898
+ {
2899
+ pattern: /\[DEVICE[_-]?ID\]/gi,
2900
+ getValue: function getValue(ctx) {
2901
+ return ctx.deviceId;
2902
+ }
2903
+ },
2904
+ {
2905
+ pattern: /\[IDTYPE\]/gi,
2906
+ getValue: function getValue(ctx) {
2907
+ return ctx.deviceIdType;
2908
+ }
2909
+ },
2910
+ {
2911
+ pattern: /\{rdid\}/gi,
2912
+ getValue: function getValue(ctx) {
2913
+ return ctx.deviceId;
2914
+ }
2915
+ },
2916
+ {
2917
+ pattern: /\{device[_-]?id\}/gi,
2918
+ getValue: function getValue(ctx) {
2919
+ return ctx.deviceId;
2920
+ }
2921
+ },
2922
+ {
2923
+ pattern: /\{idtype\}/gi,
2924
+ getValue: function getValue(ctx) {
2925
+ return ctx.deviceIdType;
2926
+ }
2927
+ },
2928
+ {
2929
+ pattern: /%%ADVERTISING_IDENTIFIER_PLAIN%%/gi,
2930
+ getValue: function getValue(ctx) {
2931
+ return ctx.deviceId;
2932
+ }
2933
+ },
2934
+ {
2935
+ pattern: /%%ADVERTISING_ID_OPT_OUT%%/gi,
2936
+ getValue: function getValue(ctx) {
2937
+ return ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2938
+ }
2939
+ },
2940
+ {
2941
+ pattern: /%%ADVERTISING_ID_TYPE%%/gi,
2942
+ getValue: function getValue(ctx) {
2943
+ return ctx.deviceIdType;
2944
+ }
2945
+ },
2946
+ {
2947
+ pattern: /%%ADVERTISING_ID%%/gi,
2948
+ getValue: function getValue(ctx) {
2949
+ return ctx.deviceId;
2950
+ }
2951
+ },
2952
+ {
2953
+ pattern: /%%LIMIT_AD_TRACKING%%/gi,
2954
+ getValue: function getValue(ctx) {
2955
+ return ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2956
+ }
2957
+ },
2958
+ {
2959
+ pattern: /%%MSID%%/gi,
2960
+ getValue: function getValue(ctx) {
2961
+ return ctx.appId;
2962
+ }
2963
+ },
2964
+ {
2965
+ pattern: /%%APP_NAME%%/gi,
2966
+ getValue: function getValue(ctx) {
2967
+ return ctx.appName;
2968
+ }
2969
+ },
2970
+ {
2971
+ pattern: /%%SESSION_ID%%/gi,
2972
+ getValue: function getValue(ctx) {
2973
+ return ctx.sessionId;
2974
+ }
2975
+ },
2976
+ {
2977
+ pattern: /%%CORRELATOR%%/gi,
2978
+ getValue: function getValue(ctx) {
2979
+ return ctx.correlator;
2980
+ }
2981
+ }
2982
+ ];
2983
+ function isMacroPlaceholder(value) {
2984
+ if (value == null) return true;
2985
+ var trimmed = value.trim();
2986
+ if (!trimmed) return true;
2987
+ if (UNEXPANDED_MACRO_PATTERN.test(trimmed)) return true;
2988
+ return /^(unknown|null|undefined|none|n\/a|\$\{[^}]+\})$/i.test(trimmed);
2989
+ }
2990
+ function generateCorrelator() {
2991
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
2992
+ try {
2993
+ var _buf_, _buf_1;
2994
+ var buf = new Uint32Array(2);
2995
+ crypto.getRandomValues(buf);
2996
+ 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);
2997
+ if (value > 0) {
2998
+ return String(value);
2999
+ }
3000
+ } catch (unused) {}
3001
+ }
3002
+ return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);
3003
+ }
3004
+ function expandInlineMacroPlaceholders(baseUrl, ctx) {
3005
+ var url = baseUrl;
3006
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3007
+ try {
3008
+ for(var _iterator = INLINE_DEVICE_MACRO_REPLACEMENTS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3009
+ var _step_value = _step.value, pattern = _step_value.pattern, getValue = _step_value.getValue;
3010
+ var value = getValue(ctx);
3011
+ if (value != null && value !== "") {
3012
+ url = url.replace(pattern, encodeURIComponent(value));
3013
+ }
3014
+ }
3015
+ } catch (err) {
3016
+ _didIteratorError = true;
3017
+ _iteratorError = err;
3018
+ } finally{
3019
+ try {
3020
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
3021
+ _iterator.return();
3022
+ }
3023
+ } finally{
3024
+ if (_didIteratorError) {
3025
+ throw _iteratorError;
3026
+ }
3027
+ }
3028
+ }
3029
+ return url;
3030
+ }
3031
+ function applyDeviceIdentityParams(params, ctx) {
3032
+ var _ctx_deviceId, _ctx_deviceIdType;
3033
+ var runtimeId = (_ctx_deviceId = ctx.deviceId) === null || _ctx_deviceId === void 0 ? void 0 : _ctx_deviceId.trim();
3034
+ var runtimeType = ((_ctx_deviceIdType = ctx.deviceIdType) === null || _ctx_deviceIdType === void 0 ? void 0 : _ctx_deviceIdType.trim()) || inferDeviceIdType();
3035
+ var tagRdid = params.get("rdid");
3036
+ var tagType = params.get("idtype");
3037
+ var tagLat = params.get("is_lat");
3038
+ var latValue = ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
3039
+ if (runtimeId) {
3040
+ params.set("rdid", runtimeId);
3041
+ params.set("idtype", runtimeType || tagType || "aaid");
3042
+ params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder(tagLat) ? "0" : tagLat);
3043
+ return;
3044
+ }
3045
+ var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));
3046
+ var tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));
3047
+ if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {
3048
+ params.delete("rdid");
3049
+ params.delete("idtype");
3050
+ params.delete("is_lat");
3051
+ return;
3052
+ }
3053
+ if (tagRdidValid) {
3054
+ if (isMacroPlaceholder(tagType) && runtimeType) {
3055
+ params.set("idtype", runtimeType);
3056
+ }
3057
+ if (isMacroPlaceholder(tagLat)) {
3058
+ params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : "0");
3059
+ }
3060
+ return;
3061
+ }
3062
+ params.delete("rdid");
3063
+ params.delete("idtype");
3064
+ params.delete("is_lat");
3065
+ }
3066
+ function removeBrokenAppNameOrphans(params, appName) {
3067
+ var toDelete = [];
3068
+ params.forEach(function(_value, key) {
3069
+ if (!key || INVALID_VAST_PARAM_KEY.test(key)) {
3070
+ toDelete.push(key);
3071
+ }
3072
+ });
3073
+ if (appName && appName.includes("&")) {
3074
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3075
+ try {
3076
+ for(var _iterator = appName.split("&").slice(1)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3077
+ var suffix = _step.value;
3078
+ var trimmed = suffix.trimStart();
3079
+ if (!trimmed) continue;
3080
+ toDelete.push(suffix, " ".concat(trimmed), trimmed);
3081
+ }
3082
+ } catch (err) {
3083
+ _didIteratorError = true;
3084
+ _iteratorError = err;
3085
+ } finally{
3086
+ try {
3087
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
3088
+ _iterator.return();
3089
+ }
3090
+ } finally{
3091
+ if (_didIteratorError) {
3092
+ throw _iteratorError;
3093
+ }
3094
+ }
3095
+ }
3096
+ }
3097
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
3098
+ try {
3099
+ for(var _iterator1 = new Set(toDelete)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
3100
+ var key = _step1.value;
3101
+ if (key) params.delete(key);
3102
+ }
3103
+ } catch (err) {
3104
+ _didIteratorError1 = true;
3105
+ _iteratorError1 = err;
3106
+ } finally{
3107
+ try {
3108
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
3109
+ _iterator1.return();
3110
+ }
3111
+ } finally{
3112
+ if (_didIteratorError1) {
3113
+ throw _iteratorError1;
3114
+ }
3115
+ }
3116
+ }
3117
+ }
3118
+ function normalizeVastTagUrl(raw) {
3119
+ if (!raw) return raw;
3120
+ try {
3121
+ var url = new URL(raw);
3122
+ var anValue = url.searchParams.get("an");
3123
+ if (anValue !== null) {
3124
+ var orphanFragments = [];
3125
+ url.searchParams.forEach(function(_value, key) {
3126
+ if (key && INVALID_VAST_PARAM_KEY.test(key)) {
3127
+ orphanFragments.push(key.trim());
3128
+ }
3129
+ });
3130
+ if (orphanFragments.length > 0) {
3131
+ var reconstructed = [
3132
+ anValue.trimEnd()
3133
+ ].concat(_to_consumable_array(orphanFragments)).filter(Boolean).join(" & ");
3134
+ url.searchParams.forEach(function(_value, key) {
3135
+ if (key && INVALID_VAST_PARAM_KEY.test(key)) {
3136
+ url.searchParams.delete(key);
3137
+ }
3138
+ });
3139
+ url.searchParams.set("an", reconstructed);
3140
+ return url.toString().replace(/([?&]an=)([^&]*)/, function(_match, prefix, val) {
3141
+ return prefix + val.replace(/\+/g, "%20");
3142
+ });
3143
+ }
3144
+ }
3145
+ removeBrokenAppNameOrphans(url.searchParams);
3146
+ return url.toString();
3147
+ } catch (unused) {
3148
+ return raw;
3149
+ }
3150
+ }
2563
3151
  function applyVastMacros(baseUrl, ctx) {
3152
+ var expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);
2564
3153
  var url;
2565
3154
  try {
2566
- url = new URL(baseUrl);
3155
+ url = new URL(normalizeVastTagUrl(expandedUrl));
2567
3156
  } catch (unused) {
2568
- return replaceCorrelatorFallback(baseUrl, ctx.correlator);
3157
+ return replaceCorrelatorFallback(expandedUrl, ctx.correlator);
2569
3158
  }
2570
3159
  var params = url.searchParams;
3160
+ removeBrokenAppNameOrphans(params, ctx.appName);
2571
3161
  params.set("correlator", ctx.correlator);
2572
3162
  if (ctx.isCtv) {
2573
3163
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
@@ -2605,6 +3195,12 @@ function applyVastMacros(baseUrl, ctx) {
2605
3195
  if (!ctx.isCtv) {
2606
3196
  params.set("description_url", requestUrl);
2607
3197
  }
3198
+ } else {
3199
+ var existingUrl = params.get("url") || "";
3200
+ if (EXAMPLE_COM_URL.test(existingUrl)) {
3201
+ params.delete("url");
3202
+ params.delete("description_url");
3203
+ }
2608
3204
  }
2609
3205
  if (ctx.adWillPlayMuted != null) {
2610
3206
  params.set("vpmute", ctx.adWillPlayMuted ? "1" : "0");
@@ -2616,6 +3212,7 @@ function applyVastMacros(baseUrl, ctx) {
2616
3212
  params.set("msid", ctx.appId);
2617
3213
  }
2618
3214
  if (ctx.appName) {
3215
+ removeBrokenAppNameOrphans(params, ctx.appName);
2619
3216
  params.set("an", ctx.appName);
2620
3217
  }
2621
3218
  if (ctx.sessionId) {
@@ -2626,15 +3223,7 @@ function applyVastMacros(baseUrl, ctx) {
2626
3223
  } else if (ctx.isCtv) {
2627
3224
  params.set("dth", "5");
2628
3225
  }
2629
- if (ctx.deviceId && ctx.deviceIdType) {
2630
- params.set("rdid", ctx.deviceId);
2631
- params.set("idtype", ctx.deviceIdType);
2632
- params.set("is_lat", ctx.limitAdTracking ? "1" : "0");
2633
- } else {
2634
- params.delete("rdid");
2635
- params.delete("idtype");
2636
- params.delete("is_lat");
2637
- }
3226
+ applyDeviceIdentityParams(params, ctx);
2638
3227
  if (!ctx.isCtv) {
2639
3228
  var consent = ctx.consent;
2640
3229
  if ((consent === null || consent === void 0 ? void 0 : consent.gdpr) != null) {
@@ -2652,7 +3241,7 @@ function applyVastMacros(baseUrl, ctx) {
2652
3241
  }
2653
3242
  var staleKeys = [];
2654
3243
  params.forEach(function(value, key) {
2655
- if (UNEXPANDED_MACRO_PATTERN.test(value)) {
3244
+ if (isMacroPlaceholder(value)) {
2656
3245
  staleKeys.push(key);
2657
3246
  }
2658
3247
  });
@@ -2676,6 +3265,7 @@ function applyVastMacros(baseUrl, ctx) {
2676
3265
  }
2677
3266
  }
2678
3267
  }
3268
+ removeBrokenAppNameOrphans(params, ctx.appName);
2679
3269
  return url.toString();
2680
3270
  }
2681
3271
  function replaceCorrelatorFallback(baseUrl, correlator) {
@@ -3949,276 +4539,10 @@ var Scte35CueManager = /*#__PURE__*/ function() {
3949
4539
  ]);
3950
4540
  return Scte35CueManager;
3951
4541
  }();
3952
- // src/utils/ctvVastSignals.ts
3953
- var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
3954
- var AIRY_APP_NAME = "AiryTV Movies & TV";
3955
- var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
3956
- var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
3957
- var DEVICE_ID_STORAGE_KEYS = [
3958
- "rdid",
3959
- "ifa",
3960
- "advertisingId",
3961
- "advertising_id",
3962
- "deviceAdvertisingId",
3963
- "aaid",
3964
- "adid",
3965
- "rida",
3966
- "tifa"
3967
- ];
3968
- function resolveCtvVastSignals() {
3969
- var _ref, _bridgeSignals_limitAdTracking;
3970
- var bridgeSignals = readNativeBridgeSignals();
3971
- var deviceId = bridgeSignals.deviceId || readStoredDeviceId();
3972
- var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || inferDeviceIdType();
3973
- var contentUrl = bridgeSignals.contentUrl || readStoredString("contentUrl") || AIRY_DEFAULT_CONTENT_URL;
3974
- return _object_spread_props(_object_spread({
3975
- contentUrl: contentUrl,
3976
- appId: AIRY_ANDROID_APP_ID,
3977
- appName: AIRY_APP_NAME,
3978
- sessionId: getOrCreateCtvSessionId()
3979
- }, deviceId ? {
3980
- deviceId: deviceId
3981
- } : {}, deviceId && deviceIdType ? {
3982
- deviceIdType: deviceIdType
3983
- } : {}, deviceId ? {
3984
- limitAdTracking: (_ref = (_bridgeSignals_limitAdTracking = bridgeSignals.limitAdTracking) !== null && _bridgeSignals_limitAdTracking !== void 0 ? _bridgeSignals_limitAdTracking : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false
3985
- } : {}), {
3986
- deviceTypeHint: 5
3987
- });
3988
- }
3989
- function getOrCreateCtvSessionId() {
3990
- var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
3991
- if (existing) {
3992
- return existing;
3993
- }
3994
- var sessionId = createUuid();
3995
- try {
3996
- var _window_localStorage;
3997
- (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
3998
- } catch (unused) {}
3999
- return sessionId;
4000
- }
4001
- function createUuid() {
4002
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
4003
- return crypto.randomUUID();
4004
- }
4005
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
4006
- var value = Math.floor(Math.random() * 16);
4007
- var nibble = char === "x" ? value : value & 3 | 8;
4008
- return nibble.toString(16);
4009
- });
4010
- }
4011
- function readNativeBridgeSignals() {
4012
- if (typeof window === "undefined") {
4013
- return {};
4014
- }
4015
- var candidates = [
4016
- window.__STORMCLOUD_CTV_AD_INFO__,
4017
- window.__STORMCLOUD_CTV__,
4018
- window.stormcloudCtv,
4019
- window.AiryTV,
4020
- window.Android
4021
- ].filter(Boolean);
4022
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4023
- try {
4024
- for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4025
- var source = _step.value;
4026
- var contentUrl = readBridgeValue(source, [
4027
- "contentUrl",
4028
- "url",
4029
- "videoUrl",
4030
- "canonicalUrl"
4031
- ]) || void 0;
4032
- var deviceId = readBridgeValue(source, [
4033
- "rdid",
4034
- "ifa",
4035
- "advertisingId",
4036
- "adId",
4037
- "deviceId"
4038
- ]) || void 0;
4039
- if (!contentUrl && !deviceId) continue;
4040
- var deviceIdType = readBridgeValue(source, [
4041
- "idtype",
4042
- "deviceIdType",
4043
- "advertisingIdType"
4044
- ]) || inferDeviceIdType();
4045
- var limitAdTracking = readBridgeBoolean(source, [
4046
- "is_lat",
4047
- "limitAdTracking",
4048
- "limitedAdTracking",
4049
- "lat"
4050
- ]);
4051
- return _object_spread({}, contentUrl ? {
4052
- contentUrl: contentUrl
4053
- } : {}, deviceId ? {
4054
- deviceId: deviceId
4055
- } : {}, deviceId && deviceIdType ? {
4056
- deviceIdType: deviceIdType
4057
- } : {}, deviceId && limitAdTracking != null ? {
4058
- limitAdTracking: limitAdTracking
4059
- } : {});
4060
- }
4061
- } catch (err) {
4062
- _didIteratorError = true;
4063
- _iteratorError = err;
4064
- } finally{
4065
- try {
4066
- if (!_iteratorNormalCompletion && _iterator.return != null) {
4067
- _iterator.return();
4068
- }
4069
- } finally{
4070
- if (_didIteratorError) {
4071
- throw _iteratorError;
4072
- }
4073
- }
4074
- }
4075
- return {};
4076
- }
4077
- function readBridgeValue(source, keys) {
4078
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4079
- try {
4080
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4081
- var key = _step.value;
4082
- var value = source === null || source === void 0 ? void 0 : source[key];
4083
- if (typeof value === "string" && value) {
4084
- return value;
4085
- }
4086
- if (typeof value === "function") {
4087
- try {
4088
- var result = value.call(source);
4089
- if (typeof result === "string" && result) {
4090
- return result;
4091
- }
4092
- } catch (unused) {}
4093
- }
4094
- }
4095
- } catch (err) {
4096
- _didIteratorError = true;
4097
- _iteratorError = err;
4098
- } finally{
4099
- try {
4100
- if (!_iteratorNormalCompletion && _iterator.return != null) {
4101
- _iterator.return();
4102
- }
4103
- } finally{
4104
- if (_didIteratorError) {
4105
- throw _iteratorError;
4106
- }
4107
- }
4108
- }
4109
- return void 0;
4110
- }
4111
- function readBridgeBoolean(source, keys) {
4112
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4113
- try {
4114
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4115
- var key = _step.value;
4116
- var value = source === null || source === void 0 ? void 0 : source[key];
4117
- var normalized = normalizeBoolean(value);
4118
- if (normalized != null) {
4119
- return normalized;
4120
- }
4121
- if (typeof value === "function") {
4122
- try {
4123
- var result = normalizeBoolean(value.call(source));
4124
- if (result != null) {
4125
- return result;
4126
- }
4127
- } catch (unused) {}
4128
- }
4129
- }
4130
- } catch (err) {
4131
- _didIteratorError = true;
4132
- _iteratorError = err;
4133
- } finally{
4134
- try {
4135
- if (!_iteratorNormalCompletion && _iterator.return != null) {
4136
- _iterator.return();
4137
- }
4138
- } finally{
4139
- if (_didIteratorError) {
4140
- throw _iteratorError;
4141
- }
4142
- }
4143
- }
4144
- return void 0;
4145
- }
4146
- function readStoredDeviceId() {
4147
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4148
- try {
4149
- for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4150
- var key = _step.value;
4151
- var value = readStoredString(key);
4152
- if (value) {
4153
- return value;
4154
- }
4155
- }
4156
- } catch (err) {
4157
- _didIteratorError = true;
4158
- _iteratorError = err;
4159
- } finally{
4160
- try {
4161
- if (!_iteratorNormalCompletion && _iterator.return != null) {
4162
- _iterator.return();
4163
- }
4164
- } finally{
4165
- if (_didIteratorError) {
4166
- throw _iteratorError;
4167
- }
4168
- }
4169
- }
4170
- return void 0;
4171
- }
4172
- function readStoredString(key) {
4173
- if (typeof window === "undefined") {
4174
- return void 0;
4175
- }
4176
- try {
4177
- var _window_localStorage;
4178
- var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
4179
- return value || void 0;
4180
- } catch (unused) {
4181
- return void 0;
4182
- }
4183
- }
4184
- function readStoredLimitAdTracking() {
4185
- return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
4186
- }
4187
- function normalizeBoolean(value) {
4188
- if (typeof value === "boolean") {
4189
- return value;
4190
- }
4191
- if (typeof value === "number") {
4192
- return value === 1;
4193
- }
4194
- if (typeof value === "string") {
4195
- var normalized = value.toLowerCase();
4196
- if (normalized === "1" || normalized === "true" || normalized === "yes") {
4197
- return true;
4198
- }
4199
- if (normalized === "0" || normalized === "false" || normalized === "no") {
4200
- return false;
4201
- }
4202
- }
4203
- return void 0;
4204
- }
4205
- function inferDeviceIdType() {
4206
- if (typeof navigator === "undefined") {
4207
- return void 0;
4208
- }
4209
- var ua = navigator.userAgent;
4210
- if (/Roku/i.test(ua)) return "rida";
4211
- if (/Tizen|Samsung/i.test(ua)) return "tifa";
4212
- if (/AppleTV/i.test(ua)) return "tvOS";
4213
- if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
4214
- if (/Web0S|webOS|LG/i.test(ua)) return "lgudid";
4215
- if (/Android|Google TV/i.test(ua)) return "aaid";
4216
- return void 0;
4217
- }
4218
- // src/player/VmapManager.ts
4219
- var VmapManager = /*#__PURE__*/ function() {
4220
- function VmapManager(config, video) {
4221
- _class_call_check(this, VmapManager);
4542
+ // src/player/AdConfigManager.ts
4543
+ var AdConfigManager = /*#__PURE__*/ function() {
4544
+ function AdConfigManager(config, video) {
4545
+ _class_call_check(this, AdConfigManager);
4222
4546
  this.vmapBreaks = [];
4223
4547
  this.consumedVmapBreakIds = /* @__PURE__ */ new Set();
4224
4548
  this.streamCorrelator = generateCorrelator();
@@ -4230,7 +4554,7 @@ var VmapManager = /*#__PURE__*/ function() {
4230
4554
  this.config = config;
4231
4555
  this.video = video;
4232
4556
  }
4233
- _create_class(VmapManager, [
4557
+ _create_class(AdConfigManager, [
4234
4558
  {
4235
4559
  key: "debug",
4236
4560
  get: function get() {
@@ -4248,7 +4572,7 @@ var VmapManager = /*#__PURE__*/ function() {
4248
4572
  key: "fetchAdConfiguration",
4249
4573
  value: function fetchAdConfiguration() {
4250
4574
  return _async_to_generator(function() {
4251
- 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;
4575
+ 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;
4252
4576
  return _ts_generator(this, function(_state) {
4253
4577
  switch(_state.label){
4254
4578
  case 0:
@@ -4292,7 +4616,7 @@ var VmapManager = /*#__PURE__*/ function() {
4292
4616
  ];
4293
4617
  }
4294
4618
  if (this.config.vastTagUrl) {
4295
- this.apiVastTagUrl = this.config.vastTagUrl;
4619
+ this.apiVastTagUrl = normalizeVastTagUrl(this.config.vastTagUrl);
4296
4620
  if (this.debug) {
4297
4621
  console.log("[StormcloudVideoPlayer] Using custom VAST tag URL:", this.apiVastTagUrl);
4298
4622
  }
@@ -4332,9 +4656,16 @@ var VmapManager = /*#__PURE__*/ function() {
4332
4656
  data = _state.sent();
4333
4657
  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;
4334
4658
  if (imaPayload) {
4335
- this.apiVastTagUrl = decodeURIComponent(imaPayload);
4659
+ decodedPayload = imaPayload;
4660
+ try {
4661
+ decodedPayload = decodeURIComponent(imaPayload);
4662
+ } catch (unused) {
4663
+ console.warn("[StormcloudVideoPlayer] imaPayload was not URI-encoded; using as-is:", imaPayload);
4664
+ }
4665
+ console.log("[StormcloudVideoPlayer] Raw VAST tag URL (from API):", decodedPayload);
4666
+ this.apiVastTagUrl = normalizeVastTagUrl(decodedPayload);
4336
4667
  if (this.debug) {
4337
- console.log("[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:", this.apiVastTagUrl);
4668
+ console.log("[StormcloudVideoPlayer] Normalized VAST tag URL:", this.apiVastTagUrl);
4338
4669
  }
4339
4670
  } else {
4340
4671
  if (this.debug) {
@@ -4647,28 +4978,30 @@ var VmapManager = /*#__PURE__*/ function() {
4647
4978
  for(var i = 0; i < count; i++){
4648
4979
  this.adRequestPositionInBreak++;
4649
4980
  var adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;
4650
- var ctvSignals = this.config.ctvAdRequest ? resolveCtvVastSignals() : void 0;
4981
+ var envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);
4651
4982
  var urlWithMacros = applyVastMacros(baseUrl, {
4652
4983
  correlator: generateCorrelator(),
4653
4984
  streamCorrelator: this.streamCorrelator,
4654
4985
  pod: this.podCounter > 0 ? this.podCounter : void 0,
4655
4986
  adPosition: this.adRequestPositionInBreak,
4656
- isCtv: this.config.ctvAdRequest,
4657
- contentUrl: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.contentUrl,
4658
- pageUrl: !this.config.ctvAdRequest && typeof window !== "undefined" ? window.location.href : void 0,
4987
+ isCtv: envSignals.isCtv,
4988
+ contentUrl: envSignals.contentUrl,
4989
+ pageUrl: !envSignals.isCtv && typeof window !== "undefined" ? window.location.href : void 0,
4659
4990
  adWillPlayMuted: adWillPlayMuted,
4660
4991
  adWillAutoPlay: !!this.config.autoplay,
4661
- appId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.appId,
4662
- appName: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.appName,
4663
- sessionId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.sessionId,
4664
- deviceId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceId,
4665
- deviceIdType: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceIdType,
4666
- limitAdTracking: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.limitAdTracking,
4667
- deviceTypeHint: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceTypeHint,
4992
+ appId: envSignals.appId,
4993
+ appName: envSignals.appName,
4994
+ sessionId: envSignals.sessionId,
4995
+ deviceId: envSignals.deviceId,
4996
+ deviceIdType: envSignals.deviceIdType,
4997
+ limitAdTracking: envSignals.limitAdTracking,
4998
+ deviceTypeHint: envSignals.deviceTypeHint,
4668
4999
  adTest: this.config.adTest,
4669
5000
  consent: this.consentSignals
4670
5001
  });
4671
- urls.push(palNonce.injectNonce(urlWithMacros));
5002
+ var finalUrl = palNonce.injectNonce(urlWithMacros);
5003
+ console.log("[StormcloudVideoPlayer] Resolved ad request URL (pod=".concat(this.podCounter, ", pos=").concat(this.adRequestPositionInBreak, "):"), finalUrl);
5004
+ urls.push(finalUrl);
4672
5005
  }
4673
5006
  return urls;
4674
5007
  }
@@ -4717,7 +5050,7 @@ var VmapManager = /*#__PURE__*/ function() {
4717
5050
  }
4718
5051
  }
4719
5052
  ]);
4720
- return VmapManager;
5053
+ return AdConfigManager;
4721
5054
  }();
4722
5055
  // src/player/AdTimingService.ts
4723
5056
  var AdTimingService = /*#__PURE__*/ function() {
@@ -6444,7 +6777,7 @@ function resizePlayer(video, adPlayer, debug) {
6444
6777
  }
6445
6778
  // src/player/AdBreakOrchestrator.ts
6446
6779
  var AdBreakOrchestrator = /*#__PURE__*/ function() {
6447
- function AdBreakOrchestrator(host, timing, preloadPool, vmap, cueManager, placeholder) {
6780
+ function AdBreakOrchestrator(host, timing, preloadPool, adConfig, cueManager, placeholder) {
6448
6781
  _class_call_check(this, AdBreakOrchestrator);
6449
6782
  this.inAdBreak = false;
6450
6783
  this.showAds = false;
@@ -6459,7 +6792,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6459
6792
  this.host = host;
6460
6793
  this.timing = timing;
6461
6794
  this.preloadPool = preloadPool;
6462
- this.vmap = vmap;
6795
+ this.adConfig = adConfig;
6463
6796
  this.cueManager = cueManager;
6464
6797
  this.placeholder = placeholder;
6465
6798
  }
@@ -6625,7 +6958,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6625
6958
  }
6626
6959
  this.pendingAdBreak = null;
6627
6960
  this.cueManager.pendingScte35CueKey = void 0;
6628
- this.vmap.podAssignedByPrefetch = false;
6961
+ this.adConfig.podAssignedByPrefetch = false;
6629
6962
  }
6630
6963
  },
6631
6964
  {
@@ -6639,15 +6972,15 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6639
6972
  return _ts_generator(this, function(_state) {
6640
6973
  switch(_state.label){
6641
6974
  case 0:
6642
- scheduled = this.vmap.findCurrentOrNextBreak(this.host.video.currentTime * 1e3);
6975
+ scheduled = this.adConfig.findCurrentOrNextBreak(this.host.video.currentTime * 1e3);
6643
6976
  if (scheduled) {
6644
- this.vmap.consumedVmapBreakIds.add(this.vmap.getAdBreakKey(scheduled));
6977
+ this.adConfig.consumedVmapBreakIds.add(this.adConfig.getAdBreakKey(scheduled));
6645
6978
  }
6646
- tags = this.vmap.selectVastTagsForBreak(scheduled);
6979
+ tags = this.adConfig.selectVastTagsForBreak(scheduled);
6647
6980
  if (tags && tags.length > 0 && tags[0]) {
6648
6981
  baseVastUrl = tags[0];
6649
- } else if (this.vmap.apiVastTagUrl) {
6650
- baseVastUrl = this.vmap.apiVastTagUrl;
6982
+ } else if (this.adConfig.apiVastTagUrl) {
6983
+ baseVastUrl = this.adConfig.apiVastTagUrl;
6651
6984
  } else {
6652
6985
  this.clearPendingAdBreak();
6653
6986
  return [
@@ -6665,10 +6998,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6665
6998
  this.continuousFetchingActive = true;
6666
6999
  this.isShowingPlaceholder = false;
6667
7000
  this.timing.totalAdRequestsInBreak = 0;
6668
- if (this.vmap.podAssignedByPrefetch) {
6669
- this.vmap.podAssignedByPrefetch = false;
7001
+ if (this.adConfig.podAssignedByPrefetch) {
7002
+ this.adConfig.podAssignedByPrefetch = false;
6670
7003
  } else {
6671
- this.vmap.beginNewAdPod();
7004
+ this.adConfig.beginNewAdPod();
6672
7005
  }
6673
7006
  currentMuted = this.host.video.muted;
6674
7007
  currentVolume = this.host.video.volume;
@@ -7940,7 +8273,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7940
8273
  return _this.adBreak.inAdBreak;
7941
8274
  }
7942
8275
  });
7943
- this.vmap = new VmapManager(this.config, this.video);
8276
+ this.adConfig = new AdConfigManager(this.config, this.video);
7944
8277
  this.timing = new AdTimingService(this.config, this.video, {
7945
8278
  onAdStopTimerFired: function onAdStopTimerFired() {
7946
8279
  return _this.onAdStopTimerFired();
@@ -8020,7 +8353,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8020
8353
  generateVastUrls: function generateVastUrls(base, count) {
8021
8354
  return _this.generateVastUrls(base, count);
8022
8355
  }
8023
- }, this.timing, this.preloadPool, this.vmap, this.cueManager, this.placeholder);
8356
+ }, this.timing, this.preloadPool, this.adConfig, this.cueManager, this.placeholder);
8024
8357
  }
8025
8358
  _create_class(StormcloudVideoPlayer, [
8026
8359
  {
@@ -8048,7 +8381,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8048
8381
  {
8049
8382
  key: "generateVastUrls",
8050
8383
  value: function generateVastUrls(baseUrl, count) {
8051
- return this.vmap.generateVastUrlsWithCorrelators(baseUrl, count, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
8384
+ return this.adConfig.generateVastUrlsWithCorrelators(baseUrl, count, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
8052
8385
  }
8053
8386
  },
8054
8387
  {
@@ -8076,7 +8409,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8076
8409
  ]);
8077
8410
  return [
8078
8411
  4,
8079
- this.vmap.fetchAdConfiguration()
8412
+ this.adConfig.fetchAdConfiguration()
8080
8413
  ];
8081
8414
  case 2:
8082
8415
  _state.sent();
@@ -8103,9 +8436,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8103
8436
  continuousPlayback: (_this_config_lowLatencyMode = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false
8104
8437
  }).catch(function() {});
8105
8438
  fetchConsentSignals().then(function(signals) {
8106
- _this.vmap.consentSignals = signals;
8439
+ _this.adConfig.consentSignals = signals;
8107
8440
  }).catch(function() {});
8108
- this.vmap.initializeTracking();
8441
+ this.adConfig.initializeTracking();
8109
8442
  if (!this.hlsEngine.shouldUseNativeHls(function() {
8110
8443
  return _this.getStreamType();
8111
8444
  })) return [
@@ -8140,14 +8473,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8140
8473
  return _async_to_generator(function() {
8141
8474
  var prerollKey, adBehavior;
8142
8475
  return _ts_generator(this, function(_state) {
8143
- if (!this.vmap.isVmapEnabled() && !isLive && this.vmap.vmapBreaks.length === 0 && this.vmap.apiVastTagUrl) {
8476
+ if (!this.adConfig.isVmapEnabled() && !isLive && this.adConfig.vmapBreaks.length === 0 && this.adConfig.apiVastTagUrl) {
8144
8477
  prerollKey = "synthetic-vod-preroll";
8145
- if (!this.vmap.consumedVmapBreakIds.has(prerollKey)) {
8146
- this.vmap.vmapBreaks = [
8478
+ if (!this.adConfig.consumedVmapBreakIds.has(prerollKey)) {
8479
+ this.adConfig.vmapBreaks = [
8147
8480
  {
8148
8481
  id: prerollKey,
8149
8482
  startTimeMs: 0,
8150
- vastTagUrl: this.vmap.apiVastTagUrl
8483
+ vastTagUrl: this.adConfig.apiVastTagUrl
8151
8484
  }
8152
8485
  ];
8153
8486
  if (this.debug) {
@@ -8414,19 +8747,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8414
8747
  key: "startAdPrefetch",
8415
8748
  value: function startAdPrefetch(marker, fragmentSn, cueKey) {
8416
8749
  if (this.adBreak.pendingAdBreak || this.adBreak.inAdBreak) return;
8417
- var scheduled = this.vmap.findCurrentOrNextBreak(this.video.currentTime * 1e3);
8418
- var tags = this.vmap.selectVastTagsForBreak(scheduled);
8750
+ var scheduled = this.adConfig.findCurrentOrNextBreak(this.video.currentTime * 1e3);
8751
+ var tags = this.adConfig.selectVastTagsForBreak(scheduled);
8419
8752
  var baseVastUrl;
8420
8753
  if (tags && tags.length > 0 && tags[0]) {
8421
8754
  baseVastUrl = tags[0];
8422
- } else if (this.vmap.apiVastTagUrl) {
8423
- baseVastUrl = this.vmap.apiVastTagUrl;
8755
+ } else if (this.adConfig.apiVastTagUrl) {
8756
+ baseVastUrl = this.adConfig.apiVastTagUrl;
8424
8757
  } else {
8425
8758
  if (this.debug) console.warn("[StormcloudVideoPlayer] No VAST URL available for prefetch");
8426
8759
  return;
8427
8760
  }
8428
- this.vmap.beginNewAdPod();
8429
- this.vmap.podAssignedByPrefetch = true;
8761
+ this.adConfig.beginNewAdPod();
8762
+ this.adConfig.podAssignedByPrefetch = true;
8430
8763
  var generatedUrls = this.generateVastUrls(baseVastUrl, 1);
8431
8764
  this.adBreak.pendingAdBreak = _object_spread_props(_object_spread({
8432
8765
  marker: marker
@@ -8461,10 +8794,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8461
8794
  key: "onTimeUpdate",
8462
8795
  value: function onTimeUpdate(currentTimeSec) {
8463
8796
  var _this = this;
8464
- if (!this.vmap.isVmapEnabled() || this.vmap.vmapBreaks.length === 0) return;
8797
+ if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;
8465
8798
  if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;
8466
8799
  var nowMs = currentTimeSec * 1e3;
8467
- var breakToPlay = this.vmap.findBreakForTime(nowMs);
8800
+ var breakToPlay = this.adConfig.findBreakForTime(nowMs);
8468
8801
  if (breakToPlay) {
8469
8802
  void this.handleVmapAdBreak(breakToPlay, nowMs).catch(function(error) {
8470
8803
  if (_this.debug) {
@@ -8478,11 +8811,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8478
8811
  key: "onVideoEnded",
8479
8812
  value: function onVideoEnded() {
8480
8813
  var _this = this;
8481
- if (!this.vmap.isVmapEnabled() || this.vmap.vmapBreaks.length === 0) return;
8814
+ if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;
8482
8815
  if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;
8483
8816
  var durationMs = Number.isFinite(this.video.duration) ? Math.floor(this.video.duration * 1e3) : 0;
8484
- var postroll = this.vmap.vmapBreaks.find(function(b) {
8485
- return b.startTimeMs === -1 && !_this.vmap.consumedVmapBreakIds.has(_this.vmap.getAdBreakKey(b));
8817
+ var postroll = this.adConfig.vmapBreaks.find(function(b) {
8818
+ return b.startTimeMs === -1 && !_this.adConfig.consumedVmapBreakIds.has(_this.adConfig.getAdBreakKey(b));
8486
8819
  });
8487
8820
  if (postroll) {
8488
8821
  void this.handleVmapAdBreak(postroll, durationMs).catch(function(error) {
@@ -8501,11 +8834,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8501
8834
  return _ts_generator(this, function(_state) {
8502
8835
  switch(_state.label){
8503
8836
  case 0:
8504
- key = this.vmap.getAdBreakKey(adBreak);
8505
- if (this.vmap.consumedVmapBreakIds.has(key)) return [
8837
+ key = this.adConfig.getAdBreakKey(adBreak);
8838
+ if (this.adConfig.consumedVmapBreakIds.has(key)) return [
8506
8839
  2
8507
8840
  ];
8508
- breakStartMs = this.vmap.resolveBreakStartMs(adBreak);
8841
+ breakStartMs = this.adConfig.resolveBreakStartMs(adBreak);
8509
8842
  if (breakStartMs == null) return [
8510
8843
  2
8511
8844
  ];
@@ -8516,8 +8849,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8516
8849
  3,
8517
8850
  4
8518
8851
  ];
8519
- this.vmap.consumedVmapBreakIds.add(key);
8520
- tags = this.vmap.selectVastTagsForBreak(adBreak);
8852
+ this.adConfig.consumedVmapBreakIds.add(key);
8853
+ tags = this.adConfig.selectVastTagsForBreak(adBreak);
8521
8854
  if (!tags || tags.length === 0) return [
8522
8855
  2
8523
8856
  ];
@@ -8709,7 +9042,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8709
9042
  this.video.removeEventListener("emptied", this.emptiedHandler);
8710
9043
  delete this.emptiedHandler;
8711
9044
  }
8712
- this.vmap.destroyTracking();
9045
+ this.adConfig.destroyTracking();
8713
9046
  this.hlsEngine.destroy();
8714
9047
  (_this_adPlayer = this.adPlayer) === null || _this_adPlayer === void 0 ? void 0 : _this_adPlayer.destroy();
8715
9048
  if (this.palPlaybackStarted) {