Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add network cache functionality to video_player #28094

Open
nagoya0 opened this issue Feb 18, 2019 · 32 comments · May be fixed by flutter/plugins#2130
Open

Add network cache functionality to video_player #28094

nagoya0 opened this issue Feb 18, 2019 · 32 comments · May be fixed by flutter/plugins#2130

Comments

@nagoya0
Copy link

@nagoya0 nagoya0 commented Feb 18, 2019

Steps to Reproduce

I built this sample:

https://github.com/flutter/plugins/tree/master/packages/video_player/example
(v0.10.0+2)

and switched tab from side to side. Downloaded videos are disappear and started redownloading every time.

Flutter Doctor

[√] Flutter (Channel beta, v0.11.10, on Microsoft Windows [Version 10.0.17763.316], locale ja-JP)
    • Flutter version 0.11.10 at C:\flutter
    • Framework revision c27c4a265e (3 months ago), 2018-11-26 17:07:24 -0500
    • Engine revision eebc6a5895
    • Dart version 2.1.0 (build 2.1.0-dev.9.4 f9ebf21297)

[√] Android toolchain - develop for Android devices (Android SDK 28.0.3)
    • Android SDK at C:\Users\XXXXXXXX\AppData\Local\Android\sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-28, build-tools 28.0.3
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)
    • All Android licenses accepted.

[√] Android Studio (version 3.3)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 33.0.1
    • Dart plugin version 182.5215
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)

[√] Connected device (1 available)
    • Pixel 3 • XXXXXXXXX • android-arm64 • Android 9 (API 28)

• No issues found!
@Agraphie

This comment has been minimized.

Copy link

@Agraphie Agraphie commented May 22, 2019

Is there any intermediate solution for this problem? Otherwise any app which uses videos will drain your data volume quite fast.

@ohjs88

This comment has been minimized.

Copy link

@ohjs88 ohjs88 commented Aug 6, 2019

I cached the data by adding some code as shown below.
(I modified video_player 0.10.1+6.)

VideoPlayerPlugin.java

Added code


    private static SimpleCache sDownloadCache;

    class CacheDataSourceFactory implements DataSource.Factory {
      private final Context context;
      private final DefaultDataSourceFactory defaultDatasourceFactory;
      private final long maxFileSize, maxCacheSize;

      CacheDataSourceFactory(Context context, long maxCacheSize, long maxFileSize) {
        super();
        this.context = context;
        this.maxCacheSize = maxCacheSize;
        this.maxFileSize = maxFileSize;
        //String userAgent = Util.getUserAgent(context, context.getString("ExoPlayer"));
        DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        defaultDatasourceFactory = new DefaultDataSourceFactory(this.context, bandwidthMeter,
            new DefaultHttpDataSourceFactory("ExoPlayer", bandwidthMeter,DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,true));
      }

      @Override
      public DataSource createDataSource() {
        LeastRecentlyUsedCacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(maxCacheSize);
        
        if (sDownloadCache == null) {
            sDownloadCache = new SimpleCache(context.getCacheDir(),evictor);
        }

        return new CacheDataSource(sDownloadCache, defaultDatasourceFactory.createDataSource(), new FileDataSource(),
            new CacheDataSink(sDownloadCache, maxFileSize),
            CacheDataSource.FLAG_BLOCK_ON_CACHE | CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR, null);
      }
    }

Modified code


 if (isFileOrAsset(uri)) {
        dataSourceFactory = new DefaultDataSourceFactory(context, "ExoPlayer");
      } else {
        // dataSourceFactory = new DefaultHttpDataSourceFactory("ExoPlayer", null,
        //     DefaultHttpDataSource.DEFAULT_CONNECT_TIMEOUT_MILLIS, DefaultHttpDataSource.DEFAULT_READ_TIMEOUT_MILLIS,
        //     true);
        dataSourceFactory = new CacheDataSourceFactory(context, 100 * 1024 * 1024, 5 * 1024 * 1024);
      }

See the url below.

@lifenautjoe

This comment has been minimized.

Copy link

@lifenautjoe lifenautjoe commented Sep 3, 2019

Any other way so far that doesn't involve monkey-patching the library? And that works for iOS as well?

@lifenautjoe

This comment has been minimized.

Copy link

@lifenautjoe lifenautjoe commented Sep 3, 2019

Here's a plugin for the iOS AV player that might help. https://github.com/vitoziv/VIMediaCache

@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 20, 2019

I need video caching as well, iOS and Android with video_player, does anyone have time to put this together? Use case is a Instagram Stories type of interface where users will progress slowly through videos but reverse quickly. Even if we could get video_player to cache the first 10 seconds that would be fine, just enough to give it time to buffer again.

@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 20, 2019

@ohjs88 Can you make a PR against video_player for your cached android code? Do you happen to have iOS code as well?

@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 20, 2019

Is it possible to get the file out of video_player and save it to disk with Dart code? Not sure if that's obscene or not.

@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 20, 2019

Has anyone tried caching the loaded VideoPlayerControllers in Dart?

@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 21, 2019

I tried that out and it does work but you end up with some strange behavior. The app runs out of memory real quick.

@lifenautjoe

This comment has been minimized.

Copy link

@lifenautjoe lifenautjoe commented Sep 21, 2019

For what's worth, @999eagle got caching working on both iOS and android on a custom fork of the plugins repository video_player. We hope to open a PR with this back into the plugins repo at some point.

  video_player:
    git:
      url: https://github.com/999eagle/plugins.git
      ref: feature/caching
      path: packages/video_player

Limit is set to 200mbs

Here are the commits with the magic.

https://github.com/999eagle/plugins/commits/feature/caching

Thanks to her work, we've now got video playing in our app :-)

@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 21, 2019

@lifenautjoe Thanks for the heads up, is there any reason why there hasn't been a PR back to flutter/plugins ?

@lifenautjoe

This comment has been minimized.

Copy link

@lifenautjoe lifenautjoe commented Sep 21, 2019

We're busy with post release activities 😬 , we just got this working a couple days back. We'll PR it back ASAP.

@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 21, 2019

Much appreciated for the updates, I'm going to watch that repo for movement/PR. Congrats on the launch!

@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 21, 2019

@lifenautjoe Do you guys have a commit cherry picked? This branch appears to not load a .mov file over network that otherwise works with video_player: ^0.10.2+1

Video in question: https://firebasestorage.googleapis.com/v0/b/skatex-8d802.appspot.com/o/test%2Ftest.mov?alt=media&token=a59686ca-09cc-4be4-ba70-5069b3c42da7

For some reason the feature/caching branch doesn't like the URL

When running on XCode these are the logs

2019-09-21 18:08:27.812871-0400 Runner[5519:1637802] flutter: Observatory listening on http://127.0.0.1:57074/-yBssRMosLw=/

2019-09-21 18:08:28.280307-0400 Runner[5519:1637790] flutter: VideoPlayerValue(duration: null, size: null, position: 0:00:00.000000, buffered: [], isPlaying: false, isLooping: false, isBuffering: falsevolume: 1.0, errorDescription: null)

2019-09-21 18:08:28.280977-0400 Runner[5519:1637790] flutter: VideoPlayerValue(duration: null, size: null, position: 0:00:00.000000, buffered: [], isPlaying: true, isLooping: false, isBuffering: falsevolume: 1.0, errorDescription: null)

2019-09-21 18:08:28.384399-0400 Runner[5519:1637782] Task .<1> finished with error - code: -1002

2019-09-21 18:08:28.386857-0400 Runner[5519:1637781] Task .<1> load failed with error Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo={NSLocalizedDescription=unsupported URL, NSErrorFailingURLStringKey=a59686ca-09cc-4be4-ba70-5069b3c42da7, NSErrorFailingURLKey=a59686ca-09cc-4be4-ba70-5069b3c42da7, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask .<1>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask .<1>, NSUnderlyingError=0x2821c0210 {Error Domain=kCFErrorDomainCFNetwork Code=-1002 "(null)"}} [-1002]

2019-09-21 18:08:28.453100-0400 Runner[5519:1637790] flutter: VideoPlayerValue(duration: null, size: null, position: 0:00:00.000000, buffered: [], isPlaying: false, isLooping: false, isBuffering: falsevolume: 1.0, errorDescription: Failed to load video: unsupported URL)

@lifenautjoe

This comment has been minimized.

Copy link

@lifenautjoe lifenautjoe commented Sep 21, 2019

@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 22, 2019

I did get it to work, and the caching works beautifully. However, there are still some strange issues.

This video & URL works. http://techslides.com/demos/sample-videos/small.mp4

Copied to my host, this URL fails. https://firebasestorage.googleapis.com/v0/b/skatex-8d802.appspot.com/o/test%2Fsmall.mp4?alt=media&token=82cdf4a4-78e4-46e6-a6ab-8456f7f0a0eb

Using Dart URI encoding, it also fails Uri.encodeFull("https://firebasestorage.googleapis.com/v0/b/skatex-8d802.appspot.com/o/test%2Fsmall.mp4?alt=media&token=82cdf4a4-78e4-46e6-a6ab-8456f7f0a0eb")

That method produces this link https://firebasestorage.googleapis.com/v0/b/skatex-8d802.appspot.com/o/test%252Fsmall.mp4?alt=media&token=82cdf4a4-78e4-46e6-a6ab-8456f7f0a0eb

Percent encoded (using https://www.url-encode-decode.com), it works. https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fskatex-8d802.appspot.com%2Fo%2Ftest%252Fsmall.mp4%3Falt%3Dmedia%26token%3D82cdf4a4-78e4-46e6-a6ab-8456f7f0a0eb

Not sure if this is helpful, but I did see some mention to percent encoding here https://stackoverflow.com/questions/11362153/bad-url-error-with-nsurlrequest

@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 22, 2019

Another case....

This works on the pub.dev version of video_player but fails on the feature/caching version

https://firebasestorage.googleapis.com/v0/b/skatex-8d802.appspot.com/o/test%2Ftest-Broadband%20Low.mp4?alt=media&token=00f64abd-c552-4d7b-a964-72a22811722f

However, it will not play on either as a percent encoded url
https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fskatex-8d802.appspot.com%2Fo%2Ftest%252Ftest-Broadband%2520Low.mp4%3Falt%3Dmedia%26token%3D00f64abd-c552-4d7b-a964-72a22811722f

@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 22, 2019

Alright, I got it working by encoding the URL with this line. It seems heavy handed but I'm getting good results.

NSString *escapedURL = [uriArg stringByAddingPercentEncodingWithAllowedCharacters:NSMutableCharacterSet.alphanumericCharacterSet];
@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 22, 2019

Pull request: 999eagle/plugins@ed5e865

@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 23, 2019

@lifenautjoe @999eagle just got to it and VideoPlayerController.file() does not work on iOS on 999eagle/plugins/video_player @ feature/caching. Any insights?

@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Sep 25, 2019

I believe this makes feature/caching ready for PR on iOS. I haven't tried Android yet

999eagle/plugins#2

@999eagle 999eagle mentioned this issue Oct 1, 2019
11 of 13 tasks complete
@recastrodiaz

This comment has been minimized.

Copy link

@recastrodiaz recastrodiaz commented Oct 4, 2019

I have an alternative video networking caching implementation if anyone is interested in using it:

flutter/plugins@master...recastrodiaz:develop2

It has other features as well like:

  • audio focus
  • clipping videos
  • playback speed feature
  • fixes some videos showing a black screen on iOS
  • more recent ExoPlayer
  • load videos from phAssets on iOS
@lukepighetti

This comment has been minimized.

Copy link

@lukepighetti lukepighetti commented Oct 5, 2019

I’m going to check it out because you’ve added some features I need myself. Will you be making a PR against video_player? Is it cross platform?

@recastrodiaz

This comment has been minimized.

Copy link

@recastrodiaz recastrodiaz commented Oct 5, 2019

It is indeed cross platform (Android + iOS):

There are separate PRs for most of the features except the caching of videos and clipping:

I'm not planning on doing PRs for the other features for now as these PRs will most likely stay unmerged.

@lifenautjoe

This comment has been minimized.

Copy link

@lifenautjoe lifenautjoe commented Oct 17, 2019

Hi Rodrigo ! (@recastrodiaz ) How does the caching configuration work on your solution? 🤔

@lifenautjoe

This comment has been minimized.

Copy link

@lifenautjoe lifenautjoe commented Oct 17, 2019

Thanks for the quick reply!

With the latest flutter/plugins master and flutter master version, our solution is not working.

videoPlayerController.initialize() fails with errors of the following type

2019-10-07 19:23:44.422820+0200 Runner[4520:1777202] Task <2916A884-BCD7-4AC2-8DF8-50297E8F5884>.<1> finished with error [-1002] Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo={NSLocalizedDescription=unsupported URL, NSErrorFailingURLStringKey=https%3A%2F%2Fassets%2Dapi%2Dopenbook%2Dsocial%2Es3%2Daccelerate%2Eamazonaws%2Ecom%2Fmedia%2Fpublic%2Fformats%2Fmp4%5Fsd%2Fposts%2F3b8683f9%2Dbda1%2D422a%2D9f61%2D7e5a126f7b90%2F70678389%2D5265%2D41db%2Da92e%2D1a8a8996a318%2Emp4, NSErrorFailingURLKey=https%3A%2F%2Fassets%2Dapi%2Dopenbook%2Dsocial%2Es3%2Daccelerate%2Eamazonaws%2Ecom%2Fmedia%2Fpublic%2Fformats%2Fmp4%5Fsd%2Fposts%2F3b8683f9%2Dbda1%2D422a%2D9f61%2D7e5a126f7b90%2F70678389%2D5265%2D41db%2Da92e%2D1a8a8996a318%2Emp4, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <2916A884-BCD7-4AC2-8DF8-50297E8F5884>.<1>"
), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <2916A884-BCD7-4AC2-8DF8-50297E8F5884>.<1>, NSUnderlyingError=0x283a4fba0 {Error Domain=kCFErrorDomainCFNetwork Code=-1002 "(null)"}}

I wanted to try with your solution to see if it was the same case. Some 50% of the time videos fail too.

In the logs I see

2019-10-17 15:57:10.678838+0200 Runner[1407:370002] VIDEO__ 0.000000, 0.000000, 480.000000, 852.000000, 0
2019-10-17 15:57:11.077348+0200 Runner[1407:369906] Task <33027A16-19C4-477E-B4D2-0A403D1EBF6B>.<1> HTTP load failed, 0/0 bytes (error code: -999 [1:89])
2019-10-17 15:57:11.078681+0200 Runner[1407:369906] Connection 4: unable to determine interface type without an established connection
2019-10-17 15:57:11.078709+0200 Runner[1407:369906] Connection 4: unable to determine fallback status without a connection

Had you noticed this too?

CC @lukepighetti @999eagle

EDIT:

Here's the branch with your commits, updated with latest flutter/plugins commits

https://github.com/OkunaOrg/plugins/tree/ricardo/develop2

Perhaps relevant, and might be an iOS13 issue: Alamofire/Alamofire#2951

@recastrodiaz

This comment has been minimized.

Copy link

@recastrodiaz recastrodiaz commented Oct 17, 2019

I noticed my cached videos don't always open the first time around. On the second try they always open and play correctly. It may be the same issue you are experiencing but I haven't looked closely at the issue.

@lifenautjoe

This comment has been minimized.

Copy link

@lifenautjoe lifenautjoe commented Oct 17, 2019

Sounds about right! Unfortunately I'm limited when it comes to iOS. Let me know if there's another way I can help resolve this.

@lifenautjoe

This comment has been minimized.

Copy link

@lifenautjoe lifenautjoe commented Oct 17, 2019

Another thing noticed, on the current master of flutter/plugins, there's no loading issue. So I'm assuming it's on the caching part.

@Nisthar

This comment has been minimized.

Copy link

@Nisthar Nisthar commented Dec 5, 2019

any updates on this?

@blbhargav

This comment has been minimized.

Copy link

@blbhargav blbhargav commented Dec 8, 2019

any updates on this?
https://pub.dev/packages/flutter_cache_manager
Using this plugin with video player. Together works perfectly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
9 participants
You can’t perform that action at this time.