Merge remote-tracking branch 'upstream/master' into implement-ios-caching
This commit is contained in:
commit
8fcdc6e02a
10
CHANGELOG.md
10
CHANGELOG.md
@ -1,9 +1,17 @@
|
|||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
### Next Version
|
### Next Version
|
||||||
|
|
||||||
|
* Support video cachging for iOS ([#955](https://github.com/react-native-community/react-native-video/pull/955))
|
||||||
|
|
||||||
|
### Version 3.2.0
|
||||||
* Basic fullscreen support for Android MediaPlayer [#1138](https://github.com/react-native-community/react-native-video/pull/1138)
|
* Basic fullscreen support for Android MediaPlayer [#1138](https://github.com/react-native-community/react-native-video/pull/1138)
|
||||||
* Simplify default Android SDK code [#1145](https://github.com/react-native-community/react-native-video/pull/1145) [#1146](https://github.com/react-native-community/react-native-video/pull/1146)
|
* Simplify default Android SDK code [#1145](https://github.com/react-native-community/react-native-video/pull/1145) [#1146](https://github.com/react-native-community/react-native-video/pull/1146)
|
||||||
* Support video cachging for iOS ([#955](https://github.com/react-native-community/react-native-video/pull/955))
|
* Various iOS sideloaded text track fixes [#1157](https://github.com/react-native-community/react-native-video/pull/1157)
|
||||||
|
* Fix #1150 where assets with bundled assets don't work on iOS in release mode [#1162](https://github.com/react-native-community/react-native-video/pull/1162)
|
||||||
|
* Support configuring the buffer on Android ExoPlayer [#1160](https://github.com/react-native-community/react-native-video/pull/1160)
|
||||||
|
* Prevent sleep from sleeping while videos are playing on Android MediaPlayer [#1117](https://github.com/react-native-community/react-native-video/pull/1117)
|
||||||
|
* Update NewtonSoft JSON to match react-native-windows version [#1169](https://github.com/react-native-community/react-native-video/pull/1169)
|
||||||
|
|
||||||
### Version 3.1.0
|
### Version 3.1.0
|
||||||
* Support sidecar text tracks on iOS [#1109](https://github.com/react-native-community/react-native-video/pull/1109)
|
* Support sidecar text tracks on iOS [#1109](https://github.com/react-native-community/react-native-video/pull/1109)
|
||||||
|
25
README.md
25
README.md
@ -236,6 +236,7 @@ var styles = StyleSheet.create({
|
|||||||
### Configurable props
|
### Configurable props
|
||||||
* [allowsExternalPlayback](#allowsexternalplayback)
|
* [allowsExternalPlayback](#allowsexternalplayback)
|
||||||
* [audioOnly](#audioonly)
|
* [audioOnly](#audioonly)
|
||||||
|
* [bufferConfig](#bufferconfig)
|
||||||
* [ignoreSilentSwitch](#ignoresilentswitch)
|
* [ignoreSilentSwitch](#ignoresilentswitch)
|
||||||
* [muted](#muted)
|
* [muted](#muted)
|
||||||
* [paused](#paused)
|
* [paused](#paused)
|
||||||
@ -288,6 +289,30 @@ For this to work, the poster prop must be set.
|
|||||||
|
|
||||||
Platforms: all
|
Platforms: all
|
||||||
|
|
||||||
|
#### bufferConfig
|
||||||
|
Adjust the buffer settings. This prop takes an object with one or more of the properties listed below.
|
||||||
|
|
||||||
|
Property | Type | Description
|
||||||
|
--- | --- | ---
|
||||||
|
minBufferMs | number | The default minimum duration of media that the player will attempt to ensure is buffered at all times, in milliseconds.
|
||||||
|
maxBufferMs | number | The default maximum duration of media that the player will attempt to buffer, in milliseconds.
|
||||||
|
bufferForPlaybackMs | number | The default duration of media that must be buffered for playback to start or resume following a user action such as a seek, in milliseconds.
|
||||||
|
playbackAfterRebufferMs | number | The default duration of media that must be buffered for playback to resume after a rebuffer, in milliseconds. A rebuffer is defined to be caused by buffer depletion rather than a user action.
|
||||||
|
|
||||||
|
This prop should only be set when you are setting the source, changing it after the media is loaded will cause it to be reloaded.
|
||||||
|
|
||||||
|
Example with default values:
|
||||||
|
```
|
||||||
|
bufferConfig={{
|
||||||
|
minBufferMs: 15000,
|
||||||
|
maxBufferMs: 50000,
|
||||||
|
bufferForPlaybackMs: 2500,
|
||||||
|
bufferForPlaybackAfterRebufferMs: 5000
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
Platforms: Android ExoPlayer
|
||||||
|
|
||||||
#### ignoreSilentSwitch
|
#### ignoreSilentSwitch
|
||||||
Controls the iOS silent switch behavior
|
Controls the iOS silent switch behavior
|
||||||
* **"inherit" (default)** - Use the default AVPlayer behavior
|
* **"inherit" (default)** - Use the default AVPlayer behavior
|
||||||
|
6
Video.js
6
Video.js
@ -345,6 +345,12 @@ Video.propTypes = {
|
|||||||
paused: PropTypes.bool,
|
paused: PropTypes.bool,
|
||||||
muted: PropTypes.bool,
|
muted: PropTypes.bool,
|
||||||
volume: PropTypes.number,
|
volume: PropTypes.number,
|
||||||
|
bufferConfig: PropTypes.shape({
|
||||||
|
minBufferMs: PropTypes.number,
|
||||||
|
maxBufferMs: PropTypes.number,
|
||||||
|
bufferForPlaybackMs: PropTypes.number,
|
||||||
|
bufferForPlaybackAfterRebufferMs: PropTypes.number,
|
||||||
|
}),
|
||||||
stereoPan: PropTypes.number,
|
stereoPan: PropTypes.number,
|
||||||
rate: PropTypes.number,
|
rate: PropTypes.number,
|
||||||
playInBackground: PropTypes.bool,
|
playInBackground: PropTypes.bool,
|
||||||
|
@ -58,6 +58,7 @@ import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
|
|||||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
|
import com.google.android.exoplayer2.upstream.DefaultAllocator;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
@ -109,6 +110,11 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
private boolean isBuffering;
|
private boolean isBuffering;
|
||||||
private float rate = 1f;
|
private float rate = 1f;
|
||||||
|
|
||||||
|
private int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
||||||
|
private int maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
||||||
|
private int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
||||||
|
private int bufferForPlaybackAfterRebufferMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS;
|
||||||
|
|
||||||
// Props from React
|
// Props from React
|
||||||
private Uri srcUri;
|
private Uri srcUri;
|
||||||
private String extension;
|
private String extension;
|
||||||
@ -234,7 +240,9 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
if (player == null) {
|
if (player == null) {
|
||||||
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
|
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(BANDWIDTH_METER);
|
||||||
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
|
trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
|
||||||
player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, new DefaultLoadControl());
|
DefaultAllocator allocator = new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE);
|
||||||
|
DefaultLoadControl defaultLoadControl = new DefaultLoadControl(allocator, minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, -1, true);
|
||||||
|
player = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, defaultLoadControl);
|
||||||
player.addListener(this);
|
player.addListener(this);
|
||||||
player.setMetadataOutput(this);
|
player.setMetadataOutput(this);
|
||||||
exoPlayerView.setPlayer(player);
|
exoPlayerView.setPlayer(player);
|
||||||
@ -320,7 +328,6 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
|
|
||||||
private void releasePlayer() {
|
private void releasePlayer() {
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
isPaused = player.getPlayWhenReady();
|
|
||||||
updateResumePosition();
|
updateResumePosition();
|
||||||
player.release();
|
player.release();
|
||||||
player.setMetadataOutput(null);
|
player.setMetadataOutput(null);
|
||||||
@ -931,4 +938,13 @@ class ReactExoplayerView extends FrameLayout implements
|
|||||||
public void setUseTextureView(boolean useTextureView) {
|
public void setUseTextureView(boolean useTextureView) {
|
||||||
exoPlayerView.setUseTextureView(useTextureView);
|
exoPlayerView.setUseTextureView(useTextureView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBufferForPlaybackMs, int newBufferForPlaybackAfterRebufferMs) {
|
||||||
|
minBufferMs = newMinBufferMs;
|
||||||
|
maxBufferMs = newMaxBufferMs;
|
||||||
|
bufferForPlaybackMs = newBufferForPlaybackMs;
|
||||||
|
bufferForPlaybackAfterRebufferMs = newBufferForPlaybackAfterRebufferMs;
|
||||||
|
releasePlayer();
|
||||||
|
initializePlayer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import com.facebook.react.common.MapBuilder;
|
|||||||
import com.facebook.react.uimanager.ThemedReactContext;
|
import com.facebook.react.uimanager.ThemedReactContext;
|
||||||
import com.facebook.react.uimanager.ViewGroupManager;
|
import com.facebook.react.uimanager.ViewGroupManager;
|
||||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||||
|
import com.google.android.exoplayer2.DefaultLoadControl;
|
||||||
import com.google.android.exoplayer2.upstream.RawResourceDataSource;
|
import com.google.android.exoplayer2.upstream.RawResourceDataSource;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -38,6 +39,11 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
private static final String PROP_PAUSED = "paused";
|
private static final String PROP_PAUSED = "paused";
|
||||||
private static final String PROP_MUTED = "muted";
|
private static final String PROP_MUTED = "muted";
|
||||||
private static final String PROP_VOLUME = "volume";
|
private static final String PROP_VOLUME = "volume";
|
||||||
|
private static final String PROP_BUFFER_CONFIG = "bufferConfig";
|
||||||
|
private static final String PROP_BUFFER_CONFIG_MIN_BUFFER_MS = "minBufferMs";
|
||||||
|
private static final String PROP_BUFFER_CONFIG_MAX_BUFFER_MS = "maxBufferMs";
|
||||||
|
private static final String PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS = "bufferForPlaybackMs";
|
||||||
|
private static final String PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS = "bufferForPlaybackAfterRebufferMs";
|
||||||
private static final String PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval";
|
private static final String PROP_PROGRESS_UPDATE_INTERVAL = "progressUpdateInterval";
|
||||||
private static final String PROP_SEEK = "seek";
|
private static final String PROP_SEEK = "seek";
|
||||||
private static final String PROP_RATE = "rate";
|
private static final String PROP_RATE = "rate";
|
||||||
@ -214,6 +220,25 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
videoView.setUseTextureView(useTextureView);
|
videoView.setUseTextureView(useTextureView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = PROP_BUFFER_CONFIG)
|
||||||
|
public void setBufferConfig(final ReactExoplayerView videoView, @Nullable ReadableMap bufferConfig) {
|
||||||
|
int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
||||||
|
int maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
||||||
|
int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
||||||
|
int bufferForPlaybackAfterRebufferMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS;
|
||||||
|
if (bufferConfig != null) {
|
||||||
|
minBufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MIN_BUFFER_MS)
|
||||||
|
? bufferConfig.getInt(PROP_BUFFER_CONFIG_MIN_BUFFER_MS) : minBufferMs;
|
||||||
|
maxBufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_MAX_BUFFER_MS)
|
||||||
|
? bufferConfig.getInt(PROP_BUFFER_CONFIG_MAX_BUFFER_MS) : maxBufferMs;
|
||||||
|
bufferForPlaybackMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS)
|
||||||
|
? bufferConfig.getInt(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS) : bufferForPlaybackMs;
|
||||||
|
bufferForPlaybackAfterRebufferMs = bufferConfig.hasKey(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS)
|
||||||
|
? bufferConfig.getInt(PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS) : bufferForPlaybackAfterRebufferMs;
|
||||||
|
videoView.setBufferConfig(minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean startsWithValidScheme(String uriString) {
|
private boolean startsWithValidScheme(String uriString) {
|
||||||
return uriString.startsWith("http://")
|
return uriString.startsWith("http://")
|
||||||
|| uriString.startsWith("https://")
|
|| uriString.startsWith("https://")
|
||||||
|
@ -10,6 +10,7 @@ import android.os.Build;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.WindowManager;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.webkit.CookieManager;
|
import android.webkit.CookieManager;
|
||||||
@ -96,7 +97,6 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
|||||||
private Handler videoControlHandler = new Handler();
|
private Handler videoControlHandler = new Handler();
|
||||||
private MediaController mediaController;
|
private MediaController mediaController;
|
||||||
|
|
||||||
|
|
||||||
private String mSrcUriString = null;
|
private String mSrcUriString = null;
|
||||||
private String mSrcType = "mp4";
|
private String mSrcType = "mp4";
|
||||||
private ReadableMap mRequestHeaders = null;
|
private ReadableMap mRequestHeaders = null;
|
||||||
@ -359,7 +359,6 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setPausedModifier(final boolean paused) {
|
public void setPausedModifier(final boolean paused) {
|
||||||
|
|
||||||
mPaused = paused;
|
mPaused = paused;
|
||||||
|
|
||||||
if (!mMediaPlayerValid) {
|
if (!mMediaPlayerValid) {
|
||||||
@ -382,6 +381,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
|||||||
mProgressUpdateHandler.post(mProgressUpdateRunnable);
|
mProgressUpdateHandler.post(mProgressUpdateRunnable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setKeepScreenOn(!mPaused);
|
||||||
}
|
}
|
||||||
|
|
||||||
// reduces the volume based on stereoPan
|
// reduces the volume based on stereoPan
|
||||||
@ -501,7 +501,6 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
|||||||
this.mUseNativeControls = controls;
|
this.mUseNativeControls = controls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepared(MediaPlayer mp) {
|
public void onPrepared(MediaPlayer mp) {
|
||||||
|
|
||||||
@ -625,21 +624,22 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCompletion(MediaPlayer mp) {
|
public void onCompletion(MediaPlayer mp) {
|
||||||
|
|
||||||
isCompleted = true;
|
isCompleted = true;
|
||||||
mEventEmitter.receiveEvent(getId(), Events.EVENT_END.toString(), null);
|
mEventEmitter.receiveEvent(getId(), Events.EVENT_END.toString(), null);
|
||||||
|
if (!mRepeat) {
|
||||||
|
setKeepScreenOn(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDetachedFromWindow() {
|
protected void onDetachedFromWindow() {
|
||||||
|
|
||||||
mMediaPlayerValid = false;
|
mMediaPlayerValid = false;
|
||||||
super.onDetachedFromWindow();
|
super.onDetachedFromWindow();
|
||||||
|
setKeepScreenOn(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onAttachedToWindow() {
|
protected void onAttachedToWindow() {
|
||||||
|
|
||||||
super.onAttachedToWindow();
|
super.onAttachedToWindow();
|
||||||
|
|
||||||
if(mMainVer>0) {
|
if(mMainVer>0) {
|
||||||
@ -648,7 +648,7 @@ public class ReactVideoView extends ScalableVideoView implements MediaPlayer.OnP
|
|||||||
else {
|
else {
|
||||||
setSrc(mSrcUriString, mSrcType, mSrcIsNetwork, mSrcIsAsset, mRequestHeaders);
|
setSrc(mSrcUriString, mSrcType, mSrcIsNetwork, mSrcIsAsset, mRequestHeaders);
|
||||||
}
|
}
|
||||||
|
setKeepScreenOn(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -313,7 +313,7 @@ static int const RCTVideoUnset = -1;
|
|||||||
[self removePlayerItemObservers];
|
[self removePlayerItemObservers];
|
||||||
|
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
// perform on next run loop, otherwise other passed react-props may not be set
|
// perform on next run loop, otherwise other passed react-props may not be set
|
||||||
[self playerItemForSource:source withCallback:^(AVPlayerItem * playerItem) {
|
[self playerItemForSource:source withCallback:^(AVPlayerItem * playerItem) {
|
||||||
_playerItem = playerItem;
|
_playerItem = playerItem;
|
||||||
@ -353,8 +353,12 @@ static int const RCTVideoUnset = -1;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (NSURL*) urlFilePath:(NSString*) filepath {
|
- (NSURL*) urlFilePath:(NSString*) filepath {
|
||||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
if ([filepath containsString:@"file://"]) {
|
||||||
|
return [NSURL URLWithString:filepath];
|
||||||
|
}
|
||||||
|
|
||||||
|
// code to support local caching
|
||||||
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||||
NSString* relativeFilePath = [filepath lastPathComponent];
|
NSString* relativeFilePath = [filepath lastPathComponent];
|
||||||
// the file may be multiple levels below the documents directory
|
// the file may be multiple levels below the documents directory
|
||||||
NSArray* fileComponents = [filepath componentsSeparatedByString:@"Documents/"];
|
NSArray* fileComponents = [filepath componentsSeparatedByString:@"Documents/"];
|
||||||
@ -392,6 +396,7 @@ static int const RCTVideoUnset = -1;
|
|||||||
atTime:kCMTimeZero
|
atTime:kCMTimeZero
|
||||||
error:nil];
|
error:nil];
|
||||||
|
|
||||||
|
NSMutableArray* validTextTracks = [NSMutableArray array];
|
||||||
for (int i = 0; i < _textTracks.count; ++i) {
|
for (int i = 0; i < _textTracks.count; ++i) {
|
||||||
AVURLAsset *textURLAsset;
|
AVURLAsset *textURLAsset;
|
||||||
NSString *textUri = [_textTracks objectAtIndex:i][@"uri"];
|
NSString *textUri = [_textTracks objectAtIndex:i][@"uri"];
|
||||||
@ -401,6 +406,8 @@ static int const RCTVideoUnset = -1;
|
|||||||
textURLAsset = [AVURLAsset URLAssetWithURL:[self urlFilePath:textUri] options:nil];
|
textURLAsset = [AVURLAsset URLAssetWithURL:[self urlFilePath:textUri] options:nil];
|
||||||
}
|
}
|
||||||
AVAssetTrack *textTrackAsset = [textURLAsset tracksWithMediaType:AVMediaTypeText].firstObject;
|
AVAssetTrack *textTrackAsset = [textURLAsset tracksWithMediaType:AVMediaTypeText].firstObject;
|
||||||
|
if (!textTrackAsset) continue; // fix when there's no textTrackAsset
|
||||||
|
[validTextTracks addObject:[_textTracks objectAtIndex:i]];
|
||||||
AVMutableCompositionTrack *textCompTrack = [mixComposition
|
AVMutableCompositionTrack *textCompTrack = [mixComposition
|
||||||
addMutableTrackWithMediaType:AVMediaTypeText
|
addMutableTrackWithMediaType:AVMediaTypeText
|
||||||
preferredTrackID:kCMPersistentTrackID_Invalid];
|
preferredTrackID:kCMPersistentTrackID_Invalid];
|
||||||
@ -409,6 +416,9 @@ static int const RCTVideoUnset = -1;
|
|||||||
atTime:kCMTimeZero
|
atTime:kCMTimeZero
|
||||||
error:nil];
|
error:nil];
|
||||||
}
|
}
|
||||||
|
if (validTextTracks.count != _textTracks.count) {
|
||||||
|
[self setTextTracks:validTextTracks];
|
||||||
|
}
|
||||||
|
|
||||||
handler([AVPlayerItem playerItemWithAsset:mixComposition]);
|
handler([AVPlayerItem playerItemWithAsset:mixComposition]);
|
||||||
}
|
}
|
||||||
@ -892,7 +902,10 @@ static int const RCTVideoUnset = -1;
|
|||||||
selectedTrackIndex = index;
|
selectedTrackIndex = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // type "system"
|
}
|
||||||
|
|
||||||
|
// in the situation that a selected text track is not available (eg. specifies a textTrack not available)
|
||||||
|
if (![type isEqualToString:@"disabled"] && selectedTrackIndex == RCTVideoUnset) {
|
||||||
CFArrayRef captioningMediaCharacteristics = MACaptionAppearanceCopyPreferredCaptioningMediaCharacteristics(kMACaptionAppearanceDomainUser);
|
CFArrayRef captioningMediaCharacteristics = MACaptionAppearanceCopyPreferredCaptioningMediaCharacteristics(kMACaptionAppearanceDomainUser);
|
||||||
NSArray *captionSettings = (__bridge NSArray*)captioningMediaCharacteristics;
|
NSArray *captionSettings = (__bridge NSArray*)captioningMediaCharacteristics;
|
||||||
if ([captionSettings containsObject:AVMediaCharacteristicTranscribesSpokenDialogForAccessibility]) {
|
if ([captionSettings containsObject:AVMediaCharacteristicTranscribesSpokenDialogForAccessibility]) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "react-native-video",
|
"name": "react-native-video",
|
||||||
"version": "3.1.0",
|
"version": "3.2.0",
|
||||||
"description": "A <Video /> element for react-native",
|
"description": "A <Video /> element for react-native",
|
||||||
"main": "Video.js",
|
"main": "Video.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
<OutputPath>bin\x86\Release\</OutputPath>
|
<OutputPath>bin\x86\Release\</OutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="PresentationCore" />
|
<Reference Include="PresentationCore" />
|
||||||
@ -71,4 +71,4 @@
|
|||||||
<Target Name="AfterBuild">
|
<Target Name="AfterBuild">
|
||||||
</Target>
|
</Target>
|
||||||
-->
|
-->
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net46" />
|
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net46" />
|
||||||
</packages>
|
</packages>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2",
|
"Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2",
|
||||||
"Newtonsoft.Json": "9.0.1"
|
"Newtonsoft.Json": "10.0.3"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"uap10.0": {}
|
"uap10.0": {}
|
||||||
@ -14,4 +14,4 @@
|
|||||||
"win10-x64": {},
|
"win10-x64": {},
|
||||||
"win10-x64-aot": {}
|
"win10-x64-aot": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user