feat(android): cache (#3514)
* feat: android cache * docs: bufferSize * Revert "docs: bufferSize" This reverts commit 09637b134e121b9ca3ffd78f2f5bc657319ed67a. * fix: cacheSize name * feat: singleton android cache * fix: local cache resolve * fix: lint * docs: android cache * chore: merge conflict * fix: lint * chore: useCache button * chore: fix state in the sample * fix: cache factory * chore: update cacheSizeMB docs --------- Co-authored-by: Olivier Bouillet <freeboub@gmail.com>
This commit is contained in:
parent
518a9a93e0
commit
ecc946d1c1
@ -0,0 +1,31 @@
|
|||||||
|
package com.brentvatne.exoplayer
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.media3.database.StandaloneDatabaseProvider
|
||||||
|
import androidx.media3.datasource.DataSource
|
||||||
|
import androidx.media3.datasource.HttpDataSource
|
||||||
|
import androidx.media3.datasource.cache.CacheDataSource
|
||||||
|
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
|
||||||
|
import androidx.media3.datasource.cache.SimpleCache
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
object RNVSimpleCache {
|
||||||
|
// TODO: when to release? how to check if cache is released?
|
||||||
|
private var simpleCache: SimpleCache? = null
|
||||||
|
var cacheDataSourceFactory: DataSource.Factory? = null
|
||||||
|
|
||||||
|
fun setSimpleCache(context: Context, cacheSize: Int, factory: HttpDataSource.Factory) {
|
||||||
|
if (cacheDataSourceFactory != null || cacheSize == 0) return
|
||||||
|
simpleCache = SimpleCache(
|
||||||
|
File(context.cacheDir, "RNVCache"),
|
||||||
|
LeastRecentlyUsedCacheEvictor(
|
||||||
|
cacheSize.toLong() * 1024 * 1024
|
||||||
|
),
|
||||||
|
StandaloneDatabaseProvider(context)
|
||||||
|
)
|
||||||
|
cacheDataSourceFactory =
|
||||||
|
CacheDataSource.Factory()
|
||||||
|
.setCache(simpleCache!!)
|
||||||
|
.setUpstreamDataSourceFactory(factory)
|
||||||
|
}
|
||||||
|
}
|
@ -105,7 +105,6 @@ import com.brentvatne.react.BuildConfig;
|
|||||||
import com.brentvatne.react.R;
|
import com.brentvatne.react.R;
|
||||||
import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
|
import com.brentvatne.receiver.AudioBecomingNoisyReceiver;
|
||||||
import com.brentvatne.receiver.BecomingNoisyListener;
|
import com.brentvatne.receiver.BecomingNoisyListener;
|
||||||
import com.facebook.react.bridge.Dynamic;
|
|
||||||
import com.facebook.react.bridge.LifecycleEventListener;
|
import com.facebook.react.bridge.LifecycleEventListener;
|
||||||
import com.facebook.react.bridge.ReadableArray;
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
import com.facebook.react.bridge.ReadableMap;
|
import com.facebook.react.bridge.ReadableMap;
|
||||||
@ -188,7 +187,6 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
private boolean hasDrmFailed = false;
|
private boolean hasDrmFailed = false;
|
||||||
private boolean isUsingContentResolution = false;
|
private boolean isUsingContentResolution = false;
|
||||||
private boolean selectTrackWhenReady = false;
|
private boolean selectTrackWhenReady = false;
|
||||||
|
|
||||||
private int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
private int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
||||||
private int maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
private int maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
||||||
private int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
private int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
||||||
@ -199,6 +197,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
private double minBufferMemoryReservePercent = ReactExoplayerView.DEFAULT_MIN_BUFFER_MEMORY_RESERVE;
|
private double minBufferMemoryReservePercent = ReactExoplayerView.DEFAULT_MIN_BUFFER_MEMORY_RESERVE;
|
||||||
private Handler mainHandler;
|
private Handler mainHandler;
|
||||||
private Runnable mainRunnable;
|
private Runnable mainRunnable;
|
||||||
|
private DataSource.Factory cacheDataSourceFactory;
|
||||||
|
|
||||||
// Props from React
|
// Props from React
|
||||||
private Uri srcUri;
|
private Uri srcUri;
|
||||||
@ -623,8 +622,11 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
.setAdEventListener(this)
|
.setAdEventListener(this)
|
||||||
.setAdErrorListener(this)
|
.setAdErrorListener(this)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
DefaultMediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(mediaDataSourceFactory);
|
DefaultMediaSourceFactory mediaSourceFactory = new DefaultMediaSourceFactory(mediaDataSourceFactory);
|
||||||
|
if (cacheDataSourceFactory != null) {
|
||||||
|
mediaSourceFactory.setDataSourceFactory(cacheDataSourceFactory);
|
||||||
|
}
|
||||||
|
|
||||||
if (adsLoader != null) {
|
if (adsLoader != null) {
|
||||||
mediaSourceFactory.setLocalAdInsertionComponents(unusedAdTagUri -> adsLoader, exoPlayerView);
|
mediaSourceFactory.setLocalAdInsertionComponents(unusedAdTagUri -> adsLoader, exoPlayerView);
|
||||||
}
|
}
|
||||||
@ -839,9 +841,17 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case CONTENT_TYPE_OTHER:
|
case CONTENT_TYPE_OTHER:
|
||||||
mediaSourceFactory = new ProgressiveMediaSource.Factory(
|
if (uri.toString().startsWith("file://") ||
|
||||||
mediaDataSourceFactory
|
cacheDataSourceFactory == null) {
|
||||||
);
|
mediaSourceFactory = new ProgressiveMediaSource.Factory(
|
||||||
|
mediaDataSourceFactory
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
mediaSourceFactory = new ProgressiveMediaSource.Factory(
|
||||||
|
cacheDataSourceFactory
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CONTENT_TYPE_RTSP:
|
case CONTENT_TYPE_RTSP:
|
||||||
if (!BuildConfig.USE_EXOPLAYER_RTSP) {
|
if (!BuildConfig.USE_EXOPLAYER_RTSP) {
|
||||||
@ -2015,7 +2025,7 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
exoPlayerView.setHideShutterView(hideShutterView);
|
exoPlayerView.setHideShutterView(hideShutterView);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBufferForPlaybackMs, int newBufferForPlaybackAfterRebufferMs, double newMaxHeapAllocationPercent, double newMinBackBufferMemoryReservePercent, double newMinBufferMemoryReservePercent, int newBackBufferDurationMs) {
|
public void setBufferConfig(int newMinBufferMs, int newMaxBufferMs, int newBufferForPlaybackMs, int newBufferForPlaybackAfterRebufferMs, double newMaxHeapAllocationPercent, double newMinBackBufferMemoryReservePercent, double newMinBufferMemoryReservePercent, int newBackBufferDurationMs, int cacheSize) {
|
||||||
minBufferMs = newMinBufferMs;
|
minBufferMs = newMinBufferMs;
|
||||||
maxBufferMs = newMaxBufferMs;
|
maxBufferMs = newMaxBufferMs;
|
||||||
bufferForPlaybackMs = newBufferForPlaybackMs;
|
bufferForPlaybackMs = newBufferForPlaybackMs;
|
||||||
@ -2023,6 +2033,17 @@ public class ReactExoplayerView extends FrameLayout implements
|
|||||||
maxHeapAllocationPercent = newMaxHeapAllocationPercent;
|
maxHeapAllocationPercent = newMaxHeapAllocationPercent;
|
||||||
minBackBufferMemoryReservePercent = newMinBackBufferMemoryReservePercent;
|
minBackBufferMemoryReservePercent = newMinBackBufferMemoryReservePercent;
|
||||||
minBufferMemoryReservePercent = newMinBufferMemoryReservePercent;
|
minBufferMemoryReservePercent = newMinBufferMemoryReservePercent;
|
||||||
|
if (cacheSize > 0) {
|
||||||
|
RNVSimpleCache.INSTANCE.setSimpleCache(
|
||||||
|
this.getContext(),
|
||||||
|
cacheSize,
|
||||||
|
buildHttpDataSourceFactory(false)
|
||||||
|
);
|
||||||
|
cacheDataSourceFactory = RNVSimpleCache.INSTANCE.getCacheDataSourceFactory();
|
||||||
|
} else {
|
||||||
|
cacheDataSourceFactory = null;
|
||||||
|
}
|
||||||
|
|
||||||
backBufferDurationMs = newBackBufferDurationMs;
|
backBufferDurationMs = newBackBufferDurationMs;
|
||||||
releasePlayer();
|
releasePlayer();
|
||||||
initializePlayer();
|
initializePlayer();
|
||||||
|
@ -59,6 +59,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
private static final String PROP_AUDIO_OUTPUT = "audioOutput";
|
private static final String PROP_AUDIO_OUTPUT = "audioOutput";
|
||||||
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 = "bufferConfig";
|
||||||
|
private static final String PROP_BUFFER_CONFIG_CACHE_SIZE = "cacheSizeMB";
|
||||||
private static final String PROP_BUFFER_CONFIG_MIN_BUFFER_MS = "minBufferMs";
|
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_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_MS = "bufferForPlaybackMs";
|
||||||
@ -402,6 +403,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
|
|
||||||
@ReactProp(name = PROP_BUFFER_CONFIG)
|
@ReactProp(name = PROP_BUFFER_CONFIG)
|
||||||
public void setBufferConfig(final ReactExoplayerView videoView, @Nullable ReadableMap bufferConfig) {
|
public void setBufferConfig(final ReactExoplayerView videoView, @Nullable ReadableMap bufferConfig) {
|
||||||
|
int cacheSize = 0;
|
||||||
int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
int minBufferMs = DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
||||||
int maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
int maxBufferMs = DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
||||||
int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
int bufferForPlaybackMs = DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
||||||
@ -412,6 +414,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
double minBufferMemoryReservePercent = ReactExoplayerView.DEFAULT_MIN_BUFFER_MEMORY_RESERVE;
|
double minBufferMemoryReservePercent = ReactExoplayerView.DEFAULT_MIN_BUFFER_MEMORY_RESERVE;
|
||||||
|
|
||||||
if (bufferConfig != null) {
|
if (bufferConfig != null) {
|
||||||
|
cacheSize = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_CACHE_SIZE, 0);
|
||||||
minBufferMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_MIN_BUFFER_MS, minBufferMs);
|
minBufferMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_MIN_BUFFER_MS, minBufferMs);
|
||||||
maxBufferMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_MAX_BUFFER_MS, maxBufferMs);
|
maxBufferMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_MAX_BUFFER_MS, maxBufferMs);
|
||||||
bufferForPlaybackMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS, bufferForPlaybackMs);
|
bufferForPlaybackMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_BUFFER_FOR_PLAYBACK_MS, bufferForPlaybackMs);
|
||||||
@ -420,7 +423,7 @@ public class ReactExoplayerViewManager extends ViewGroupManager<ReactExoplayerVi
|
|||||||
minBackBufferMemoryReservePercent = ReactBridgeUtils.safeGetDouble(bufferConfig, PROP_BUFFER_CONFIG_MIN_BACK_BUFFER_MEMORY_RESERVE_PERCENT, minBackBufferMemoryReservePercent);
|
minBackBufferMemoryReservePercent = ReactBridgeUtils.safeGetDouble(bufferConfig, PROP_BUFFER_CONFIG_MIN_BACK_BUFFER_MEMORY_RESERVE_PERCENT, minBackBufferMemoryReservePercent);
|
||||||
minBufferMemoryReservePercent = ReactBridgeUtils.safeGetDouble(bufferConfig, PROP_BUFFER_CONFIG_MIN_BUFFER_MEMORY_RESERVE_PERCENT, minBufferMemoryReservePercent);
|
minBufferMemoryReservePercent = ReactBridgeUtils.safeGetDouble(bufferConfig, PROP_BUFFER_CONFIG_MIN_BUFFER_MEMORY_RESERVE_PERCENT, minBufferMemoryReservePercent);
|
||||||
backBufferDurationMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_BACK_BUFFER_DURATION_MS, backBufferDurationMs);
|
backBufferDurationMs = ReactBridgeUtils.safeGetInt(bufferConfig, PROP_BUFFER_CONFIG_BACK_BUFFER_DURATION_MS, backBufferDurationMs);
|
||||||
videoView.setBufferConfig(minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, maxHeapAllocationPercent, minBackBufferMemoryReservePercent, minBufferMemoryReservePercent, backBufferDurationMs);
|
videoView.setBufferConfig(minBufferMs, maxBufferMs, bufferForPlaybackMs, bufferForPlaybackAfterRebufferMs, maxHeapAllocationPercent, minBackBufferMemoryReservePercent, minBufferMemoryReservePercent, backBufferDurationMs, cacheSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ Adjust the buffer settings. This prop takes an object with one or more of the pr
|
|||||||
| maxHeapAllocationPercent | number | The percentage of available heap that the video can use to buffer, between 0 and 1 |
|
| maxHeapAllocationPercent | number | The percentage of available heap that the video can use to buffer, between 0 and 1 |
|
||||||
| minBackBufferMemoryReservePercent | number | The percentage of available app memory at which during startup the back buffer will be disabled, between 0 and 1 |
|
| minBackBufferMemoryReservePercent | number | The percentage of available app memory at which during startup the back buffer will be disabled, between 0 and 1 |
|
||||||
| minBufferMemoryReservePercent | number | The percentage of available app memory to keep in reserve that prevents buffer from using it, between 0 and 1 |
|
| minBufferMemoryReservePercent | number | The percentage of available app memory to keep in reserve that prevents buffer from using it, between 0 and 1 |
|
||||||
|
| cacheSizeMB | number | Cache size in MB, enabling this to prevent new src requests and save bandwidth while repeating videos, or 0 to disable. Android only. |
|
||||||
|
|
||||||
Example with default values:
|
Example with default values:
|
||||||
|
|
||||||
@ -74,9 +74,12 @@ bufferConfig={{
|
|||||||
bufferForPlaybackMs: 2500,
|
bufferForPlaybackMs: 2500,
|
||||||
bufferForPlaybackAfterRebufferMs: 5000,
|
bufferForPlaybackAfterRebufferMs: 5000,
|
||||||
backBufferDurationMs: 120000,
|
backBufferDurationMs: 120000,
|
||||||
|
cacheSizeMB: 0
|
||||||
}}
|
}}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Please note that the Android cache is a global cache that is shared among all components; individual components can still opt out of caching behavior by setting cacheSizeMB to 0, but multiple components with a positive cacheSizeMB will be sharing the same one, and the cache size will always be the first value set; it will not change during the app's lifecycle.
|
||||||
|
|
||||||
### `chapters`
|
### `chapters`
|
||||||
|
|
||||||
<PlatformsList types={['tvOS']} />
|
<PlatformsList types={['tvOS']} />
|
||||||
@ -610,7 +613,7 @@ Pass directly the asset to play (deprecated)
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const sintel = require('./sintel.mp4');
|
const sintel = require('./sintel.mp4');
|
||||||
source={ sintel };
|
source = {sintel};
|
||||||
```
|
```
|
||||||
|
|
||||||
Or by using an uri (starting from 6.0.0-beta.6)
|
Or by using an uri (starting from 6.0.0-beta.6)
|
||||||
@ -620,7 +623,6 @@ const sintel = require('./sintel.mp4');
|
|||||||
source={{ uri: sintel }}
|
source={{ uri: sintel }}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
#### URI string
|
#### URI string
|
||||||
|
|
||||||
A number of URI schemes are supported by passing an object with a `uri` attribute.
|
A number of URI schemes are supported by passing an object with a `uri` attribute.
|
||||||
@ -725,14 +727,14 @@ source={{
|
|||||||
|
|
||||||
### `subtitleStyle`
|
### `subtitleStyle`
|
||||||
|
|
||||||
| Property | Description | Platforms |
|
| Property | Description | Platforms |
|
||||||
| ------------- | ----------------------------------------------------------------------- | --------- |
|
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
|
||||||
| fontSize | Adjust the font size of the subtitles. Default: font size of the device | Android |
|
| fontSize | Adjust the font size of the subtitles. Default: font size of the device | Android |
|
||||||
| paddingTop | Adjust the top padding of the subtitles. Default: 0 | Android |
|
| paddingTop | Adjust the top padding of the subtitles. Default: 0 | Android |
|
||||||
| paddingBottom | Adjust the bottom padding of the subtitles. Default: 0 | Android |
|
| paddingBottom | Adjust the bottom padding of the subtitles. Default: 0 | Android |
|
||||||
| paddingLeft | Adjust the left padding of the subtitles. Default: 0 | Android |
|
| paddingLeft | Adjust the left padding of the subtitles. Default: 0 | Android |
|
||||||
| paddingRight | Adjust the right padding of the subtitles. Default: 0 | Android |
|
| paddingRight | Adjust the right padding of the subtitles. Default: 0 | Android |
|
||||||
| opacity | Adjust the visibility of subtitles with 0 hiding and 1 fully showing them. Android supports float values between 0 and 1 for varying opacity levels, whereas iOS supports only 0 or 1. Default: 1. | Android, iOS |
|
| opacity | Adjust the visibility of subtitles with 0 hiding and 1 fully showing them. Android supports float values between 0 and 1 for varying opacity levels, whereas iOS supports only 0 or 1. Default: 1. | Android, iOS |
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -1,22 +1,30 @@
|
|||||||
# Caching
|
# Caching
|
||||||
|
|
||||||
Caching is currently only supported on `iOS` platforms with a CocoaPods setup.
|
Caching is supported on `iOS` platforms with a CocoaPods setup, and on `android` using `SimpleCache`.
|
||||||
|
|
||||||
## Technology
|
## Android
|
||||||
|
|
||||||
|
Android uses a LRU `SimpleCache` with a variable cache size that can be specified by bufferConfig - cacheSizeMB. This creates a folder named `RNVCache` in the app's `cache` folder. Do note RNV does not yet offer a native call to flush the cache, it can be flushed by clearing the app's cache.
|
||||||
|
|
||||||
|
In addition, this resolves RNV6's repeated source URI call problem when looping a video on Android.
|
||||||
|
|
||||||
|
## iOS
|
||||||
|
|
||||||
|
### Technology
|
||||||
|
|
||||||
The cache is backed by [SPTPersistentCache](https://github.com/spotify/SPTPersistentCache) and [DVAssetLoaderDelegate](https://github.com/vdugnist/DVAssetLoaderDelegate).
|
The cache is backed by [SPTPersistentCache](https://github.com/spotify/SPTPersistentCache) and [DVAssetLoaderDelegate](https://github.com/vdugnist/DVAssetLoaderDelegate).
|
||||||
|
|
||||||
## How Does It Work
|
### How Does It Work
|
||||||
|
|
||||||
The caching is based on the url of the asset.
|
The caching is based on the url of the asset.
|
||||||
SPTPersistentCache is a LRU ([Least Recently Used](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU))) cache.
|
SPTPersistentCache is a LRU ([Least Recently Used](<https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)>)) cache.
|
||||||
|
|
||||||
## Restrictions
|
### Restrictions
|
||||||
|
|
||||||
Currently, caching is only supported for URLs that end in a `.mp4`, `.m4v`, or `.mov` extension. In future versions, URLs that end in a query string (e.g. test.mp4?resolution=480p) will be support once dependencies allow access to the `Content-Type` header. At this time, HLS playlists (.m3u8) and videos that sideload text tracks are not supported and will bypass the cache.
|
Currently, caching is only supported for URLs that end in a `.mp4`, `.m4v`, or `.mov` extension. In future versions, URLs that end in a query string (e.g. test.mp4?resolution=480p) will be support once dependencies allow access to the `Content-Type` header. At this time, HLS playlists (.m3u8) and videos that sideload text tracks are not supported and will bypass the cache.
|
||||||
|
|
||||||
You will also receive warnings in the Xcode logs by using the `debug` mode. So if you are not 100% sure if your video is cached, check your Xcode logs!
|
You will also receive warnings in the Xcode logs by using the `debug` mode. So if you are not 100% sure if your video is cached, check your Xcode logs!
|
||||||
|
|
||||||
By default files expire after 30 days and the maximum cache size is 100mb.
|
By default files expire after 30 days and the maximum cache size is 100mb.
|
||||||
|
|
||||||
In a future release the cache might have more configurable options.
|
In a future release the cache might have more configurable options.
|
||||||
|
@ -69,6 +69,7 @@ interface StateType {
|
|||||||
srcListId: number;
|
srcListId: number;
|
||||||
loop: boolean;
|
loop: boolean;
|
||||||
showRNVControls: boolean;
|
showRNVControls: boolean;
|
||||||
|
useCache: boolean;
|
||||||
poster?: string;
|
poster?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +98,7 @@ class VideoPlayer extends Component {
|
|||||||
srcListId: 0,
|
srcListId: 0,
|
||||||
loop: false,
|
loop: false,
|
||||||
showRNVControls: false,
|
showRNVControls: false,
|
||||||
|
useCache: false,
|
||||||
poster: undefined,
|
poster: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -669,6 +671,14 @@ class VideoPlayer extends Component {
|
|||||||
}}
|
}}
|
||||||
text="decoderInfo"
|
text="decoderInfo"
|
||||||
/>
|
/>
|
||||||
|
<ToggleControl
|
||||||
|
isSelected={this.state.useCache}
|
||||||
|
onPress={() => {
|
||||||
|
this.setState({useCache: !this.state.useCache});
|
||||||
|
}}
|
||||||
|
selectedText="enable cache"
|
||||||
|
unselectedText="disable cache"
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
) : null}
|
) : null}
|
||||||
<ToggleControl
|
<ToggleControl
|
||||||
@ -864,6 +874,13 @@ class VideoPlayer extends Component {
|
|||||||
selectedTextTrack={this.state.selectedTextTrack}
|
selectedTextTrack={this.state.selectedTextTrack}
|
||||||
selectedAudioTrack={this.state.selectedAudioTrack}
|
selectedAudioTrack={this.state.selectedAudioTrack}
|
||||||
playInBackground={false}
|
playInBackground={false}
|
||||||
|
bufferConfig={{
|
||||||
|
minBufferMs: 15000,
|
||||||
|
maxBufferMs: 50000,
|
||||||
|
bufferForPlaybackMs: 2500,
|
||||||
|
bufferForPlaybackAfterRebufferMs: 5000,
|
||||||
|
cacheSizeMB: this.state.useCache ? 200 : 0,
|
||||||
|
}}
|
||||||
preventsDisplaySleepDuringVideoPlayback={true}
|
preventsDisplaySleepDuringVideoPlayback={true}
|
||||||
poster={this.state.poster}
|
poster={this.state.poster}
|
||||||
onPlaybackRateChange={this.onPlaybackRateChange}
|
onPlaybackRateChange={this.onPlaybackRateChange}
|
||||||
|
@ -72,6 +72,7 @@ export type BufferConfig = {
|
|||||||
maxHeapAllocationPercent?: number;
|
maxHeapAllocationPercent?: number;
|
||||||
minBackBufferMemoryReservePercent?: number;
|
minBackBufferMemoryReservePercent?: number;
|
||||||
minBufferMemoryReservePercent?: number;
|
minBufferMemoryReservePercent?: number;
|
||||||
|
cacheSizeMB?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum SelectedTrackType {
|
export enum SelectedTrackType {
|
||||||
|
Loading…
Reference in New Issue
Block a user