@mux/mux-data-react-native-video 0.5.7
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/.eslintrc +9 -0
- package/CHANGELOG.md +124 -0
- package/DemoApp/.buckconfig +6 -0
- package/DemoApp/.eslintrc.js +4 -0
- package/DemoApp/.flowconfig +75 -0
- package/DemoApp/.gitattributes +1 -0
- package/DemoApp/.prettierrc.js +6 -0
- package/DemoApp/.watchmanconfig +1 -0
- package/DemoApp/App.js +121 -0
- package/DemoApp/README.md +17 -0
- package/DemoApp/__tests__/App-test.js +14 -0
- package/DemoApp/android/app/BUCK +55 -0
- package/DemoApp/android/app/build.gradle +201 -0
- package/DemoApp/android/app/build_defs.bzl +19 -0
- package/DemoApp/android/app/debug.keystore +0 -0
- package/DemoApp/android/app/proguard-rules.pro +10 -0
- package/DemoApp/android/app/src/debug/AndroidManifest.xml +8 -0
- package/DemoApp/android/app/src/main/AndroidManifest.xml +26 -0
- package/DemoApp/android/app/src/main/java/com/demoapp/MainActivity.java +15 -0
- package/DemoApp/android/app/src/main/java/com/demoapp/MainApplication.java +74 -0
- package/DemoApp/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/DemoApp/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/DemoApp/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/DemoApp/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/DemoApp/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/DemoApp/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/DemoApp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/DemoApp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/DemoApp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/DemoApp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/DemoApp/android/app/src/main/res/values/strings.xml +3 -0
- package/DemoApp/android/app/src/main/res/values/styles.xml +9 -0
- package/DemoApp/android/build.gradle +38 -0
- package/DemoApp/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/DemoApp/android/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/DemoApp/android/gradle.properties +21 -0
- package/DemoApp/android/gradlew +188 -0
- package/DemoApp/android/gradlew.bat +100 -0
- package/DemoApp/android/settings.gradle +3 -0
- package/DemoApp/app.json +4 -0
- package/DemoApp/babel.config.js +3 -0
- package/DemoApp/index.js +9 -0
- package/DemoApp/ios/DemoApp/AppDelegate.h +15 -0
- package/DemoApp/ios/DemoApp/AppDelegate.m +42 -0
- package/DemoApp/ios/DemoApp/Base.lproj/LaunchScreen.xib +42 -0
- package/DemoApp/ios/DemoApp/Images.xcassets/AppIcon.appiconset/Contents.json +38 -0
- package/DemoApp/ios/DemoApp/Images.xcassets/Contents.json +6 -0
- package/DemoApp/ios/DemoApp/Info.plist +57 -0
- package/DemoApp/ios/DemoApp/main.m +16 -0
- package/DemoApp/ios/DemoApp-tvOS/Info.plist +53 -0
- package/DemoApp/ios/DemoApp-tvOSTests/Info.plist +24 -0
- package/DemoApp/ios/DemoApp.xcodeproj/project.pbxproj +942 -0
- package/DemoApp/ios/DemoApp.xcodeproj/xcshareddata/xcschemes/DemoApp-tvOS.xcscheme +129 -0
- package/DemoApp/ios/DemoApp.xcodeproj/xcshareddata/xcschemes/DemoApp.xcscheme +129 -0
- package/DemoApp/ios/DemoApp.xcworkspace/contents.xcworkspacedata +10 -0
- package/DemoApp/ios/DemoAppTests/DemoAppTests.m +72 -0
- package/DemoApp/ios/DemoAppTests/Info.plist +24 -0
- package/DemoApp/ios/Podfile +59 -0
- package/DemoApp/ios/Podfile.lock +429 -0
- package/DemoApp/metro.config.js +17 -0
- package/DemoApp/package.json +32 -0
- package/DemoApp/yarn.lock +7143 -0
- package/README.md +96 -0
- package/README_INTERNAL.md +11 -0
- package/mux-react-native-video-sdk.podspec +19 -0
- package/package.json +27 -0
- package/src/index.js +258 -0
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://mux.com/">
|
|
3
|
+
<img src="https://avatars.githubusercontent.com/u/16199997?s=200&v=4" alt="Mux Logo">
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
# Mux Data SDK for monitoring react-native-video
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+

|
|
11
|
+

|
|
12
|
+

|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
Mux Data gives you insight into video engagement and Quality of Experience using client-side SDKs for your player.
|
|
16
|
+
|
|
17
|
+
This SDK monitors [react-native-video](https://github.com/react-native-video/react-native-video), [see all supported players here](https://docs.mux.com/guides/data).
|
|
18
|
+
|
|
19
|
+
View the DemoApp/ directory to see a demo application that implements this library.
|
|
20
|
+
|
|
21
|
+
## Documentation
|
|
22
|
+
|
|
23
|
+
Visit our [documentation](https://docs.mux.com/guides/data/monitor-react-native-video) to get started.
|
|
24
|
+
|
|
25
|
+
## Requirements
|
|
26
|
+
|
|
27
|
+
1. A functioning react-native application that uses react-native-video.
|
|
28
|
+
1. react-native ~> 16.9
|
|
29
|
+
1. react-native-video ~> 5.0.2
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
Install from github in your package.json (when this is officially released then it will be availble on npm).
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
yarn add "https://github.com/muxinc/mux-stats-sdk-react-native-video#v0.2.0"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
OR
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
npm install "https://github.com/muxinc/mux-stats-sdk-react-native-video#v0.2.0" --save
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Usage
|
|
46
|
+
|
|
47
|
+
This package works by wrapping your `Video` component in a higher order component.
|
|
48
|
+
|
|
49
|
+
For more information about what keys can be passed into the `data` key in the `muxOptions` prop see
|
|
50
|
+
[the javascript docs](https://docs.mux.com/docs/web-integration-guide#section-5-add-metadata).
|
|
51
|
+
|
|
52
|
+
```jsx
|
|
53
|
+
import app from './package.json' // this is your application's package.json
|
|
54
|
+
import Video from 'react-native-video'; // import Video from react-native-video like you normally would
|
|
55
|
+
import muxReactNativeVideo from 'mux-react-native-video-sdk';
|
|
56
|
+
|
|
57
|
+
// wrap the `Video` component with Mux functionality
|
|
58
|
+
const MuxVideo = muxReactNativeVideo(Video);
|
|
59
|
+
|
|
60
|
+
// Pass the same props to `MuxVideo` that you would pass to the
|
|
61
|
+
// `Video` element. All of these props will be passed through to your underlying react-native-video component
|
|
62
|
+
// Include a new prop for `muxOptions`
|
|
63
|
+
<MuxVideo
|
|
64
|
+
style={styles.video}
|
|
65
|
+
source={{
|
|
66
|
+
uri:
|
|
67
|
+
'https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8',
|
|
68
|
+
}}
|
|
69
|
+
controls
|
|
70
|
+
muted
|
|
71
|
+
muxOptions={{
|
|
72
|
+
application_name: app.name, // (required) the name of your application
|
|
73
|
+
application_version: app.version, // the version of your application (optional, but encouraged)
|
|
74
|
+
data: {
|
|
75
|
+
env_key: 'YOUR_ENVIRONMENT_KEY', // (required)
|
|
76
|
+
player_software_version: '5.0.2' // (optional, but encouraged) the version of react-native-video that you are using
|
|
77
|
+
player_name: 'React Native Player', // See metadata docs for available metadata fields https://docs.mux.com/docs/web-integration-guide#section-5-add-metadata
|
|
78
|
+
video_id: 'My Video Id',
|
|
79
|
+
video_title: 'My awesome video',
|
|
80
|
+
},
|
|
81
|
+
}}
|
|
82
|
+
/>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Known Issues
|
|
86
|
+
|
|
87
|
+
1. The `paused` property does not behave as expected on Android when using the default player controls. (the `onProgress` event, which is something the Mux SDK needs to hook into does not fire): https://github.com/react-native-community/react-native-video/issues/1979. If you are using the `paused` property it will work on iOS with the default controls but if you need to use it on Android you will have to implement your own controls and set/unset the `paused` property yourself.
|
|
88
|
+
1. The `player_is_fullscreen` property is not reported as expected on iOS. The react-native-video callbacks for fullscreen status `onFullscreenPlayerDidPresent` and `onFullscreenPlayerDidDismiss` do not get called when entering fullscreen using the native controls: https://github.com/react-native-video/react-native-video/issues/552
|
|
89
|
+
|
|
90
|
+
## Caveats
|
|
91
|
+
|
|
92
|
+
1. Upscale and downscale % metrics are not calculated because we are unable to get player width and player height measurments from react-native-video.
|
|
93
|
+
1. Even if we could get player width and height, we still wouldn't be able to calculate upscale and downscale % metrics for HLS sources is because of this open issue related to getting the video source width & height: https://github.com/react-native-community/react-native-video/issues/1194.
|
|
94
|
+
1. This library is intended for use with react-native-video when targeting iOS and Android platforms. For targeting web platforms we have other SDKs that will work better for monitiring the HTML5 `video` element.
|
|
95
|
+
1. If you are overriding react-native-video's default of 250ms for `progressUpdateInterval` this library will: (1) ignore your setting and revert back to 250ms (2) log a warning. This library depends on a progressUpdateInterval of 250ms in order to correctly calculate rebuffering
|
|
96
|
+
1. 'Seeking' events are not tracked by this SDK because of inconsistent `onSeek` callback behavior between iOS and Android: https://github.com/react-native-community/react-native-video/issues/1977
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Release
|
|
2
|
+
|
|
3
|
+
1. Update version in package.json
|
|
4
|
+
1. Update tag version in `yarn add` and `npm i` commands in the README
|
|
5
|
+
1. Open PR
|
|
6
|
+
1. Get PR merged
|
|
7
|
+
1. Pull master, tag master with your new version `git tag v0.1.0-beta.1`
|
|
8
|
+
1. Push tags `git push origin --tags`
|
|
9
|
+
|
|
10
|
+
For now, usere can install from Github. When this gets further along
|
|
11
|
+
and closer to non-beta release then we will release to NPM
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = package['name']
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = package['license']
|
|
10
|
+
|
|
11
|
+
s.authors = package['author']
|
|
12
|
+
s.homepage = package['homepage']
|
|
13
|
+
s.platforms = { :ios => "9.0", :osx => "10.13" }
|
|
14
|
+
|
|
15
|
+
s.source = { :git => "https://github.com/muxinc/mux-stats-sdk-react-native-video.git", :tag => "v#{s.version}" }
|
|
16
|
+
s.source_files = "apple/**/*.{h,m}"
|
|
17
|
+
|
|
18
|
+
s.dependency 'React-Core'
|
|
19
|
+
end
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mux/mux-data-react-native-video",
|
|
3
|
+
"version": "0.5.7",
|
|
4
|
+
"author": "Mux, Inc.",
|
|
5
|
+
"description": "Mux analytics plugin for react-native-video",
|
|
6
|
+
"homepage": "https://github.com/muxinc/mux-stats-sdk-react-native-video",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"main": "src/index.js",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"lint": "eslint 'src/*.js' --quiet"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"eslint": "^6.8.0",
|
|
14
|
+
"eslint-config-standard": "^14.1.0",
|
|
15
|
+
"eslint-plugin-import": "^2.20.1",
|
|
16
|
+
"eslint-plugin-node": "^11.0.0",
|
|
17
|
+
"eslint-plugin-promise": "^4.2.1",
|
|
18
|
+
"eslint-plugin-standard": "^4.0.1"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"react": "^16.9",
|
|
22
|
+
"react-native-video": "^5.0"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"mux-embed": "4.12.1"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import mux from 'mux-embed';
|
|
2
|
+
import React, { useEffect, useImperativeHandle, useRef } from 'react';
|
|
3
|
+
import { Platform } from 'react-native';
|
|
4
|
+
import lib from '../package.json';
|
|
5
|
+
const secondsToMs = mux.utils.secondsToMs;
|
|
6
|
+
const assign = mux.utils.assign;
|
|
7
|
+
|
|
8
|
+
const MIN_REBUFFER_DURATION = 300; // this should be more than 250 because getPlayheadTime will only update every 250ms
|
|
9
|
+
|
|
10
|
+
const noop = function () { };
|
|
11
|
+
|
|
12
|
+
export default (WrappedComponent) => {
|
|
13
|
+
return React.forwardRef(({
|
|
14
|
+
onProgress = noop,
|
|
15
|
+
onEnd = noop,
|
|
16
|
+
onSeek = noop,
|
|
17
|
+
onLoad = noop,
|
|
18
|
+
onPlaybackRateChange = noop,
|
|
19
|
+
onFullscreenPlayerDidPresent = noop,
|
|
20
|
+
onFullscreenPlayerDidDismiss = noop,
|
|
21
|
+
muxOptions,
|
|
22
|
+
progressUpdateInterval,
|
|
23
|
+
source,
|
|
24
|
+
...otherProps
|
|
25
|
+
}, ref) => {
|
|
26
|
+
const videoRef = useRef();
|
|
27
|
+
const options = Object.assign({}, muxOptions);
|
|
28
|
+
|
|
29
|
+
if (!options.application_name) {
|
|
30
|
+
console.error('[mux-react-native-video] missing muxOptions.application_name - this value is required');
|
|
31
|
+
}
|
|
32
|
+
if (progressUpdateInterval && progressUpdateInterval !== 250) {
|
|
33
|
+
console.log(`[mux-react-native-video] found progressUpdateInterval value of ${progressUpdateInterval} - overriding to 250. This is required for the mux-react-native-video to correctly track rebuffering`);
|
|
34
|
+
progressUpdateInterval = 250;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const didStartPaused = otherProps.paused;
|
|
38
|
+
|
|
39
|
+
const stateRef = React.useRef({ playerID: mux.utils.generateShortID() });
|
|
40
|
+
const saveStateForPlayer = (key, value) => {
|
|
41
|
+
stateRef.current[key] = value;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const getStateForPlayer = (key) => {
|
|
45
|
+
return stateRef.current[key];
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const emit = (eventType, data) => {
|
|
49
|
+
mux.emit(stateRef.current.playerID, eventType, data);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const emitPlay = () => {
|
|
53
|
+
setPlayerStatus('play');
|
|
54
|
+
emit('play');
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const setPlayerStatus = (status) => saveStateForPlayer('currentStatus', status);
|
|
58
|
+
const getPlayerStatus = () => getStateForPlayer('currentStatus');
|
|
59
|
+
|
|
60
|
+
useImperativeHandle(ref, () => Object.assign(videoRef.current, { mux: { emit } }));
|
|
61
|
+
|
|
62
|
+
const _onProgress = evt => {
|
|
63
|
+
saveStateForPlayer('currentTime', secondsToMs(evt.currentTime));
|
|
64
|
+
if (getPlayerStatus() === 'paused') {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (getPlayerStatus() === 'play') {
|
|
69
|
+
setPlayerStatus('playing');
|
|
70
|
+
emit('playing');
|
|
71
|
+
}
|
|
72
|
+
emit('timeupdate', { player_playhead_time: secondsToMs(evt.currentTime) });
|
|
73
|
+
onProgress(evt);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const _onEnd = evt => {
|
|
77
|
+
emit('ended');
|
|
78
|
+
onEnd(evt);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const _onSeek = evt => {
|
|
82
|
+
emit('seeked');
|
|
83
|
+
onSeek(evt);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const _onLoad = evt => {
|
|
87
|
+
if (evt.duration) {
|
|
88
|
+
saveStateForPlayer('duration', secondsToMs(evt.duration));
|
|
89
|
+
}
|
|
90
|
+
if (evt.naturalSize) {
|
|
91
|
+
//
|
|
92
|
+
// You may be wondering why we're comparing this value to the string 'undefined' instead
|
|
93
|
+
// of the value 'undefined'. Glad you asked. This is not a typeo, it turns out that sometimes,
|
|
94
|
+
// infact the value is the string 'undefined'
|
|
95
|
+
//
|
|
96
|
+
// https://github.com/react-native-community/react-native-video/issues/1194
|
|
97
|
+
//
|
|
98
|
+
if (evt.naturalSize.width && evt.naturalSize.width !== 'undefined') {
|
|
99
|
+
saveStateForPlayer('sourceWidth', evt.naturalSize.width);
|
|
100
|
+
}
|
|
101
|
+
if (evt.naturalSize.height && evt.naturalSize.height !== 'undefined') {
|
|
102
|
+
saveStateForPlayer('sourceHeight', evt.naturalSize.height);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
onLoad(evt);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const _onPlaybackRateChange = evt => {
|
|
109
|
+
const lastRate = getStateForPlayer('lastRateChange');
|
|
110
|
+
const newRate = evt.playbackRate;
|
|
111
|
+
const isFirstPlayAttempt = (didStartPaused && lastRate === undefined && newRate);
|
|
112
|
+
const isUnPausing = (lastRate === 0 && newRate);
|
|
113
|
+
|
|
114
|
+
saveStateForPlayer('lastRateChange', evt.playbackRate);
|
|
115
|
+
|
|
116
|
+
if (lastRate === newRate) {
|
|
117
|
+
onPlaybackRateChange(evt);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (isFirstPlayAttempt || isUnPausing) {
|
|
122
|
+
emitPlay();
|
|
123
|
+
onPlaybackRateChange(evt);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (newRate === 0) {
|
|
128
|
+
emit('pause');
|
|
129
|
+
setPlayerStatus('paused');
|
|
130
|
+
onPlaybackRateChange(evt);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const _onFullscreenPlayerDidPresent = evt => {
|
|
135
|
+
saveStateForPlayer('isFullscreen', true);
|
|
136
|
+
onFullscreenPlayerDidPresent(evt);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const _onFullscreenPlayerDidDismiss = evt => {
|
|
140
|
+
saveStateForPlayer('isFullscreen', false);
|
|
141
|
+
onFullscreenPlayerDidDismiss(evt);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
useEffect(() => {
|
|
145
|
+
options.getPlayheadTime = () => {
|
|
146
|
+
return getStateForPlayer('currentTime');
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
options.minimumRebufferDuration = MIN_REBUFFER_DURATION;
|
|
150
|
+
const platformName = options.application_name;
|
|
151
|
+
|
|
152
|
+
delete options.application_name;
|
|
153
|
+
|
|
154
|
+
const platformVersion = options.application_version;
|
|
155
|
+
|
|
156
|
+
delete options.application_version;
|
|
157
|
+
|
|
158
|
+
options.data = assign(
|
|
159
|
+
{
|
|
160
|
+
player_software_name: 'React native video',
|
|
161
|
+
player_is_paused: getStateForPlayer('isPaused'),
|
|
162
|
+
// player_software_version: player.constructor.version, // TODO
|
|
163
|
+
player_mux_plugin_name: 'react-native-video-mux',
|
|
164
|
+
player_mux_plugin_version: lib.version
|
|
165
|
+
},
|
|
166
|
+
options.data
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
options.getStateData = function () {
|
|
170
|
+
return {
|
|
171
|
+
// Required properties - these must be provided every time this is called
|
|
172
|
+
// You _should_ only provide these values if they are defined (i.e. not 'undefined')
|
|
173
|
+
player_is_paused: getStateForPlayer('isPaused'),
|
|
174
|
+
// player_width: getStateForPlayer('playerWidth'),
|
|
175
|
+
// player_height: getStateForPlayer('playerHeight'),
|
|
176
|
+
video_source_height: getStateForPlayer('sourceWidth'),
|
|
177
|
+
video_source_width: getStateForPlayer('sourceHeight'),
|
|
178
|
+
|
|
179
|
+
// Preferred properties - these should be provided in this callback if possible
|
|
180
|
+
// If any are missing, that is okay, but this will be a lack of data for the customer at a later time
|
|
181
|
+
player_is_fullscreen: getStateForPlayer('isFullscreen'),
|
|
182
|
+
player_autoplay_on: !otherProps.paused,
|
|
183
|
+
// player_preload_on: isPreload(),
|
|
184
|
+
video_source_url: source && source.uri,
|
|
185
|
+
// video_source_mime_type: getMimeType(),
|
|
186
|
+
video_source_duration: getStateForPlayer('duration'),
|
|
187
|
+
|
|
188
|
+
// Optional properties - if you have them, send them, but if not, no big deal
|
|
189
|
+
video_poster_url: otherProps.poster
|
|
190
|
+
// player_language_code: getVideoElementProp('lang') // Return the language code (e.g. `en`, `en-us`)
|
|
191
|
+
};
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
options.platform = {
|
|
195
|
+
// layout:
|
|
196
|
+
// product:
|
|
197
|
+
// manufacturer:
|
|
198
|
+
os: {
|
|
199
|
+
family: Platform.OS,
|
|
200
|
+
version: Platform.Version
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
if (platformName) {
|
|
204
|
+
options.platform.name = platformName;
|
|
205
|
+
}
|
|
206
|
+
if (platformVersion) {
|
|
207
|
+
options.platform.version = platformVersion;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
mux.init(stateRef.current.playerID, options);
|
|
211
|
+
if (!didStartPaused) {
|
|
212
|
+
emitPlay();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return () => {
|
|
216
|
+
emit('destroy');
|
|
217
|
+
};
|
|
218
|
+
}, []);
|
|
219
|
+
|
|
220
|
+
const sourceUri = source && source.uri;
|
|
221
|
+
|
|
222
|
+
useEffect(() => {
|
|
223
|
+
if (!sourceUri) return;
|
|
224
|
+
|
|
225
|
+
if (!getStateForPlayer('sourceUri')) {
|
|
226
|
+
// do not send a videochange event for the first source
|
|
227
|
+
saveStateForPlayer('sourceUri', sourceUri);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
saveStateForPlayer('sourceUri', sourceUri);
|
|
232
|
+
emit('videochange', {
|
|
233
|
+
video_id: options.data.video_id,
|
|
234
|
+
video_title: options.data.video_title,
|
|
235
|
+
video_series: options.data.video_series,
|
|
236
|
+
video_duration: options.data.video_duration,
|
|
237
|
+
video_stream_type: options.data.video_stream_type,
|
|
238
|
+
video_encoding_variant: options.data.video_encoding_variant
|
|
239
|
+
});
|
|
240
|
+
}, [sourceUri]);
|
|
241
|
+
|
|
242
|
+
return (
|
|
243
|
+
<WrappedComponent
|
|
244
|
+
onProgress={_onProgress}
|
|
245
|
+
onEnd={_onEnd}
|
|
246
|
+
onSeek={_onSeek}
|
|
247
|
+
onLoad={_onLoad}
|
|
248
|
+
onPlaybackRateChange={_onPlaybackRateChange}
|
|
249
|
+
progressUpdateInterval={progressUpdateInterval}
|
|
250
|
+
onFullscreenPlayerDidPresent={_onFullscreenPlayerDidPresent}
|
|
251
|
+
onFullscreenPlayerDidDismiss={_onFullscreenPlayerDidDismiss}
|
|
252
|
+
source={source}
|
|
253
|
+
ref={videoRef}
|
|
254
|
+
{...otherProps}
|
|
255
|
+
/>
|
|
256
|
+
);
|
|
257
|
+
});
|
|
258
|
+
};
|