unified-video-framework 1.4.404 → 1.4.406

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.
@@ -1,362 +0,0 @@
1
- import React, { useState } from 'react';
2
- import { WebPlayerView } from '../WebPlayerView';
3
-
4
- /**
5
- * Example: Live Stream Ads with Metadata and Periodic Modes
6
- *
7
- * This example demonstrates how to integrate ads with live streaming using:
8
- * 1. Metadata-based ad insertion (detects cues in HLS stream)
9
- * 2. Periodic timer-based ad insertion (every X seconds)
10
- * 3. Hybrid mode (both metadata and periodic)
11
- */
12
-
13
- export const LiveStreamAdsExample: React.FC = () => {
14
- const [adEvents, setAdEvents] = useState<string[]>([]);
15
- const [mode, setMode] = useState<'metadata' | 'periodic' | 'hybrid'>('periodic');
16
-
17
- const logAdEvent = (event: string) => {
18
- console.log(`[Ad Event] ${event}`);
19
- setAdEvents(prev => [...prev, `${new Date().toLocaleTimeString()}: ${event}`].slice(-10)); // Keep last 10
20
- };
21
-
22
- return (
23
- <div style={{ height: '100vh', display: 'flex', flexDirection: 'column' }}>
24
- {/* Mode Selector */}
25
- <div style={{ padding: '20px', backgroundColor: '#f5f5f5', borderBottom: '1px solid #ddd' }}>
26
- <h2 style={{ margin: '0 0 15px 0' }}>Live Stream Ads - Example</h2>
27
-
28
- <div style={{ display: 'flex', gap: '10px', marginBottom: '10px' }}>
29
- <button
30
- onClick={() => setMode('metadata')}
31
- style={{
32
- padding: '10px 20px',
33
- backgroundColor: mode === 'metadata' ? '#007bff' : '#6c757d',
34
- color: 'white',
35
- border: 'none',
36
- borderRadius: '4px',
37
- cursor: 'pointer'
38
- }}
39
- >
40
- Metadata Mode
41
- </button>
42
-
43
- <button
44
- onClick={() => setMode('periodic')}
45
- style={{
46
- padding: '10px 20px',
47
- backgroundColor: mode === 'periodic' ? '#007bff' : '#6c757d',
48
- color: 'white',
49
- border: 'none',
50
- borderRadius: '4px',
51
- cursor: 'pointer'
52
- }}
53
- >
54
- Periodic Mode (Every 2 min)
55
- </button>
56
-
57
- <button
58
- onClick={() => setMode('hybrid')}
59
- style={{
60
- padding: '10px 20px',
61
- backgroundColor: mode === 'hybrid' ? '#007bff' : '#6c757d',
62
- color: 'white',
63
- border: 'none',
64
- borderRadius: '4px',
65
- cursor: 'pointer'
66
- }}
67
- >
68
- Hybrid Mode
69
- </button>
70
- </div>
71
-
72
- <div style={{ fontSize: '14px', color: '#666' }}>
73
- <strong>Current Mode:</strong> {mode}
74
- {mode === 'metadata' && ' - Detects #EXT-X-DATERANGE tags in HLS stream'}
75
- {mode === 'periodic' && ' - Shows ads every 2 minutes of playback'}
76
- {mode === 'hybrid' && ' - Uses both metadata detection AND periodic fallback'}
77
- </div>
78
- </div>
79
-
80
- {/* Video Player */}
81
- <div style={{ flex: 1, position: 'relative', backgroundColor: '#000' }}>
82
- <WebPlayerView
83
- // Live HLS stream
84
- url="https://stream.example.com/live.m3u8"
85
- type="hls"
86
-
87
- // Player config
88
- autoPlay={false}
89
- controls={true}
90
- muted={true} // Start muted for autoplay compatibility
91
-
92
- // Google Ads for Live Streaming
93
- googleAds={{
94
- // VAST ad tag URL
95
- adTagUrl: 'https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_ad_samples&sz=640x480&cust_params=sample_ct%3Dlinear&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator=',
96
-
97
- // ========================================
98
- // LIVE STREAM AD CONFIGURATION
99
- // ========================================
100
-
101
- // Choose ad insertion mode
102
- liveAdBreakMode: mode,
103
-
104
- // For periodic mode: ad every X seconds (default: 300 = 5 minutes)
105
- periodicAdInterval: 120, // 2 minutes for demo
106
-
107
- // Sync to live edge after ad (recommended for live streams)
108
- syncToLiveEdge: true,
109
- liveEdgeOffset: 3, // Stay 3 seconds behind live edge
110
-
111
- // Metadata detection config (for metadata/hybrid modes)
112
- metadataConfig: {
113
- detectDateRange: true, // Detect #EXT-X-DATERANGE tags
114
- detectID3: true, // Detect ID3 timed metadata
115
- adClassNames: ['com.google.ads', 'ads', 'ad-break']
116
- },
117
-
118
- // ========================================
119
- // AD EVENT CALLBACKS
120
- // ========================================
121
-
122
- onAdStart: () => {
123
- logAdEvent(`🎬 Ad Started (Mode: ${mode})`);
124
- },
125
-
126
- onAdEnd: () => {
127
- logAdEvent('✅ Ad Ended - Resuming Live Stream');
128
- },
129
-
130
- onAdError: (error: any) => {
131
- logAdEvent(`❌ Ad Error: ${error?.getMessage?.() || error}`);
132
- },
133
-
134
- onAllAdsComplete: () => {
135
- logAdEvent('✅ All Ads in Pod Completed');
136
- },
137
-
138
- // Live-specific callbacks
139
- onLiveAdBreakDetected: (metadata) => {
140
- logAdEvent(`📍 Live Ad Cue Detected: ${JSON.stringify(metadata).slice(0, 50)}...`);
141
- },
142
-
143
- onAdBreakScheduled: (scheduledTime) => {
144
- logAdEvent(`⏰ Ad Break Scheduled at ${scheduledTime.toFixed(0)}s playback time`);
145
- },
146
- }}
147
-
148
- // Player callbacks
149
- onReady={(player) => {
150
- console.log('Player ready with live stream ads');
151
- logAdEvent('🎥 Player Ready');
152
- }}
153
-
154
- onError={(error) => {
155
- console.error('Player error:', error);
156
- logAdEvent(`❌ Player Error: ${error instanceof Error ? error.message : String(error)}`);
157
- }}
158
-
159
- onTimeUpdate={(time) => {
160
- // Optional: Track playback time
161
- }}
162
- />
163
- </div>
164
-
165
- {/* Ad Event Log */}
166
- <div style={{
167
- padding: '20px',
168
- backgroundColor: '#f9f9f9',
169
- borderTop: '1px solid #ddd',
170
- maxHeight: '200px',
171
- overflowY: 'auto',
172
- }}>
173
- <h3 style={{ margin: '0 0 10px 0', fontSize: '16px' }}>Live Ad Events Log:</h3>
174
- {adEvents.length === 0 ? (
175
- <p style={{ color: '#999', margin: 0 }}>No ad events yet. Play the video to see ads.</p>
176
- ) : (
177
- <ul style={{ margin: 0, padding: '0 0 0 20px' }}>
178
- {adEvents.map((event, index) => (
179
- <li key={index} style={{ fontSize: '14px', marginBottom: '5px' }}>
180
- {event}
181
- </li>
182
- ))}
183
- </ul>
184
- )}
185
- </div>
186
-
187
- {/* Implementation Notes */}
188
- <div style={{
189
- padding: '20px',
190
- backgroundColor: '#e7f3ff',
191
- borderTop: '1px solid #b3d9ff'
192
- }}>
193
- <h3 style={{ margin: '0 0 10px 0', fontSize: '16px' }}>💡 Implementation Notes:</h3>
194
- <ul style={{ margin: 0, paddingLeft: '20px', fontSize: '14px' }}>
195
- <li>
196
- <strong>Metadata Mode:</strong> Requires HLS stream with #EXT-X-DATERANGE tags or ID3 metadata.
197
- Your encoder must embed ad cues in the manifest.
198
- </li>
199
- <li>
200
- <strong>Periodic Mode:</strong> Works with any live stream. Ads trigger every X seconds of actual playback.
201
- Simple but users see ads at different times (not synchronized).
202
- </li>
203
- <li>
204
- <strong>Hybrid Mode:</strong> Uses metadata when available, falls back to periodic timer.
205
- Best of both worlds!
206
- </li>
207
- <li>
208
- <strong>Live Edge Sync:</strong> After ads, player jumps to live edge (catches up to "now").
209
- Disable if you want DVR-style behavior (continue from where paused).
210
- </li>
211
- </ul>
212
- </div>
213
- </div>
214
- );
215
- };
216
-
217
- /**
218
- * ========================================================================
219
- * USAGE EXAMPLE 1: METADATA-BASED LIVE ADS
220
- * ========================================================================
221
- */
222
- export const MetadataLiveAdsExample: React.FC = () => {
223
- return (
224
- <WebPlayerView
225
- url="https://stream.example.com/live.m3u8"
226
- type="hls"
227
-
228
- googleAds={{
229
- adTagUrl: 'https://pubads.g.doubleclick.net/...',
230
-
231
- // Use metadata mode
232
- liveAdBreakMode: 'metadata',
233
-
234
- // Metadata detection config
235
- metadataConfig: {
236
- detectDateRange: true,
237
- detectID3: true,
238
- adClassNames: ['com.google.ads', 'ads']
239
- },
240
-
241
- // Sync to live edge after ads
242
- syncToLiveEdge: true,
243
- liveEdgeOffset: 3,
244
-
245
- onLiveAdBreakDetected: (metadata) => {
246
- console.log('Ad cue detected:', metadata);
247
- }
248
- }}
249
- />
250
- );
251
- };
252
-
253
- /**
254
- * ========================================================================
255
- * USAGE EXAMPLE 2: PERIODIC TIMER-BASED LIVE ADS
256
- * ========================================================================
257
- */
258
- export const PeriodicLiveAdsExample: React.FC = () => {
259
- return (
260
- <WebPlayerView
261
- url="https://stream.example.com/live.m3u8"
262
- type="hls"
263
-
264
- googleAds={{
265
- adTagUrl: 'https://pubads.g.doubleclick.net/...',
266
-
267
- // Use periodic mode
268
- liveAdBreakMode: 'periodic',
269
-
270
- // Ad every 5 minutes (300 seconds)
271
- periodicAdInterval: 300,
272
-
273
- // Sync to live edge after ads
274
- syncToLiveEdge: true,
275
-
276
- onAdBreakScheduled: (scheduledTime) => {
277
- console.log(`Next ad at ${scheduledTime}s playback time`);
278
- }
279
- }}
280
- />
281
- );
282
- };
283
-
284
- /**
285
- * ========================================================================
286
- * USAGE EXAMPLE 3: HYBRID MODE (METADATA + PERIODIC FALLBACK)
287
- * ========================================================================
288
- */
289
- export const HybridLiveAdsExample: React.FC = () => {
290
- return (
291
- <WebPlayerView
292
- url="https://stream.example.com/live.m3u8"
293
- type="hls"
294
-
295
- googleAds={{
296
- adTagUrl: 'https://pubads.g.doubleclick.net/...',
297
-
298
- // Use hybrid mode
299
- liveAdBreakMode: 'hybrid',
300
-
301
- // Metadata detection (primary)
302
- metadataConfig: {
303
- detectDateRange: true,
304
- detectID3: true
305
- },
306
-
307
- // Periodic fallback (if no metadata detected)
308
- periodicAdInterval: 300,
309
-
310
- // Sync to live edge
311
- syncToLiveEdge: true,
312
-
313
- // Callbacks for both modes
314
- onLiveAdBreakDetected: (metadata) => {
315
- console.log('✅ Metadata ad cue detected');
316
- },
317
-
318
- onAdBreakScheduled: (scheduledTime) => {
319
- console.log('⏰ Fallback periodic ad scheduled');
320
- }
321
- }}
322
- />
323
- );
324
- };
325
-
326
- /**
327
- * ========================================================================
328
- * BACKEND-CONTROLLED EXAMPLE
329
- * ========================================================================
330
- * Fetch ad schedule from backend and configure player accordingly
331
- */
332
- export const BackendControlledLiveAdsExample: React.FC = () => {
333
- const [adConfig, setAdConfig] = useState<any>(null);
334
-
335
- // Fetch ad configuration from backend
336
- React.useEffect(() => {
337
- fetch('/api/live-stream/ad-config')
338
- .then(res => res.json())
339
- .then(config => {
340
- setAdConfig(config);
341
- });
342
- }, []);
343
-
344
- if (!adConfig) return <div>Loading...</div>;
345
-
346
- return (
347
- <WebPlayerView
348
- url={adConfig.streamUrl}
349
- type="hls"
350
-
351
- googleAds={{
352
- adTagUrl: adConfig.adTagUrl,
353
- liveAdBreakMode: adConfig.mode, // Backend decides: metadata | periodic | hybrid
354
- periodicAdInterval: adConfig.periodicInterval,
355
- metadataConfig: adConfig.metadataConfig,
356
- syncToLiveEdge: true
357
- }}
358
- />
359
- );
360
- };
361
-
362
- export default LiveStreamAdsExample;