Merge branch 'master' of https://github.com/react-native-video/react-native-video into feat/add_new_events_on_tracks_changed
# Conflicts: # CHANGELOG.md # android/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java # examples/basic/src/VideoPlayer.android.tsx
This commit is contained in:
commit
64e024d149
23
API.md
23
API.md
@ -277,6 +277,7 @@ var styles = StyleSheet.create({
|
||||
|[disableDisconnectError](#disableDisconnectError)|Android|
|
||||
|[filter](#filter)|iOS|
|
||||
|[filterEnabled](#filterEnabled)|iOS|
|
||||
|[focusable](#focusable)|Android|
|
||||
|[fullscreen](#fullscreen)|iOS|
|
||||
|[fullscreenAutorotate](#fullscreenautorotate)|iOS|
|
||||
|[fullscreenOrientation](#fullscreenorientation)|iOS|
|
||||
@ -424,12 +425,12 @@ Determines whether to show player controls.
|
||||
* **true** - Show player controls
|
||||
|
||||
Note on iOS, controls are always shown when in fullscreen mode.
|
||||
Note on Android, native controls are available by default.
|
||||
If needed, you can also add your controls or use a package like [react-native-video-controls](https://github.com/itsnubix/react-native-video-controls) or [react-native-media-console](https://github.com/criszz77/react-native-media-console), see [Usefull Side Project](./docs/PROJECTS.md).
|
||||
|
||||
### contentStartTime
|
||||
The start time in ms for SSAI content. This determines at what time to load the video info like resolutions. Use this only when you have SSAI stream where ads resolution is not the same as content resolution.
|
||||
|
||||
Note on Android, native controls are available by default. If needed, you can also add your controls or use a package like [react-native-video-controls].
|
||||
|
||||
Platforms: Android, iOS
|
||||
|
||||
#### disableFocus
|
||||
@ -489,6 +490,14 @@ Enable video filter.
|
||||
|
||||
Platforms: iOS
|
||||
|
||||
#### Focusable
|
||||
Whether this video view should be focusable with a non-touch input device, eg. receive focus with a hardware keyboard.
|
||||
* **false** - Makes view unfocusable
|
||||
* **true (default)** - Makes view focusable
|
||||
|
||||
Platforms: Android
|
||||
|
||||
|
||||
#### fullscreen
|
||||
Controls whether the player enters fullscreen on play.
|
||||
* **false (default)** - Don't display the video in fullscreen
|
||||
@ -1703,12 +1712,4 @@ allprojects {
|
||||
}
|
||||
```
|
||||
If you encounter an error `Could not find com.android.support:support-annotations:27.0.0.` reinstall your Android Support Repository.
|
||||
|
||||
## Black Screen on Release build (Android)
|
||||
If your video work on Debug mode, but on Release you see only black screen, please, check the link to your video. If you use 'http' protocol there, you will need to add next string to your AndroidManifest.xml file.
|
||||
```
|
||||
<application
|
||||
...
|
||||
android:usesCleartextTraffic="true"
|
||||
>
|
||||
```
|
||||
|
10
CHANGELOG.md
10
CHANGELOG.md
@ -3,10 +3,17 @@
|
||||
### Version 6.0.0-alpha.4
|
||||
|
||||
- Exoplayer: add new events on tracks changed to be notified of audio/text/video Tracks update during playback [2806](https://github.com/react-native-video/react-native-video/pull/2806)
|
||||
- ensure src is always provided to native player even if it is invalid [#2857](https://github.com/react-native-video/react-native-video/pull/2857)
|
||||
- Sample: Add react-native-video controls support [#2852](https://github.com/react-native-video/react-native-video/pull/2852)
|
||||
- Android: Switch Google's maven repository to default `google()` [#2860](https://github.com/react-native-video/react-native-video/pull/2860)
|
||||
- Android: Implement focusable prop so the video view can toggle whether it is focusable for non-touch devices [#2819](https://github.com/react-native-video/react-native-video/issues/2819)
|
||||
- Android: fix linter warning [#2891] (https://github.com/react-native-video/react-native-video/pull/2891)
|
||||
- Fix iOS RCTSwiftLog naming collision [#2868](https://github.com/react-native-video/react-native-video/issues/2868)
|
||||
- Added "homepage" to package.json [#2882](https://github.com/react-native-video/react-native-video/pull/2882)
|
||||
|
||||
### Version 6.0.0-alpha.3
|
||||
|
||||
- fix ios build [#2854](https://gthub.com/react-native-video/react-native-video/pull/2854)
|
||||
- Fix ios build [#2854](https://github.com/react-native-video/react-native-video/pull/2854)
|
||||
|
||||
### Version 6.0.0-alpha.2
|
||||
|
||||
@ -33,6 +40,7 @@
|
||||
- Fix video endless loop when repeat set to false or not specified. [#2329](https://github.com/react-native-video/react-native-video/pull/2329)
|
||||
|
||||
### Version 6.0.0-alpha.0
|
||||
|
||||
- Support disabling buffering [#2689](https://github.com/react-native-video/react-native-video/pull/2689)
|
||||
- Fix AudioFocus bug that could cause the player to stop responding to play/pause in some instances. [#2689](https://github.com/react-native-video/react-native-video/pull/2689)
|
||||
- Fix player crashing when it is being cleared. [#2689](https://github.com/react-native-video/react-native-video/pull/2689)
|
||||
|
20
README.md
20
README.md
@ -1,17 +1,31 @@
|
||||
# react-native-video
|
||||
|
||||
#### A `<Video>` component for react-native.
|
||||
> :warning: **Version 6 Alpha**: The following documentation may refer to features only available through the v6.0.0 alpha releases, [please see version 5.2.x](https://github.com/react-native-video/react-native-video/blob/v5.2.0/README.md) for the current documentation!
|
||||
|
||||
Version 6.x recommends react-native >= 0.68.2. For older versions of react-native, [please use version 5.x](https://github.com/react-native-video/react-native-video/tree/v5.2.0).
|
||||
## A `<Video>` component for react-native.
|
||||
Version 6.x recommends react-native >= 0.68.2.
|
||||
<br>For older versions of react-native, [please use version 5.x](https://github.com/react-native-video/react-native-video/tree/v5.2.0).
|
||||
|
||||
### Version 6.0.0 breaking changes
|
||||
|
||||
Version 6.0.0 is introducing dozens of breaking changes, mostly through updated dependecies and significant refactoring. While the API remains compatible, the significant internal changes require full testing with your app to ensure all functionality remains operational. Please view the [Changelog](CHANGELOG.md) for specific breaking changes.
|
||||
|
||||
## Useful resources
|
||||
### Installing Version 6.0.0 Alphas
|
||||
Whilst we finalise version 6.0.0 you can install the latest alpha from npm
|
||||
Using npm:
|
||||
```
|
||||
npm install --save react-native-video@alpha
|
||||
```
|
||||
using yarn:
|
||||
```
|
||||
yarn add react-native-video@alpha
|
||||
```
|
||||
|
||||
## Useful resources
|
||||
- [Documentation](API.md)
|
||||
- [Changelog](CHANGELOG.md)
|
||||
- [Contribution guide](CONTRIBUTING.md)
|
||||
- [Usefull Side Project](./docs/PROJECTS.md)
|
||||
- [Advanced debugging](./docs/DEBUGGING.md)
|
||||
|
||||
**react-native-video** was originally created by [Brent Vatne](https://github.com/brentvatne)
|
||||
|
15
Video.js
15
Video.js
@ -294,16 +294,20 @@ export default class Video extends Component {
|
||||
let uri = source.uri || '';
|
||||
if (uri && uri.match(/^\//)) {
|
||||
uri = `file://${uri}`;
|
||||
} else if (uri === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!uri) {
|
||||
console.warn('Trying to load empty source.');
|
||||
console.log('Trying to load empty source.');
|
||||
}
|
||||
|
||||
const isNetwork = !!(uri && uri.match(/^https?:/));
|
||||
const isAsset = !!(uri && uri.match(/^(assets-library|ph|ipod-library|file|content|ms-appx|ms-appdata):/));
|
||||
const isNetwork = !!(uri && uri.match(/^https?:/i));
|
||||
const isAsset = !!(uri && uri.match(/^(assets-library|ph|ipod-library|file|content|ms-appx|ms-appdata):/i));
|
||||
|
||||
if ((uri || uri === '') && !isNetwork && !isAsset) {
|
||||
if (this.props.onError) {
|
||||
this.props.onError({error: {errorString: 'invalid url, player will stop', errorCode: 'INVALID_URL'}});
|
||||
}
|
||||
}
|
||||
|
||||
let nativeResizeMode;
|
||||
const RCTVideoInstance = this.getViewManagerConfig('RCTVideo');
|
||||
@ -504,6 +508,7 @@ Video.propTypes = {
|
||||
reportBandwidth: PropTypes.bool,
|
||||
contentStartTime: PropTypes.number,
|
||||
disableFocus: PropTypes.bool,
|
||||
focusable: PropTypes.bool,
|
||||
disableBuffering: PropTypes.bool,
|
||||
controls: PropTypes.bool,
|
||||
audioOnly: PropTypes.bool,
|
||||
|
@ -1 +0,0 @@
|
||||
M Video.js
|
@ -27,8 +27,7 @@ android {
|
||||
}
|
||||
|
||||
repositories {
|
||||
// Remove this repository line after google releases to google() or mavenCentral()
|
||||
maven { url "https://dl.google.com/android/maven2" }
|
||||
google()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@ -41,11 +40,10 @@ dependencies {
|
||||
implementation "androidx.annotation:annotation:1.1.0"
|
||||
implementation "androidx.core:core:1.1.0"
|
||||
implementation "androidx.media:media:1.1.0"
|
||||
implementation 'androidx.activity:activity:1.4.0'
|
||||
implementation "androidx.activity:activity:1.4.0"
|
||||
|
||||
implementation('com.google.android.exoplayer:extension-okhttp:2.18.1') {
|
||||
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
|
||||
}
|
||||
implementation 'com.squareup.okhttp3:okhttp:${OKHTTP_VERSION}'
|
||||
|
||||
implementation "com.squareup.okhttp3:okhttp:" + '$OKHTTP_VERSION'
|
||||
}
|
||||
|
@ -178,6 +178,7 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
private Dynamic textTrackValue;
|
||||
private ReadableArray textTracks;
|
||||
private boolean disableFocus;
|
||||
private boolean focusable = true;
|
||||
private boolean disableBuffering;
|
||||
private long contentStartTime = -1L;
|
||||
private boolean disableDisconnectError;
|
||||
@ -272,6 +273,8 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
|
||||
addView(exoPlayerView, 0, layoutParams);
|
||||
|
||||
exoPlayerView.setFocusable(this.focusable);
|
||||
|
||||
mainHandler = new Handler();
|
||||
}
|
||||
|
||||
@ -559,7 +562,7 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
}
|
||||
}
|
||||
}, 1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void initializePlayerCore(ReactExoplayerView self) {
|
||||
@ -1589,7 +1592,7 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
for (int j = 0; j < group.length; j++) {
|
||||
allTracks.add(j);
|
||||
}
|
||||
|
||||
|
||||
// Valiate list of all tracks and add only supported formats
|
||||
int supportedFormatLength = 0;
|
||||
ArrayList<Integer> supportedTrackList = new ArrayList<Integer>();
|
||||
@ -1748,13 +1751,18 @@ class ReactExoplayerView extends FrameLayout implements
|
||||
this.disableFocus = disableFocus;
|
||||
}
|
||||
|
||||
public void setFocusable(boolean focusable) {
|
||||
this.focusable = focusable;
|
||||
exoPlayerView.setFocusable(this.focusable);
|
||||
}
|
||||
|
||||
public void setBackBufferDurationMs(int backBufferDurationMs) {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
long usedMemory = runtime.totalMemory() - runtime.freeMemory();
|
||||
long freeMemory = runtime.maxMemory() - usedMemory;
|
||||
long reserveMemory = (long)minBackBufferMemoryReservePercent * runtime.maxMemory();
|
||||
if (reserveMemory > freeMemory) {
|
||||
// We don't have enough memory in reserve so we will
|
||||
// We don't have enough memory in reserve so we will
|
||||
Log.w("ExoPlayer Warning", "Not enough reserve memory, setting back buffer to 0ms to reduce memory pressure!");
|
||||
this.backBufferDurationMs = 0;
|
||||
return;
|
||||
|
@ -70,6 +70,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
private static final String PROP_DISABLE_FOCUS = "disableFocus";
|
||||
private static final String PROP_DISABLE_BUFFERING = "disableBuffering";
|
||||
private static final String PROP_DISABLE_DISCONNECT_ERROR = "disableDisconnectError";
|
||||
private static final String PROP_FOCUSABLE = "focusable";
|
||||
private static final String PROP_FULLSCREEN = "fullscreen";
|
||||
private static final String PROP_USE_TEXTURE_VIEW = "useTextureView";
|
||||
private static final String PROP_SECURE_VIEW = "useSecureView";
|
||||
@ -182,6 +183,8 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
if (srcUri != null) {
|
||||
videoView.setRawSrc(srcUri, extension);
|
||||
}
|
||||
} else {
|
||||
videoView.clearSrc();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -304,6 +307,11 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
videoView.setDisableFocus(disableFocus);
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_FOCUSABLE, defaultBoolean = true)
|
||||
public void setFocusable(final ReactExoplayerView videoView, final boolean focusable) {
|
||||
videoView.setFocusable(focusable);
|
||||
}
|
||||
|
||||
@ReactProp(name = PROP_BACK_BUFFER_DURATION_MS, defaultInt = 0)
|
||||
public void setBackBufferDurationMs(final ReactExoplayerView videoView, final int backBufferDurationMs) {
|
||||
videoView.setBackBufferDurationMs(backBufferDurationMs);
|
||||
@ -384,11 +392,12 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
||||
}
|
||||
|
||||
private boolean startsWithValidScheme(String uriString) {
|
||||
return uriString.startsWith("http://")
|
||||
|| uriString.startsWith("https://")
|
||||
|| uriString.startsWith("content://")
|
||||
|| uriString.startsWith("file://")
|
||||
|| uriString.startsWith("asset://");
|
||||
String lowerCaseUri = uriString.toLowerCase();
|
||||
return lowerCaseUri.startsWith("http://")
|
||||
|| lowerCaseUri.startsWith("https://")
|
||||
|| lowerCaseUri.startsWith("content://")
|
||||
|| lowerCaseUri.startsWith("file://")
|
||||
|| lowerCaseUri.startsWith("asset://");
|
||||
}
|
||||
|
||||
private @ResizeMode.Mode int convertToIntDef(String resizeModeOrdinalString) {
|
||||
|
47
docs/DEBUGGING.md
Normal file
47
docs/DEBUGGING.md
Normal file
@ -0,0 +1,47 @@
|
||||
# Advanced debuging and common issues
|
||||
|
||||
### HTTP playback doesn't work or Black Screen on Release build (Android)
|
||||
If your video work on Debug mode, but on Release you see only black screen, please, check the link to your video. If you use 'http' protocol there, you will need to add next string to your AndroidManifest.xml file. [Details here](https://developer.android.com/guide/topics/manifest/application-element#usesCleartextTraffic)
|
||||
|
||||
```
|
||||
<application
|
||||
...
|
||||
android:usesCleartextTraffic="true"
|
||||
>
|
||||
```
|
||||
|
||||
### Decoder Issue (Android)
|
||||
|
||||
Devices have a maximum of simulataneous possible playback. It means you have reach this limit. Exoplayer returns: 'Unable to instantiate decoder'
|
||||
|
||||
**known issue**: This issue happen really often in debug mode.
|
||||
|
||||
## You cannot play clean content (all OS)
|
||||
|
||||
Here are the steps to consider before opening a ticket in issue tracker
|
||||
|
||||
### Check you can access to remote file
|
||||
|
||||
Ensure you can download to manifest / content file with a browser for exemple
|
||||
|
||||
### Check another player can read the content
|
||||
|
||||
Usually clear playback can be read with all Video player. Then you should ensure content can be played without any issue with another player ([VideoLan/VLC](https://www.videolan.org/vlc/) is a good reference implementation)
|
||||
|
||||
## You cannot play protected content (all OS)
|
||||
|
||||
### Protected content gives error (token error / access forbidden)
|
||||
|
||||
If content is protected with an access token or any other http header, ensure you can access to you data with a wget call or a rest client app. You need to provide all needed access token / authentication parameters.
|
||||
|
||||
### Everything seems correct but content cannot be accessed
|
||||
|
||||
You need to record network trace to ensure communications with server is correct.
|
||||
[Charles proxy](https://www.charlesproxy.com/) is a simple and usefull tool to sniff all http/https calls.
|
||||
With this tool you should be able to analyze what is going on with network. You will see all access to content and DRM, audio / vido chuncks, ...
|
||||
|
||||
Then try to compare exchanges with previous tests you made.
|
||||
|
||||
### It's still not working
|
||||
|
||||
You can try to open a ticket now !
|
9
docs/PROJECTS.md
Normal file
9
docs/PROJECTS.md
Normal file
@ -0,0 +1,9 @@
|
||||
This page links other open source projects which can be usefull for your player implementation
|
||||
|
||||
# UI over react-native-video
|
||||
- [react-native-video-controls](https://github.com/itsnubix/react-native-video-controls): First reference player UI
|
||||
- [react-native-media-console](https://github.com/criszz77/react-native-media-console): React-native-video-controls updated and rewritten in typescript
|
||||
- [react-native-corner-video](https://github.com/Lg0gs/react-native-corner-video): A floating video player
|
||||
|
||||
# Other tools
|
||||
- [react-native-music-control](https://github.com/tanguyantoine/react-native-music-control): A toolbox to control player over media session
|
@ -43,6 +43,7 @@ class VideoPlayer extends Component {
|
||||
selectedTextTrack: undefined,
|
||||
srcListId: 0,
|
||||
loop: false,
|
||||
showRNVControls: false,
|
||||
};
|
||||
|
||||
seekerWidth = 0
|
||||
@ -67,6 +68,12 @@ class VideoPlayer extends Component {
|
||||
'http://www.youtube.com/api/manifest/dash/id/bf5bb2419360daf1/source/youtube?as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,source,id,as&ip=0.0.0.0&ipbits=0&expire=19000000000&signature=51AF5F39AB0CEC3E5497CD9C900EBFEAECCCB5C7.8506521BFC350652163895D4C26DEE124209AA9E&key=ik0',
|
||||
type: 'mpd',
|
||||
},
|
||||
{
|
||||
description: 'invalid URL',
|
||||
uri:
|
||||
'mmt://www.youtube.com',
|
||||
type: 'mpd',
|
||||
},
|
||||
{ description: '(no url) Stopped playback', uri: undefined },
|
||||
{
|
||||
description: '(no view) no View',
|
||||
@ -246,8 +253,8 @@ class VideoPlayer extends Component {
|
||||
}
|
||||
|
||||
onError = (err: any) => {
|
||||
console.log(JSON.stringify(err))
|
||||
this.toast(true, 'error: ' + err?.error?.code)
|
||||
console.log(JSON.stringify(err?.error.errorCode))
|
||||
this.toast(true, 'error: ' + err?.error.errorCode)
|
||||
}
|
||||
|
||||
onEnd = () => {
|
||||
@ -258,6 +265,9 @@ class VideoPlayer extends Component {
|
||||
toggleFullscreen() {
|
||||
this.setState({ fullscreen: !this.state.fullscreen })
|
||||
}
|
||||
toggleControls() {
|
||||
this.setState({ showRNVControls: !this.state.showRNVControls })
|
||||
}
|
||||
|
||||
toggleDecoration() {
|
||||
this.setState({ decoration: !this.state.decoration })
|
||||
@ -558,118 +568,133 @@ class VideoPlayer extends Component {
|
||||
else return <View />
|
||||
}
|
||||
|
||||
renderTopControl() {
|
||||
return (<>
|
||||
<Text style={[styles.controlOption]}>
|
||||
{this.srcList[this.state.srcListId]?.description || 'local file'}
|
||||
</Text>
|
||||
<View >
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
this.toggleControls()
|
||||
}}
|
||||
>
|
||||
<Text style={[styles.leftRightControlOption]}>{this.state.showRNVControls ? 'Hide controls' : 'Show controls'}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</>)
|
||||
}
|
||||
|
||||
|
||||
renderOverlay() {
|
||||
return (
|
||||
<>
|
||||
{this.IndicatorLoadingView()}
|
||||
<View style={styles.topControls}>
|
||||
<Text style={[styles.controlOption]}>
|
||||
{this.srcList[this.state.srcListId]?.description || 'local file'}
|
||||
</Text>
|
||||
<View style={styles.resizeModeControl}>{this.renderTopControl()}</View>
|
||||
</View>
|
||||
<View style={styles.leftControls}>
|
||||
<View style={styles.resizeModeControl}>{this.renderLeftControl()}</View>
|
||||
</View>
|
||||
<View style={styles.rightControls}>
|
||||
<View style={styles.resizeModeControl}>{this.renderRightControl()}</View>
|
||||
</View>
|
||||
<View style={styles.bottomControls}>
|
||||
<View style={styles.generalControls}>
|
||||
<View style={styles.generalControls}>
|
||||
<View style={styles.resizeModeControl}>{this.renderInfoControl()}</View>
|
||||
</View>
|
||||
<View style={styles.resizeModeControl}>{this.renderPause()}</View>
|
||||
<View style={styles.resizeModeControl}>
|
||||
{this.renderRepeatModeControl()}
|
||||
</View>
|
||||
<View style={styles.resizeModeControl}>
|
||||
{this.renderFullScreenControl()}
|
||||
</View>
|
||||
<View style={styles.resizeModeControl}>
|
||||
{this.renderDecorationsControl()}
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.generalControls}>
|
||||
<View style={styles.rateControl}>
|
||||
{this.renderRateControl(0.25)}
|
||||
{this.renderRateControl(0.5)}
|
||||
{this.renderRateControl(1.0)}
|
||||
{this.renderRateControl(1.5)}
|
||||
{this.renderRateControl(2.0)}
|
||||
</View>
|
||||
{!this.state.showRNVControls ? (
|
||||
<>
|
||||
<View style={styles.leftControls}>
|
||||
<View style={styles.resizeModeControl}>{this.renderLeftControl()}</View>
|
||||
</View><View style={styles.rightControls}>
|
||||
<View style={styles.resizeModeControl}>{this.renderRightControl()}</View>
|
||||
</View><View style={styles.bottomControls}>
|
||||
<View style={styles.generalControls}>
|
||||
<View style={styles.generalControls}>
|
||||
<View style={styles.resizeModeControl}>{this.renderInfoControl()}</View>
|
||||
</View>
|
||||
<View style={styles.resizeModeControl}>{this.renderPause()}</View>
|
||||
<View style={styles.resizeModeControl}>
|
||||
{this.renderRepeatModeControl()}
|
||||
</View>
|
||||
<View style={styles.resizeModeControl}>
|
||||
{this.renderFullScreenControl()}
|
||||
</View>
|
||||
<View style={styles.resizeModeControl}>
|
||||
{this.renderDecorationsControl()}
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.generalControls}>
|
||||
<View style={styles.rateControl}>
|
||||
{this.renderRateControl(0.25)}
|
||||
{this.renderRateControl(0.5)}
|
||||
{this.renderRateControl(1.0)}
|
||||
{this.renderRateControl(1.5)}
|
||||
{this.renderRateControl(2.0)}
|
||||
</View>
|
||||
|
||||
<View style={styles.volumeControl}>
|
||||
{this.renderVolumeControl(0.5)}
|
||||
{this.renderVolumeControl(1)}
|
||||
{this.renderVolumeControl(1.5)}
|
||||
</View>
|
||||
<View style={styles.volumeControl}>
|
||||
{this.renderVolumeControl(0.5)}
|
||||
{this.renderVolumeControl(1)}
|
||||
{this.renderVolumeControl(1.5)}
|
||||
</View>
|
||||
|
||||
<View style={styles.resizeModeControl}>
|
||||
{this.renderResizeModeControl('cover')}
|
||||
{this.renderResizeModeControl('contain')}
|
||||
{this.renderResizeModeControl('stretch')}
|
||||
</View>
|
||||
</View>
|
||||
{this.renderSeekBar()}
|
||||
<View style={styles.generalControls}>
|
||||
<Text style={styles.controlOption}>AudioTrack</Text>
|
||||
{this.state.audioTracks?.length <= 0 ? (
|
||||
<Text style={styles.controlOption}>empty</Text>
|
||||
) : (
|
||||
<Picker
|
||||
style={styles.picker}
|
||||
selectedValue={this.state.selectedAudioTrack?.value}
|
||||
onValueChange={(itemValue, itemIndex) => {
|
||||
console.log('on audio value change ' + itemValue)
|
||||
this.setState({
|
||||
selectedAudioTrack: {
|
||||
type: 'language',
|
||||
value: itemValue,
|
||||
},
|
||||
})
|
||||
}}
|
||||
>
|
||||
{this.state.audioTracks.map((track) => {
|
||||
return (
|
||||
<Picker.Item
|
||||
label={track.language}
|
||||
value={track.language}
|
||||
key={track.language}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Picker>
|
||||
)}
|
||||
<Text style={styles.controlOption}>TextTrack</Text>
|
||||
{this.state.textTracks?.length <= 0 ? (
|
||||
<Text style={styles.controlOption}>empty</Text>
|
||||
) : (
|
||||
<Picker
|
||||
style={styles.picker}
|
||||
selectedValue={this.state.selectedTextTrack?.value}
|
||||
onValueChange={(itemValue, itemIndex) => {
|
||||
console.log('on value change ' + itemValue)
|
||||
this.setState({
|
||||
selectedTextTrack: {
|
||||
type: 'language',
|
||||
value: itemValue,
|
||||
},
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Picker.Item label={'none'} value={'none'} key={'none'} />
|
||||
|
||||
{this.state.textTracks?.map?.((track) => (
|
||||
<Picker.Item
|
||||
label={track.language}
|
||||
value={track.language}
|
||||
key={track.language}
|
||||
/>
|
||||
))}
|
||||
</Picker>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.resizeModeControl}>
|
||||
{this.renderResizeModeControl('cover')}
|
||||
{this.renderResizeModeControl('contain')}
|
||||
{this.renderResizeModeControl('stretch')}
|
||||
</View>
|
||||
</View>
|
||||
{this.renderSeekBar()}
|
||||
<View style={styles.generalControls}>
|
||||
<Text style={styles.controlOption}>AudioTrack</Text>
|
||||
{this.state.audioTracks?.length <= 0 ? (
|
||||
<Text style={styles.controlOption}>empty</Text>
|
||||
) : (
|
||||
<Picker
|
||||
style={styles.picker}
|
||||
selectedValue={this.state.selectedAudioTrack?.value}
|
||||
onValueChange={(itemValue, itemIndex) => {
|
||||
console.log('on audio value change ' + itemValue);
|
||||
this.setState({
|
||||
selectedAudioTrack: {
|
||||
type: 'language',
|
||||
value: itemValue,
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
{this.state.audioTracks.map((track) => {
|
||||
return (
|
||||
<Picker.Item
|
||||
label={track.language}
|
||||
value={track.language}
|
||||
key={track.language} />
|
||||
);
|
||||
})}
|
||||
</Picker>
|
||||
)}
|
||||
<Text style={styles.controlOption}>TextTrack</Text>
|
||||
{this.state.textTracks?.length <= 0 ? (
|
||||
<Text style={styles.controlOption}>empty</Text>
|
||||
) : (
|
||||
<Picker
|
||||
style={styles.picker}
|
||||
selectedValue={this.state.selectedTextTrack?.value}
|
||||
onValueChange={(itemValue, itemIndex) => {
|
||||
console.log('on value change ' + itemValue);
|
||||
this.setState({
|
||||
selectedTextTrack: {
|
||||
type: 'language',
|
||||
value: itemValue,
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Picker.Item label={'none'} value={'none'} key={'none'} />
|
||||
{this.state.textTracks.map((track) => (
|
||||
<Picker.Item
|
||||
label={track.language}
|
||||
value={track.language}
|
||||
key={track.language} />
|
||||
))}
|
||||
</Picker>
|
||||
)}
|
||||
</View>
|
||||
</View></>
|
||||
) : null
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -689,6 +714,7 @@ class VideoPlayer extends Component {
|
||||
paused={this.state.paused}
|
||||
volume={this.state.volume}
|
||||
muted={this.state.muted}
|
||||
controls={this.state.showRNVControls}
|
||||
resizeMode={this.state.resizeMode}
|
||||
onLoad={this.onLoad}
|
||||
onAudioTracks={this.onAudioTracks}
|
||||
@ -706,6 +732,7 @@ class VideoPlayer extends Component {
|
||||
repeat={this.state.loop}
|
||||
selectedTextTrack={this.state.selectedTextTrack}
|
||||
selectedAudioTrack={this.state.selectedAudioTrack}
|
||||
playInBackground={false}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
|
@ -2573,11 +2573,6 @@ electron-to-chromium@^1.4.17:
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.59.tgz#657f2588c048fb95975779f8fea101fad854de89"
|
||||
integrity sha512-AOJ3cAE0TWxz4fQ9zkND5hWrQg16nsZKVz9INOot1oV//u4wWu5xrj9CQMmPTYskkZRunSRc9sAnr4EkexXokg==
|
||||
|
||||
eme-encryption-scheme-polyfill@^2.0.3:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/eme-encryption-scheme-polyfill/-/eme-encryption-scheme-polyfill-2.0.4.tgz#7d818302af3f3b19d5974255dcc92dc087413845"
|
||||
integrity sha512-MHYJX1v145Pjj2YJTrVVuJOYyXrxGVy8LWf6kV5M4jrV/GyoeuJKyTuD+GaD+VAiE8Ip+MptiH4dXk6ZVmMNow==
|
||||
|
||||
emitter-listener@^1.0.1, emitter-listener@^1.1.1:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/emitter-listener/-/emitter-listener-1.1.2.tgz#56b140e8f6992375b3d7cb2cab1cc7432d9632e8"
|
||||
@ -5774,13 +5769,12 @@ react-is@^16.12.0, react-is@^16.13.1, react-is@^16.8.4, react-is@^16.8.6:
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
||||
react-native-video@../..:
|
||||
version "6.0.0-alpha1"
|
||||
react-native-video@../../:
|
||||
version "6.0.0-alpha.3"
|
||||
dependencies:
|
||||
deprecated-react-native-prop-types "^2.2.0"
|
||||
keymirror "^0.1.1"
|
||||
prop-types "^15.7.2"
|
||||
shaka-player "^3.3.2"
|
||||
|
||||
react-native-windows@0.63.41:
|
||||
version "0.63.41"
|
||||
@ -6309,13 +6303,6 @@ setprototypeof@1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
|
||||
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
|
||||
|
||||
shaka-player@^3.3.2:
|
||||
version "3.3.4"
|
||||
resolved "https://registry.yarnpkg.com/shaka-player/-/shaka-player-3.3.4.tgz#7d137a18fc0f55c50852a4348c8319495b5fa546"
|
||||
integrity sha512-8PrUBA8aOABGvhQVa59XMoPo5myAoQF4ptx6gvZWPOBtdsyVaamqQKELY77ikZJ1ejup7BmHf42MXGFmxQfcaA==
|
||||
dependencies:
|
||||
eme-encryption-scheme-polyfill "^2.0.3"
|
||||
|
||||
shallow-clone@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
|
||||
|
@ -1,5 +1,5 @@
|
||||
#import <React/RCTViewManager.h>
|
||||
#import "RCTSwiftLog.h"
|
||||
#import "RCTVideoSwiftLog.h"
|
||||
|
||||
#if __has_include(<react-native-video/RCTVideoCache.h>)
|
||||
#import "RCTVideoCache.h"
|
||||
|
@ -219,6 +219,12 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
|
||||
@objc
|
||||
func setSrc(_ source:NSDictionary!) {
|
||||
_source = VideoSource(source)
|
||||
if (_source?.uri == nil || _source?.uri == "") {
|
||||
DispatchQueue.global(qos: .default).async {
|
||||
self._player?.replaceCurrentItem(with: nil)
|
||||
}
|
||||
return;
|
||||
}
|
||||
removePlayerLayer()
|
||||
_playerObserver.player = nil
|
||||
_playerObserver.playerItem = nil
|
||||
|
@ -1,6 +1,6 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface RCTSwiftLog : NSObject
|
||||
@interface RCTVideoSwiftLog : NSObject
|
||||
|
||||
+ (void)error:(NSString * _Nonnull)message file:(NSString * _Nonnull)file line:(NSUInteger)line;
|
||||
+ (void)warn:(NSString * _Nonnull)message file:(NSString * _Nonnull)file line:(NSUInteger)line;
|
@ -1,8 +1,8 @@
|
||||
#import <React/RCTLog.h>
|
||||
|
||||
#import "RCTSwiftLog.h"
|
||||
#import "RCTVideoSwiftLog.h"
|
||||
|
||||
@implementation RCTSwiftLog
|
||||
@implementation RCTVideoSwiftLog
|
||||
|
||||
+ (void)info:(NSString *)message file:(NSString *)file line:(NSUInteger)line
|
||||
{
|
@ -26,23 +26,23 @@
|
||||
*/
|
||||
|
||||
func RCTLogError(_ message: String, _ file: String=#file, _ line: UInt=#line) {
|
||||
RCTSwiftLog.error(message, file: file, line: line)
|
||||
RCTVideoSwiftLog.error(message, file: file, line: line)
|
||||
}
|
||||
|
||||
func RCTLogWarn(_ message: String, _ file: String=#file, _ line: UInt=#line) {
|
||||
RCTSwiftLog.warn(message, file: file, line: line)
|
||||
RCTVideoSwiftLog.warn(message, file: file, line: line)
|
||||
}
|
||||
|
||||
func RCTLogInfo(_ message: String, _ file: String=#file, _ line: UInt=#line) {
|
||||
RCTSwiftLog.info(message, file: file, line: line)
|
||||
RCTVideoSwiftLog.info(message, file: file, line: line)
|
||||
}
|
||||
|
||||
func RCTLog(_ message: String, _ file: String=#file, _ line: UInt=#line) {
|
||||
RCTSwiftLog.log(message, file: file, line: line)
|
||||
RCTVideoSwiftLog.log(message, file: file, line: line)
|
||||
}
|
||||
|
||||
func RCTLogTrace(_ message: String, _ file: String=#file, _ line: UInt=#line) {
|
||||
RCTSwiftLog.trace(message, file: file, line: line)
|
||||
RCTVideoSwiftLog.trace(message, file: file, line: line)
|
||||
}
|
||||
|
||||
func DebugLog(_ message: String) {
|
@ -5,6 +5,7 @@
|
||||
"main": "Video.js",
|
||||
"license": "MIT",
|
||||
"author": "Community Contributors",
|
||||
"homepage": "https://github.com/react-native-video/react-native-video#readme",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:react-native-video/react-native-video.git"
|
||||
|
Loading…
Reference in New Issue
Block a user