Closed jamesfzhang closed 2 years ago
Has anyone solved this problem?
@DavitVosk I am not sure how others have solved it (looks like my way is similar to @rnowm), but the way I solved it on my project is I started writing my own downloader based off of this project: https://github.com/kfiroo/react-native-cached-image. Once you make that downloader work, you could load the local file path as your source uri.
Something like:
const mediaUrl = MEDIA.cached ? `file://${MEDIA.path}` : MEDIA.url
<Video source={ uri: mediaUrl } />
@hkdahal thanks for your answer. Can you please share your created downloader file that we can use it? Thanks
@hkdahal Also can you please explain how that work? You use https://github.com/kfiroo/react-native-cached-image package with https://github.com/kfiroo/react-native-cached-image/commit/31ad016afabcbe42e3c1eb058a0d9a57b0fb615f PR, but how react-native-video sees that the videos are cached? How they interact with each other?
@n1ru4l I got error as image bellow.
@DavitVosk I will create a gist or share a separate project that does the interaction between these packages later this weekend. I will mention you over there.
@BunHouth @DavitVosk Sorry for the late answer. Did you all setup the package like described in the Pull Request? Lets continue there and stop spamming this issue 😅https://github.com/react-native-community/react-native-video/pull/955
@n1ru4l It's not spamming if people are trying your package and responding with roadblocks it's very healthy discussion. I see you added SPTPersistentCache in your podspec as dependency. Any idea why the header isn't found?
@roycclu It is better to discuss possible problems related to the pull request in the comments of the pull request..
@roycclu @BunHouth @DavitVosk I updated my pull request (#955). Please check out the private fork n1ru4l/react-native-video@3.1.0-alpha.2
or the example app, located under (examples/video-caching
) (if you do not know how to setup your project with cocoapods.
The issues you guys mentioned should be fixed by now.
Would love to hear your feedback (in the discussion of #955)!
Thanks for making these changes @n1ru4l! I will add feedback on the PR.
This is a pretty impactful change and as @n1ru4l has mentioned, we need testing and feedback to make sure this is ready to go. If you want to use this feature, please start testing it and letting us know how well it works. Once I have a couple thumbs up, I will do a review and get it merged.
As caching is not yet availalbe out of the box for react-native-video on both Android and IOS, we have been using: https://github.com/joltup/rn-fetch-blob to download our videos from S3, (it supports progress callback so you can add progress-bars etc), save it to a device storage and point react-native-video to URI like so:
rfblob.config({
fileCache: true,
path: filePath // where you want to save a file
}).fetch('GET', 'your-hosting-url/file.mp4')
.then(result => {
const filePath = result.path();
const sourceForVideoPlayer = {
uri: 'file://' + filePath
}
})
}
And when Video Player component is mounted, we check if there is already a file on device storage with matching name and if so, we just load video from storage instead of downloading it once more. Of course, you also need to clean your cache directory by yourself but this is a small trade off for solution that works on both IOS and Android. Maybe it will help someone else, as soon as caching is supported on both platforms, we will be happy to switch
As caching is not yet availalbe out of the box for react-native-video on both Android and IOS, we have been using: https://github.com/joltup/rn-fetch-blob to download our videos from S3, (it supports progress callback so you can add progress-bars etc), save it to a device storage and point react-native-video to URI like so:
rfblob.config({ fileCache: true, path: filePath // where you want to save a file }).fetch('GET', 'your-hosting-url/file.mp4') .then(result => { const filePath = result.path(); const sourceForVideoPlayer = { uri: 'file://' + filePath } }) }
And when Video Player component is mounted, we check if there is already a file on device storage with matching name and if so, we just load video from storage instead of downloading it once more. Of course, you also need to clean your cache directory by yourself but this is a small trade off for solution that works on both IOS and Android. Maybe it will help someone else, as soon as caching is supported on both platforms, we will be happy to switch
hello, is there any way to download the video with rn-fetch-blob, and play the video while downloading?It's so long for waiting the downloading task complete.
@webbin No, there is not.
For android video caching I am currently using this: https://github.com/n1ru4l/react-native-video/commit/0e1c7c273e2793392580bda2c1f9926092547546 (uses a HTTP proxy to cache the file).
The idea came from this article: https://instagram-engineering.com/improving-video-playback-on-android-2f6c6a0058d
I use this is my private fork and hope I will have the time to someday do a proper implementation for react-native-video
.
@webbin No, there is not.
For android video caching I am currently using this: n1ru4l@0e1c7c2 (uses a HTTP proxy to cache the file).
The idea came from this article: https://instagram-engineering.com/improving-video-playback-on-android-2f6c6a0058d
I use this is my private fork and hope I will have the time to someday do a proper implementation for
react-native-video
.
What's the progress on this?
@gazedash I am still using it with patch-package on react-native-video@4.3.1
. Had no time to clean it up and release it as part of react-native-video
.
patches/react-native-video+4.3.1.patch
patch-package
--- a/node_modules/react-native-video/android-exoplayer/build.gradle
+++ b/node_modules/react-native-video/android-exoplayer/build.gradle
@@ -31,5 +31,5 @@ dependencies {
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
}
implementation 'com.squareup.okhttp3:okhttp:3.12.1'
-
+ implementation 'com.danikula:videocache:2.7.1'
}
--- a/node_modules/react-native-video/android-exoplayer/src/main/java/com/brentvatne/exoplayer/DataSourceUtil.java
+++ b/node_modules/react-native-video/android-exoplayer/src/main/java/com/brentvatne/exoplayer/DataSourceUtil.java
@@ -2,6 +2,7 @@ package com.brentvatne.exoplayer;
import android.content.Context;
import android.content.ContextWrapper;
+import android.net.Uri;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.network.CookieJarContainer;
@@ -17,6 +18,7 @@ import com.google.android.exoplayer2.util.Util;
import okhttp3.Cookie;
import okhttp3.JavaNetCookieJar;
import okhttp3.OkHttpClient;
+import com.danikula.videocache.HttpProxyCacheServer;
import java.util.Map;
@@ -27,6 +29,7 @@ public class DataSourceUtil {
private static DataSource.Factory rawDataSourceFactory = null;
private static DataSource.Factory defaultDataSourceFactory = null;
+ private static HttpProxyCacheServer proxy = null;
private static String userAgent = null;
public static void setUserAgent(String userAgent) {
@@ -84,4 +87,14 @@ public class DataSourceUtil {
return okHttpDataSourceFactory;
}
+
+ public static Uri getCacheUri(Uri uri, Context context) {
+ if (proxy == null) {
+ proxy = new HttpProxyCacheServer.Builder(context)
+ .maxCacheSize(1024 * 1024 * 512)
+ .maxCacheFilesCount(20)
+ .build();
+ }
+ return Uri.parse(proxy.getProxyUrl(uri.toString()));
+ }
}
--- a/node_modules/react-native-video/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java
+++ b/node_modules/react-native-video/android-exoplayer/src/main/java/com/brentvatne/exoplayer/ReactExoplayerView.java
@@ -366,13 +366,7 @@ class ReactExoplayerView extends FrameLayout implements
}
private boolean requestAudioFocus() {
- if (disableFocus) {
- return true;
- }
- int result = audioManager.requestAudioFocus(this,
- AudioManager.STREAM_MUSIC,
- AudioManager.AUDIOFOCUS_GAIN);
- return result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
+ return true;
}
private void setPlayWhenReady(boolean playWhenReady) {
@@ -759,7 +753,7 @@ class ReactExoplayerView extends FrameLayout implements
boolean isOriginalSourceNull = srcUri == null;
boolean isSourceEqual = uri.equals(srcUri);
- this.srcUri = uri;
+ this.srcUri = DataSourceUtil.getCacheUri(uri, themedReactContext);
this.extension = extension;
this.requestHeaders = headers;
this.mediaDataSourceFactory = DataSourceUtil.getDefaultDataSourceFactory(this.themedReactContext, BANDWIDTH_METER, this.requestHeaders);
Have there been any plans for implementing the cache functionality in this library?
Hi there! What about caching video files when a url ends like https://.../file.mp4?access_token=xxx ?
@igor-lemon feel free to send a pull request that allows registering a cache key normalizer.
Any update?
@vargajacint We just created a fork to add basic caching feature to the <Video/>
component (Android and ExoPlayer only, since caching is already native on iOS)
You can find it here: https://github.com/jowapp/react-native-video
(@n1ru4l if you think it's worth it, we can send a PR)
tl;dr: just reference our repo in your package.json
react-native-video
entry and add the useCache
prop to your <Video/>
component. For more details and advanced features, have a look at our updated README
[Note: We are Jow, a wonderful startup based in Paris, offering delighful recipes and helping do your grocery shopping according to what you like to eat. And we're also hiring talented people, especially back & front developers!)]
Hi @antoinemaillard . Thanks for providing this repo!
Does this work for HLS?
If useCache prop is set, cache will be used for all non-streamed content (ie. except for Microsoft SmoothSteaming, DASH, HLS)
I see that it does support HLS but when I try to console log the cache stats with:
ExoPlayerCache.getCacheStats()
.then(cacheStats => {
console.log(cacheStats)
})
It shows an empty object. Yet, with an mp4, I see all of the stats.
Also, does this handle deleting the cached video as well?
Thanks :)
@antoinemaillard Thank you for your fork enabling caching on Android! Is there any way to imperatively cache video ahead of time in order to be able to play it instantly? (Something like
Nevermind, I managed to achieve it by downloading the videos in advance with React Native FS and playing them from local source.Image.prefetch()
in React Native or FastImage.preload()
in React Native FastImage)
Hi @antoinemaillard . Thanks for providing this repo!
Does this work for HLS?
looking at the code there is support for those types of media but for some reason the cache does not work
case C.TYPE_DASH:
DataSource.Factory dataSourceFactory = buildDataSourceFactory(false);
mediaSource = new DashMediaSource.Factory(
new DefaultDashChunkSource.Factory(mediaDataSourceFactory),
buildDataSourceFactory(false)
).setLoadErrorHandlingPolicy(
config.buildLoadErrorHandlingPolicy(minLoadRetryCount)
).createMediaSource(uri);
break;
given a url like https://fictive-api.com/dash/1766e4a8f33d49a497e9ff0fe59c130c.mp4/manifest.mpd
it will detect that the type is DASH, play the video but won't cache :(
Thank you for your fork enabling caching on Android! ~Is there any way to imperatively cache video ahead of time in order to be able to play it instantly? (Something like
Image.prefetch()
in React Native orFastImage.preload()
in React Native FastImage)~ Nevermind, I managed to achieve it by downloading the videos in advance with React Native FS and playing them from local source.
Can you tell me how you did this ??
How do you cache a video that's downloaded over the network?