stormcloud-video-player 0.8.18 → 0.8.19

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 (34) hide show
  1. package/README.md +67 -83
  2. package/dist/stormcloud-vp.min.js +1 -1
  3. package/lib/index.cjs +635 -346
  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 +635 -346
  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 +3 -3
  12. package/lib/player/{VmapManager.cjs → AdConfigManager.cjs} +503 -214
  13. package/lib/player/AdConfigManager.cjs.map +1 -0
  14. package/lib/player/{VmapManager.d.cts → AdConfigManager.d.cts} +2 -2
  15. package/lib/player/StormcloudVideoPlayer.cjs +635 -346
  16. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  17. package/lib/player/StormcloudVideoPlayer.d.cts +1 -1
  18. package/lib/players/HlsPlayer.cjs +635 -346
  19. package/lib/players/HlsPlayer.cjs.map +1 -1
  20. package/lib/players/index.cjs +635 -346
  21. package/lib/players/index.cjs.map +1 -1
  22. package/lib/ui/StormcloudVideoPlayer.cjs +635 -346
  23. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  24. package/lib/utils/ctvVastSignals.cjs +92 -33
  25. package/lib/utils/ctvVastSignals.cjs.map +1 -1
  26. package/lib/utils/ctvVastSignals.d.cts +1 -13
  27. package/lib/utils/vastEnvironmentSignals.cjs +439 -0
  28. package/lib/utils/vastEnvironmentSignals.cjs.map +1 -0
  29. package/lib/utils/vastEnvironmentSignals.d.cts +16 -0
  30. package/lib/utils/vastMacros.cjs +299 -25
  31. package/lib/utils/vastMacros.cjs.map +1 -1
  32. package/lib/utils/vastMacros.d.cts +3 -1
  33. package/package.json +1 -1
  34. package/lib/player/VmapManager.cjs.map +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Stormcloud Video Player
2
2
 
3
- A professional video player with advanced ad integration for web applications. Built with precision ad break alignment, SCTE-35 signal parsing, VMAP ad-break scheduling, custom VAST ad serving, and optional Google IMA SDK integration for seamless ad playback. Now featuring a modern, extensible architecture inspired by react-player.
3
+ A professional video player with advanced ad integration for web applications. Built with precision ad break alignment, SCTE-35 signal parsing, VMAP ad-break scheduling, and a native HLS ad player for VAST-based ad playback. Now featuring a modern, extensible architecture inspired by react-player.
4
4
 
5
5
  ## 🎯 Key Features
6
6
 
@@ -12,7 +12,7 @@ A professional video player with advanced ad integration for web applications. B
12
12
  - **Enhanced UI Controls**: Beautiful, adaptive video controls that work on any background color
13
13
  - **Live Mode Support**: Specialized controls for live streaming with volume adjustment
14
14
  - **Cross-Platform & Smart TV Ready**: Desktop, mobile, tablets, LG WebOS, Samsung Tizen, Sony BRAVIA, Android TV, Roku, Apple TV
15
- - **Automatic Browser Compatibility**: Built-in browser detection, polyfills, and automatic ad-player selection for legacy Smart TVs
15
+ - **Automatic Browser Compatibility**: Built-in browser detection, polyfills, and Smart TV playback overrides (e.g. native HLS)
16
16
  - **React Ready**: Multiple React components for different use cases
17
17
  - **TypeScript Support**: Full type definitions included
18
18
  - **Professional Architecture**: Modular player system with lazy loading
@@ -44,7 +44,8 @@ function MyVideoApp() {
44
44
  hideLoadingIndicator={false} // Hide the built-in loading spinner
45
45
  allowNativeHls={true} // Allow native HLS for better performance
46
46
  licenseKey="your_license_key_here"
47
- vastMode="adstorm" // Use AdStorm mode with HLS ad player
47
+ vastMode="adstorm" // AdStorm VAST endpoint resolution
48
+ isVmap={true}
48
49
  vmapUrl="https://your-cdn.com/ads.vmap" // Optional VMAP manifest for scheduled breaks
49
50
  style={{ width: "100%", aspectRatio: "16/9" }}
50
51
  wrapperStyle={{ borderRadius: "12px", overflow: "hidden" }}
@@ -174,7 +175,7 @@ StormcloudPlayer (Main Component)
174
175
  - **Purpose**: Handles HLS (.m3u8) streams with advanced features
175
176
  - **Features**:
176
177
  - SCTE-35 ad marker detection and processing
177
- - Google IMA SDK integration for VAST/VPAID ads
178
+ - HLS ad player with VAST XML parsing (HLS and progressive media files)
178
179
  - Live stream support with low-latency mode
179
180
  - Drift correction for live timing
180
181
  - Manifest-based and ID3 ad markers
@@ -279,10 +280,10 @@ interface StormcloudPlayerProps {
279
280
  minSegmentsBeforePlay?: number; // Number of segments to buffer before starting playback (default: 2)
280
281
 
281
282
  // Ad player configuration
282
- vastMode?: 'adstorm' | 'default'; // VAST mode: 'adstorm' (HLS player + AdStorm VAST endpoint) or 'default' (IMA SDK + /ads/web endpoint) (default: 'default')
283
- vastTagUrl?: string; // Custom VAST URL (used in default mode if provided; when not provided, uses /ads/web endpoint)
284
- vmapUrl?: string; // Optional VMAP 1.0 manifest URL used to schedule pre/mid/post-roll ad breaks
285
- adPlayerType?: 'ima' | 'hls'; // Manual override for ad player type (auto-determined by vastMode if not specified)
283
+ vastMode?: 'adstorm' | 'default'; // VAST endpoint resolution: 'adstorm' (/vast/{licenseKey}) or 'default' (/ads/web or vastTagUrl) (default: 'default')
284
+ vastTagUrl?: string; // Custom VAST tag URL (default mode; when omitted, /ads/web supplies the tag URL)
285
+ isVmap?: boolean; // Enable VMAP manifest scheduling (requires vmapUrl)
286
+ vmapUrl?: string; // VMAP 1.0 manifest URL for pre/mid/post-roll ad breaks (requires isVmap: true)
286
287
 
287
288
  // Event handlers
288
289
  onReady?: (player: StormcloudVideoPlayer) => void;
@@ -372,10 +373,12 @@ interface StormcloudVideoPlayerConfig {
372
373
  maxAdBreakExtensionMs?: number; // Max time an ad break may be extended past its SCTE-35 duration when ads are still playing/queued (default: 60000)
373
374
 
374
375
  // Ad configuration
375
- vastMode?: 'adstorm' | 'default'; // VAST mode: 'adstorm' (uses HLS player + AdStorm VAST endpoint) or 'default' (uses Google IMA SDK + /ads/web endpoint) (default: 'default')
376
- vastTagUrl?: string; // Custom VAST tag URL (used in default mode if provided; when not provided, defaults to /ads/web endpoint)
377
- vmapUrl?: string; // Optional VMAP 1.0 manifest URL used to schedule pre/mid/post-roll ad breaks
378
- adPlayerType?: 'ima' | 'hls'; // Manual override for ad player type (auto-determined by vastMode/browser if not specified)
376
+ vastMode?: 'adstorm' | 'default'; // VAST endpoint resolution: 'adstorm' (/vast/{licenseKey}) or 'default' (/ads/web or vastTagUrl) (default: 'default')
377
+ vastTagUrl?: string; // Custom VAST tag URL (default mode; when omitted, /ads/web supplies the tag URL)
378
+ isVmap?: boolean; // Enable VMAP manifest scheduling (requires vmapUrl)
379
+ vmapUrl?: string; // VMAP 1.0 manifest URL (requires isVmap: true)
380
+ ctvAdRequest?: boolean; // Include CTV device signals in VAST macro substitution
381
+ adTest?: boolean; // Enable test ad mode in VAST requests
379
382
 
380
383
  onVolumeToggle?: () => void; // Callback for volume toggle
381
384
  onFullscreenToggle?: () => void; // Callback for fullscreen toggle
@@ -438,11 +441,11 @@ All controls use a consistent high-contrast design:
438
441
 
439
442
  ### VAST Mode Configuration
440
443
 
441
- The player supports two VAST modes that automatically configure the appropriate ad player:
444
+ The player always uses the **HLS ad player** to fetch VAST XML and play ad media (HLS or progressive). The `vastMode` option only controls **which endpoint supplies the VAST tag URL**:
442
445
 
443
446
  #### 1. **AdStorm Mode** (Recommended)
444
447
 
445
- Uses AdStorm backend with HLS ad player for optimal performance:
448
+ Uses the AdStorm `/vast/{licenseKey}` endpoint, which returns VAST XML directly:
446
449
 
447
450
  ```javascript
448
451
  const player = new StormcloudVideoPlayer({
@@ -450,7 +453,6 @@ const player = new StormcloudVideoPlayer({
450
453
  src: "https://your-stream.com/playlist.m3u8",
451
454
  licenseKey: "your-license-key",
452
455
 
453
- // AdStorm mode - uses HLS ad player automatically
454
456
  vastMode: 'adstorm',
455
457
 
456
458
  debugAdTiming: true,
@@ -458,7 +460,6 @@ const player = new StormcloudVideoPlayer({
458
460
  ```
459
461
 
460
462
  **What happens:**
461
- - 🎯 Automatically uses HLS ad player (`adPlayerType: 'hls'`)
462
463
  - 🔗 VAST endpoint: `GET https://adstorm.co/api-adstorm-dev/adstorm/vast/{licenseKey}`
463
464
  - License key is passed in the URL path (no authorization header needed)
464
465
  - Returns VAST XML directly with HLS media files
@@ -468,20 +469,20 @@ const player = new StormcloudVideoPlayer({
468
469
  **API Flow:**
469
470
  1. Player calls `/vast/{licenseKey}` endpoint
470
471
  2. Backend returns VAST XML with HLS media files
471
- 3. Player parses VAST XML and extracts MediaFile URLs
472
- 4. HLS ad player loads and plays the ad segments
472
+ 3. HLS ad player parses VAST XML and extracts MediaFile URLs
473
+ 4. Ad segments are loaded and played
473
474
 
474
475
  **Benefits:**
475
- - ✅ Zero external dependencies (no Google IMA SDK)
476
+ - ✅ Zero external ad SDK dependencies
476
477
  - ✅ Full control over ad serving
477
478
  - ✅ Native HLS playback (same format as content)
478
- - ✅ Better performance and reliability
479
+ - ✅ Better performance and reliability on Smart TVs
479
480
  - ✅ Custom targeting and selection
480
481
  - ✅ Proper error handling (distinguishes parsing errors from "no ads available")
481
482
 
482
483
  #### 2. **Default Mode**
483
484
 
484
- Uses Google IMA SDK for traditional ad serving:
485
+ Uses the AdStorm `/ads/web` API (or a custom `vastTagUrl`) to obtain a VAST tag URL, then plays ads through the same HLS ad player:
485
486
 
486
487
  ```javascript
487
488
  const player = new StormcloudVideoPlayer({
@@ -489,7 +490,6 @@ const player = new StormcloudVideoPlayer({
489
490
  src: "https://your-stream.com/playlist.m3u8",
490
491
  licenseKey: "your-license-key",
491
492
 
492
- // Default mode - uses Google IMA SDK automatically
493
493
  vastMode: 'default', // or omit this property entirely
494
494
  vastTagUrl: 'https://your-vast-server.com/vast.xml', // optional
495
495
 
@@ -498,27 +498,24 @@ const player = new StormcloudVideoPlayer({
498
498
  ```
499
499
 
500
500
  **What happens:**
501
- - 🎯 Automatically uses Google IMA SDK (`adPlayerType: 'ima'`)
502
- - 🔗 VAST endpoint resolution:
501
+ - 🔗 VAST tag URL resolution:
503
502
  1. If `vastTagUrl` is provided, uses that URL directly
504
503
  2. Otherwise, calls `GET https://adstorm.co/api-adstorm-dev/adstorm/ads/web`
505
504
  - Requires `Authorization: Bearer {licenseKey}` header
506
- - Returns JSON response with IMA payload: `{ response: { ima: { "publisherdesk.ima": { payload: "VAST_URL" } } } }`
507
- - Extracts VAST tag URL from the `payload` field
508
- - 📊 Standard VAST/VPAID ad serving through Google IMA SDK
505
+ - Returns JSON with a VAST tag URL in `response.ima["publisherdesk.ima"].payload`
506
+ - 📊 HLS ad player fetches VAST XML from the resolved tag URL and plays returned media files
509
507
 
510
508
  **API Flow:**
511
- 1. Player calls `/ads/web` endpoint with Bearer token (if no `vastTagUrl` provided)
512
- 2. Backend returns JSON with IMA configuration
513
- 3. Player extracts VAST tag URL from `response.ima["publisherdesk.ima"].payload`
514
- 4. Google IMA SDK loads and plays the VAST ad
509
+ 1. Player calls `/ads/web` with Bearer token (if no `vastTagUrl` provided)
510
+ 2. Backend returns JSON with a VAST tag URL in `response.ima["publisherdesk.ima"].payload`
511
+ 3. HLS ad player requests VAST XML from that URL
512
+ 4. Ad media is parsed from VAST and played
515
513
 
516
514
  **Benefits:**
517
- - ✅ Industry-standard ad serving
518
- - ✅ Wide format support (VAST, VPAID)
519
- - ✅ Established ecosystem
520
- - ✅ Backward compatible with existing VAST tags
521
- - ✅ Supports both custom VAST URLs and AdStorm backend
515
+ - ✅ Industry-standard VAST tag URLs (e.g. Google Ad Manager)
516
+ - ✅ Backward compatible with existing AdStorm `/ads/web` integrations
517
+ - ✅ Supports both custom VAST URLs and AdStorm backend configuration
518
+ - ✅ Same HLS ad player stack as AdStorm mode
522
519
 
523
520
  ### Ad Pod Generation (Multiple Consecutive Ads)
524
521
 
@@ -644,7 +641,7 @@ In addition to SCTE-35 markers and continuous-ad-fetch, the player supports **VM
644
641
 
645
642
  #### Usage
646
643
 
647
- Provide a `vmapUrl` in addition to (or instead of) a VAST/AdStorm configuration:
644
+ Provide `isVmap: true` and a `vmapUrl` in addition to (or instead of) a VAST/AdStorm configuration:
648
645
 
649
646
  ```javascript
650
647
  const player = new StormcloudVideoPlayer({
@@ -653,6 +650,7 @@ const player = new StormcloudVideoPlayer({
653
650
  licenseKey: "your-license-key",
654
651
 
655
652
  vastMode: 'default',
653
+ isVmap: true,
656
654
  vmapUrl: 'https://your-cdn.com/schedule.vmap', // VMAP 1.0 manifest
657
655
 
658
656
  debugAdTiming: true,
@@ -665,6 +663,7 @@ Or with React:
665
663
  <StormcloudPlayer
666
664
  src="https://your-stream.com/video.m3u8"
667
665
  licenseKey="your-license-key"
666
+ isVmap={true}
668
667
  vmapUrl="https://your-cdn.com/schedule.vmap"
669
668
  playing={true}
670
669
  />
@@ -726,26 +725,18 @@ The VMAP parser recognizes all standard `timeOffset` values:
726
725
  - ✅ Supports pre-roll, mid-roll, percentage-based, and post-roll breaks
727
726
  - ✅ Gracefully handles malformed XML and fetch failures (logged when `debugAdTiming` is enabled)
728
727
 
729
- ### Manual Ad Player Override
728
+ ### Ad Player Architecture
730
729
 
731
- You can still manually override the ad player type if needed:
730
+ All ads are played through the built-in **HLS ad player** (`createHlsAdPlayer`).
732
731
 
733
- ```javascript
734
- const player = new StormcloudVideoPlayer({
735
- videoElement: video,
736
- src: "https://your-stream.com/playlist.m3u8",
737
-
738
- vastMode: 'default',
739
- adPlayerType: 'hls', // Manual override to use HLS player with default mode
740
- vastTagUrl: 'https://your-backend.com/vast', // Will use this URL directly
741
-
742
- debugAdTiming: true,
743
- });
744
- ```
732
+ The player:
733
+ 1. Resolves a VAST tag URL (`vastMode`, `vastTagUrl`, VMAP, or `/ads/web`)
734
+ 2. Fetches and parses VAST XML (including wrapper chains)
735
+ 3. Plays HLS or progressive `MediaFile` URLs from the VAST response
745
736
 
746
- **Note:** When `adPlayerType` is manually set, the `vastMode` property still determines which backend endpoint is called:
747
- - `vastMode: 'adstorm'` → Always calls `/vast/{licenseKey}` endpoint
748
- - `vastMode: 'default'` → Calls `/ads/web` endpoint (unless `vastTagUrl` is provided)
737
+ `vastMode` only changes how the initial VAST tag URL is obtained:
738
+ - `vastMode: 'adstorm'` → `/vast/{licenseKey}` returns VAST XML directly (used as the tag URL for pod generation)
739
+ - `vastMode: 'default'` → `/ads/web` or `vastTagUrl` supplies the tag URL; the HLS ad player fetches VAST from that URL
749
740
 
750
741
  ### SCTE-35 Support
751
742
 
@@ -919,7 +910,7 @@ Authenticated requests are sent to:
919
910
 
920
911
  - **Default Mode** (`vastMode: 'default'`):
921
912
  - Ad configuration: `GET https://adstorm.co/api-adstorm-dev/adstorm/ads/web` (requires `Authorization: Bearer {licenseKey}` header)
922
- - Returns JSON with IMA payload containing VAST tag URL
913
+ - Returns JSON with a VAST tag URL in `response.ima["publisherdesk.ima"].payload`
923
914
 
924
915
  - **Player Tracking** (both modes):
925
916
  - Player tracking: `POST https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track` (requires `Authorization: Bearer {licenseKey}` header)
@@ -957,14 +948,14 @@ await sendAdDetectTracking(licenseKey, {
957
948
  });
958
949
 
959
950
  await sendAdLoadedTracking(licenseKey, {
960
- source: "ima", // 'prebid' | 'ima' | 'hls'
951
+ source: "hls", // 'vast' | 'hls' (ad playback path)
961
952
  vastUrl: "https://...",
962
953
  durationSeconds: 15,
963
954
  timestamp: new Date().toISOString(),
964
955
  });
965
956
 
966
957
  await sendAdImpressionTracking(licenseKey, {
967
- source: "ima",
958
+ source: "hls",
968
959
  adIndex: 0,
969
960
  durationSeconds: 15,
970
961
  timestamp: new Date().toISOString(),
@@ -1084,15 +1075,13 @@ console.log("Supports PIP:", canPIP); // true for file player
1084
1075
  - **Mobile**: iOS Safari 12+, Chrome Mobile 60+
1085
1076
  - **Smart TV**: LG WebOS (v2+), Samsung Tizen (v2+), Sony BRAVIA, Android TV, Roku, Apple TV, generic Smart TV user-agents
1086
1077
 
1087
- ### Automatic Browser Detection & Ad Player Selection
1078
+ ### Automatic Browser Detection & Smart TV Overrides
1088
1079
 
1089
- The player automatically detects the runtime environment and chooses the optimal ad-player configuration. This is especially useful for Smart TVs where the Google IMA SDK may not be available on older devices.
1080
+ The player detects the runtime environment and applies Smart TV-friendly defaults via `getBrowserConfigOverrides()`.
1090
1081
 
1091
1082
  ```javascript
1092
1083
  import {
1093
1084
  detectBrowser,
1094
- supportsGoogleIMA,
1095
- getRecommendedAdPlayer,
1096
1085
  supportsModernJS,
1097
1086
  logBrowserInfo,
1098
1087
  getBrowserConfigOverrides,
@@ -1106,25 +1095,22 @@ const info = detectBrowser();
1106
1095
  // majorVersion: 5,
1107
1096
  // isSmartTV: true,
1108
1097
  // isLegacyTV: false,
1109
- // supportsIMA: true,
1110
1098
  // supportsModernJS: true,
1111
- // recommendedAdPlayer: 'ima',
1112
1099
  // webOSVersion: 5,
1113
1100
  // chromeVersion: 79,
1114
1101
  // ...
1115
1102
  // }
1116
1103
 
1117
- console.log(supportsGoogleIMA()); // true | false
1118
- console.log(getRecommendedAdPlayer()); // 'ima' | 'hls'
1104
+ console.log(supportsModernJS()); // true | false
1119
1105
  console.log(supportsFeature('fetch')); // true | false
1106
+ console.log(getBrowserConfigOverrides()); // e.g. { allowNativeHls: true } on Smart TVs
1120
1107
  ```
1121
1108
 
1122
1109
  **What happens automatically:**
1123
1110
 
1124
- - **Legacy Smart TVs** (LG NetCast, old WebOS < 3, old Tizen): `adPlayerType` is forced to `'hls'` and `allowNativeHls` is enabled.
1125
- - **Modern Smart TVs**: `allowNativeHls` is enabled by default (TVs generally play HLS better natively).
1126
- - **If IMA SDK is unsupported**: the player falls back to the HLS ad player automatically.
1111
+ - **Smart TVs** (LG WebOS, Samsung Tizen, etc.): `allowNativeHls` is enabled by default (TVs generally play HLS better natively).
1127
1112
  - **Browser overrides** are merged with your config — user-provided options always take precedence.
1113
+ - **Ads**: HLS ad player on all supported devices.
1128
1114
 
1129
1115
  Call `logBrowserInfo(true)` (or enable `debugAdTiming`) to print a detailed compatibility report to the console.
1130
1116
 
@@ -1198,8 +1184,8 @@ src/
1198
1184
  ├── ui/
1199
1185
  │ └── StormcloudVideoPlayer.tsx # Legacy React component
1200
1186
  ├── sdk/
1201
- │ ├── ima.ts # Google IMA integration
1202
- │ └── hlsAdPlayer.ts # Native HLS ad player (AdStorm mode, legacy TVs)
1187
+ │ ├── pal.ts # Google PAL nonce manager
1188
+ │ └── hlsAdPlayer.ts # HLS / progressive VAST ad player
1203
1189
  ├── utils/
1204
1190
  │ ├── tracking.ts # Analytics and ad tracking
1205
1191
  │ ├── browserCompat.ts # Browser / Smart TV detection & auto-overrides
@@ -1321,19 +1307,18 @@ Built with ❤️ by the Stormcloud team
1321
1307
 
1322
1308
  ### What's New in v0.5
1323
1309
 
1324
- - 🗓️ **VMAP 1.0 Support**: New `vmapUrl` config/prop loads a VMAP manifest and schedules pre-roll, mid-roll, percentage-based, and post-roll breaks automatically
1310
+ - 🗓️ **VMAP 1.0 Support**: `isVmap` + `vmapUrl` load a VMAP manifest and schedule pre-roll, mid-roll, percentage-based, and post-roll breaks automatically
1325
1311
  - Supports `start`, `end`, `HH:MM:SS[.mmm]`, and `NN%` `timeOffset` values
1326
1312
  - Namespaced (`vmap:AdBreak`) and non-namespaced manifests both supported
1327
1313
  - Breaks are consumed-once-per-session and integrate with the existing late-join policy
1328
1314
  - 📺 **Smart TV First-Class Support**: New browser-compat layer auto-detects LG WebOS, Samsung Tizen, Sony BRAVIA, LG NetCast and generic Smart TV UAs
1329
- - Exports `detectBrowser`, `supportsGoogleIMA`, `getRecommendedAdPlayer`, `supportsModernJS`, `logBrowserInfo`, `getBrowserConfigOverrides`, `supportsFeature`
1330
- - Automatically forces HLS ad player on legacy TVs where IMA SDK is not available
1315
+ - Exports `detectBrowser`, `supportsModernJS`, `logBrowserInfo`, `getBrowserConfigOverrides`, `supportsFeature`
1331
1316
  - Automatically enables `allowNativeHls` on Smart TVs for more reliable playback
1332
1317
  - 🧩 **Automatic Polyfills**: `initializePolyfills()` runs at construction time and backfills `URLSearchParams`, `TextEncoder`, `Promise.prototype.finally`, `Object.assign`, `Array.from`, and `String.prototype.startsWith/endsWith/includes` for legacy environments
1333
- - 📊 **Expanded Ad Tracking**: New `sendAdDetectTracking`, `sendAdLoadedTracking`, and `sendAdImpressionTracking` helpers (plus `AdDetectInfo`, `AdLoadedInfo`, `AdImpressionInfo`, and `AdTrackingSource` types) for prebid/IMA/HLS ad lifecycle events
1318
+ - 📊 **Expanded Ad Tracking**: New `sendAdDetectTracking`, `sendAdLoadedTracking`, and `sendAdImpressionTracking` helpers (plus `AdDetectInfo`, `AdLoadedInfo`, `AdImpressionInfo` types) for SCTE-35 and HLS ad lifecycle events
1334
1319
  - ⚙️ **Ad-Break Timing Controls**: New `adBreakCheckIntervalMs` (default 1000ms, min 250ms) and `maxAdBreakExtensionMs` (default 60000ms) options give you precise control over how long the player is allowed to extend an ad break past its SCTE-35 duration when ads are still playing or queued
1335
1320
  - 🙈 **Hide Loading Indicator**: New `hideLoadingIndicator` prop/config hides the built-in buffering spinner when you want to render your own overlay
1336
- - 🔌 **Expanded Public API**: `createImaController`, `createHlsAdPlayer`, and `initializePolyfills` are now exported alongside the new browser-compat utilities, making it easier to build custom integrations on top of the player core
1321
+ - 🔌 **Expanded Public API**: `createHlsAdPlayer`, `createPalNonceManager`, and `initializePolyfills` are exported alongside browser-compat utilities for custom integrations
1337
1322
 
1338
1323
  ### What's New in v0.4
1339
1324
 
@@ -1358,17 +1343,16 @@ Built with ❤️ by the Stormcloud team
1358
1343
 
1359
1344
  ### What's New in v0.3
1360
1345
 
1361
- - 🎬 **Custom HLS Ad Player**: Native HLS ad playback with custom VAST service
1362
- - 🎯 **Flexible Ad Integration**: Choose between custom HLS or Google IMA SDK
1346
+ - 🎬 **Custom HLS Ad Player**: Native HLS ad playback with VAST XML parsing
1347
+ - 🎯 **VAST Tag Resolution**: `vastMode` selects AdStorm `/vast/{licenseKey}` vs `/ads/web` or custom `vastTagUrl`
1363
1348
  - 📊 **Direct Analytics**: Full control over ad tracking and metrics
1364
1349
  - ⚡ **Better Performance**: Native HLS playback for ads (same format as content)
1365
1350
  - 🔧 **Custom VAST URLs**: Point to your own ad serving backend
1366
- - 🔄 **Backward Compatible**: Existing Google IMA integration still works
1367
- - 📦 **Zero Dependencies**: No external ad SDKs required (when using HLS ad player)
1368
- - 🎨 **Seamless Playback**: Same player for content and ads
1369
- - 🔀 **VAST Mode System**: `vastMode` property automatically configures endpoints and ad players
1370
- - `vastMode: 'adstorm'` → Uses `/vast/{licenseKey}` endpoint with HLS ad player
1371
- - `vastMode: 'default'` → Uses `/ads/web` endpoint with Google IMA SDK
1351
+ - 📦 **Zero external ad SDK dependencies**
1352
+ - 🎨 **Seamless Playback**: Same player stack for content and ads
1353
+ - 🔀 **VAST Mode System**: `vastMode` configures which endpoint supplies the VAST tag URL
1354
+ - `vastMode: 'adstorm'` `/vast/{licenseKey}` endpoint
1355
+ - `vastMode: 'default'` → `/ads/web` endpoint or `vastTagUrl` (both resolve to HLS ad player playback)
1372
1356
  - ⚠️ **Improved Error Handling**: Distinguishes between parsing errors and "no ads available" scenarios
1373
1357
  - Logs warnings for "no ads available" (graceful handling)
1374
1358
  - Logs errors for actual parsing/fetch failures