bitmovin-player-react-native 0.6.0 → 0.7.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 (31) hide show
  1. package/README.md +23 -906
  2. package/RNBitmovinPlayer.podspec +2 -2
  3. package/android/build.gradle +5 -4
  4. package/android/gradle.properties +1 -0
  5. package/android/gradlew +244 -0
  6. package/android/gradlew.bat +92 -0
  7. package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewManager.kt +36 -7
  8. package/android/src/main/java/com/bitmovin/player/reactnative/RNPlayerViewPackage.kt +3 -1
  9. package/android/src/main/java/com/bitmovin/player/reactnative/converter/JsonConverter.kt +7 -1
  10. package/android/src/main/java/com/bitmovin/player/reactnative/extensions/ReadableMap.kt +19 -0
  11. package/android/src/main/java/com/bitmovin/player/reactnative/extensions/ReadableMapExtension.kt +7 -0
  12. package/android/src/main/java/com/bitmovin/player/reactnative/ui/CustomMessageHandlerBridge.kt +37 -0
  13. package/android/src/main/java/com/bitmovin/player/reactnative/ui/CustomMessageHandlerModule.kt +86 -0
  14. package/ios/CustomMessageHandlerBridge.swift +50 -0
  15. package/ios/CustomMessageHandlerModule.m +10 -0
  16. package/ios/CustomMessageHandlerModule.swift +83 -0
  17. package/ios/RCTBridge+Generics.swift +6 -0
  18. package/ios/RCTConvert+BitmovinPlayer.swift +3 -0
  19. package/ios/RNPlayerViewManager.m +1 -0
  20. package/ios/RNPlayerViewManager.swift +19 -1
  21. package/lib/index.d.ts +46 -2
  22. package/lib/index.js +111 -20
  23. package/lib/index.mjs +98 -8
  24. package/package.json +5 -2
  25. package/src/components/PlayerView/index.tsx +29 -1
  26. package/src/components/PlayerView/native.ts +2 -0
  27. package/src/source.ts +4 -0
  28. package/src/ui/custommessagehandler.ts +68 -0
  29. package/src/ui/custommessagehandlerbridge.ts +72 -0
  30. package/src/ui/custommessagesender.ts +3 -0
  31. package/src/ui/index.ts +1 -0
package/README.md CHANGED
@@ -2,63 +2,41 @@
2
2
 
3
3
  Official React Native bindings for Bitmovin's mobile Player SDKs.
4
4
 
5
- [![npm](https://img.shields.io/npm/v/bitmovin-player-react-native)](https://www.npmjs.com/package/bitmovin-player-react-native)
5
+ [![Build](https://github.com/bitmovin/bitmovin-player-react-native/actions/workflows/ci.yml/badge.svg)](https://github.com/bitmovin/bitmovin-player-react-native/actions/workflows/ci.yml)
6
6
  ![Platforms](https://img.shields.io/badge/platforms-iOS%20%7C%20tvOS%20%7C%20Android%20%7C%20Android%20TV-lightgrey.svg)
7
7
  [![MIT License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE)
8
8
  [![Bitmovin Community](https://img.shields.io/discourse/users?label=community&server=https%3A%2F%2Fcommunity.bitmovin.com)](https://community.bitmovin.com/?utm_source=github&utm_medium=bitmovin-player-react-native&utm_campaign=dev-community)
9
+ [![npm version](https://img.shields.io/npm/v/bitmovin-player-react-native)](https://www.npmjs.com/package/bitmovin-player-react-native)
10
+ [![npm dm](https://img.shields.io/npm/dm/bitmovin-player-react-native.svg)](https://www.npmjs.com/package/bitmovin-player-react-native)
11
+ [![npm dt](https://img.shields.io/npm/dt/bitmovin-player-react-native.svg)](https://www.npmjs.com/package/bitmovin-player-react-native)
9
12
 
10
- > As the library is under active development, this means certain features from our native SDKs are not yet exposed through these React Native bindings.
13
+ > As the library is under active development, this means certain features from our native SDKs are not yet exposed through these React Native bindings.
11
14
  > See [Feature Support](#feature-support) for an overview of the supported features.
12
15
  >
13
- > Not seeing the features you’re looking for?
16
+ > Not seeing the features you’re looking for?
14
17
  > We are accepting community pull requests to this open-source project so please feel free to contribute.
15
18
  > or let us know in [our community](https://community.bitmovin.com/c/requests/14) what features we should work on next.
16
19
 
17
20
  - [Bitmovin Player React Native](#bitmovin-player-react-native)
18
21
  - [Platform Support](#platform-support)
19
22
  - [Feature Support](#feature-support)
20
- - [Installation](#installation)
21
- - [Add package dependency](#add-package-dependency)
22
- - [Setup iOS Player SDK](#setup-ios-player-sdk)
23
- - [Setup Android Player SDK](#setup-android-player-sdk)
24
- - [Getting Started](#getting-started)
25
- - [Setting up a license key](#setting-up-a-license-key)
26
- - [Through code](#through-code)
27
- - [Through `Info.plist`](#through-infoplist)
28
- - [Through `AndroidManifest.xml`](#through-androidmanifestxml)
29
- - [Setting up the playback configuration](#setting-up-the-playback-configuration)
30
- - [Accessing native `Player` instances](#accessing-native-player-instances)
31
- - [Listening to events](#listening-to-events)
32
- - [Enabling DRM protection](#enabling-drm-protection)
33
- - [Prepare hooks](#prepare-hooks)
34
- - [Adding external subtitle tracks](#adding-external-subtitle-tracks)
35
- - [Adding external thumbnail track](#adding-external-thumbnail-track)
36
- - [Enabling Picture in Picture mode](#enabling-picture-in-picture-mode)
37
- - [Android](#android)
38
- - [iOS](#ios)
39
- - [Showing the Picture in Picture UI option](#showing-the-picture-in-picture-ui-option)
40
- - [Supported Picture in Picture events](#supported-picture-in-picture-events)
41
- - [Customize HTML UI](#customize-html-ui-android-and-ios-only)
42
- - [Setting up fullscreen handling](#setting-up-fullscreen-handling)
43
- - [Supported fullscreen related events](#supported-fullscreen-related-events)
44
- - [Setting up ads](#setting-up-ads)
45
- - [Static ads configuration](#static-ads-configuration)
46
- - [Dynamic ads scheduling](#dynamic-ads-scheduling)
47
- - [Supported ads events](#supported-ads-events)
48
- - [Setting up analytics](#setting-up-analytics)
23
+ - [Documentation](#documentation)
24
+ - [Getting Started](#getting-started-guide)
25
+ - [Feature Guides](#feature-guides)
26
+ - [Sample Application](#sample-application)
49
27
  - [Contributing](#contributing)
50
28
 
51
29
  ## Platform Support
52
30
 
53
31
  This library requires at least React Native 0.64+ and React 17+ to work properly. The currently supported platforms are:
54
32
 
55
- - iOS 12.0+
56
- - tvOS 12.0+
57
- - Android API 16+
58
- - Android TV API 17+
59
- - Fire TV (just make sure the Android API level is at least 17+)
33
+ - iOS 14.0+
34
+ - tvOS 14.0+
35
+ - Android API Level 21+
36
+ - Android TV API Level 21+
37
+ - Fire TV FireOS 5.0+
60
38
 
61
- Please note that browsers and other browser-like environments such as webOS and Tizen are not supported.
39
+ Please note that browsers and other browser-like environments such as webOS and Tizen are not supported. For more details regarding Bitmovin Player SDK platform and device support, please refer to the [Supported Platforms & Devices](https://developer.bitmovin.com/playback/docs/supported-platforms-devices-player) page of our documentation.
62
40
 
63
41
  ## Feature Support
64
42
 
@@ -74,880 +52,19 @@ Features of the native mobile Player SDKs are progressively being implemented in
74
52
  | Casting | :x: Not available |
75
53
  | Offline Playback | :x: Not available |
76
54
 
77
- ## Installation
55
+ ## Documentation
78
56
 
79
- Since Bitmovin's native SDKs are distributed through custom [Cocoapods](https://github.com/bitmovin/cocoapod-specs) and [Maven](https://artifacts.bitmovin.com/ui/native/public-releases) repositories, the installation cannot be managed by React Native's Autolink and requires some extra steps. Please refer to the installation instructions for each platform below. For more information on integrating the native SDKs, refer to the [Getting Started guides](https://bitmovin.com/docs/getting-started).
57
+ ### Getting Started Guide
80
58
 
81
- ### Add package dependency
59
+ Our [Getting Started Guide](https://developer.bitmovin.com/playback/docs/getting-started-react-native) walks you through setting up and configuring the Bitmovin Player in React Native projects.
82
60
 
83
- This library is available as an [NPM package](https://www.npmjs.com/package/bitmovin-player-react-native) and may be added as a dependency to your project using any node-based package manager, e.g.
61
+ ### Feature Guides
84
62
 
85
- > npm
63
+ Check out our [React Native Guides](https://developer.bitmovin.com/playback/docs/guides-react-native) for more information on how to set up Player features such as Advertising, DRM-protected playback, Subtitles and more.
86
64
 
87
- ```sh
88
- npm install bitmovin-player-react-native --save
89
- ```
65
+ ### Sample Application
90
66
 
91
- > yarn
92
-
93
- ```sh
94
- yarn add bitmovin-player-react-native
95
- ```
96
-
97
- ### Setup iOS Player SDK
98
-
99
- If you ran `pod install` after installing the node package and received an error similar to the one below, it is because Bitmovin's custom cocoapods repository has not been added to the `Podfile` and the [`iOS Player SDK`](https://github.com/bitmovin/bitmovin-player-ios-samples) could not be resolved:
100
-
101
- ```
102
- [!] Unable to find a specification for `BitmovinPlayer (= 3.xx.x)` depended upon by `RNBitmovinPlayer`
103
-
104
- You have either:
105
- * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
106
- * mistyped the name or version.
107
- * not added the source repo that hosts the Podspec to your Podfile.
108
- ```
109
-
110
- To fix above error, open your `ios/Podfile` and set up Bitmovin's pods source url:
111
-
112
- ```ruby
113
- require_relative '../node_modules/react-native/scripts/react_native_pods'
114
- require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
115
-
116
- # Bitmovin pods source url
117
- source 'https://github.com/bitmovin/cocoapod-specs.git'
118
-
119
- # iOS version should be 12 or greater.
120
- # If you are running RN 0.69 you should be fine already.
121
- platform :ios, '12.4'
122
- install! 'cocoapods', :deterministic_uuids => false
123
-
124
- target 'MyApp' do
125
- config = use_native_modules!
126
-
127
- # Rest of Podfile...
128
- ```
129
-
130
- Now run `pod install` again (try with `--repo-update` if the error persists) - the error should now be resolved.
131
-
132
- ### Setup Android Player SDK
133
-
134
- The Android setup also needs an extra step in order to correctly resolve the [Android Player SDK](https://github.com/bitmovin/bitmovin-player-android-samples) native dependency.
135
-
136
- Just make sure to add Bitmovin's artifacts repository to the `allprojects.repositories` section of your `android/build.gradle`:
137
-
138
- ```groovy
139
- allprojects {
140
- repositories {
141
- maven { url("$rootDir/../node_modules/react-native/android") }
142
- maven { url("$rootDir/../node_modules/jsc-android/dist") }
143
- mavenCentral {
144
- content {
145
- excludeGroup "com.facebook.react"
146
- }
147
- }
148
- google()
149
- maven { url 'https://www.jitpack.io' }
150
- // Add Bitmovin's artifacts repository url
151
- maven { url 'https://artifacts.bitmovin.com/artifactory/public-releases' }
152
- }
153
- }
154
- ```
155
-
156
- ## Getting Started
157
-
158
- The following is the simplest working component one can create using this library:
159
-
160
- ```typescript
161
- import React, { useEffect, useCallback } from 'react';
162
- import { View, Platform, StyleSheet } from 'react-native';
163
- import {
164
- usePlayer,
165
- SourceType,
166
- PlayerView,
167
- } from 'bitmovin-player-react-native';
168
-
169
- export default function PlayerSample() {
170
- // The `usePlayer` hook creates or references a certain native `Player`
171
- // instance from within any component.
172
- const player = usePlayer({
173
- // The only required parameter is the license key but it can be omitted from code upon correct
174
- // Info.plist/AndroidManifest.xml configuration.
175
- //
176
- // Head to `Setting up a license key` for more information.
177
- licenseKey: '<ENTER-YOUR-LICENSE-KEY>',
178
- });
179
-
180
- useEffect(() => {
181
- // Load a streamable video source during component's initialization.
182
- player.load({
183
- // Select url and type dependeding on the running platform.
184
- url:
185
- Platform.OS === 'ios'
186
- ? // HLS for iOS
187
- 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8'
188
- : // Dash for Android
189
- 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/mpds/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.mpd',
190
- type: Platform.OS === 'ios' ? SourceType.HLS : SourceType.DASH,
191
- // Optionally set a title that will appear at player's top-left corner.
192
- title: 'Art of Motion',
193
- // Optionally load a poster image over the player.
194
- poster:
195
- 'https://bitmovin-a.akamaihd.net/content/MI201109210084_1/poster.jpg',
196
- // Optionally set whether poster image will persist over player.
197
- // Useful for audio-only streams. Default to false.
198
- isPosterPersistent: false,
199
- });
200
- }, [player]);
201
-
202
- // onReady is called when the player has downloaded initial
203
- // video and audio and is ready to start playback.
204
- const onReady = useCallback(
205
- (event) => {
206
- // Start playback
207
- player.play();
208
- // Print event timestamp
209
- console.log(event.timestamp);
210
- },
211
- [player]
212
- );
213
-
214
- // Make sure to pass the `player` prop in `PlayerView`.
215
- return (
216
- <View style={styles.flex1}>
217
- <PlayerView style={styles.flex1} player={player} onReady={onReady} />
218
- </View>
219
- );
220
- }
221
-
222
- const styles = StyleSheet.create({
223
- flex1: {
224
- flex: 1,
225
- },
226
- });
227
- ```
228
-
229
- If you're interested in a complete running example, head to [`example/`](https://github.com/bitmovin/bitmovin-player-react-native/tree/main/example).
230
-
231
- ### Setting up a license key
232
-
233
- First of all, create a license key on the [Dashboard](https://bitmovin.com/dashboard) and then make sure to associate your iOS app bundle id with it (see more [here](https://bitmovin.com/docs/player/getting-started/ios#step-3-configure-your-player-license)).
234
-
235
- Then your license key can be either set from code or by configuring `Info.plist` and `AndroidManifest.xml`.
236
-
237
- #### Through code
238
-
239
- ```typescript
240
- // Simply pass the `licenseKey` property to `PlayerConfig` when instantiating a player.
241
-
242
- // With hooks
243
- import { usePlayer } from 'bitmovin-player-react-native';
244
- const player = usePlayer({
245
- licenseKey: '<ENTER-YOUR-LICENSE-KEY>',
246
- });
247
-
248
- // Without hooks
249
- import { Player } from 'bitmovin-player-react-native';
250
- const player = new Player({
251
- // Make sure to use React.createRef if instantiating inside a component.
252
- licenseKey: '<ENTER-YOUR-LICENSE-KEY>',
253
- });
254
- ```
255
-
256
- #### Through `Info.plist`
257
-
258
- Add the following lines to the `<dict>` section of your `ios/Info.plist`:
259
-
260
- ```xml
261
- <key>BitmovinPlayerLicenseKey</key>
262
- <string>ENTER-YOUR-LICENSE-KEY</string>
263
- ```
264
-
265
- #### Through `AndroidManifest.xml`
266
-
267
- Add the following line to the `<application>` section of your `android/app/src/main/AndroidManifest.xml`:
268
-
269
- ```xml
270
- <meta-data android:name="BITMOVIN_PLAYER_LICENSE_KEY" android:value="ENTER-YOUR-LICENSE-KEY" />
271
- ```
272
-
273
- ### Setting up the playback configuration
274
-
275
- If needed, the default player behavior can be configured through the `playbackConfig` key when initialized.
276
-
277
- ```typescript
278
- // Simply pass the `playbackConfig` property to `PlayerConfig` when instantiating a player.
279
-
280
- // With hooks
281
- import { usePlayer } from 'bitmovin-player-react-native';
282
- const player = usePlayer({
283
- playbackConfig: {
284
- // Specifies whether the playback starts immediately after loading a source or not. Default is false.
285
- isAutoplayEnabled: true,
286
- // Specifies if playback starts muted. Default is false.
287
- isMuted: true,
288
- // Specifies if time shift for live streams should be enabled. Default is true.
289
- isTimeShiftEnabled: true,
290
- // Whether background playback is enabled or not. Default is false.
291
- // Only available for iOS.
292
- isBackgroundPlaybackEnabled: true,
293
- // Enable the Picture in Picture mode option on the player controls.
294
- //
295
- // Note iOS requires the audio session category of your app to be set to `playback` otherwise
296
- // PiP mode won't work.
297
- //
298
- // Check out `Enabling Picture in Picture mode` section of README for more information
299
- // on how to properly configure your app to support PiP.
300
- isPictureInPictureEnabled: true,
301
- },
302
- });
303
-
304
- // Without hooks
305
- import { Player } from 'bitmovin-player-react-native';
306
- const player = new Player({
307
- // Make sure to use React.createRef if instantiating inside a component.
308
- playbackConfig: {
309
- isAutoplayEnabled: true,
310
- isMuted: true,
311
- isTimeShiftEnabled: true,
312
- isBackgroundPlaybackEnabled: true,
313
- isPictureInPictureEnabled: true,
314
- },
315
- });
316
- ```
317
-
318
- ### Accessing native `Player` instances
319
-
320
- When you instantiate a player with `usePlayer` or `new Player()` from javascript, you're actually either creating a new `Player` instance in the native side (see [SDKs docs](https://bitmovin.com/docs/player/sdks) for more info) or referencing an existing one.
321
-
322
- So it means that a player with the same `nativeId` in two different parts of the code is referencing the same in-memory instance internally.
323
-
324
- **Example**
325
-
326
- Both components in the example below are referencing the same native `Player` indexed as `my-player`. And even though each `<PlayerView />` creates a different `View` internally, the `Player` instance (which is a separate thing) remains the same. It just gets attached to a different view.
327
-
328
- ```typescript
329
- // Using `usePlayer`
330
- export const CompA = () => {
331
- // Same `player` as in `CompB`.
332
- const player = usePlayer({
333
- nativeId: 'my-player',
334
- });
335
- return <PlayerView player={player} />;
336
- };
337
-
338
- // Using `new Player()`
339
- export const CompB = () => {
340
- // Same `player` as in `CompA`.
341
- const player = useRef(
342
- new Player({
343
- nativeId: 'my-player',
344
- })
345
- );
346
- return <PlayerView player={player.current} />;
347
- };
348
- ```
349
-
350
- ### Listening to events
351
-
352
- Both player and source events can be registered from `PlayerView`, but not all of them. For a complete list of the events currently available, checkout [`EventProps`](https://github.com/bitmovin/bitmovin-player-react-native/blob/main/src/components/PlayerView/events.ts#L29) and [`events.ts`](https://github.com/bitmovin/bitmovin-player-react-native/blob/main/src/events.ts).
353
-
354
- To register an event callback, just pass its name prefixed with `on` as a `PlayerView` prop:
355
-
356
- ```typescript
357
- return (
358
- <PlayerView
359
- onReady={onReady}
360
- onMuted={onMuted}
361
- onPaused={onPaused}
362
- onPlayerActive={onPlayerActive}
363
- onSourceLoaded={onSourceLoaded}
364
- onPlayerError={onPlayerError}
365
- onSourceError={onSourceError}
366
- onPlaybackFinished={onPlaybackFinished}
367
- {...}
368
- />
369
- );
370
- ```
371
-
372
- ### Enabling DRM protection
373
-
374
- > ⚠️ **Beta Version**: For now, only `FairPlay` is supported on iOS and
375
- > only `Widevine` is supported on Android. More DRM systems will be added in the future.
376
-
377
- Simple streaming of protected assets can be enabled with just a little configuration on `SourceConfig.drmConfig`:
378
-
379
- ```typescript
380
- import { Platform } from 'react-native';
381
- import { SourceConfig, SourceType } from 'bitmovin-player-react-native';
382
-
383
- // Source configuration for protected assets.
384
- const drmSource: SourceConfig = {
385
- // Protected stream URL.
386
- url:
387
- Platform.OS === 'ios'
388
- ? 'https://fps.ezdrm.com/demo/video/ezdrm.m3u8' // iOS stream url
389
- : 'https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/mpds/11331.mpd', // Android stream url
390
- // Stream type.
391
- type: Platform.OS === 'ios' ? SourceType.HLS : SourceType.DASH,
392
- // DRM setup.
393
- // Each key in this object maps to a different DRM system config (`widevine` or `fairplay`).
394
- drmConfig: {
395
- // Widevine is the default and only DRM system supported on Android for now.
396
- widevine: {
397
- licenseUrl: 'https://cwip-shaka-proxy.appspot.com/no_auth',
398
- },
399
- // FairPlay is the default and only DRM system supported on iOS for now.
400
- fairplay: {
401
- licenseUrl:
402
- 'https://fps.ezdrm.com/api/licenses/09cc0377-6dd4-40cb-b09d-b582236e70fe',
403
- certificateUrl: 'https://fps.ezdrm.com/demo/video/eleisure.cer',
404
- },
405
- },
406
- };
407
- ```
408
-
409
- #### Prepare hooks
410
-
411
- In the native SDKs, some DRM properties like `message` and `license` can have their value transformed before use in order
412
- to enable some more complex use cases: such as extracting the `license` from a `JSON`, for example.
413
-
414
- In order to handle such transformations, it's possible to hook methods onto `SourceConfig.drmConfig` to proxy DRM values
415
- and potentially alter them:
416
-
417
- ```typescript
418
- import { Platform } from 'react-native';
419
- import { SourceConfig, SourceType } from 'bitmovin-player-react-native';
420
-
421
- // Source configuration for protected assets.
422
- const drmSource: SourceConfig = {
423
- // Protected stream URL.
424
- url:
425
- Platform.OS === 'ios'
426
- ? 'https://fps.ezdrm.com/demo/video/ezdrm.m3u8' // iOS stream url
427
- : 'https://bitmovin-a.akamaihd.net/content/art-of-motion_drm/mpds/11331.mpd', // Android stream url
428
- // Stream type.
429
- type: Platform.OS === 'ios' ? SourceType.HLS : SourceType.DASH,
430
- // DRM setup.
431
- drmConfig: {
432
- // Widevine is the default and only DRM system supported on Android for now.
433
- widevine: {
434
- licenseUrl: 'https://cwip-shaka-proxy.appspot.com/no_auth',
435
- // Data is passed as a base64 string and expects to return a base64 string.
436
- prepareLicense: (license: string) => {
437
- // Do something with the `license` value...
438
- // And return processed data as base64 string.
439
- return license; // base64 string
440
- },
441
- },
442
- // FairPlay is the default and only DRM system supported on iOS for now.
443
- fairplay: {
444
- licenseUrl:
445
- 'https://fps.ezdrm.com/api/licenses/09cc0377-6dd4-40cb-b09d-b582236e70fe',
446
- certificateUrl: 'https://fps.ezdrm.com/demo/video/eleisure.cer',
447
- // Data is passed as a base64 string and expects to return a base64 string.
448
- prepareLicense: (license: string) => {
449
- // Do something with the `license` value...
450
- // And return processed data as base64 string.
451
- return license; // base64 string
452
- },
453
- // Data is passed as a base64 string and expects to return a base64 string.
454
- prepareMessage: (message: string, assetId: string) => {
455
- // Do something with the `assetId` and `message` values...
456
- // And return processed data as base64 string.
457
- return message; // base64 string
458
- },
459
- },
460
- },
461
- };
462
- ```
463
-
464
- The [`FairplayConfig`](https://github.com/bitmovin/bitmovin-player-react-native/blob/development/src/drm/fairplayConfig.ts) interface provides a bunch of hooks that can be used to fetch and transform different DRM related data. Check out the [docs]([https://github.com/bitmovin/bitmovin-player-react-native/blob/development/src/drm/fairplayConfig.ts](https://github.com/bitmovin/bitmovin-player-react-native/blob/development/src/drm/fairplayConfig.ts)) for a complete list and detailed information on them.
465
-
466
- Also, don't forget to check out the [example](https://github.com/bitmovin/bitmovin-player-react-native/tree/development/example) app for a complete iOS/Android [DRM example](https://github.com/bitmovin/bitmovin-player-react-native/blob/development/example/src/screens/BasicDrmPlayback.tsx).
467
-
468
- ### Adding external subtitle tracks
469
-
470
- Usually, subtitle tracks are provided in the manifest of your content (see [Enconding Manifests API](https://bitmovin.com/docs/encoding/api-reference/sections/manifests) for more information). And if they are provided this way, the player already recognizes them and show them in the subtitles selection menu without any further configuration.
471
-
472
- Otherwise, it's also possible to add external tracks via the subtitle API:
473
-
474
- ```typescript
475
- import { Platform } from 'react-native';
476
- import {
477
- SourceConfig,
478
- SourceType,
479
- SubtitleFormat,
480
- } from 'bitmovin-player-react-native';
481
-
482
- // Source config with an external subtitle track.
483
- const config: SourceConfig = {
484
- url:
485
- Platform.OS === 'ios'
486
- ? 'https://bitmovin-a.akamaihd.net/content/sintel/hls/playlist.m3u8'
487
- : 'https://bitmovin-a.akamaihd.net/content/sintel/sintel.mpd',
488
- type: Platform.OS === 'ios' ? SourceType.HLS : SourceType.DASH,
489
- poster: 'https://bitmovin-a.akamaihd.net/content/sintel/poster.png',
490
- // External subtitle tracks list to be added to this source.
491
- subtitleTracks: [
492
- // You can select 'Custom English' in the subtitles menu.
493
- {
494
- // The URL of the subtitle file. Required.
495
- url: 'https://bitdash-a.akamaihd.net/content/sintel/subtitles/subtitles_en.vtt',
496
- // External file format.
497
- // Supports `.vtt`, `.ttml` and `.cea` extensions.
498
- //
499
- // This option can be left empty since the player automatically recognizes the format
500
- // from the provided url most of the time.
501
- format: SubtitleFormat.VTT,
502
- // Label for this track shown under the selection menu. Required.
503
- label: 'Custom English',
504
- // The IETF BCP 47 language tag associated with this track. Required.
505
- language: 'en',
506
- // The unique identifier used for this track.
507
- // The default value for this options is a randomly generated UUID.
508
- identifier: 'sub1',
509
- // This track is considered the default if set to `true`.
510
- // The default value for this option is `false`.
511
- isDefault: false,
512
- // If set to `true` it means that the player should automatically select and switch this
513
- // subtitle according to the selected audio language. Forced subtitles do not appear in
514
- // `Player.getAvailableSubtitles`.
515
- //
516
- // The default value for this option is `false`.
517
- isForced: false,
518
- },
519
- // You may add even more tracks to the list...
520
- ],
521
- };
522
- ```
523
-
524
- The supported `PlayerView` events for subtitles are:
525
-
526
- - `onSubtitleAdded`
527
- - `onSubtitleRemoved`
528
- - `onSubtitleChanged`
529
-
530
- You might check out a complete subtitle example in the [`example/`](https://github.com/bitmovin/bitmovin-player-react-native/tree/development/example) app.
531
-
532
- ### Adding external thumbnail track
533
-
534
- Thumbnail seeking is a must have for any video longer than a few minutes. It increases usability and the general QoE [(Quality of Experience)](https://bitmovin.com/ultra-high-definition-quality-experience-mpeg-dash-part-1/) dramatically.
535
-
536
- Setting up is simple with the Bitmovin Player. Thumbnails are loaded into the timeline as a track. All you need to do is to tell the player the location of the thumbnail file:
537
-
538
- ```typescript
539
- import { Platform } from 'react-native';
540
- import {
541
- SourceConfig,
542
- SourceType,
543
- SubtitleFormat,
544
- } from 'bitmovin-player-react-native';
545
-
546
- // Source config with an external subtitle track.
547
- const config: SourceConfig = {
548
- url:
549
- Platform.OS === 'ios'
550
- ? 'https://bitmovin-a.akamaihd.net/content/sintel/hls/playlist.m3u8'
551
- : 'https://bitmovin-a.akamaihd.net/content/sintel/sintel.mpd',
552
- type: Platform.OS === 'ios' ? SourceType.HLS : SourceType.DASH,
553
- poster: 'https://bitmovin-a.akamaihd.net/content/sintel/poster.png',
554
- // External thumbnail track url to be added to this source.
555
- thumbnailTrack:
556
- 'https://cdn.bitmovin.com/content/assets/art-of-motion-dash-hls-progressive/thumbnails/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.vtt',
557
- };
558
- ```
559
-
560
- What’s required for a video player with thumbnails
561
-
562
- Adaptive Streaming relies on encoding your video into several groups of files (streams) at various resolutions, while thumbnails also need to be generated in the encoding process. The encoder creates a set of thumbnail images and combines them into a single image file (“Sprite”). For more information on encoding your videos, have a look at our [Cloud Encoding Service](https://bitmovin.com/encoding/).
563
-
564
- ### Enabling Picture in Picture mode
565
-
566
- In order to make use of the Picture in Picture functionalities provided by the player, it's first necessary to configure your native application to properly support PiP.
567
-
568
- The steps required for each platform are described below:
569
-
570
- #### Android
571
-
572
- **Declare Picture in Picture support on AndroidManifest.xml**
573
-
574
- Open `android/app/src/main/AndroidManifest.xml` and set `android:supportsPictureInPicture` to `true`
575
- on your main activity's manifest. Also, specify that your activity handles layout configuration changes
576
- so that your activity doesn't relaunch when layout changes occur during PiP mode transitions:
577
-
578
- ```xml
579
- <activity android:name=".MainActivity"
580
- android:supportsPictureInPicture="true"
581
- android:configChanges=
582
- "screenSize|smallestScreenSize|screenLayout|orientation"
583
- ...
584
- ```
585
-
586
- #### iOS
587
-
588
- **Set background modes capability**
589
-
590
- Make sure to add the `UIBackgroundModes` key to the `dict` section of your `Info.plist`:
591
-
592
- ```xml
593
- <key>UIBackgroundModes</key>
594
- <array>
595
- <string>audio</string>
596
- </array>
597
- ```
598
-
599
- This step can also be performed from [Xcode](https://developer.apple.com/documentation/xcode/configuring-background-execution-modes).
600
-
601
- **Configure audio session on app startup**
602
-
603
- Configure your app's `AudioSession` category to `playback` during the main component's initialization:
604
-
605
- ```typescript
606
- import { AudioSession } from 'bitmovin-player-react-native';
607
-
608
- // App's root component
609
- const App = () => {
610
- useEffect(() => {
611
- // Set your app's `AudioSession` category to `playback` on initialization.
612
- // Please, note even though this step is required for iOS it won't take any effect on Android.
613
- AudioSession.setCategory('playback').catch((error) => {
614
- // Handle any native error that might occur during this process.
615
- handleError(error);
616
- });
617
- });
618
- // ...
619
- return /* ... */;
620
- };
621
- ```
622
-
623
- This step is required in order to properly enable background playback on iOS. Without it, the Picture in Picture option appears on the player UI but has no effect when used.
624
-
625
- You can read more about it on [Apple's docs](https://developer.apple.com/documentation/avfaudio/avaudiosession/category/1616509-playback).
626
-
627
- #### Showing the Picture in Picture UI option
628
-
629
- Now that your native application is properly configured to support PiP changes, the player instance
630
- in your JS code can be configured to show the Picture in Picture option in the player UI.
631
-
632
- Simply add `isPictureInPictureEnabled: true` on your player's `playbackConfig` option:
633
-
634
- ```typescript
635
- const player = usePlayer({
636
- playbackConfig: {
637
- isPictureInPictureEnabled: true,
638
- },
639
- });
640
- ```
641
-
642
- #### Supported Picture in Picture events
643
-
644
- The supported Picture in Picture events on `PlayerView` are:
645
-
646
- - `onPictureInPictureEnter`
647
- - `onPictureInPictureExit`
648
-
649
- **iOS only**
650
-
651
- - `onPictureInPictureEntered`
652
- - `onPictureInPictureExited`
653
-
654
- **Android only**
655
-
656
- - `onPictureInPictureAvailabilityChanged`
657
-
658
- Check [`events.ts`](https://github.com/bitmovin/bitmovin-player-react-native/blob/development/src/components/PlayerView/events.ts) for more information about them.
659
-
660
- ### Customize HTML UI (Android and iOS only)
661
-
662
- The Bitmovin Player SDKs use the open source [Bitmovin Player Web UI](https://github.com/bitmovin/bitmovin-player-ui) on all platforms, except tvOS.
663
- The UI is customizable in multiple ways.
664
-
665
- #### Custom implementation
666
-
667
- Since the Bitmovin Player Web UI is open source, it can be forked and modified to tailor to any application's needs.
668
- See [Cusomizing the UI](https://github.com/bitmovin/bitmovin-player-ui#customizing-the-ui) section for details.
669
-
670
- In case a custom implementation of the Player UI is desired, configure the hosted JS and CSS files via the `StyleConfig` as shown in the following example:
671
-
672
- ```ts
673
- const player = usePlayer({
674
- styleConfig: {
675
- playerUiCss: 'CUSTOM_UI_CSS_URL',
676
- playerUiJs: 'CUSTOM_UI_JS_URL',
677
- },
678
- });
679
- ```
680
-
681
- #### Custom CSS
682
-
683
- Customization of the default built-in Bitmovin Player UI is possible via providing custom styling CSS by only configuring `playerUiCss` as shown in the following example:
684
-
685
- ```ts
686
- const player = usePlayer({
687
- styleConfig: {
688
- playerUiCss: 'CUSTOM_UI_CSS_URL',
689
- },
690
- });
691
- ```
692
-
693
- #### Supplemental CSS
694
-
695
- In case the usage of the default Bitmovin Player UI is sufficient with minor additional styling, it can be achieved via providing the URL to the additional CSS stylesheet via `supplementalPlayerUiCss`.
696
-
697
- ```ts
698
- const player = usePlayer({
699
- styleConfig: {
700
- supplementalPlayerUiCss: 'SUPPLEMENTAL_UI_CSS_URL',
701
- },
702
- });
703
- ```
704
-
705
- ### Setting up fullscreen handling
706
-
707
- In order to enable the player to support fullscreen and show the fullscreen button when using the Bitmovin Player Web UI, a `FullscreenHandler` needs to be implemented.
708
- Its responsibility is to update the UI when transitioning between fullscreen and non-fullscreen states.
709
- The player view itself does not update it's presentation as the meaning of fullscreen is determined by the application integrating our library.
710
-
711
- Here are the basics of enabling fullscreen support:
712
-
713
- ```typescript
714
- // Define a handler to take care of fullscreen transitions
715
- class SampleFullscreenHandler implements FullscreenHandler {
716
- isFullscreenActive: boolean = true;
717
- onFullscreen: (fullscreenMode: boolean) => void;
718
-
719
- constructor(
720
- isFullscreenActive: boolean,
721
- onFullscreen: (fullscreenMode: boolean) => void
722
- ) {
723
- this.isFullscreenActive = isFullscreenActive;
724
- this.onFullscreen = onFullscreen;
725
- }
726
-
727
- enterFullscreen(): void {
728
- // Update UI state for fullscreen mode
729
- this.onFullscreen(true);
730
- this.isFullscreenActive = true;
731
- console.log('enter fullscreen');
732
- }
733
-
734
- exitFullscreen(): void {
735
- // Update UI state for non-fullscreen mode
736
- this.onFullscreen(false);
737
- this.isFullscreenActive = false;
738
- console.log('exit fullscreen');
739
- }
740
- }
741
-
742
- export default function BasicFullscreenHandling() {
743
- // Set up player and other components
744
-
745
- // Create SampleFullscreenHandler instance and enable it to update state
746
- const [fullscreenMode, setFullscreenMode] = useState(false);
747
- const fullscreenHandler = new SampleFullscreenHandler(
748
- fullscreenMode,
749
- setFullscreenMode
750
- );
751
-
752
- return (
753
- <View>
754
- <PlayerView
755
- player={player}
756
- style={fullscreenMode ? styles.playerFullscreen : styles.player}
757
- fullscreenHandler={fullscreenHandler}
758
- onFullscreenEnter={onFullscreenEnter}
759
- onFullscreenExit={onFullscreenExit}
760
- onFullscreenEnabled={onFullscreenEnabled}
761
- onFullscreenDisabled={onFullscreenDisabled}
762
- />
763
- </View>
764
- );
765
- }
766
-
767
- // Define your styles
768
- const styles = StyleSheet.create({
769
- player: {
770
- flex: 1,
771
- backgroundColor: 'black',
772
- },
773
- playerFullscreen: {
774
- position: 'absolute',
775
- top: 0,
776
- right: 0,
777
- bottom: 0,
778
- left: 0,
779
- backgroundColor: 'black',
780
- },
781
- });
782
- ```
783
-
784
- Check [`BasicFullscreenHandling.tsx`](https://github.com/bitmovin/bitmovin-player-react-native/blob/development/example/src/screens/BasicFullscreenHandling.tsx) for a full example implementation.
785
-
786
- #### Supported fullscreen related events
787
-
788
- The supported fullscreen events on `PlayerView` are:
789
-
790
- - `onFullscreenEnter`
791
- - `onFullscreenExit`
792
- - `onFullscreenEnabled`
793
- - `onFullscreenDisabled`
794
-
795
- Check [`events.ts`](https://github.com/bitmovin/bitmovin-player-react-native/blob/development/src/components/PlayerView/events.ts) for more information about them.
796
-
797
- ### Setting up ads
798
-
799
- The Bitmovin Player SDKs are capable of displaying Ads out of the box and there are two ways they can be
800
- configured with the player. One option is to use static configuration in the player config object,
801
- and the other is to schedule them dynamically using `Player.scheduleAd`.
802
-
803
- #### Static ads configuration
804
-
805
- The easiest way to configure Ads is by adding the `advertisingConfig` property to the player configuration object.
806
- All that needs to be provided is a URL pointing to a target Ad tag along with the type of the tag.
807
-
808
- ```typescript
809
- const player = usePlayer({
810
- licenseKey: '<PLAYER_LICENSE_KEY>',
811
- advertisingConfig: {
812
- // Each object in `schedule` represents an `AdItem`.
813
- schedule: [
814
- // An `AdItem` represents a time slot within the streamed content dedicated to ads playback.
815
- {
816
- // Each item specifies a list of sources with a type and URL to the ad manifest in the ads
817
- // server. All but the first source act as fallback if the first one fails to load.
818
- // The start and end of an ad break are signaled via `AdBreakStartedEvent` and `AdBreakFinishedEvent`.
819
- sources: [
820
- {
821
- type: AdSourceType.IMA,
822
- tag: 'https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/single_ad_samples&ciu_szs=300x250&impl=s&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ct%3Dskippablelinear&correlator=',
823
- },
824
- // Fallback sources...
825
- ],
826
- // Each item also specifies the position where it should appear during playback.
827
- // The possible position values are documented below.
828
- // The default value is `pre`.
829
- position: '20%',
830
- },
831
- ],
832
- },
833
- });
834
- ```
835
-
836
- The possible `AdItem` position values are:
837
-
838
- - `"pre"`: pre-roll ad (for VoD and Live streaming; appears before playback starts)
839
- - `"post"`: post-roll ad (for VoD streaming only; appears after playback finishes)
840
- - Fractional seconds: `"10"`, `"12.5"` (mid-roll ad, for VoD and Live streaming)
841
- - Percentage of the entire video duration: `"25%"`, `"50%"` (mid-roll ad, for VoD streaming only)
842
- - Timecode `hh:mm:ss.mmm`: `"00:10:30.000"`, `"01:00:00.000"` (mid-roll ad, for VoD streaming only)
843
-
844
- #### Dynamic ads scheduling
845
-
846
- To gain more flexibility, it is also possible to schedule an `AdItem` dynamically in code using the
847
- `Player` instance. To do this, you need to call the `scheduleAd` method.
848
-
849
- ```typescript
850
- // The object passed to `scheduleAd` must be an `AdItem`.
851
- player.scheduleAd({
852
- // Ad source with fallbacks.
853
- sources: [
854
- {
855
- tag: '<AD-URL>',
856
- type: AdSourceType.IMA,
857
- },
858
- ],
859
- });
860
- ```
861
-
862
- An `AdScheduledEvent` event is dispatched when the ad is successfully scheduled via `scheduleAd`.
863
-
864
- Also, during playback, it's also possible to check whether an ad is being played with `player.isAd()`
865
- and skip the ad being currently played with `player.skipAd()` (see `AdSkippedEvent`).
866
-
867
- #### Supported ads events
868
-
869
- The supported `PlayerView` events for ads are:
870
-
871
- - `onAdBreakFinished`
872
- - `onAdBreakStarted`
873
- - `onAdClicked`
874
- - `onAdError`
875
- - `onAdFinished`
876
- - `onAdManifestLoad`
877
- - `onAdManifestLoaded`
878
- - `onAdQuartile`
879
- - `onAdScheduled`
880
- - `onAdSkipped`
881
- - `onAdStarted`
882
-
883
- You can check out a complete ads example in the [`example/`](https://github.com/bitmovin/bitmovin-player-react-native/tree/development/example) app.
884
-
885
- ### Setting up analytics
886
-
887
- Each `Player` instance has an associated analytics collector that can be configured to send analytics information about it. By default,
888
- the associated collector is disabled unless an `analyticsConfig` option is specified. So in order to get analytics up and running, add the following configuration options to your `PlayerConfig`:
889
-
890
- ```typescript
891
- const player = usePlayer({
892
- analyticsConfig: {
893
- // Bitmovin analytics key from the Analytics Dashboard
894
- key: '<ANALYTICS-KEY>', // `key` is the only required parameter.
895
- // Bitmovin player license key
896
- playerKey: '<BITMOVIN-PLAYER-KEY>',
897
- // Asset CDN provider. Check out `CdnProvider` on `src/analytics/config.ts` for more options.
898
- cdnProvider: CdnProvider.AKAMAI,
899
- // User-defined user ID.
900
- customUserId: 'Custom user ID',
901
- // Whether the user ID should be randomly generated or not. Default value is false.
902
- randomizeUserId: false,
903
- // Experiment name that'll appear at the Analytics Dashboard.
904
- experimentName: 'Experiment name',
905
- // Video ID on your server
906
- videoId: 'MyVideoId',
907
- // Video title
908
- title: 'Art of Motion',
909
- // Whether this is a live stream video. Default is false.
910
- isLive: false,
911
- // Whether collector should also collect statistics about ads
912
- // Can be changed to `true` in case `advertisingConfig` is also present.
913
- // Default is false.
914
- ads: false,
915
- // Navigation breadcrumb.
916
- // The path taken by the user inside your application.
917
- path: '/examples/basic_analytics',
918
- // List of custom data fields to be registered at the Analytics Dashboard.
919
- // Useful to customize collection with your own data along with the SDK.
920
- customData1: 'Custom data field 1',
921
- customData2: 'Custom data field 2',
922
- customData3: 'Custom data field 3',
923
- customData4: 'Custom data field 4',
924
- customData5: 'Custom data field 5',
925
- // Usage of customData properties are supported up to 30 fields
926
- customData30: 'Custom data field 30',
927
- },
928
- });
929
- ```
930
-
931
- And that's it. Now you should start receiving analytics information about your `player` instance on the [Analytics Dashboard](https://bitmovin.com/dashboard/analytics).
932
-
933
- Optionally, you can also access the configured `analyticsCollector` object in order to get some information (like `userId`) or
934
- update your custom data during runtime:
935
-
936
- ```typescript
937
- // Get the current user id.
938
- const userId = await player.analyticsCollector?.getUserId();
939
-
940
- // Get the current custom data config.
941
- const customData = await player.analyticsCollector?.getCustomData();
942
-
943
- // Update the current custom data config.
944
- player.analyticsCollector?.setCustomDataOnce({
945
- customData2: 'Updated custom data field 2',
946
- customData4: 'Updated custom data field 4',
947
- });
948
- ```
949
-
950
- You can check out a complete analytics example in the [`example/`](https://github.com/bitmovin/bitmovin-player-react-native/tree/development/example) app.
67
+ In the [/example/](https://github.com/bitmovin/bitmovin-player-react-native/tree/development/example) folder you can find a sample application showcasing many of the features of the Player React Native SDK.
951
68
 
952
69
  ## Contributing
953
70