@jwplayer/jwplayer-react-native 1.2.0 → 1.3.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 +114 -21
- package/RNJWPlayer.podspec +1 -1
- package/android/build.gradle +14 -1
- package/android/src/main/java/com/jwplayer/rnjwplayer/RNJWPlayerModule.java +19 -4
- package/android/src/main/java/com/jwplayer/rnjwplayer/RNJWPlayerView.java +270 -105
- package/android/src/main/java/com/jwplayer/rnjwplayer/Util.java +13 -1
- package/badges/version.svg +1 -1
- package/docs/CONFIG-REFERENCE.md +747 -0
- package/docs/MIGRATION-GUIDE.md +617 -0
- package/docs/PLATFORM-DIFFERENCES.md +693 -0
- package/docs/props.md +15 -3
- package/index.d.ts +207 -249
- package/ios/RNJWPlayer/RNJWPlayerView.swift +278 -21
- package/ios/RNJWPlayer/RNJWPlayerViewController.swift +33 -16
- package/package.json +2 -2
- package/types/advertising.d.ts +514 -0
- package/types/index.d.ts +21 -0
- package/types/legacy.d.ts +82 -0
- package/types/platform-specific.d.ts +641 -0
- package/types/playlist.d.ts +410 -0
- package/types/unified-config.d.ts +591 -0
- package/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/docs/types.md +0 -254
|
@@ -0,0 +1,747 @@
|
|
|
1
|
+
# JWPlayer React Native Configuration Reference
|
|
2
|
+
|
|
3
|
+
Complete reference for the unified configuration system supporting both iOS and Android platforms.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Overview](#overview)
|
|
8
|
+
- [Quick Start](#quick-start)
|
|
9
|
+
- [Core Configuration](#core-configuration)
|
|
10
|
+
- [Media Content](#media-content)
|
|
11
|
+
- [Playback Settings](#playback-settings)
|
|
12
|
+
- [Advertising](#advertising)
|
|
13
|
+
- [Related Content](#related-content)
|
|
14
|
+
- [Platform-Specific Features](#platform-specific-features)
|
|
15
|
+
- [iOS Only](#ios-only-features)
|
|
16
|
+
- [Android Only](#android-only-features)
|
|
17
|
+
- [Advertising Configuration](#advertising-configuration-detailed)
|
|
18
|
+
- [Playlist Items](#playlist-items)
|
|
19
|
+
- [Complete Examples](#complete-examples)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Overview
|
|
24
|
+
|
|
25
|
+
The JWPlayer React Native wrapper uses a unified configuration system that works across both iOS (`JWJSONParser`) and Android (`JsonHelper`) platforms. The configuration is passed as a JavaScript object and automatically parsed by the native SDK.
|
|
26
|
+
|
|
27
|
+
### Key Features
|
|
28
|
+
|
|
29
|
+
- ✅ **Single Configuration Object**: One config works on both platforms
|
|
30
|
+
- ✅ **Type Safety**: Full TypeScript support with autocomplete
|
|
31
|
+
- ✅ **Platform Annotations**: Clear documentation of platform-specific features
|
|
32
|
+
- ✅ **Backward Compatible**: Existing configs continue to work
|
|
33
|
+
- ✅ **Flexible Naming**: Supports multiple naming conventions where needed
|
|
34
|
+
|
|
35
|
+
### Import Types
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { JWPlayerConfig } from '@jwplayer/jwplayer-react-native';
|
|
39
|
+
// Or import from types directory
|
|
40
|
+
import type { JWPlayerConfig } from '@jwplayer/jwplayer-react-native/types';
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
### Minimal Configuration
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import JWPlayer from '@jwplayer/jwplayer-react-native';
|
|
51
|
+
|
|
52
|
+
const config: JWPlayerConfig = {
|
|
53
|
+
license: 'YOUR_LICENSE_KEY', // Required
|
|
54
|
+
file: 'https://example.com/video.m3u8'
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
<JWPlayer config={config} />
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### With Autostart and Poster
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
const config: JWPlayerConfig = {
|
|
64
|
+
license: 'YOUR_LICENSE_KEY',
|
|
65
|
+
file: 'https://example.com/video.m3u8',
|
|
66
|
+
image: 'https://example.com/poster.jpg',
|
|
67
|
+
autostart: true,
|
|
68
|
+
mute: false
|
|
69
|
+
};
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Core Configuration
|
|
75
|
+
|
|
76
|
+
### Media Content
|
|
77
|
+
|
|
78
|
+
#### Single File
|
|
79
|
+
|
|
80
|
+
Use `file` for a single video:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
const config: JWPlayerConfig = {
|
|
84
|
+
license: 'YOUR_LICENSE_KEY',
|
|
85
|
+
file: 'https://example.com/video.m3u8',
|
|
86
|
+
title: 'My Video',
|
|
87
|
+
description: 'Video description',
|
|
88
|
+
image: 'https://example.com/poster.jpg'
|
|
89
|
+
};
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Supported Fields:**
|
|
93
|
+
- `file` (string): URL of the media file
|
|
94
|
+
- `title` (string): Video title
|
|
95
|
+
- `description` (string): Video description
|
|
96
|
+
- `image` (string): Poster image URL
|
|
97
|
+
- `tracks` (JWTrack[]): Caption/thumbnail tracks
|
|
98
|
+
|
|
99
|
+
#### Multiple Quality Sources
|
|
100
|
+
|
|
101
|
+
Use `sources` for multiple quality levels:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
const config: JWPlayerConfig = {
|
|
105
|
+
license: 'YOUR_LICENSE_KEY',
|
|
106
|
+
sources: [
|
|
107
|
+
{
|
|
108
|
+
file: 'https://example.com/video-1080p.mp4',
|
|
109
|
+
label: '1080p',
|
|
110
|
+
default: true
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
file: 'https://example.com/video-720p.mp4',
|
|
114
|
+
label: '720p'
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
file: 'https://example.com/video-480p.mp4',
|
|
118
|
+
label: '480p'
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
};
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**JWSource Fields:**
|
|
125
|
+
- `file` (string): Source URL - **Required**
|
|
126
|
+
- `label` (string): Quality label (e.g., "1080p")
|
|
127
|
+
- `default` (boolean): Whether this is the default quality
|
|
128
|
+
- `type` (string): Media type (e.g., "mp4", "hls")
|
|
129
|
+
- `drm` (JWDrm): DRM configuration
|
|
130
|
+
|
|
131
|
+
#### Playlist
|
|
132
|
+
|
|
133
|
+
Use `playlist` for multiple videos:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
const config: JWPlayerConfig = {
|
|
137
|
+
license: 'YOUR_LICENSE_KEY',
|
|
138
|
+
playlist: [
|
|
139
|
+
{
|
|
140
|
+
file: 'https://example.com/video1.m3u8',
|
|
141
|
+
title: 'Video 1',
|
|
142
|
+
image: 'https://example.com/poster1.jpg'
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
file: 'https://example.com/video2.m3u8',
|
|
146
|
+
title: 'Video 2',
|
|
147
|
+
image: 'https://example.com/poster2.jpg'
|
|
148
|
+
}
|
|
149
|
+
],
|
|
150
|
+
autostart: true
|
|
151
|
+
};
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Or load from a remote playlist:**
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
const config: JWPlayerConfig = {
|
|
158
|
+
license: 'YOUR_LICENSE_KEY',
|
|
159
|
+
playlist: 'https://cdn.jwplayer.com/v2/media/MEDIAID?format=json',
|
|
160
|
+
autostart: true
|
|
161
|
+
};
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Platform Support:** iOS, Android
|
|
165
|
+
**Mutually Exclusive:** Can only use ONE of: `file`, `sources`, or `playlist`
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
### Playback Settings
|
|
170
|
+
|
|
171
|
+
#### Basic Playback
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
const config: JWPlayerConfig = {
|
|
175
|
+
license: 'YOUR_LICENSE_KEY',
|
|
176
|
+
file: 'https://example.com/video.m3u8',
|
|
177
|
+
|
|
178
|
+
autostart: true, // Auto-play on load
|
|
179
|
+
mute: false, // Initial mute state
|
|
180
|
+
repeat: false, // Loop content
|
|
181
|
+
preload: 'auto', // Preload behavior: 'auto' | 'none'
|
|
182
|
+
stretching: 'uniform', // Video scaling: 'uniform' | 'fill' | 'exactfit' | 'none'
|
|
183
|
+
playlistIndex: 0, // Start playlist at index (0-based)
|
|
184
|
+
|
|
185
|
+
// Playback speed controls
|
|
186
|
+
playbackRates: [0.5, 0.75, 1, 1.25, 1.5, 2],
|
|
187
|
+
playbackRateControls: true,
|
|
188
|
+
|
|
189
|
+
// Bandwidth limit (bits per second)
|
|
190
|
+
bitrateUpperBound: 2000000
|
|
191
|
+
};
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Field Reference:**
|
|
195
|
+
|
|
196
|
+
| Field | Type | Default | Description | Platforms |
|
|
197
|
+
|-------|------|---------|-------------|-----------|
|
|
198
|
+
| `autostart` | boolean | false | Auto-play on load | iOS, Android |
|
|
199
|
+
| `mute` | boolean | false | Mute audio initially | iOS, Android |
|
|
200
|
+
| `repeat` | boolean | false | Loop content | iOS, Android |
|
|
201
|
+
| `preload` | 'auto' \| 'none' | 'auto' | Preload behavior | iOS, Android |
|
|
202
|
+
| `stretching` | Stretching | 'uniform' | Video scaling mode | iOS, Android |
|
|
203
|
+
| `playlistIndex` | number | 0 | Starting playlist index | iOS, Android |
|
|
204
|
+
| `playbackRates` | number[] | - | Available speed rates (0.25-4.0) | iOS, Android |
|
|
205
|
+
| `playbackRateControls` | boolean | false | Show speed controls | iOS, Android |
|
|
206
|
+
| `bitrateUpperBound` | number | - | Max bitrate (bps) | iOS, Android |
|
|
207
|
+
| `pid` / `playerId` | string | - | Player ID for analytics (8 chars) | iOS, Android |
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
### Advertising
|
|
212
|
+
|
|
213
|
+
See [Advertising Configuration (Detailed)](#advertising-configuration-detailed) section below for complete advertising documentation.
|
|
214
|
+
|
|
215
|
+
**Quick Example - IMA DAI VOD:**
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
const config: JWPlayerConfig = {
|
|
219
|
+
license: 'YOUR_LICENSE_KEY',
|
|
220
|
+
file: 'https://example.com/video.m3u8',
|
|
221
|
+
advertising: {
|
|
222
|
+
client: 'dai',
|
|
223
|
+
imaDaiSettings: {
|
|
224
|
+
videoId: 'tears-of-steel',
|
|
225
|
+
cmsId: '2528370',
|
|
226
|
+
streamType: 'hls'
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
### Related Content
|
|
235
|
+
|
|
236
|
+
Configure the related content overlay that appears after playback:
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
const config: JWPlayerConfig = {
|
|
240
|
+
license: 'YOUR_LICENSE_KEY',
|
|
241
|
+
file: 'https://example.com/video.m3u8',
|
|
242
|
+
related: {
|
|
243
|
+
file: 'https://example.com/related.json', // Related feed URL
|
|
244
|
+
onclick: 'play', // 'play' | 'link'
|
|
245
|
+
oncomplete: 'show', // 'show' | 'hide' | 'autoplay'
|
|
246
|
+
autoplaytimer: 10 // Countdown seconds
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Platform Notes:**
|
|
252
|
+
- iOS: Full support with additional options (`heading`, `autoplayMessage`)
|
|
253
|
+
- Android: Basic support with `file`, `onclick`, `oncomplete`, `autoplaytimer`
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Platform-Specific Features
|
|
258
|
+
|
|
259
|
+
### iOS Only Features
|
|
260
|
+
|
|
261
|
+
#### Styling
|
|
262
|
+
|
|
263
|
+
Customize colors, fonts, and UI appearance (iOS only):
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
const config: JWPlayerConfig = {
|
|
267
|
+
license: 'YOUR_LICENSE_KEY',
|
|
268
|
+
file: 'https://example.com/video.m3u8',
|
|
269
|
+
styling: {
|
|
270
|
+
colors: {
|
|
271
|
+
buttons: '#FF0000',
|
|
272
|
+
backgroundColor: '#000000',
|
|
273
|
+
fontColor: '#FFFFFF',
|
|
274
|
+
timeslider: {
|
|
275
|
+
thumb: '#FF0000',
|
|
276
|
+
rail: '#808080',
|
|
277
|
+
slider: '#FF0000'
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
font: {
|
|
281
|
+
name: 'Helvetica',
|
|
282
|
+
size: 14
|
|
283
|
+
},
|
|
284
|
+
showTitle: true,
|
|
285
|
+
showDesc: true,
|
|
286
|
+
captionsStyle: {
|
|
287
|
+
fontColor: '#FFFF00',
|
|
288
|
+
fontSize: 16,
|
|
289
|
+
backgroundColor: '#000000',
|
|
290
|
+
backgroundOpacity: 75,
|
|
291
|
+
edgeStyle: 'dropshadow'
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**⚠️ Android:** Use XML styling instead. See [Android Styling Guide](https://docs.jwplayer.com/players/docs/android-styling-guide)
|
|
298
|
+
|
|
299
|
+
#### Background Audio
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
const config: JWPlayerConfig = {
|
|
303
|
+
license: 'YOUR_LICENSE_KEY',
|
|
304
|
+
file: 'https://example.com/video.m3u8',
|
|
305
|
+
backgroundAudioEnabled: true,
|
|
306
|
+
category: 'Playback',
|
|
307
|
+
categoryOptions: ['MixWithOthers', 'DuckOthers'],
|
|
308
|
+
mode: 'MoviePlayback'
|
|
309
|
+
};
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
#### Interface Control
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
const config: JWPlayerConfig = {
|
|
316
|
+
license: 'YOUR_LICENSE_KEY',
|
|
317
|
+
file: 'https://example.com/video.m3u8',
|
|
318
|
+
interfaceBehavior: 'normal', // 'normal' | 'hidden' | 'onscreen'
|
|
319
|
+
interfaceFadeDelay: 3, // Seconds before UI fades
|
|
320
|
+
hideUIGroups: ['settings_menu', 'casting_menu']
|
|
321
|
+
};
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
#### FairPlay DRM
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
const config: JWPlayerConfig = {
|
|
328
|
+
license: 'YOUR_LICENSE_KEY',
|
|
329
|
+
sources: [{
|
|
330
|
+
file: 'https://example.com/video.m3u8',
|
|
331
|
+
drm: {
|
|
332
|
+
fairplay: {
|
|
333
|
+
processSpcUrl: 'https://your-drm-server.com/process-spc',
|
|
334
|
+
certificateUrl: 'https://your-drm-server.com/certificate'
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}]
|
|
338
|
+
};
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
### Android Only Features
|
|
344
|
+
|
|
345
|
+
#### UI Configuration
|
|
346
|
+
|
|
347
|
+
Control which UI elements are visible (Android only):
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
const config: JWPlayerConfig = {
|
|
351
|
+
license: 'YOUR_LICENSE_KEY',
|
|
352
|
+
file: 'https://example.com/video.m3u8',
|
|
353
|
+
uiConfig: {
|
|
354
|
+
hasOverlay: true,
|
|
355
|
+
hasControlbar: true,
|
|
356
|
+
hasCenterControls: true,
|
|
357
|
+
hasNextUp: true,
|
|
358
|
+
hasQualitySubMenu: true,
|
|
359
|
+
hasCaptionsSubMenu: true,
|
|
360
|
+
hasPlaybackRatesSubMenu: true,
|
|
361
|
+
hasMenu: true,
|
|
362
|
+
hasAds: true
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
**⚠️ Note:** When using `uiConfig`, all unspecified elements default to `false`. Specify all elements you want visible.
|
|
368
|
+
|
|
369
|
+
#### Android-Specific Settings
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
const config: JWPlayerConfig = {
|
|
373
|
+
license: 'YOUR_LICENSE_KEY',
|
|
374
|
+
file: 'https://example.com/video.m3u8',
|
|
375
|
+
useTextureView: true, // Use TextureView instead of SurfaceView
|
|
376
|
+
allowCrossProtocolRedirectsSupport: true, // Allow HTTP->HTTPS redirects
|
|
377
|
+
displaytitle: true,
|
|
378
|
+
displaydescription: true,
|
|
379
|
+
thumbnailPreview: 102 // Thumbnail preview quality (101-103)
|
|
380
|
+
};
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
#### Widevine DRM
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
const config: JWPlayerConfig = {
|
|
387
|
+
license: 'YOUR_LICENSE_KEY',
|
|
388
|
+
sources: [{
|
|
389
|
+
file: 'https://example.com/video.mpd',
|
|
390
|
+
drm: {
|
|
391
|
+
widevine: {
|
|
392
|
+
url: 'https://your-drm-server.com/license',
|
|
393
|
+
keySetId: 'optional-key-set-id'
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}]
|
|
397
|
+
};
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## Advertising Configuration (Detailed)
|
|
403
|
+
|
|
404
|
+
The wrapper supports multiple advertising systems across both platforms.
|
|
405
|
+
|
|
406
|
+
### Supported Ad Types
|
|
407
|
+
|
|
408
|
+
| Ad Type | iOS | Android | Client Value |
|
|
409
|
+
|---------|-----|---------|--------------|
|
|
410
|
+
| VAST with Schedule | ✅ | ✅ | `'vast'` |
|
|
411
|
+
| VMAP | ✅ | ✅ | `'vast'` |
|
|
412
|
+
| Google IMA | ✅ | ✅ | `'googima'` or `'IMA'` |
|
|
413
|
+
| Google IMA DAI | ✅ | ✅ | `'dai'` or `'IMA_DAI'` or `'GoogleIMADAI'` |
|
|
414
|
+
|
|
415
|
+
### IMA DAI Configuration
|
|
416
|
+
|
|
417
|
+
#### VOD Stream (Video on Demand)
|
|
418
|
+
|
|
419
|
+
Requires `videoId` + `cmsId`:
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
const config: JWPlayerConfig = {
|
|
423
|
+
license: 'YOUR_LICENSE_KEY',
|
|
424
|
+
file: 'https://example.com/video.m3u8',
|
|
425
|
+
advertising: {
|
|
426
|
+
client: 'dai',
|
|
427
|
+
imaDaiSettings: {
|
|
428
|
+
videoId: 'tears-of-steel',
|
|
429
|
+
cmsId: '2528370',
|
|
430
|
+
streamType: 'hls', // 'hls' or 'dash'
|
|
431
|
+
apiKey: 'your-api-key', // Optional
|
|
432
|
+
adTagParameters: {
|
|
433
|
+
'custom_param': 'value'
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
imaSdkSettings: {
|
|
437
|
+
language: 'en',
|
|
438
|
+
autoPlayAdBreaks: true
|
|
439
|
+
},
|
|
440
|
+
skipoffset: 5 // Skip button after 5 seconds
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
#### Live Stream
|
|
446
|
+
|
|
447
|
+
Requires `assetKey`:
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
const config: JWPlayerConfig = {
|
|
451
|
+
license: 'YOUR_LICENSE_KEY',
|
|
452
|
+
file: 'https://example.com/live.m3u8',
|
|
453
|
+
advertising: {
|
|
454
|
+
client: 'dai',
|
|
455
|
+
imaDaiSettings: {
|
|
456
|
+
assetKey: 'sN_IYUG8STe1ZzhIIE_ksA',
|
|
457
|
+
streamType: 'hls'
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
**Platform Note:** Both iOS and Android support `imaDaiSettings`. iOS also accepts `googimadai` as an alias.
|
|
464
|
+
|
|
465
|
+
### VAST Advertising
|
|
466
|
+
|
|
467
|
+
#### With Schedule
|
|
468
|
+
|
|
469
|
+
```typescript
|
|
470
|
+
const config: JWPlayerConfig = {
|
|
471
|
+
license: 'YOUR_LICENSE_KEY',
|
|
472
|
+
file: 'https://example.com/video.m3u8',
|
|
473
|
+
advertising: {
|
|
474
|
+
client: 'vast',
|
|
475
|
+
schedule: [
|
|
476
|
+
{
|
|
477
|
+
offset: 'pre',
|
|
478
|
+
tag: 'https://example.com/preroll.xml'
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
offset: '50%', // Midroll at 50%
|
|
482
|
+
tag: 'https://example.com/midroll.xml',
|
|
483
|
+
skipoffset: 5
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
offset: 'post',
|
|
487
|
+
tag: 'https://example.com/postroll.xml'
|
|
488
|
+
}
|
|
489
|
+
],
|
|
490
|
+
skipoffset: 5,
|
|
491
|
+
admessage: 'Ad - {remaining}',
|
|
492
|
+
skipmessage: 'Skip in {remaining}',
|
|
493
|
+
skiptext: 'Skip Ad'
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
#### With VMAP
|
|
499
|
+
|
|
500
|
+
```typescript
|
|
501
|
+
const config: JWPlayerConfig = {
|
|
502
|
+
license: 'YOUR_LICENSE_KEY',
|
|
503
|
+
file: 'https://example.com/video.m3u8',
|
|
504
|
+
advertising: {
|
|
505
|
+
client: 'vast',
|
|
506
|
+
tag: 'https://example.com/vmap.xml', // VMAP URL
|
|
507
|
+
skipoffset: 5
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### Google IMA
|
|
513
|
+
|
|
514
|
+
```typescript
|
|
515
|
+
const config: JWPlayerConfig = {
|
|
516
|
+
license: 'YOUR_LICENSE_KEY',
|
|
517
|
+
file: 'https://example.com/video.m3u8',
|
|
518
|
+
advertising: {
|
|
519
|
+
client: 'googima',
|
|
520
|
+
schedule: [
|
|
521
|
+
{
|
|
522
|
+
offset: 'pre',
|
|
523
|
+
tag: 'https://pubads.g.doubleclick.net/gampad/ads?...'
|
|
524
|
+
}
|
|
525
|
+
],
|
|
526
|
+
imaSdkSettings: {
|
|
527
|
+
language: 'en',
|
|
528
|
+
autoPlayAdBreaks: true,
|
|
529
|
+
maxRedirects: 5,
|
|
530
|
+
isDebugMode: false
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### Ad Rules (Android Primary)
|
|
537
|
+
|
|
538
|
+
Control ad playback across a playlist:
|
|
539
|
+
|
|
540
|
+
```typescript
|
|
541
|
+
const config: JWPlayerConfig = {
|
|
542
|
+
license: 'YOUR_LICENSE_KEY',
|
|
543
|
+
playlist: [...],
|
|
544
|
+
advertising: {
|
|
545
|
+
client: 'vast',
|
|
546
|
+
schedule: [...],
|
|
547
|
+
rules: {
|
|
548
|
+
startOn: 2, // Start ads on 2nd playlist item
|
|
549
|
+
frequency: 2, // Show ads every 2 items
|
|
550
|
+
timeBetweenAds: 300, // Min 5 minutes between midrolls
|
|
551
|
+
startOnSeek: 'pre' // Show preroll after seeking
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
};
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
**Platform Note:** Android has full support. iOS has limited support for `startOn` and `frequency`.
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
## Playlist Items
|
|
562
|
+
|
|
563
|
+
Complete configuration for playlist items:
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
const playlistItem: JWPlaylistItem = {
|
|
567
|
+
// Media source (Required: file OR sources)
|
|
568
|
+
file: 'https://example.com/video.m3u8',
|
|
569
|
+
// OR
|
|
570
|
+
sources: [
|
|
571
|
+
{ file: 'https://example.com/1080p.mp4', label: '1080p' },
|
|
572
|
+
{ file: 'https://example.com/720p.mp4', label: '720p' }
|
|
573
|
+
],
|
|
574
|
+
|
|
575
|
+
// Metadata
|
|
576
|
+
title: 'Video Title',
|
|
577
|
+
description: 'Video description',
|
|
578
|
+
image: 'https://example.com/poster.jpg',
|
|
579
|
+
mediaId: 'unique-id',
|
|
580
|
+
|
|
581
|
+
// Playback
|
|
582
|
+
starttime: 0, // Start position in seconds
|
|
583
|
+
duration: 600, // Duration in seconds
|
|
584
|
+
|
|
585
|
+
// Tracks
|
|
586
|
+
tracks: [
|
|
587
|
+
{
|
|
588
|
+
file: 'https://example.com/captions-en.vtt',
|
|
589
|
+
kind: 'captions',
|
|
590
|
+
label: 'English',
|
|
591
|
+
locale: 'en',
|
|
592
|
+
default: true
|
|
593
|
+
}
|
|
594
|
+
],
|
|
595
|
+
|
|
596
|
+
// Item-level advertising
|
|
597
|
+
imaDaiSettings: {
|
|
598
|
+
videoId: 'video-id',
|
|
599
|
+
cmsId: 'cms-id'
|
|
600
|
+
},
|
|
601
|
+
|
|
602
|
+
// Related content
|
|
603
|
+
recommendations: 'https://example.com/related.json',
|
|
604
|
+
|
|
605
|
+
// Chromecast
|
|
606
|
+
userInfo: {
|
|
607
|
+
customData: 'value'
|
|
608
|
+
},
|
|
609
|
+
|
|
610
|
+
// DRM (platform-specific)
|
|
611
|
+
drm: {
|
|
612
|
+
fairplay: { // iOS
|
|
613
|
+
processSpcUrl: '...',
|
|
614
|
+
certificateUrl: '...'
|
|
615
|
+
},
|
|
616
|
+
widevine: { // Android
|
|
617
|
+
url: '...',
|
|
618
|
+
keySetId: '...'
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
---
|
|
625
|
+
|
|
626
|
+
## Complete Examples
|
|
627
|
+
|
|
628
|
+
### Basic Video with Captions
|
|
629
|
+
|
|
630
|
+
```typescript
|
|
631
|
+
import JWPlayer, { JWPlayerConfig } from '@jwplayer/jwplayer-react-native';
|
|
632
|
+
|
|
633
|
+
const config: JWPlayerConfig = {
|
|
634
|
+
license: 'YOUR_LICENSE_KEY',
|
|
635
|
+
file: 'https://example.com/video.m3u8',
|
|
636
|
+
title: 'Sample Video',
|
|
637
|
+
image: 'https://example.com/poster.jpg',
|
|
638
|
+
tracks: [
|
|
639
|
+
{
|
|
640
|
+
file: 'https://example.com/captions-en.vtt',
|
|
641
|
+
kind: 'captions',
|
|
642
|
+
label: 'English',
|
|
643
|
+
locale: 'en',
|
|
644
|
+
default: true
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
file: 'https://example.com/captions-es.vtt',
|
|
648
|
+
kind: 'captions',
|
|
649
|
+
label: 'Español',
|
|
650
|
+
locale: 'es'
|
|
651
|
+
}
|
|
652
|
+
],
|
|
653
|
+
autostart: true
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
export default () => (
|
|
657
|
+
<JWPlayer config={config} style={{ flex: 1 }} />
|
|
658
|
+
);
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
### IMA DAI with Playlist
|
|
662
|
+
|
|
663
|
+
```typescript
|
|
664
|
+
const config: JWPlayerConfig = {
|
|
665
|
+
license: 'YOUR_LICENSE_KEY',
|
|
666
|
+
autostart: true,
|
|
667
|
+
playlist: [
|
|
668
|
+
{
|
|
669
|
+
title: 'VOD with Ads',
|
|
670
|
+
file: 'https://example.com/vod.m3u8',
|
|
671
|
+
imaDaiSettings: {
|
|
672
|
+
videoId: 'tears-of-steel',
|
|
673
|
+
cmsId: '2528370'
|
|
674
|
+
}
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
title: 'Live Stream with Ads',
|
|
678
|
+
file: 'https://example.com/live.m3u8',
|
|
679
|
+
imaDaiSettings: {
|
|
680
|
+
assetKey: 'sN_IYUG8STe1ZzhIIE_ksA'
|
|
681
|
+
}
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
title: 'Video without Ads',
|
|
685
|
+
file: 'https://example.com/no-ads.m3u8'
|
|
686
|
+
}
|
|
687
|
+
],
|
|
688
|
+
advertising: {
|
|
689
|
+
client: 'dai'
|
|
690
|
+
}
|
|
691
|
+
};
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
### Multi-Quality with DRM
|
|
695
|
+
|
|
696
|
+
```typescript
|
|
697
|
+
import { Platform } from 'react-native';
|
|
698
|
+
|
|
699
|
+
const config: JWPlayerConfig = {
|
|
700
|
+
license: Platform.OS === 'ios' ? 'IOS_LICENSE' : 'ANDROID_LICENSE',
|
|
701
|
+
sources: [
|
|
702
|
+
{
|
|
703
|
+
file: Platform.OS === 'ios'
|
|
704
|
+
? 'https://example.com/fairplay.m3u8'
|
|
705
|
+
: 'https://example.com/widevine.mpd',
|
|
706
|
+
label: '1080p',
|
|
707
|
+
default: true,
|
|
708
|
+
drm: Platform.OS === 'ios' ? {
|
|
709
|
+
fairplay: {
|
|
710
|
+
processSpcUrl: 'https://drm.example.com/spc',
|
|
711
|
+
certificateUrl: 'https://drm.example.com/cert'
|
|
712
|
+
}
|
|
713
|
+
} : {
|
|
714
|
+
widevine: {
|
|
715
|
+
url: 'https://drm.example.com/license'
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
],
|
|
720
|
+
autostart: true
|
|
721
|
+
};
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
---
|
|
725
|
+
|
|
726
|
+
## See Also
|
|
727
|
+
|
|
728
|
+
- [Platform Differences Guide](./PLATFORM-DIFFERENCES.md) - Detailed platform-specific information
|
|
729
|
+
- [Migration Guide](./MIGRATION-GUIDE.md) - Upgrading from legacy configs
|
|
730
|
+
- [Props Documentation](./props.md) - Component props reference
|
|
731
|
+
- [iOS JSON Parser Docs](../ios-json-parser/README.md) - iOS parser details
|
|
732
|
+
- [Android JSON Parser Docs](../android-json-parser/README.md) - Android parser details
|
|
733
|
+
|
|
734
|
+
---
|
|
735
|
+
|
|
736
|
+
## Need Help?
|
|
737
|
+
|
|
738
|
+
- **Configuration Issues**: Check [PLATFORM-DIFFERENCES.md](./PLATFORM-DIFFERENCES.md)
|
|
739
|
+
- **Migration Questions**: See [MIGRATION-GUIDE.md](./MIGRATION-GUIDE.md)
|
|
740
|
+
- **TypeScript Errors**: Import types from `'@jwplayer/jwplayer-react-native/types'`
|
|
741
|
+
- **Platform-Specific**: Review [iOS](../ios-json-parser/) or [Android](../android-json-parser/) parser docs
|
|
742
|
+
|
|
743
|
+
---
|
|
744
|
+
|
|
745
|
+
*Last Updated: October 2025*
|
|
746
|
+
*SDK Version: JWPlayer React Native*
|
|
747
|
+
|