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.
- package/README.md +245 -156
- package/dist/stormcloud-vp.min.js +1 -1
- package/lib/index.cjs +9759 -5311
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +193 -17
- package/lib/index.d.ts +193 -17
- package/lib/index.js +9761 -5329
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +7090 -1508
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +95 -9
- package/lib/players/HlsPlayer.cjs +7107 -1525
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +7098 -1516
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +302 -266
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.d.cts +2 -2
- package/lib/sdk/ima.cjs +1375 -0
- package/lib/sdk/ima.cjs.map +1 -0
- package/lib/sdk/ima.d.cts +12 -0
- package/lib/sdk/prebid.cjs +564 -0
- package/lib/sdk/prebid.cjs.map +1 -0
- package/lib/sdk/prebid.d.cts +5 -0
- package/lib/sdk/prebidController.cjs +1560 -0
- package/lib/sdk/prebidController.cjs.map +1 -0
- package/lib/sdk/prebidController.d.cts +11 -0
- package/lib/sdk/vastParser.cjs +393 -0
- package/lib/sdk/vastParser.cjs.map +1 -0
- package/lib/sdk/vastParser.d.cts +45 -0
- package/lib/{types-Ca4ZDaWw.d.cts → types-g2d4Akez.d.cts} +72 -3
- package/lib/ui/StormcloudVideoPlayer.cjs +7130 -1530
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
- package/lib/utils/browserCompat.cjs +222 -20
- package/lib/utils/browserCompat.cjs.map +1 -1
- package/lib/utils/browserCompat.d.cts +9 -1
- package/lib/utils/tracking.d.cts +1 -1
- package/package.json +2 -1
- package/lib/sdk/adstormPlayer.cjs +0 -908
- package/lib/sdk/adstormPlayer.cjs.map +0 -1
- 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
|
|
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
|
-
|
|
355
|
-
|
|
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
|
-
###
|
|
422
|
+
### VAST Mode Configuration
|
|
417
423
|
|
|
418
|
-
The player
|
|
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
|
|
431
|
-
- 🔗 VAST
|
|
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
|
|
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
|
|
466
|
-
2.
|
|
467
|
-
3.
|
|
468
|
-
4.
|
|
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
|
-
- ✅
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
- **
|
|
708
|
-
-
|
|
709
|
-
|
|
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**:
|
|
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
|
-
│
|
|
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.
|
|
1031
|
-
|
|
1032
|
-
-
|
|
1033
|
-
-
|
|
1034
|
-
-
|
|
1035
|
-
-
|
|
1036
|
-
-
|
|
1037
|
-
-
|
|
1038
|
-
-
|
|
1039
|
-
-
|
|
1040
|
-
-
|
|
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**:
|
|
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
|
-
-
|
|
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
|