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
@@ -827,6 +827,7 @@ function createHlsAdPlayer(contentVideo, options) {
827
827
  handleAdComplete();
828
828
  });
829
829
  adVideoElement.addEventListener("error", function(e) {
830
+ if (!adPlaying) return;
830
831
  console.error("[HlsAdPlayer] Ad video error:", e);
831
832
  if (currentAd) {
832
833
  fireTrackingPixels(currentAd.trackingUrls.error);
@@ -1028,15 +1029,15 @@ function createHlsAdPlayer(contentVideo, options) {
1028
1029
  adVideoElement.muted = originalMutedState;
1029
1030
  console.log("[HlsAdPlayer] Set ad video volume to ".concat(adVideoElement.volume, ", muted: ").concat(adVideoElement.muted, ", originalMutedState: ").concat(originalMutedState, ", contentVolume: ").concat(contentVolume));
1030
1031
  }
1032
+ mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1033
+ if (!mediaFile) {
1034
+ throw new Error("No media file available for ad");
1035
+ }
1031
1036
  if (adContainerEl) {
1032
1037
  adContainerEl.style.display = "flex";
1033
1038
  adContainerEl.style.pointerEvents = "auto";
1034
1039
  }
1035
1040
  emit("content_pause");
1036
- mediaFile = selectBestMediaFile(currentAd.mediaFiles);
1037
- if (!mediaFile) {
1038
- throw new Error("No media file available for ad");
1039
- }
1040
1041
  isHlsAd = isHlsMediaFile(mediaFile);
1041
1042
  console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad from: ").concat(mediaFile.url));
1042
1043
  if (isHlsAd && import_hls.default.isSupported()) {
@@ -2322,22 +2323,337 @@ function initializePolyfills() {
2322
2323
  polyfillTextEncoder();
2323
2324
  polyfillPromiseFinally();
2324
2325
  }
2325
- // src/utils/vastMacros.ts
2326
- function generateCorrelator() {
2327
- if (typeof crypto !== "undefined" && crypto.getRandomValues) {
2326
+ // src/utils/vastEnvironmentSignals.ts
2327
+ var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
2328
+ var AIRY_WEBOS_APP_ID = "com.freeairytv.webos";
2329
+ var AIRY_TIZEN_APP_ID = "com.freeairytv.samsung";
2330
+ var AIRY_ROKU_APP_ID = "com.freeairytv.roku";
2331
+ var AIRY_APP_NAME = "AiryTV Movies & TV";
2332
+ var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
2333
+ var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
2334
+ function getDefaultAppId() {
2335
+ if (typeof navigator === "undefined") return AIRY_ANDROID_APP_ID;
2336
+ var ua = navigator.userAgent;
2337
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return AIRY_WEBOS_APP_ID;
2338
+ if (/Tizen|Samsung/i.test(ua)) return AIRY_TIZEN_APP_ID;
2339
+ if (/Roku/i.test(ua)) return AIRY_ROKU_APP_ID;
2340
+ return AIRY_ANDROID_APP_ID;
2341
+ }
2342
+ var DEVICE_ID_STORAGE_KEYS = [
2343
+ "rdid",
2344
+ "ifa",
2345
+ "advertisingId",
2346
+ "advertising_id",
2347
+ "deviceAdvertisingId",
2348
+ "aaid",
2349
+ "adid",
2350
+ "rida",
2351
+ "tifa",
2352
+ "lgudid"
2353
+ ];
2354
+ var ANDROID_ID_TYPES = /* @__PURE__ */ new Set([
2355
+ "aaid",
2356
+ "adid"
2357
+ ]);
2358
+ function resolveVastEnvironmentSignals(isCtv) {
2359
+ var _ref, _bridgeSignals_limitAdTracking;
2360
+ var bridgeSignals = readNativeBridgeSignals();
2361
+ var deviceId = bridgeSignals.deviceId || readStoredDeviceId();
2362
+ var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || readStoredString("idtype") || inferDeviceIdType();
2363
+ 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;
2364
+ if (isCtv) {
2365
+ return _object_spread_props(_object_spread({
2366
+ isCtv: true,
2367
+ contentUrl: bridgeSignals.contentUrl || readStoredString("contentUrl") || AIRY_DEFAULT_CONTENT_URL,
2368
+ appId: bridgeSignals.appId || readStoredString("appId") || readStoredString("msid") || getDefaultAppId(),
2369
+ appName: bridgeSignals.appName || readStoredString("appName") || readStoredString("an") || AIRY_APP_NAME,
2370
+ sessionId: getOrCreateCtvSessionId()
2371
+ }, deviceId ? {
2372
+ deviceId: deviceId
2373
+ } : {}, deviceIdType ? {
2374
+ deviceIdType: deviceIdType
2375
+ } : {}, limitAdTracking != null ? {
2376
+ limitAdTracking: limitAdTracking
2377
+ } : {}), {
2378
+ deviceTypeHint: 5
2379
+ });
2380
+ }
2381
+ return _object_spread({
2382
+ isCtv: false
2383
+ }, deviceId ? {
2384
+ deviceId: deviceId
2385
+ } : {}, deviceIdType ? {
2386
+ deviceIdType: deviceIdType
2387
+ } : {}, limitAdTracking != null ? {
2388
+ limitAdTracking: limitAdTracking
2389
+ } : {});
2390
+ }
2391
+ function inferDeviceIdType() {
2392
+ if (typeof navigator === "undefined") {
2393
+ return void 0;
2394
+ }
2395
+ var ua = navigator.userAgent;
2396
+ if (/Roku/i.test(ua)) return "rida";
2397
+ if (/Tizen|Samsung/i.test(ua)) return "tifa";
2398
+ if (/AppleTV|Apple TV/i.test(ua)) return "tvOS";
2399
+ if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
2400
+ if (/Web0S|webOS|LG Browser|LGSTB|LGE/i.test(ua)) return "lgudid";
2401
+ if (/Android|Google TV/i.test(ua)) return "aaid";
2402
+ if (/iPhone|iPad|iPod/i.test(ua)) return "idfa";
2403
+ return void 0;
2404
+ }
2405
+ function isEquivalentDeviceIdType(tagType, runtimeType) {
2406
+ if (!tagType || !runtimeType) return false;
2407
+ var tag = tagType.toLowerCase();
2408
+ var runtime = runtimeType.toLowerCase();
2409
+ if (tag === runtime) return true;
2410
+ return ANDROID_ID_TYPES.has(tag) && ANDROID_ID_TYPES.has(runtime);
2411
+ }
2412
+ function getOrCreateCtvSessionId() {
2413
+ var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
2414
+ if (existing) {
2415
+ return existing;
2416
+ }
2417
+ var sessionId = createUuid();
2418
+ try {
2419
+ var _window_localStorage;
2420
+ (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
2421
+ } catch (unused) {}
2422
+ return sessionId;
2423
+ }
2424
+ function createUuid() {
2425
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
2426
+ return crypto.randomUUID();
2427
+ }
2428
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
2429
+ var value = Math.floor(Math.random() * 16);
2430
+ var nibble = char === "x" ? value : value & 3 | 8;
2431
+ return nibble.toString(16);
2432
+ });
2433
+ }
2434
+ function readNativeBridgeSignals() {
2435
+ if (typeof window === "undefined") {
2436
+ return {};
2437
+ }
2438
+ var candidates = [
2439
+ window.__STORMCLOUD_CTV_AD_INFO__,
2440
+ window.__STORMCLOUD_CTV__,
2441
+ window.stormcloudCtv,
2442
+ window.AiryTV,
2443
+ window.Android,
2444
+ window.webOS,
2445
+ window.tizen,
2446
+ window.amazon
2447
+ ].filter(Boolean);
2448
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2449
+ try {
2450
+ for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2451
+ var source = _step.value;
2452
+ var contentUrl = readBridgeValue(source, [
2453
+ "contentUrl",
2454
+ "url",
2455
+ "videoUrl",
2456
+ "canonicalUrl"
2457
+ ]) || void 0;
2458
+ var appId = readBridgeValue(source, [
2459
+ "appId",
2460
+ "msid",
2461
+ "applicationId",
2462
+ "packageName"
2463
+ ]) || void 0;
2464
+ var appName = readBridgeValue(source, [
2465
+ "appName",
2466
+ "an",
2467
+ "applicationName"
2468
+ ]) || void 0;
2469
+ var deviceId = readBridgeValue(source, [
2470
+ "rdid",
2471
+ "ifa",
2472
+ "advertisingId",
2473
+ "adId",
2474
+ "deviceId",
2475
+ "lgudid",
2476
+ "LGUDID",
2477
+ "tifa",
2478
+ "rida",
2479
+ "afai",
2480
+ "aaid"
2481
+ ]) || void 0;
2482
+ if (!contentUrl && !deviceId && !appId && !appName) continue;
2483
+ var deviceIdType = readBridgeValue(source, [
2484
+ "idtype",
2485
+ "deviceIdType",
2486
+ "advertisingIdType",
2487
+ "idType"
2488
+ ]) || inferDeviceIdType();
2489
+ var limitAdTracking = readBridgeBoolean(source, [
2490
+ "is_lat",
2491
+ "limitAdTracking",
2492
+ "limitedAdTracking",
2493
+ "lat"
2494
+ ]);
2495
+ return _object_spread({}, contentUrl ? {
2496
+ contentUrl: contentUrl
2497
+ } : {}, appId ? {
2498
+ appId: appId
2499
+ } : {}, appName ? {
2500
+ appName: appName
2501
+ } : {}, deviceId ? {
2502
+ deviceId: deviceId
2503
+ } : {}, deviceId && deviceIdType ? {
2504
+ deviceIdType: deviceIdType
2505
+ } : {}, deviceId && limitAdTracking != null ? {
2506
+ limitAdTracking: limitAdTracking
2507
+ } : {});
2508
+ }
2509
+ } catch (err) {
2510
+ _didIteratorError = true;
2511
+ _iteratorError = err;
2512
+ } finally{
2328
2513
  try {
2329
- var _buf_, _buf_1;
2330
- var buf = new Uint32Array(2);
2331
- crypto.getRandomValues(buf);
2332
- 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);
2333
- if (value > 0) {
2334
- return String(value);
2514
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2515
+ _iterator.return();
2335
2516
  }
2336
- } catch (unused) {}
2517
+ } finally{
2518
+ if (_didIteratorError) {
2519
+ throw _iteratorError;
2520
+ }
2521
+ }
2337
2522
  }
2338
- return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);
2523
+ return {};
2524
+ }
2525
+ function readBridgeValue(source, keys) {
2526
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2527
+ try {
2528
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2529
+ var key = _step.value;
2530
+ var value = source === null || source === void 0 ? void 0 : source[key];
2531
+ if (typeof value === "string" && value) {
2532
+ return value;
2533
+ }
2534
+ if (typeof value === "function") {
2535
+ try {
2536
+ var result = value.call(source);
2537
+ if (typeof result === "string" && result) {
2538
+ return result;
2539
+ }
2540
+ } catch (unused) {}
2541
+ }
2542
+ }
2543
+ } catch (err) {
2544
+ _didIteratorError = true;
2545
+ _iteratorError = err;
2546
+ } finally{
2547
+ try {
2548
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2549
+ _iterator.return();
2550
+ }
2551
+ } finally{
2552
+ if (_didIteratorError) {
2553
+ throw _iteratorError;
2554
+ }
2555
+ }
2556
+ }
2557
+ return void 0;
2558
+ }
2559
+ function readBridgeBoolean(source, keys) {
2560
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2561
+ try {
2562
+ for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2563
+ var key = _step.value;
2564
+ var value = source === null || source === void 0 ? void 0 : source[key];
2565
+ var normalized = normalizeBoolean(value);
2566
+ if (normalized != null) {
2567
+ return normalized;
2568
+ }
2569
+ if (typeof value === "function") {
2570
+ try {
2571
+ var result = normalizeBoolean(value.call(source));
2572
+ if (result != null) {
2573
+ return result;
2574
+ }
2575
+ } catch (unused) {}
2576
+ }
2577
+ }
2578
+ } catch (err) {
2579
+ _didIteratorError = true;
2580
+ _iteratorError = err;
2581
+ } finally{
2582
+ try {
2583
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2584
+ _iterator.return();
2585
+ }
2586
+ } finally{
2587
+ if (_didIteratorError) {
2588
+ throw _iteratorError;
2589
+ }
2590
+ }
2591
+ }
2592
+ return void 0;
2593
+ }
2594
+ function readStoredDeviceId() {
2595
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2596
+ try {
2597
+ for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2598
+ var key = _step.value;
2599
+ var value = readStoredString(key);
2600
+ if (value) {
2601
+ return value;
2602
+ }
2603
+ }
2604
+ } catch (err) {
2605
+ _didIteratorError = true;
2606
+ _iteratorError = err;
2607
+ } finally{
2608
+ try {
2609
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2610
+ _iterator.return();
2611
+ }
2612
+ } finally{
2613
+ if (_didIteratorError) {
2614
+ throw _iteratorError;
2615
+ }
2616
+ }
2617
+ }
2618
+ return void 0;
2619
+ }
2620
+ function readStoredString(key) {
2621
+ if (typeof window === "undefined") {
2622
+ return void 0;
2623
+ }
2624
+ try {
2625
+ var _window_localStorage;
2626
+ var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
2627
+ return value || void 0;
2628
+ } catch (unused) {
2629
+ return void 0;
2630
+ }
2631
+ }
2632
+ function readStoredLimitAdTracking() {
2633
+ return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
2339
2634
  }
2635
+ function normalizeBoolean(value) {
2636
+ if (typeof value === "boolean") {
2637
+ return value;
2638
+ }
2639
+ if (typeof value === "number") {
2640
+ return value === 1;
2641
+ }
2642
+ if (typeof value === "string") {
2643
+ var normalized = value.toLowerCase();
2644
+ if (normalized === "1" || normalized === "true" || normalized === "yes") {
2645
+ return true;
2646
+ }
2647
+ if (normalized === "0" || normalized === "false" || normalized === "no") {
2648
+ return false;
2649
+ }
2650
+ }
2651
+ return void 0;
2652
+ }
2653
+ // src/utils/vastMacros.ts
2340
2654
  var UNEXPANDED_MACRO_PATTERN = /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/;
2655
+ var INVALID_VAST_PARAM_KEY = /^\s|\s$/;
2656
+ var EXAMPLE_COM_URL = /example\.com/i;
2341
2657
  var CTV_UNSUPPORTED_PARAMS = [
2342
2658
  "description_url",
2343
2659
  "tfcd",
@@ -2352,14 +2668,288 @@ var CTV_UNSUPPORTED_PARAMS = [
2352
2668
  "gdpr_consent",
2353
2669
  "us_privacy"
2354
2670
  ];
2671
+ var INLINE_DEVICE_MACRO_REPLACEMENTS = [
2672
+ {
2673
+ pattern: /\[RDID\]/gi,
2674
+ getValue: function getValue(ctx) {
2675
+ return ctx.deviceId;
2676
+ }
2677
+ },
2678
+ {
2679
+ pattern: /\[IFA\]/gi,
2680
+ getValue: function getValue(ctx) {
2681
+ return ctx.deviceId;
2682
+ }
2683
+ },
2684
+ {
2685
+ pattern: /\[ADVERTISING[_-]?ID(?:ENTIFIER)?\]/gi,
2686
+ getValue: function getValue(ctx) {
2687
+ return ctx.deviceId;
2688
+ }
2689
+ },
2690
+ {
2691
+ pattern: /\[DEVICE[_-]?ID\]/gi,
2692
+ getValue: function getValue(ctx) {
2693
+ return ctx.deviceId;
2694
+ }
2695
+ },
2696
+ {
2697
+ pattern: /\[IDTYPE\]/gi,
2698
+ getValue: function getValue(ctx) {
2699
+ return ctx.deviceIdType;
2700
+ }
2701
+ },
2702
+ {
2703
+ pattern: /\{rdid\}/gi,
2704
+ getValue: function getValue(ctx) {
2705
+ return ctx.deviceId;
2706
+ }
2707
+ },
2708
+ {
2709
+ pattern: /\{device[_-]?id\}/gi,
2710
+ getValue: function getValue(ctx) {
2711
+ return ctx.deviceId;
2712
+ }
2713
+ },
2714
+ {
2715
+ pattern: /\{idtype\}/gi,
2716
+ getValue: function getValue(ctx) {
2717
+ return ctx.deviceIdType;
2718
+ }
2719
+ },
2720
+ {
2721
+ pattern: /%%ADVERTISING_IDENTIFIER_PLAIN%%/gi,
2722
+ getValue: function getValue(ctx) {
2723
+ return ctx.deviceId;
2724
+ }
2725
+ },
2726
+ {
2727
+ pattern: /%%ADVERTISING_ID_OPT_OUT%%/gi,
2728
+ getValue: function getValue(ctx) {
2729
+ return ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2730
+ }
2731
+ },
2732
+ {
2733
+ pattern: /%%ADVERTISING_ID_TYPE%%/gi,
2734
+ getValue: function getValue(ctx) {
2735
+ return ctx.deviceIdType;
2736
+ }
2737
+ },
2738
+ {
2739
+ pattern: /%%ADVERTISING_ID%%/gi,
2740
+ getValue: function getValue(ctx) {
2741
+ return ctx.deviceId;
2742
+ }
2743
+ },
2744
+ {
2745
+ pattern: /%%LIMIT_AD_TRACKING%%/gi,
2746
+ getValue: function getValue(ctx) {
2747
+ return ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2748
+ }
2749
+ },
2750
+ {
2751
+ pattern: /%%MSID%%/gi,
2752
+ getValue: function getValue(ctx) {
2753
+ return ctx.appId;
2754
+ }
2755
+ },
2756
+ {
2757
+ pattern: /%%APP_NAME%%/gi,
2758
+ getValue: function getValue(ctx) {
2759
+ return ctx.appName;
2760
+ }
2761
+ },
2762
+ {
2763
+ pattern: /%%SESSION_ID%%/gi,
2764
+ getValue: function getValue(ctx) {
2765
+ return ctx.sessionId;
2766
+ }
2767
+ },
2768
+ {
2769
+ pattern: /%%CORRELATOR%%/gi,
2770
+ getValue: function getValue(ctx) {
2771
+ return ctx.correlator;
2772
+ }
2773
+ }
2774
+ ];
2775
+ function isMacroPlaceholder(value) {
2776
+ if (value == null) return true;
2777
+ var trimmed = value.trim();
2778
+ if (!trimmed) return true;
2779
+ if (UNEXPANDED_MACRO_PATTERN.test(trimmed)) return true;
2780
+ return /^(unknown|null|undefined|none|n\/a|\$\{[^}]+\})$/i.test(trimmed);
2781
+ }
2782
+ function generateCorrelator() {
2783
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
2784
+ try {
2785
+ var _buf_, _buf_1;
2786
+ var buf = new Uint32Array(2);
2787
+ crypto.getRandomValues(buf);
2788
+ 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);
2789
+ if (value > 0) {
2790
+ return String(value);
2791
+ }
2792
+ } catch (unused) {}
2793
+ }
2794
+ return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);
2795
+ }
2796
+ function expandInlineMacroPlaceholders(baseUrl, ctx) {
2797
+ var url = baseUrl;
2798
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2799
+ try {
2800
+ for(var _iterator = INLINE_DEVICE_MACRO_REPLACEMENTS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2801
+ var _step_value = _step.value, pattern = _step_value.pattern, getValue = _step_value.getValue;
2802
+ var value = getValue(ctx);
2803
+ if (value != null && value !== "") {
2804
+ url = url.replace(pattern, encodeURIComponent(value));
2805
+ }
2806
+ }
2807
+ } catch (err) {
2808
+ _didIteratorError = true;
2809
+ _iteratorError = err;
2810
+ } finally{
2811
+ try {
2812
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2813
+ _iterator.return();
2814
+ }
2815
+ } finally{
2816
+ if (_didIteratorError) {
2817
+ throw _iteratorError;
2818
+ }
2819
+ }
2820
+ }
2821
+ return url;
2822
+ }
2823
+ function applyDeviceIdentityParams(params, ctx) {
2824
+ var _ctx_deviceId, _ctx_deviceIdType;
2825
+ var runtimeId = (_ctx_deviceId = ctx.deviceId) === null || _ctx_deviceId === void 0 ? void 0 : _ctx_deviceId.trim();
2826
+ var runtimeType = ((_ctx_deviceIdType = ctx.deviceIdType) === null || _ctx_deviceIdType === void 0 ? void 0 : _ctx_deviceIdType.trim()) || inferDeviceIdType();
2827
+ var tagRdid = params.get("rdid");
2828
+ var tagType = params.get("idtype");
2829
+ var tagLat = params.get("is_lat");
2830
+ var latValue = ctx.limitAdTracking != null ? ctx.limitAdTracking ? "1" : "0" : void 0;
2831
+ if (runtimeId) {
2832
+ params.set("rdid", runtimeId);
2833
+ params.set("idtype", runtimeType || tagType || "aaid");
2834
+ params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : isMacroPlaceholder(tagLat) ? "0" : tagLat);
2835
+ return;
2836
+ }
2837
+ var tagRdidValid = Boolean(tagRdid && !isMacroPlaceholder(tagRdid));
2838
+ var tagTypeValid = Boolean(tagType && !isMacroPlaceholder(tagType));
2839
+ if (tagRdidValid && tagTypeValid && runtimeType && !isEquivalentDeviceIdType(tagType, runtimeType)) {
2840
+ params.delete("rdid");
2841
+ params.delete("idtype");
2842
+ params.delete("is_lat");
2843
+ return;
2844
+ }
2845
+ if (tagRdidValid) {
2846
+ if (isMacroPlaceholder(tagType) && runtimeType) {
2847
+ params.set("idtype", runtimeType);
2848
+ }
2849
+ if (isMacroPlaceholder(tagLat)) {
2850
+ params.set("is_lat", latValue !== null && latValue !== void 0 ? latValue : "0");
2851
+ }
2852
+ return;
2853
+ }
2854
+ params.delete("rdid");
2855
+ params.delete("idtype");
2856
+ params.delete("is_lat");
2857
+ }
2858
+ function removeBrokenAppNameOrphans(params, appName) {
2859
+ var toDelete = [];
2860
+ params.forEach(function(_value, key) {
2861
+ if (!key || INVALID_VAST_PARAM_KEY.test(key)) {
2862
+ toDelete.push(key);
2863
+ }
2864
+ });
2865
+ if (appName && appName.includes("&")) {
2866
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2867
+ try {
2868
+ for(var _iterator = appName.split("&").slice(1)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2869
+ var suffix = _step.value;
2870
+ var trimmed = suffix.trimStart();
2871
+ if (!trimmed) continue;
2872
+ toDelete.push(suffix, " ".concat(trimmed), trimmed);
2873
+ }
2874
+ } catch (err) {
2875
+ _didIteratorError = true;
2876
+ _iteratorError = err;
2877
+ } finally{
2878
+ try {
2879
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2880
+ _iterator.return();
2881
+ }
2882
+ } finally{
2883
+ if (_didIteratorError) {
2884
+ throw _iteratorError;
2885
+ }
2886
+ }
2887
+ }
2888
+ }
2889
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
2890
+ try {
2891
+ for(var _iterator1 = new Set(toDelete)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
2892
+ var key = _step1.value;
2893
+ if (key) params.delete(key);
2894
+ }
2895
+ } catch (err) {
2896
+ _didIteratorError1 = true;
2897
+ _iteratorError1 = err;
2898
+ } finally{
2899
+ try {
2900
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
2901
+ _iterator1.return();
2902
+ }
2903
+ } finally{
2904
+ if (_didIteratorError1) {
2905
+ throw _iteratorError1;
2906
+ }
2907
+ }
2908
+ }
2909
+ }
2910
+ function normalizeVastTagUrl(raw) {
2911
+ if (!raw) return raw;
2912
+ try {
2913
+ var url = new URL(raw);
2914
+ var anValue = url.searchParams.get("an");
2915
+ if (anValue !== null) {
2916
+ var orphanFragments = [];
2917
+ url.searchParams.forEach(function(_value, key) {
2918
+ if (key && INVALID_VAST_PARAM_KEY.test(key)) {
2919
+ orphanFragments.push(key.trim());
2920
+ }
2921
+ });
2922
+ if (orphanFragments.length > 0) {
2923
+ var reconstructed = [
2924
+ anValue.trimEnd()
2925
+ ].concat(_to_consumable_array(orphanFragments)).filter(Boolean).join(" & ");
2926
+ url.searchParams.forEach(function(_value, key) {
2927
+ if (key && INVALID_VAST_PARAM_KEY.test(key)) {
2928
+ url.searchParams.delete(key);
2929
+ }
2930
+ });
2931
+ url.searchParams.set("an", reconstructed);
2932
+ return url.toString().replace(/([?&]an=)([^&]*)/, function(_match, prefix, val) {
2933
+ return prefix + val.replace(/\+/g, "%20");
2934
+ });
2935
+ }
2936
+ }
2937
+ removeBrokenAppNameOrphans(url.searchParams);
2938
+ return url.toString();
2939
+ } catch (unused) {
2940
+ return raw;
2941
+ }
2942
+ }
2355
2943
  function applyVastMacros(baseUrl, ctx) {
2944
+ var expandedUrl = expandInlineMacroPlaceholders(baseUrl, ctx);
2356
2945
  var url;
2357
2946
  try {
2358
- url = new URL(baseUrl);
2947
+ url = new URL(normalizeVastTagUrl(expandedUrl));
2359
2948
  } catch (unused) {
2360
- return replaceCorrelatorFallback(baseUrl, ctx.correlator);
2949
+ return replaceCorrelatorFallback(expandedUrl, ctx.correlator);
2361
2950
  }
2362
2951
  var params = url.searchParams;
2952
+ removeBrokenAppNameOrphans(params, ctx.appName);
2363
2953
  params.set("correlator", ctx.correlator);
2364
2954
  if (ctx.isCtv) {
2365
2955
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
@@ -2397,6 +2987,12 @@ function applyVastMacros(baseUrl, ctx) {
2397
2987
  if (!ctx.isCtv) {
2398
2988
  params.set("description_url", requestUrl);
2399
2989
  }
2990
+ } else {
2991
+ var existingUrl = params.get("url") || "";
2992
+ if (EXAMPLE_COM_URL.test(existingUrl)) {
2993
+ params.delete("url");
2994
+ params.delete("description_url");
2995
+ }
2400
2996
  }
2401
2997
  if (ctx.adWillPlayMuted != null) {
2402
2998
  params.set("vpmute", ctx.adWillPlayMuted ? "1" : "0");
@@ -2408,6 +3004,7 @@ function applyVastMacros(baseUrl, ctx) {
2408
3004
  params.set("msid", ctx.appId);
2409
3005
  }
2410
3006
  if (ctx.appName) {
3007
+ removeBrokenAppNameOrphans(params, ctx.appName);
2411
3008
  params.set("an", ctx.appName);
2412
3009
  }
2413
3010
  if (ctx.sessionId) {
@@ -2418,15 +3015,7 @@ function applyVastMacros(baseUrl, ctx) {
2418
3015
  } else if (ctx.isCtv) {
2419
3016
  params.set("dth", "5");
2420
3017
  }
2421
- if (ctx.deviceId && ctx.deviceIdType) {
2422
- params.set("rdid", ctx.deviceId);
2423
- params.set("idtype", ctx.deviceIdType);
2424
- params.set("is_lat", ctx.limitAdTracking ? "1" : "0");
2425
- } else {
2426
- params.delete("rdid");
2427
- params.delete("idtype");
2428
- params.delete("is_lat");
2429
- }
3018
+ applyDeviceIdentityParams(params, ctx);
2430
3019
  if (!ctx.isCtv) {
2431
3020
  var consent = ctx.consent;
2432
3021
  if ((consent === null || consent === void 0 ? void 0 : consent.gdpr) != null) {
@@ -2444,7 +3033,7 @@ function applyVastMacros(baseUrl, ctx) {
2444
3033
  }
2445
3034
  var staleKeys = [];
2446
3035
  params.forEach(function(value, key) {
2447
- if (UNEXPANDED_MACRO_PATTERN.test(value)) {
3036
+ if (isMacroPlaceholder(value)) {
2448
3037
  staleKeys.push(key);
2449
3038
  }
2450
3039
  });
@@ -2468,6 +3057,7 @@ function applyVastMacros(baseUrl, ctx) {
2468
3057
  }
2469
3058
  }
2470
3059
  }
3060
+ removeBrokenAppNameOrphans(params, ctx.appName);
2471
3061
  return url.toString();
2472
3062
  }
2473
3063
  function replaceCorrelatorFallback(baseUrl, correlator) {
@@ -3718,276 +4308,10 @@ var Scte35CueManager = /*#__PURE__*/ function() {
3718
4308
  ]);
3719
4309
  return Scte35CueManager;
3720
4310
  }();
3721
- // src/utils/ctvVastSignals.ts
3722
- var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
3723
- var AIRY_APP_NAME = "AiryTV Movies & TV";
3724
- var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
3725
- var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
3726
- var DEVICE_ID_STORAGE_KEYS = [
3727
- "rdid",
3728
- "ifa",
3729
- "advertisingId",
3730
- "advertising_id",
3731
- "deviceAdvertisingId",
3732
- "aaid",
3733
- "adid",
3734
- "rida",
3735
- "tifa"
3736
- ];
3737
- function resolveCtvVastSignals() {
3738
- var _ref, _bridgeSignals_limitAdTracking;
3739
- var bridgeSignals = readNativeBridgeSignals();
3740
- var deviceId = bridgeSignals.deviceId || readStoredDeviceId();
3741
- var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || inferDeviceIdType();
3742
- var contentUrl = bridgeSignals.contentUrl || readStoredString("contentUrl") || AIRY_DEFAULT_CONTENT_URL;
3743
- return _object_spread_props(_object_spread({
3744
- contentUrl: contentUrl,
3745
- appId: AIRY_ANDROID_APP_ID,
3746
- appName: AIRY_APP_NAME,
3747
- sessionId: getOrCreateCtvSessionId()
3748
- }, deviceId ? {
3749
- deviceId: deviceId
3750
- } : {}, deviceId && deviceIdType ? {
3751
- deviceIdType: deviceIdType
3752
- } : {}, deviceId ? {
3753
- limitAdTracking: (_ref = (_bridgeSignals_limitAdTracking = bridgeSignals.limitAdTracking) !== null && _bridgeSignals_limitAdTracking !== void 0 ? _bridgeSignals_limitAdTracking : readStoredLimitAdTracking()) !== null && _ref !== void 0 ? _ref : false
3754
- } : {}), {
3755
- deviceTypeHint: 5
3756
- });
3757
- }
3758
- function getOrCreateCtvSessionId() {
3759
- var existing = readStoredString(CTV_SESSION_STORAGE_KEY);
3760
- if (existing) {
3761
- return existing;
3762
- }
3763
- var sessionId = createUuid();
3764
- try {
3765
- var _window_localStorage;
3766
- (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.setItem(CTV_SESSION_STORAGE_KEY, sessionId);
3767
- } catch (unused) {}
3768
- return sessionId;
3769
- }
3770
- function createUuid() {
3771
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
3772
- return crypto.randomUUID();
3773
- }
3774
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(char) {
3775
- var value = Math.floor(Math.random() * 16);
3776
- var nibble = char === "x" ? value : value & 3 | 8;
3777
- return nibble.toString(16);
3778
- });
3779
- }
3780
- function readNativeBridgeSignals() {
3781
- if (typeof window === "undefined") {
3782
- return {};
3783
- }
3784
- var candidates = [
3785
- window.__STORMCLOUD_CTV_AD_INFO__,
3786
- window.__STORMCLOUD_CTV__,
3787
- window.stormcloudCtv,
3788
- window.AiryTV,
3789
- window.Android
3790
- ].filter(Boolean);
3791
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3792
- try {
3793
- for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3794
- var source = _step.value;
3795
- var contentUrl = readBridgeValue(source, [
3796
- "contentUrl",
3797
- "url",
3798
- "videoUrl",
3799
- "canonicalUrl"
3800
- ]) || void 0;
3801
- var deviceId = readBridgeValue(source, [
3802
- "rdid",
3803
- "ifa",
3804
- "advertisingId",
3805
- "adId",
3806
- "deviceId"
3807
- ]) || void 0;
3808
- if (!contentUrl && !deviceId) continue;
3809
- var deviceIdType = readBridgeValue(source, [
3810
- "idtype",
3811
- "deviceIdType",
3812
- "advertisingIdType"
3813
- ]) || inferDeviceIdType();
3814
- var limitAdTracking = readBridgeBoolean(source, [
3815
- "is_lat",
3816
- "limitAdTracking",
3817
- "limitedAdTracking",
3818
- "lat"
3819
- ]);
3820
- return _object_spread({}, contentUrl ? {
3821
- contentUrl: contentUrl
3822
- } : {}, deviceId ? {
3823
- deviceId: deviceId
3824
- } : {}, deviceId && deviceIdType ? {
3825
- deviceIdType: deviceIdType
3826
- } : {}, deviceId && limitAdTracking != null ? {
3827
- limitAdTracking: limitAdTracking
3828
- } : {});
3829
- }
3830
- } catch (err) {
3831
- _didIteratorError = true;
3832
- _iteratorError = err;
3833
- } finally{
3834
- try {
3835
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3836
- _iterator.return();
3837
- }
3838
- } finally{
3839
- if (_didIteratorError) {
3840
- throw _iteratorError;
3841
- }
3842
- }
3843
- }
3844
- return {};
3845
- }
3846
- function readBridgeValue(source, keys) {
3847
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3848
- try {
3849
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3850
- var key = _step.value;
3851
- var value = source === null || source === void 0 ? void 0 : source[key];
3852
- if (typeof value === "string" && value) {
3853
- return value;
3854
- }
3855
- if (typeof value === "function") {
3856
- try {
3857
- var result = value.call(source);
3858
- if (typeof result === "string" && result) {
3859
- return result;
3860
- }
3861
- } catch (unused) {}
3862
- }
3863
- }
3864
- } catch (err) {
3865
- _didIteratorError = true;
3866
- _iteratorError = err;
3867
- } finally{
3868
- try {
3869
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3870
- _iterator.return();
3871
- }
3872
- } finally{
3873
- if (_didIteratorError) {
3874
- throw _iteratorError;
3875
- }
3876
- }
3877
- }
3878
- return void 0;
3879
- }
3880
- function readBridgeBoolean(source, keys) {
3881
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3882
- try {
3883
- for(var _iterator = keys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3884
- var key = _step.value;
3885
- var value = source === null || source === void 0 ? void 0 : source[key];
3886
- var normalized = normalizeBoolean(value);
3887
- if (normalized != null) {
3888
- return normalized;
3889
- }
3890
- if (typeof value === "function") {
3891
- try {
3892
- var result = normalizeBoolean(value.call(source));
3893
- if (result != null) {
3894
- return result;
3895
- }
3896
- } catch (unused) {}
3897
- }
3898
- }
3899
- } catch (err) {
3900
- _didIteratorError = true;
3901
- _iteratorError = err;
3902
- } finally{
3903
- try {
3904
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3905
- _iterator.return();
3906
- }
3907
- } finally{
3908
- if (_didIteratorError) {
3909
- throw _iteratorError;
3910
- }
3911
- }
3912
- }
3913
- return void 0;
3914
- }
3915
- function readStoredDeviceId() {
3916
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3917
- try {
3918
- for(var _iterator = DEVICE_ID_STORAGE_KEYS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3919
- var key = _step.value;
3920
- var value = readStoredString(key);
3921
- if (value) {
3922
- return value;
3923
- }
3924
- }
3925
- } catch (err) {
3926
- _didIteratorError = true;
3927
- _iteratorError = err;
3928
- } finally{
3929
- try {
3930
- if (!_iteratorNormalCompletion && _iterator.return != null) {
3931
- _iterator.return();
3932
- }
3933
- } finally{
3934
- if (_didIteratorError) {
3935
- throw _iteratorError;
3936
- }
3937
- }
3938
- }
3939
- return void 0;
3940
- }
3941
- function readStoredString(key) {
3942
- if (typeof window === "undefined") {
3943
- return void 0;
3944
- }
3945
- try {
3946
- var _window_localStorage;
3947
- var value = (_window_localStorage = window.localStorage) === null || _window_localStorage === void 0 ? void 0 : _window_localStorage.getItem(key);
3948
- return value || void 0;
3949
- } catch (unused) {
3950
- return void 0;
3951
- }
3952
- }
3953
- function readStoredLimitAdTracking() {
3954
- return normalizeBoolean(readStoredString("limitAdTracking") || readStoredString("limitedAdTracking") || readStoredString("is_lat"));
3955
- }
3956
- function normalizeBoolean(value) {
3957
- if (typeof value === "boolean") {
3958
- return value;
3959
- }
3960
- if (typeof value === "number") {
3961
- return value === 1;
3962
- }
3963
- if (typeof value === "string") {
3964
- var normalized = value.toLowerCase();
3965
- if (normalized === "1" || normalized === "true" || normalized === "yes") {
3966
- return true;
3967
- }
3968
- if (normalized === "0" || normalized === "false" || normalized === "no") {
3969
- return false;
3970
- }
3971
- }
3972
- return void 0;
3973
- }
3974
- function inferDeviceIdType() {
3975
- if (typeof navigator === "undefined") {
3976
- return void 0;
3977
- }
3978
- var ua = navigator.userAgent;
3979
- if (/Roku/i.test(ua)) return "rida";
3980
- if (/Tizen|Samsung/i.test(ua)) return "tifa";
3981
- if (/AppleTV/i.test(ua)) return "tvOS";
3982
- if (/AFT|Fire TV|Amazon/i.test(ua)) return "afai";
3983
- if (/Web0S|webOS|LG/i.test(ua)) return "lgudid";
3984
- if (/Android|Google TV/i.test(ua)) return "aaid";
3985
- return void 0;
3986
- }
3987
- // src/player/VmapManager.ts
3988
- var VmapManager = /*#__PURE__*/ function() {
3989
- function VmapManager(config, video) {
3990
- _class_call_check(this, VmapManager);
4311
+ // src/player/AdConfigManager.ts
4312
+ var AdConfigManager = /*#__PURE__*/ function() {
4313
+ function AdConfigManager(config, video) {
4314
+ _class_call_check(this, AdConfigManager);
3991
4315
  this.vmapBreaks = [];
3992
4316
  this.consumedVmapBreakIds = /* @__PURE__ */ new Set();
3993
4317
  this.streamCorrelator = generateCorrelator();
@@ -3999,7 +4323,7 @@ var VmapManager = /*#__PURE__*/ function() {
3999
4323
  this.config = config;
4000
4324
  this.video = video;
4001
4325
  }
4002
- _create_class(VmapManager, [
4326
+ _create_class(AdConfigManager, [
4003
4327
  {
4004
4328
  key: "debug",
4005
4329
  get: function get() {
@@ -4017,7 +4341,7 @@ var VmapManager = /*#__PURE__*/ function() {
4017
4341
  key: "fetchAdConfiguration",
4018
4342
  value: function fetchAdConfiguration() {
4019
4343
  return _async_to_generator(function() {
4020
- 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;
4344
+ 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;
4021
4345
  return _ts_generator(this, function(_state) {
4022
4346
  switch(_state.label){
4023
4347
  case 0:
@@ -4061,7 +4385,7 @@ var VmapManager = /*#__PURE__*/ function() {
4061
4385
  ];
4062
4386
  }
4063
4387
  if (this.config.vastTagUrl) {
4064
- this.apiVastTagUrl = this.config.vastTagUrl;
4388
+ this.apiVastTagUrl = normalizeVastTagUrl(this.config.vastTagUrl);
4065
4389
  if (this.debug) {
4066
4390
  console.log("[StormcloudVideoPlayer] Using custom VAST tag URL:", this.apiVastTagUrl);
4067
4391
  }
@@ -4101,9 +4425,16 @@ var VmapManager = /*#__PURE__*/ function() {
4101
4425
  data = _state.sent();
4102
4426
  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;
4103
4427
  if (imaPayload) {
4104
- this.apiVastTagUrl = decodeURIComponent(imaPayload);
4428
+ decodedPayload = imaPayload;
4429
+ try {
4430
+ decodedPayload = decodeURIComponent(imaPayload);
4431
+ } catch (unused) {
4432
+ console.warn("[StormcloudVideoPlayer] imaPayload was not URI-encoded; using as-is:", imaPayload);
4433
+ }
4434
+ console.log("[StormcloudVideoPlayer] Raw VAST tag URL (from API):", decodedPayload);
4435
+ this.apiVastTagUrl = normalizeVastTagUrl(decodedPayload);
4105
4436
  if (this.debug) {
4106
- console.log("[StormcloudVideoPlayer] Extracted VAST tag URL from /ads/web:", this.apiVastTagUrl);
4437
+ console.log("[StormcloudVideoPlayer] Normalized VAST tag URL:", this.apiVastTagUrl);
4107
4438
  }
4108
4439
  } else {
4109
4440
  if (this.debug) {
@@ -4416,28 +4747,30 @@ var VmapManager = /*#__PURE__*/ function() {
4416
4747
  for(var i = 0; i < count; i++){
4417
4748
  this.adRequestPositionInBreak++;
4418
4749
  var adWillPlayMuted = inAdBreak ? adPlayer.getOriginalMutedState() : this.video.muted;
4419
- var ctvSignals = this.config.ctvAdRequest ? resolveCtvVastSignals() : void 0;
4750
+ var envSignals = resolveVastEnvironmentSignals(!!this.config.ctvAdRequest);
4420
4751
  var urlWithMacros = applyVastMacros(baseUrl, {
4421
4752
  correlator: generateCorrelator(),
4422
4753
  streamCorrelator: this.streamCorrelator,
4423
4754
  pod: this.podCounter > 0 ? this.podCounter : void 0,
4424
4755
  adPosition: this.adRequestPositionInBreak,
4425
- isCtv: this.config.ctvAdRequest,
4426
- contentUrl: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.contentUrl,
4427
- pageUrl: !this.config.ctvAdRequest && typeof window !== "undefined" ? window.location.href : void 0,
4756
+ isCtv: envSignals.isCtv,
4757
+ contentUrl: envSignals.contentUrl,
4758
+ pageUrl: !envSignals.isCtv && typeof window !== "undefined" ? window.location.href : void 0,
4428
4759
  adWillPlayMuted: adWillPlayMuted,
4429
4760
  adWillAutoPlay: !!this.config.autoplay,
4430
- appId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.appId,
4431
- appName: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.appName,
4432
- sessionId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.sessionId,
4433
- deviceId: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceId,
4434
- deviceIdType: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceIdType,
4435
- limitAdTracking: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.limitAdTracking,
4436
- deviceTypeHint: ctvSignals === null || ctvSignals === void 0 ? void 0 : ctvSignals.deviceTypeHint,
4761
+ appId: envSignals.appId,
4762
+ appName: envSignals.appName,
4763
+ sessionId: envSignals.sessionId,
4764
+ deviceId: envSignals.deviceId,
4765
+ deviceIdType: envSignals.deviceIdType,
4766
+ limitAdTracking: envSignals.limitAdTracking,
4767
+ deviceTypeHint: envSignals.deviceTypeHint,
4437
4768
  adTest: this.config.adTest,
4438
4769
  consent: this.consentSignals
4439
4770
  });
4440
- urls.push(palNonce.injectNonce(urlWithMacros));
4771
+ var finalUrl = palNonce.injectNonce(urlWithMacros);
4772
+ console.log("[StormcloudVideoPlayer] Resolved ad request URL (pod=".concat(this.podCounter, ", pos=").concat(this.adRequestPositionInBreak, "):"), finalUrl);
4773
+ urls.push(finalUrl);
4441
4774
  }
4442
4775
  return urls;
4443
4776
  }
@@ -4486,7 +4819,7 @@ var VmapManager = /*#__PURE__*/ function() {
4486
4819
  }
4487
4820
  }
4488
4821
  ]);
4489
- return VmapManager;
4822
+ return AdConfigManager;
4490
4823
  }();
4491
4824
  // src/player/AdTimingService.ts
4492
4825
  var AdTimingService = /*#__PURE__*/ function() {
@@ -6213,7 +6546,7 @@ function resizePlayer(video, adPlayer, debug) {
6213
6546
  }
6214
6547
  // src/player/AdBreakOrchestrator.ts
6215
6548
  var AdBreakOrchestrator = /*#__PURE__*/ function() {
6216
- function AdBreakOrchestrator(host, timing, preloadPool, vmap, cueManager, placeholder) {
6549
+ function AdBreakOrchestrator(host, timing, preloadPool, adConfig, cueManager, placeholder) {
6217
6550
  _class_call_check(this, AdBreakOrchestrator);
6218
6551
  this.inAdBreak = false;
6219
6552
  this.showAds = false;
@@ -6228,7 +6561,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6228
6561
  this.host = host;
6229
6562
  this.timing = timing;
6230
6563
  this.preloadPool = preloadPool;
6231
- this.vmap = vmap;
6564
+ this.adConfig = adConfig;
6232
6565
  this.cueManager = cueManager;
6233
6566
  this.placeholder = placeholder;
6234
6567
  }
@@ -6394,7 +6727,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6394
6727
  }
6395
6728
  this.pendingAdBreak = null;
6396
6729
  this.cueManager.pendingScte35CueKey = void 0;
6397
- this.vmap.podAssignedByPrefetch = false;
6730
+ this.adConfig.podAssignedByPrefetch = false;
6398
6731
  }
6399
6732
  },
6400
6733
  {
@@ -6408,15 +6741,15 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6408
6741
  return _ts_generator(this, function(_state) {
6409
6742
  switch(_state.label){
6410
6743
  case 0:
6411
- scheduled = this.vmap.findCurrentOrNextBreak(this.host.video.currentTime * 1e3);
6744
+ scheduled = this.adConfig.findCurrentOrNextBreak(this.host.video.currentTime * 1e3);
6412
6745
  if (scheduled) {
6413
- this.vmap.consumedVmapBreakIds.add(this.vmap.getAdBreakKey(scheduled));
6746
+ this.adConfig.consumedVmapBreakIds.add(this.adConfig.getAdBreakKey(scheduled));
6414
6747
  }
6415
- tags = this.vmap.selectVastTagsForBreak(scheduled);
6748
+ tags = this.adConfig.selectVastTagsForBreak(scheduled);
6416
6749
  if (tags && tags.length > 0 && tags[0]) {
6417
6750
  baseVastUrl = tags[0];
6418
- } else if (this.vmap.apiVastTagUrl) {
6419
- baseVastUrl = this.vmap.apiVastTagUrl;
6751
+ } else if (this.adConfig.apiVastTagUrl) {
6752
+ baseVastUrl = this.adConfig.apiVastTagUrl;
6420
6753
  } else {
6421
6754
  this.clearPendingAdBreak();
6422
6755
  return [
@@ -6434,10 +6767,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
6434
6767
  this.continuousFetchingActive = true;
6435
6768
  this.isShowingPlaceholder = false;
6436
6769
  this.timing.totalAdRequestsInBreak = 0;
6437
- if (this.vmap.podAssignedByPrefetch) {
6438
- this.vmap.podAssignedByPrefetch = false;
6770
+ if (this.adConfig.podAssignedByPrefetch) {
6771
+ this.adConfig.podAssignedByPrefetch = false;
6439
6772
  } else {
6440
- this.vmap.beginNewAdPod();
6773
+ this.adConfig.beginNewAdPod();
6441
6774
  }
6442
6775
  currentMuted = this.host.video.muted;
6443
6776
  currentVolume = this.host.video.volume;
@@ -7709,7 +8042,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7709
8042
  return _this.adBreak.inAdBreak;
7710
8043
  }
7711
8044
  });
7712
- this.vmap = new VmapManager(this.config, this.video);
8045
+ this.adConfig = new AdConfigManager(this.config, this.video);
7713
8046
  this.timing = new AdTimingService(this.config, this.video, {
7714
8047
  onAdStopTimerFired: function onAdStopTimerFired() {
7715
8048
  return _this.onAdStopTimerFired();
@@ -7789,7 +8122,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7789
8122
  generateVastUrls: function generateVastUrls(base, count) {
7790
8123
  return _this.generateVastUrls(base, count);
7791
8124
  }
7792
- }, this.timing, this.preloadPool, this.vmap, this.cueManager, this.placeholder);
8125
+ }, this.timing, this.preloadPool, this.adConfig, this.cueManager, this.placeholder);
7793
8126
  }
7794
8127
  _create_class(StormcloudVideoPlayer, [
7795
8128
  {
@@ -7817,7 +8150,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7817
8150
  {
7818
8151
  key: "generateVastUrls",
7819
8152
  value: function generateVastUrls(baseUrl, count) {
7820
- return this.vmap.generateVastUrlsWithCorrelators(baseUrl, count, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
8153
+ return this.adConfig.generateVastUrlsWithCorrelators(baseUrl, count, this.adPlayer, this.palNonce, this.adBreak.inAdBreak);
7821
8154
  }
7822
8155
  },
7823
8156
  {
@@ -7845,7 +8178,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7845
8178
  ]);
7846
8179
  return [
7847
8180
  4,
7848
- this.vmap.fetchAdConfiguration()
8181
+ this.adConfig.fetchAdConfiguration()
7849
8182
  ];
7850
8183
  case 2:
7851
8184
  _state.sent();
@@ -7872,9 +8205,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7872
8205
  continuousPlayback: (_this_config_lowLatencyMode = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false
7873
8206
  }).catch(function() {});
7874
8207
  fetchConsentSignals().then(function(signals) {
7875
- _this.vmap.consentSignals = signals;
8208
+ _this.adConfig.consentSignals = signals;
7876
8209
  }).catch(function() {});
7877
- this.vmap.initializeTracking();
8210
+ this.adConfig.initializeTracking();
7878
8211
  if (!this.hlsEngine.shouldUseNativeHls(function() {
7879
8212
  return _this.getStreamType();
7880
8213
  })) return [
@@ -7909,14 +8242,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7909
8242
  return _async_to_generator(function() {
7910
8243
  var prerollKey, adBehavior;
7911
8244
  return _ts_generator(this, function(_state) {
7912
- if (!this.vmap.isVmapEnabled() && !isLive && this.vmap.vmapBreaks.length === 0 && this.vmap.apiVastTagUrl) {
8245
+ if (!this.adConfig.isVmapEnabled() && !isLive && this.adConfig.vmapBreaks.length === 0 && this.adConfig.apiVastTagUrl) {
7913
8246
  prerollKey = "synthetic-vod-preroll";
7914
- if (!this.vmap.consumedVmapBreakIds.has(prerollKey)) {
7915
- this.vmap.vmapBreaks = [
8247
+ if (!this.adConfig.consumedVmapBreakIds.has(prerollKey)) {
8248
+ this.adConfig.vmapBreaks = [
7916
8249
  {
7917
8250
  id: prerollKey,
7918
8251
  startTimeMs: 0,
7919
- vastTagUrl: this.vmap.apiVastTagUrl
8252
+ vastTagUrl: this.adConfig.apiVastTagUrl
7920
8253
  }
7921
8254
  ];
7922
8255
  if (this.debug) {
@@ -8183,19 +8516,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8183
8516
  key: "startAdPrefetch",
8184
8517
  value: function startAdPrefetch(marker, fragmentSn, cueKey) {
8185
8518
  if (this.adBreak.pendingAdBreak || this.adBreak.inAdBreak) return;
8186
- var scheduled = this.vmap.findCurrentOrNextBreak(this.video.currentTime * 1e3);
8187
- var tags = this.vmap.selectVastTagsForBreak(scheduled);
8519
+ var scheduled = this.adConfig.findCurrentOrNextBreak(this.video.currentTime * 1e3);
8520
+ var tags = this.adConfig.selectVastTagsForBreak(scheduled);
8188
8521
  var baseVastUrl;
8189
8522
  if (tags && tags.length > 0 && tags[0]) {
8190
8523
  baseVastUrl = tags[0];
8191
- } else if (this.vmap.apiVastTagUrl) {
8192
- baseVastUrl = this.vmap.apiVastTagUrl;
8524
+ } else if (this.adConfig.apiVastTagUrl) {
8525
+ baseVastUrl = this.adConfig.apiVastTagUrl;
8193
8526
  } else {
8194
8527
  if (this.debug) console.warn("[StormcloudVideoPlayer] No VAST URL available for prefetch");
8195
8528
  return;
8196
8529
  }
8197
- this.vmap.beginNewAdPod();
8198
- this.vmap.podAssignedByPrefetch = true;
8530
+ this.adConfig.beginNewAdPod();
8531
+ this.adConfig.podAssignedByPrefetch = true;
8199
8532
  var generatedUrls = this.generateVastUrls(baseVastUrl, 1);
8200
8533
  this.adBreak.pendingAdBreak = _object_spread_props(_object_spread({
8201
8534
  marker: marker
@@ -8230,10 +8563,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8230
8563
  key: "onTimeUpdate",
8231
8564
  value: function onTimeUpdate(currentTimeSec) {
8232
8565
  var _this = this;
8233
- if (!this.vmap.isVmapEnabled() || this.vmap.vmapBreaks.length === 0) return;
8566
+ if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;
8234
8567
  if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;
8235
8568
  var nowMs = currentTimeSec * 1e3;
8236
- var breakToPlay = this.vmap.findBreakForTime(nowMs);
8569
+ var breakToPlay = this.adConfig.findBreakForTime(nowMs);
8237
8570
  if (breakToPlay) {
8238
8571
  void this.handleVmapAdBreak(breakToPlay, nowMs).catch(function(error) {
8239
8572
  if (_this.debug) {
@@ -8247,11 +8580,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8247
8580
  key: "onVideoEnded",
8248
8581
  value: function onVideoEnded() {
8249
8582
  var _this = this;
8250
- if (!this.vmap.isVmapEnabled() || this.vmap.vmapBreaks.length === 0) return;
8583
+ if (!this.adConfig.isVmapEnabled() || this.adConfig.vmapBreaks.length === 0) return;
8251
8584
  if (this.adPlayer.isAdPlaying() || this.adBreak.inAdBreak) return;
8252
8585
  var durationMs = Number.isFinite(this.video.duration) ? Math.floor(this.video.duration * 1e3) : 0;
8253
- var postroll = this.vmap.vmapBreaks.find(function(b) {
8254
- return b.startTimeMs === -1 && !_this.vmap.consumedVmapBreakIds.has(_this.vmap.getAdBreakKey(b));
8586
+ var postroll = this.adConfig.vmapBreaks.find(function(b) {
8587
+ return b.startTimeMs === -1 && !_this.adConfig.consumedVmapBreakIds.has(_this.adConfig.getAdBreakKey(b));
8255
8588
  });
8256
8589
  if (postroll) {
8257
8590
  void this.handleVmapAdBreak(postroll, durationMs).catch(function(error) {
@@ -8270,11 +8603,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8270
8603
  return _ts_generator(this, function(_state) {
8271
8604
  switch(_state.label){
8272
8605
  case 0:
8273
- key = this.vmap.getAdBreakKey(adBreak);
8274
- if (this.vmap.consumedVmapBreakIds.has(key)) return [
8606
+ key = this.adConfig.getAdBreakKey(adBreak);
8607
+ if (this.adConfig.consumedVmapBreakIds.has(key)) return [
8275
8608
  2
8276
8609
  ];
8277
- breakStartMs = this.vmap.resolveBreakStartMs(adBreak);
8610
+ breakStartMs = this.adConfig.resolveBreakStartMs(adBreak);
8278
8611
  if (breakStartMs == null) return [
8279
8612
  2
8280
8613
  ];
@@ -8285,8 +8618,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8285
8618
  3,
8286
8619
  4
8287
8620
  ];
8288
- this.vmap.consumedVmapBreakIds.add(key);
8289
- tags = this.vmap.selectVastTagsForBreak(adBreak);
8621
+ this.adConfig.consumedVmapBreakIds.add(key);
8622
+ tags = this.adConfig.selectVastTagsForBreak(adBreak);
8290
8623
  if (!tags || tags.length === 0) return [
8291
8624
  2
8292
8625
  ];
@@ -8478,7 +8811,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8478
8811
  this.video.removeEventListener("emptied", this.emptiedHandler);
8479
8812
  delete this.emptiedHandler;
8480
8813
  }
8481
- this.vmap.destroyTracking();
8814
+ this.adConfig.destroyTracking();
8482
8815
  this.hlsEngine.destroy();
8483
8816
  (_this_adPlayer = this.adPlayer) === null || _this_adPlayer === void 0 ? void 0 : _this_adPlayer.destroy();
8484
8817
  if (this.palPlaybackStarted) {