stormcloud-video-player 0.4.0 → 0.5.0

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 (43) hide show
  1. package/README.md +245 -156
  2. package/dist/stormcloud-vp.min.js +1 -1
  3. package/lib/index.cjs +9759 -5311
  4. package/lib/index.cjs.map +1 -1
  5. package/lib/index.d.cts +193 -17
  6. package/lib/index.d.ts +193 -17
  7. package/lib/index.js +9761 -5329
  8. package/lib/index.js.map +1 -1
  9. package/lib/player/StormcloudVideoPlayer.cjs +7090 -1508
  10. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  11. package/lib/player/StormcloudVideoPlayer.d.cts +95 -9
  12. package/lib/players/HlsPlayer.cjs +7107 -1525
  13. package/lib/players/HlsPlayer.cjs.map +1 -1
  14. package/lib/players/HlsPlayer.d.cts +1 -1
  15. package/lib/players/index.cjs +7098 -1516
  16. package/lib/players/index.cjs.map +1 -1
  17. package/lib/sdk/hlsAdPlayer.cjs +302 -266
  18. package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
  19. package/lib/sdk/hlsAdPlayer.d.cts +2 -2
  20. package/lib/sdk/ima.cjs +1375 -0
  21. package/lib/sdk/ima.cjs.map +1 -0
  22. package/lib/sdk/ima.d.cts +12 -0
  23. package/lib/sdk/prebid.cjs +564 -0
  24. package/lib/sdk/prebid.cjs.map +1 -0
  25. package/lib/sdk/prebid.d.cts +5 -0
  26. package/lib/sdk/prebidController.cjs +1560 -0
  27. package/lib/sdk/prebidController.cjs.map +1 -0
  28. package/lib/sdk/prebidController.d.cts +11 -0
  29. package/lib/sdk/vastParser.cjs +393 -0
  30. package/lib/sdk/vastParser.cjs.map +1 -0
  31. package/lib/sdk/vastParser.d.cts +45 -0
  32. package/lib/{types-Ca4ZDaWw.d.cts → types-g2d4Akez.d.cts} +72 -3
  33. package/lib/ui/StormcloudVideoPlayer.cjs +7130 -1530
  34. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  35. package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
  36. package/lib/utils/browserCompat.cjs +222 -20
  37. package/lib/utils/browserCompat.cjs.map +1 -1
  38. package/lib/utils/browserCompat.d.cts +9 -1
  39. package/lib/utils/tracking.d.cts +1 -1
  40. package/package.json +2 -1
  41. package/lib/sdk/adstormPlayer.cjs +0 -908
  42. package/lib/sdk/adstormPlayer.cjs.map +0 -1
  43. package/lib/sdk/adstormPlayer.d.cts +0 -9
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, custom VAST ad serving, and optional Google IMA SDK integration for seamless ad playback. Now featuring a modern, extensible architecture inspired by react-player with comprehensive Smart TV support.
3
+ A professional video player with advanced ad integration for web applications. Built with precision ad break alignment, SCTE-35 signal parsing, custom VAST ad serving, and optional Google IMA SDK integration for seamless ad playback. Now featuring a modern, extensible architecture inspired by react-player.
4
4
 
5
5
  ## 🎯 Key Features
6
6
 
@@ -11,11 +11,9 @@ A professional video player with advanced ad integration for web applications. B
11
11
  - **Enhanced UI Controls**: Beautiful, adaptive video controls that work on any background color
12
12
  - **Live Mode Support**: Specialized controls for live streaming with volume adjustment
13
13
  - **Cross-Platform**: Works on desktop, mobile, tablets, and smart TVs
14
- - **Smart TV Optimized**: Native support for LG WebOS, Samsung Tizen, Sony BRAVIA, and other CTV platforms
15
14
  - **React Ready**: Multiple React components for different use cases
16
15
  - **TypeScript Support**: Full type definitions included
17
16
  - **Professional Architecture**: Modular player system with lazy loading
18
- - **Built-in Polyfills**: Automatic compatibility for older browsers and legacy TV platforms
19
17
 
20
18
  ## 🚀 Quick Start
21
19
 
@@ -43,6 +41,7 @@ function MyVideoApp() {
43
41
  showCustomControls={true} // Enable enhanced UI controls
44
42
  allowNativeHls={true} // Allow native HLS for better performance
45
43
  licenseKey="your_license_key_here"
44
+ vastMode="adstorm" // Use AdStorm mode with HLS ad player
46
45
  style={{ width: "100%", aspectRatio: "16/9" }}
47
46
  wrapperStyle={{ borderRadius: "12px", overflow: "hidden" }}
48
47
  onReady={(player) => {
@@ -79,6 +78,7 @@ function MyVideoApp() {
79
78
  allowNativeHls={true}
80
79
  showCustomControls={true}
81
80
  licenseKey="your_license_key_here"
81
+ vastMode="adstorm" // Use AdStorm mode (or omit for default mode)
82
82
  onReady={(player) => {
83
83
  console.log("Player is ready!", player);
84
84
  }}
@@ -264,11 +264,15 @@ interface StormcloudPlayerProps {
264
264
  immediateManifestAds?: boolean;
265
265
  debugAdTiming?: boolean;
266
266
  showCustomControls?: boolean;
267
- hideLoadingIndicator?: boolean; // Hide the loading spinner/indicator
268
267
  licenseKey?: string;
269
268
  adFailsafeTimeoutMs?: number;
270
269
  minSegmentsBeforePlay?: number; // Number of segments to buffer before starting playback (default: 2)
271
270
 
271
+ // Ad player configuration
272
+ vastMode?: 'adstorm' | 'default'; // VAST mode: 'adstorm' (HLS player + AdStorm VAST endpoint) or 'default' (IMA SDK + /ads/web endpoint) (default: 'default')
273
+ vastTagUrl?: string; // Custom VAST URL (used in default mode if provided; when not provided, uses /ads/web endpoint)
274
+ adPlayerType?: 'ima' | 'hls'; // Manual override for ad player type (auto-determined by vastMode if not specified)
275
+
272
276
  // Event handlers
273
277
  onReady?: (player: StormcloudVideoPlayer) => void;
274
278
  onStart?: () => void;
@@ -343,16 +347,18 @@ interface StormcloudVideoPlayerConfig {
343
347
  muted?: boolean; // Start muted (default: false)
344
348
  allowNativeHls?: boolean; // Use native HLS when available (default: false)
345
349
  showCustomControls?: boolean; // Enable enhanced UI controls (default: false)
346
- hideLoadingIndicator?: boolean; // Hide the loading spinner/indicator (default: false)
347
350
  lowLatencyMode?: boolean; // Enable low-latency mode for live streams (default: false)
348
351
  driftToleranceMs?: number; // Drift tolerance for live streams (default: 1000)
349
352
  immediateManifestAds?: boolean; // Load ads immediately from manifest (default: true)
350
- minSegmentsBeforePlay?: number; // Number of segments to buffer before starting playback (default: 2)
351
353
  licenseKey?: string; // API authentication key
352
354
  debugAdTiming?: boolean; // Enable debug logging (default: false)
353
355
  adFailsafeTimeoutMs?: number; // Ad timeout in milliseconds (default: 10000)
354
- adBreakCheckIntervalMs?: number; // Interval for checking ad breaks (default: 1000)
355
- maxAdBreakExtensionMs?: number; // Maximum ad break extension time (default: 5000)
356
+ minSegmentsBeforePlay?: number; // Number of segments to buffer before starting playback (default: 2)
357
+
358
+ // Ad configuration
359
+ vastMode?: 'adstorm' | 'default'; // VAST mode: 'adstorm' (uses HLS player + AdStorm VAST endpoint) or 'default' (uses Google IMA SDK + /ads/web endpoint) (default: 'default')
360
+ vastTagUrl?: string; // Custom VAST tag URL (used in default mode if provided; when not provided, defaults to /ads/web endpoint)
361
+ adPlayerType?: 'ima' | 'hls'; // Manual override for ad player type (auto-determined by vastMode if not specified)
356
362
 
357
363
  onVolumeToggle?: () => void; // Callback for volume toggle
358
364
  onFullscreenToggle?: () => void; // Callback for fullscreen toggle
@@ -413,69 +419,89 @@ All controls use a consistent high-contrast design:
413
419
 
414
420
  ## 🎬 Ad Integration (HLS Streams Only)
415
421
 
416
- ### Ad Player Configuration
422
+ ### VAST Mode Configuration
417
423
 
418
- The player uses AdStorm backend with native ad player for optimal performance:
424
+ The player supports two VAST modes that automatically configure the appropriate ad player:
425
+
426
+ #### 1. **AdStorm Mode** (Recommended)
427
+
428
+ Uses AdStorm backend with HLS ad player for optimal performance:
419
429
 
420
430
  ```javascript
421
431
  const player = new StormcloudVideoPlayer({
422
432
  videoElement: video,
423
433
  src: "https://your-stream.com/playlist.m3u8",
424
434
  licenseKey: "your-license-key",
435
+
436
+ // AdStorm mode - uses HLS ad player automatically
437
+ vastMode: 'adstorm',
438
+
425
439
  debugAdTiming: true,
426
440
  });
427
441
  ```
428
442
 
429
443
  **What happens:**
430
- - 🎯 Automatically uses native ad player with MP4/WebM/HLS support
431
- - 🔗 VAST Pod endpoint: `GET https://adstorm.co/api-adstorm-dev/adstorm/vast/{licenseKey}/pod`
432
- - Query parameters:
433
- - `duration` - Target ad break duration in seconds
434
- - `metadata` - JSON-encoded video/audio metadata for quality matching
444
+ - 🎯 Automatically uses HLS ad player (`adPlayerType: 'hls'`)
445
+ - 🔗 VAST endpoint: `GET https://adstorm.co/api-adstorm-dev/adstorm/vast/{licenseKey}`
435
446
  - License key is passed in the URL path (no authorization header needed)
436
- - Returns VAST XML with multiple ads to fill the duration (ad pod)
447
+ - Returns VAST XML directly with HLS media files
437
448
  - 📊 Direct tracking and analytics through AdStorm backend
438
449
  - ⚠️ Gracefully handles "no ads available" scenarios (logs warnings, not errors)
439
450
 
440
- **Pod Ad API Request:**
441
- ```
442
- GET /vast/{licenseKey}/pod?duration=60&metadata={"video":{"codec":"h264","width":1920,"height":1080},"audio":{"codec":"aac"}}
443
- ```
444
-
445
- **Metadata Structure:**
446
- ```typescript
447
- interface AdStormMetadata {
448
- video?: {
449
- codec?: string; // e.g., "h264"
450
- width?: number; // e.g., 1920
451
- height?: number; // e.g., 1080
452
- fps?: number; // e.g., 29.97
453
- bitrate?: number; // e.g., 5000 (kbps)
454
- profile?: string; // e.g., "high"
455
- };
456
- audio?: {
457
- codec?: string; // e.g., "aac"
458
- sample_rate?: number; // e.g., 48000
459
- bitrate?: number; // e.g., 128 (kbps)
460
- };
461
- }
462
- ```
463
-
464
451
  **API Flow:**
465
- 1. Player detects SCTE-35 marker with ad break duration
466
- 2. Calls `/vast/{licenseKey}/pod?duration={seconds}&metadata={...}` endpoint
467
- 3. Backend returns VAST XML with ad pod (multiple ads matching requested duration)
468
- 4. Native ad player loads and plays ads with quality matching content stream
452
+ 1. Player calls `/vast/{licenseKey}` endpoint
453
+ 2. Backend returns VAST XML with HLS media files
454
+ 3. Player parses VAST XML and extracts MediaFile URLs
455
+ 4. HLS ad player loads and plays the ad segments
469
456
 
470
457
  **Benefits:**
471
458
  - ✅ Zero external dependencies (no Google IMA SDK)
472
459
  - ✅ Full control over ad serving
473
- - ✅ Multi-format support (MP4, WebM, HLS)
474
- - ✅ Automatic quality matching to content stream
460
+ - ✅ Native HLS playback (same format as content)
475
461
  - ✅ Better performance and reliability
476
462
  - ✅ Custom targeting and selection
477
463
  - ✅ Proper error handling (distinguishes parsing errors from "no ads available")
478
- - ✅ Ad pod support (multiple ads per break)
464
+
465
+ #### 2. **Default Mode**
466
+
467
+ Uses Google IMA SDK for traditional ad serving:
468
+
469
+ ```javascript
470
+ const player = new StormcloudVideoPlayer({
471
+ videoElement: video,
472
+ src: "https://your-stream.com/playlist.m3u8",
473
+ licenseKey: "your-license-key",
474
+
475
+ // Default mode - uses Google IMA SDK automatically
476
+ vastMode: 'default', // or omit this property entirely
477
+ vastTagUrl: 'https://your-vast-server.com/vast.xml', // optional
478
+
479
+ debugAdTiming: true,
480
+ });
481
+ ```
482
+
483
+ **What happens:**
484
+ - 🎯 Automatically uses Google IMA SDK (`adPlayerType: 'ima'`)
485
+ - 🔗 VAST endpoint resolution:
486
+ 1. If `vastTagUrl` is provided, uses that URL directly
487
+ 2. Otherwise, calls `GET https://adstorm.co/api-adstorm-dev/adstorm/ads/web`
488
+ - Requires `Authorization: Bearer {licenseKey}` header
489
+ - Returns JSON response with IMA payload: `{ response: { ima: { "publisherdesk.ima": { payload: "VAST_URL" } } } }`
490
+ - Extracts VAST tag URL from the `payload` field
491
+ - 📊 Standard VAST/VPAID ad serving through Google IMA SDK
492
+
493
+ **API Flow:**
494
+ 1. Player calls `/ads/web` endpoint with Bearer token (if no `vastTagUrl` provided)
495
+ 2. Backend returns JSON with IMA configuration
496
+ 3. Player extracts VAST tag URL from `response.ima["publisherdesk.ima"].payload`
497
+ 4. Google IMA SDK loads and plays the VAST ad
498
+
499
+ **Benefits:**
500
+ - ✅ Industry-standard ad serving
501
+ - ✅ Wide format support (VAST, VPAID)
502
+ - ✅ Established ecosystem
503
+ - ✅ Backward compatible with existing VAST tags
504
+ - ✅ Supports both custom VAST URLs and AdStorm backend
479
505
 
480
506
  ### Ad Pod Generation (Multiple Consecutive Ads)
481
507
 
@@ -536,6 +562,8 @@ const player = new StormcloudVideoPlayer({
536
562
  videoElement: video,
537
563
  src: "https://your-live-stream.com/playlist.m3u8",
538
564
  licenseKey: "your-license-key",
565
+
566
+ vastMode: 'default',
539
567
  debugAdTiming: true, // Enable to see adaptive calculations
540
568
  });
541
569
  ```
@@ -593,6 +621,27 @@ Final: 3 ads played (perfectly fills 120 seconds)
593
621
  - ✅ **Smart**: Improves calculation as more data is gathered (uses average of fetched durations)
594
622
  - ✅ **Self-Correcting**: Automatically adjusts if actual ad lengths differ from expectations
595
623
 
624
+ ### Manual Ad Player Override
625
+
626
+ You can still manually override the ad player type if needed:
627
+
628
+ ```javascript
629
+ const player = new StormcloudVideoPlayer({
630
+ videoElement: video,
631
+ src: "https://your-stream.com/playlist.m3u8",
632
+
633
+ vastMode: 'default',
634
+ adPlayerType: 'hls', // Manual override to use HLS player with default mode
635
+ vastTagUrl: 'https://your-backend.com/vast', // Will use this URL directly
636
+
637
+ debugAdTiming: true,
638
+ });
639
+ ```
640
+
641
+ **Note:** When `adPlayerType` is manually set, the `vastMode` property still determines which backend endpoint is called:
642
+ - `vastMode: 'adstorm'` → Always calls `/vast/{licenseKey}` endpoint
643
+ - `vastMode: 'default'` → Calls `/ads/web` endpoint (unless `vastTagUrl` is provided)
644
+
596
645
  ### SCTE-35 Support
597
646
 
598
647
  The HlsPlayer automatically detects and responds to SCTE-35 signals embedded in HLS streams:
@@ -610,6 +659,85 @@ The HlsPlayer automatically detects and responds to SCTE-35 signals embedded in
610
659
  - `#EXT-X-DATERANGE`
611
660
  - ID3 timed metadata
612
661
 
662
+ ### Early Ad Prefetching & Preload Pool
663
+
664
+ The player includes an advanced ad prefetching system that dramatically reduces ad start latency:
665
+
666
+ #### Early SCTE-35 Detection
667
+
668
+ The player scans up to 5 manifest fragments ahead of current playback to detect upcoming SCTE-35 ad markers. When an ad break is detected early:
669
+
670
+ 1. **Prefetching Begins**: The player immediately starts generating VAST URLs and prefetching ads
671
+ 2. **Preload Pool**: Up to 3 ads are preloaded and ready to play instantly
672
+ 3. **Zero-Delay Starts**: When the ad break actually begins, ads start immediately (no request delay)
673
+
674
+ **Benefits:**
675
+ - ⚡ **80% reduction** in ad start latency
676
+ - 🎯 **Instant ad playback** when breaks begin
677
+ - 📊 **Better fill rates** through proactive ad preparation
678
+ - 🔄 **Seamless transitions** between content and ads
679
+
680
+ #### How It Works
681
+
682
+ ```javascript
683
+ const player = new StormcloudVideoPlayer({
684
+ videoElement: video,
685
+ src: "https://your-stream.com/playlist.m3u8",
686
+ licenseKey: "your-license-key",
687
+ debugAdTiming: true, // Enable to see prefetching logs
688
+ });
689
+
690
+ // The player automatically:
691
+ // 1. Scans manifest fragments for SCTE-35 markers
692
+ // 2. Detects upcoming ad breaks before playback reaches them
693
+ // 3. Prefetches and preloads ads into a pool
694
+ // 4. Starts ads instantly when breaks begin
695
+ ```
696
+
697
+ **Debug Output Example:**
698
+ ```
699
+ [PREFETCH] 🔄 Starting ad prefetch for upcoming ad break
700
+ [PREFETCH] 📋 Pre-generated 5 VAST URLs
701
+ [PRELOAD-POOL] 🏊 Starting preload pool EARLY (target size: 3)
702
+ [PRELOAD-POOL] 📥 Preloading ad into pool: https://...
703
+ [PRELOAD-POOL] ✅ Ad preloaded (pool size: 1/3)
704
+ [CONTINUOUS-FETCH] 🚀 Using preloaded ad from pool (preloaded in advance, ready immediately!)
705
+ ```
706
+
707
+ #### Continuous Ad Fetching
708
+
709
+ During ad breaks, the player continuously fetches additional ads to fill the entire SCTE-35 duration:
710
+
711
+ - **Dynamic Queue**: Maintains a queue of ready-to-play VAST URLs
712
+ - **Smart Rate Limiting**: 2.5s minimum interval between requests with exponential backoff
713
+ - **Automatic Filling**: Fetches ads until the SCTE-35 duration is fully filled
714
+ - **Error Recovery**: Distinguishes temporary failures (no-fill) from permanent failures
715
+
716
+ **Rate Limiting & Backoff:**
717
+ - Base interval: 2.5 seconds between requests
718
+ - Exponential backoff: Increases with consecutive failures
719
+ - Max backoff: 15 seconds
720
+ - Cooldown period: 30 seconds for temporary failures (no-fill)
721
+
722
+ #### Error Handling & Recovery
723
+
724
+ The player intelligently handles different types of ad failures:
725
+
726
+ **Temporary Failures (Retryable):**
727
+ - No-fill responses (no ads available)
728
+ - Network timeouts
729
+ - Rate limiting errors
730
+ - **Action**: URL enters 30s cooldown, then can be retried
731
+
732
+ **Permanent Failures (Blacklisted):**
733
+ - VAST parsing errors
734
+ - Malformed responses
735
+ - **Action**: URL is permanently blacklisted for the current ad break
736
+
737
+ **Fallback System:**
738
+ - If a primary ad request fails, the player automatically tries a preloaded ad from the pool
739
+ - Ensures continuous ad playback even when individual requests fail
740
+
613
741
  ### Late Join Behavior
614
742
 
615
743
  When viewers join during an ad break:
@@ -630,29 +758,6 @@ When viewers join during an ad break:
630
758
  />
631
759
  ```
632
760
 
633
- ### VAST Tracking Events
634
-
635
- The native ad player automatically fires VAST tracking pixels for the following events:
636
-
637
- | Event | When Fired |
638
- |-------|------------|
639
- | `impression` | When ad is loaded and ready to play |
640
- | `start` | When ad begins playing |
641
- | `firstQuartile` | When 25% of ad has played |
642
- | `midpoint` | When 50% of ad has played |
643
- | `thirdQuartile` | When 75% of ad has played |
644
- | `complete` | When ad finishes playing |
645
- | `mute` | When ad is muted |
646
- | `unmute` | When ad is unmuted |
647
- | `pause` | When ad is paused |
648
- | `resume` | When ad resumes after pause |
649
- | `fullscreen` | When entering fullscreen |
650
- | `exitFullscreen` | When exiting fullscreen |
651
- | `skip` | When ad is skipped |
652
- | `error` | When an error occurs |
653
-
654
- Tracking pixels include session ID and license key for analytics correlation.
655
-
656
761
  ### Error Handling
657
762
 
658
763
  The player distinguishes between different types of ad-related issues:
@@ -680,7 +785,7 @@ Example with error handling:
680
785
  ```javascript
681
786
  const player = new StormcloudVideoPlayer({
682
787
  // ... config
683
- licenseKey: "your-license-key",
788
+ vastMode: 'adstorm',
684
789
  debugAdTiming: true, // Enable detailed logging
685
790
  });
686
791
 
@@ -704,11 +809,14 @@ const player = new StormcloudVideoPlayer({
704
809
 
705
810
  Authenticated requests are sent to:
706
811
 
707
- - **VAST Pod endpoint**: `GET https://adstorm.co/api-adstorm-dev/adstorm/vast/{licenseKey}/pod` (license key in URL path)
708
- - Query parameters: `duration`, `metadata`
709
- - Returns VAST XML with ad pod for requested duration
812
+ - **AdStorm Mode** (`vastMode: 'adstorm'`):
813
+ - VAST endpoint: `GET https://adstorm.co/api-adstorm-dev/adstorm/vast/{licenseKey}` (license key in URL path)
814
+
815
+ - **Default Mode** (`vastMode: 'default'`):
816
+ - Ad configuration: `GET https://adstorm.co/api-adstorm-dev/adstorm/ads/web` (requires `Authorization: Bearer {licenseKey}` header)
817
+ - Returns JSON with IMA payload containing VAST tag URL
710
818
 
711
- - **Player Tracking**:
819
+ - **Player Tracking** (both modes):
712
820
  - Player tracking: `POST https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/track` (requires `Authorization: Bearer {licenseKey}` header)
713
821
  - Heartbeat monitoring: `POST https://adstorm.co/api-adstorm-dev/adstorm/player-tracking/heartbeat` (requires `Authorization: Bearer {licenseKey}` header)
714
822
 
@@ -747,6 +855,39 @@ StormcloudPlayer.addCustomPlayer({
747
855
  });
748
856
  ```
749
857
 
858
+ ### Buffering Configuration
859
+
860
+ #### Min Segments Before Play
861
+
862
+ Control how many segments must be buffered before playback starts. This helps ensure smooth playback, especially on slower connections:
863
+
864
+ ```javascript
865
+ const player = new StormcloudVideoPlayer({
866
+ videoElement: video,
867
+ src: "https://your-stream.com/playlist.m3u8",
868
+ autoplay: true,
869
+ minSegmentsBeforePlay: 3, // Wait for 3 segments before starting (default: 2)
870
+ });
871
+
872
+ // Or with React component
873
+ <StormcloudPlayer
874
+ src="https://your-stream.com/playlist.m3u8"
875
+ playing={true}
876
+ minSegmentsBeforePlay={3}
877
+ />
878
+ ```
879
+
880
+ **Configuration Options:**
881
+ - `minSegmentsBeforePlay: 0` - Start immediately (may cause stuttering on slow connections)
882
+ - `minSegmentsBeforePlay: 2` - Default, good balance for most use cases
883
+ - `minSegmentsBeforePlay: 3-5` - Recommended for slower connections or higher quality streams
884
+ - `minSegmentsBeforePlay: undefined` - Uses default value (2)
885
+
886
+ **When to Adjust:**
887
+ - **Increase** for high-bitrate streams or unreliable networks
888
+ - **Decrease** for low-latency requirements or fast connections
889
+ - **Set to 0** only if you need immediate playback and can tolerate potential stuttering
890
+
750
891
  ### Player Detection
751
892
 
752
893
  ```javascript
@@ -790,70 +931,7 @@ console.log("Supports PIP:", canPIP); // true for file player
790
931
 
791
932
  - **Desktop**: Chrome 60+, Firefox 55+, Safari 12+, Edge 79+
792
933
  - **Mobile**: iOS Safari 12+, Chrome Mobile 60+
793
- - **Smart TV**: LG WebOS, Samsung Tizen, Sony BRAVIA, Android TV, Roku, Apple TV, Fire TV
794
-
795
- ### Smart TV & CTV Platform Support
796
-
797
- The player includes comprehensive Smart TV detection and automatic configuration:
798
-
799
- #### Supported Platforms
800
-
801
- | Platform | Detection | Auto-Config | Notes |
802
- |----------|-----------|-------------|-------|
803
- | LG WebOS | ✅ | ✅ | Auto-enables native HLS |
804
- | Samsung Tizen | ✅ | ✅ | Auto-enables native HLS |
805
- | Sony BRAVIA | ✅ | ✅ | Auto-enables native HLS |
806
- | LG NetCast | ✅ | ✅ | Legacy mode enabled |
807
- | Android TV | ✅ | ✅ | Standard HLS.js mode |
808
- | Roku | ✅ | ✅ | Native HLS recommended |
809
- | Apple TV | ✅ | ✅ | Native HLS |
810
- | Fire TV | ✅ | ✅ | Standard HLS.js mode |
811
-
812
- #### Automatic Configuration
813
-
814
- When a Smart TV is detected, the player automatically:
815
-
816
- 1. **Enables native HLS** for better performance on TV browsers
817
- 2. **Applies legacy compatibility** for older TV platforms
818
- 3. **Logs browser info** when debug mode is enabled
819
-
820
- ```javascript
821
- // Browser info logged in debug mode
822
- {
823
- browser: "Samsung Tizen 6.0",
824
- platform: "Linux",
825
- isSmartTV: true,
826
- isLegacyTV: false,
827
- supportsModernJS: true,
828
- userAgent: "..."
829
- }
830
- ```
831
-
832
- #### Manual Override
833
-
834
- You can override automatic detection if needed:
835
-
836
- ```javascript
837
- const player = new StormcloudVideoPlayer({
838
- videoElement: video,
839
- src: "https://stream.example.com/playlist.m3u8",
840
- allowNativeHls: false, // Force HLS.js even on Smart TVs
841
- debugAdTiming: true, // Log browser detection info
842
- });
843
- ```
844
-
845
- ### Built-in Polyfills
846
-
847
- The player automatically loads polyfills for older browsers and legacy TV platforms:
848
-
849
- - **URLSearchParams** - For query string parsing
850
- - **TextEncoder** - For UTF-8 encoding
851
- - **Promise.finally** - For promise cleanup
852
- - **Object.assign** - For object merging
853
- - **Array.from** - For array-like iteration
854
- - **String.startsWith/endsWith/includes** - For string operations
855
-
856
- These polyfills are only loaded when needed and have minimal impact on modern browsers.
934
+ - **Smart TV**: WebOS, Tizen, Android TV, Roku, Apple TV
857
935
 
858
936
  ### Format Support by Player
859
937
 
@@ -906,12 +984,9 @@ src/
906
984
  ├── ui/
907
985
  │ └── StormcloudVideoPlayer.tsx # Legacy React component
908
986
  ├── sdk/
909
- ├── adstormPlayer.ts # Native ad player (MP4/WebM/HLS)
910
- │ └── hlsAdPlayer.ts # HLS-specific ad player
987
+ └── ima.ts # Google IMA integration
911
988
  ├── utils/
912
989
  │ ├── tracking.ts # Analytics and tracking
913
- │ ├── browserCompat.ts # Smart TV & browser detection
914
- │ ├── polyfills.ts # Legacy browser polyfills
915
990
  │ └── index.ts # Utility functions
916
991
  ├── props.ts # Centralized props system
917
992
  ├── patterns.ts # URL pattern matching
@@ -1027,26 +1102,40 @@ MIT License - see [LICENSE](LICENSE) file for details.
1027
1102
 
1028
1103
  Built with ❤️ by the Stormcloud team
1029
1104
 
1030
- ### What's New in v0.3.17
1031
-
1032
- - 📺 **Smart TV Support**: Comprehensive detection for LG WebOS, Samsung Tizen, Sony BRAVIA, and more
1033
- - 🔧 **Automatic Configuration**: Smart TVs automatically use native HLS for better performance
1034
- - 🛡️ **Built-in Polyfills**: URLSearchParams, TextEncoder, Promise.finally, and more for legacy platforms
1035
- - 📊 **Browser Detection API**: Detailed browser info logging in debug mode
1036
- - **Buffering Control**: New `minSegmentsBeforePlay` option to control initial buffering (default: 2 segments)
1037
- - 🎛️ **UI Enhancements**: New `hideLoadingIndicator` option to hide loading spinners
1038
- - 🎬 **Native Ad Player**: Multi-format ad playback (MP4, WebM, HLS) with quality matching
1039
- - 📦 **Pod Ad API**: New `/vast/{licenseKey}/pod` endpoint for ad pod generation with metadata
1040
- - 🎯 **Quality Matching**: Automatic ad quality selection based on content stream parameters
1105
+ ### What's New in v0.4
1106
+
1107
+ - 🚀 **Early Ad Prefetching**: Detects SCTE-35 markers in manifest fragments before playback reaches them, prefetching ads in advance for zero-delay ad starts
1108
+ - 🏊 **Ad Preload Pool**: Maintains a pool of preloaded, ready-to-play ads (up to 3 by default) for instant ad playback when breaks start
1109
+ - 🔄 **Continuous Ad Fetching**: Dynamically fetches additional ads during ad breaks to perfectly fill SCTE-35 durations, ensuring no wasted ad time
1110
+ - ⏱️ **Smart Rate Limiting**: Intelligent rate limiting (2.5s minimum interval) with exponential backoff to prevent ad server overload
1111
+ - 🛡️ **Advanced Error Handling**: Distinguishes between temporary failures (no-fill, timeouts) and permanent failures, with 30s cooldown periods for retryable errors
1112
+ - **Min Segments Before Play**: New `minSegmentsBeforePlay` option (default: 2) to ensure smooth playback start by buffering multiple segments
1113
+ - 🎯 **Ad Request Watchdog**: Timeout system prevents hanging ad requests and automatically recovers from stuck states
1114
+ - **Placeholder System**: Seamless placeholder layer shown during ad transitions, preventing content flash between ads
1115
+ - 📊 **Improved Queue Management**: Better handling of ad request queues with automatic cleanup and failure tracking
1116
+ - 🔍 **Early SCTE-35 Detection**: Scans up to 5 manifest fragments ahead to detect upcoming ad breaks, enabling proactive ad preparation
1117
+ - ⚡ **Zero-Delay Ad Starts**: Preloaded ads start instantly when ad breaks begin, eliminating the traditional ad request delay
1118
+ - 🎬 **Fallback Ad System**: Automatic fallback to preloaded ads when primary ad requests fail, ensuring continuous ad playback
1119
+
1120
+ **Performance Improvements:**
1121
+ - Reduced ad start latency by up to 80% through prefetching and preloading
1122
+ - Better resource utilization with intelligent ad pool management
1123
+ - Improved reliability with comprehensive error recovery mechanisms
1124
+ - Enhanced user experience with seamless ad transitions
1041
1125
 
1042
1126
  ### What's New in v0.3
1043
1127
 
1044
1128
  - 🎬 **Custom HLS Ad Player**: Native HLS ad playback with custom VAST service
1045
- - 🎯 **Flexible Ad Integration**: Native ad player with AdStorm VAST endpoint
1129
+ - 🎯 **Flexible Ad Integration**: Choose between custom HLS or Google IMA SDK
1046
1130
  - 📊 **Direct Analytics**: Full control over ad tracking and metrics
1047
1131
  - ⚡ **Better Performance**: Native HLS playback for ads (same format as content)
1048
- - 📦 **Zero Dependencies**: No external ad SDKs required
1132
+ - 🔧 **Custom VAST URLs**: Point to your own ad serving backend
1133
+ - 🔄 **Backward Compatible**: Existing Google IMA integration still works
1134
+ - 📦 **Zero Dependencies**: No external ad SDKs required (when using HLS ad player)
1049
1135
  - 🎨 **Seamless Playback**: Same player for content and ads
1136
+ - 🔀 **VAST Mode System**: `vastMode` property automatically configures endpoints and ad players
1137
+ - `vastMode: 'adstorm'` → Uses `/vast/{licenseKey}` endpoint with HLS ad player
1138
+ - `vastMode: 'default'` → Uses `/ads/web` endpoint with Google IMA SDK
1050
1139
  - ⚠️ **Improved Error Handling**: Distinguishes between parsing errors and "no ads available" scenarios
1051
1140
  - Logs warnings for "no ads available" (graceful handling)
1052
1141
  - Logs errors for actual parsing/fetch failures