-
-
Notifications
You must be signed in to change notification settings - Fork 695
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
Playing a remote file and cache the file at the same time #47
Comments
I'm not sure of any easy way to do this. Some podcast players make it a binary choice: You either stream it, or you download it in advance. |
This feature seems great. The flutter_cache_manager plugin's getFile method will return a Stream of FileInfo. I wonder whether it's possible to achieve this feature. |
The BTW, if you really want to play a URL while it is still being downloaded, there is a Another suggestion regarding ExoPlayer, is to implement a custom |
I would eventually like to replace the current |
I'll leave this link here for later as a guide for how this could be done on the iOS side: https://vombat.tumblr.com/post/86294492874/caching-audio-streamed-using-avplayer |
I was reading the rxdart doc when I came across this feature that could become handy for this feature request |
I am not sure since the downloading actually happens on the platform side of the plugin. However, it just occurred to me that after recently implementing an HTTP proxy in the plugin, this may actually help, since now the Flutter (Dart) side of the plugin can intercept the bytes being downloaded from the server and I could potentially implement caching in the proxy. |
As audio_service and just_audio gets more and more functional I gradually let go any thoughts of forking and implementing needed features myself as they eventually appear implemented by Ryan. So one really important feature I plan for my app is realtime caching. Since http proxy appeared, could you please expose some interception API so that data can be written to disk while being downloaded? Or since you're the mighty Ryan Heise, maybe you could make an API similar to album art cache, using flutter_cache_manager? I would be very happy. Thank you for your work, you're the MVP. |
@nuc134r hehe :-) Unfortunately, it may be a while for me to get around to this, since there are some higher priority things that need to be implemented in audio_service first. (That is an open invitation for anyone who wishes to submit a PR! It seems reasonable to add an option to the relevant |
@ryanheise exoplayer has some option to cache i guess its SimpleCache. will look into this. |
Hi @ashishfeels yes it has both custom headers and caching support, while iOS doesn't. Because I needed this to work on iOS, I ended up writing a proxy that lets me specify headers, and it would also allow me to do my own caching, and this is done in a way that would work consistently on both iOS and Android. If you take a look at the Dart code, you'll see that it is not actually too difficult to implement this solution, so either way, it is a matter of getting around to it. |
@ryanheise sorry i was not using the plugin so didn't get the chance to go through, and now im moving to just_audio as i feel this plugin is home for audio related apps. thanks man, do you mean that the feature is already implemented or it still need some work. i will go through the code anyway |
@ashishfeels , The caching side isn't implemented yet, but the proxy is, so it would be a short step from there to add a cache. (Note that since iOS doesn't have these features, and "implementing your own proxy" is the usual approach iOS developers have to resort to to have them, so that becomes our lowest common denominator.) |
@ryanheise although your words are bit hard to understand you are pretty amazing. i just saw the headers code you mentioned still looking at it. probably will have to give it some more time. As i don't own a iOS/Mac i'm pretty much doomed. |
@ashishfeels Ryan means that we need to implement caching using the proxy instead of ExoPlayer's mechanisms because on iOS (and web) there is no ExoPlayer. And that the course of this ship is to have features supported by all platforms so we better find solutions in common code which is Dart. And it already has a proxy implemented. |
@nuc134r understood thanks mate. |
Was thinking a lot about extending existing proxy to allow realtime caching (and even tried) and then stumbled upon #172. Considering that I want to provide data from disk on repeating requests, get notified of caching progress and have an index of cached data I figured that it would be better to set up my own proxy between API and just_audio. Also I see it as a better approach in terms of plugin ecosystem architecture. I think I'm going to try to implement it and if I reach any success I'll update this issue. |
@nuc134r that's an interesting thought to contemplate, although the plan is to eventually have caching support directly in the plugin as I think there are benefits in this case to having it tightly coupled. The proxy is required for other reasons, and it would not actually be difficult to tack caching onto the existing proxy, rather than have a situation where we have proxy upon proxy. |
Maybe using https://pub.dev/packages/flutter_cache_manager |
@zxl777 That would make you have to either wait for file to download fully before playing or download file twice. It is discussed above.
I want to report that I got it working and currently finishing features described above to cover my own needs. When it's ready I'm going publish a package and link it here. Not sure if Ryan would like to integrate it into just_audio but will be easy to set it up yourself anyway: final url = await _proxy.addUrl(track.url, track.key, meta: track);
_audioSource.add(ProgressiveAudioSource(url, tag: track)); And there are still performance issues in some cases that need to be addressed. |
@nuc134r excellent work! As mentioned in my previous comment, I very much would like to support this feature directly in just_audio. The proxy exists within just_audio, and I can think of 3 features that this would enable directly within the plugin:
|
I've just created a new branch called Caching could potentially be plugged in by subclassing this class, however ultimately I would like to have such a class offered by just_audio, or alternatively add an option to The way that caching support should work is that it should support partial caching, such that if a byte range request was made, that partial segment of the audio file should be cached. @nuc134r I've left the caching part unimplemented for now in case you would be interested in submitting a pull request for it. Otherwise, I'd be interested to have a discussion here about what sort of features people would like in this caching function besides the caching itself. |
yeah probably i didn't framed the question rightly. Basically is there a way where i can access the stored file and play it with other music players ? |
@afkcodes I think that's covered in the documentation so if it's not, I would suggest opening a new issue for the documentation request. |
will surely go through the docs and will update. you are awesome man. |
Since I haven't heard of any big problems introduced by my latest changes, I will go ahead and push out a release in the next day. |
Sure this seems good also for got to mention about the docs its written how to specify the cache file. |
Haven't got any bug reports about this from customers, lgtm. |
Thanks, yes the docs describe that, although certainly there's a lot of room for improvement in the docs. |
An example would be aswesome :) Thanks man. |
There is an example: I haven't put any doc comments on the |
Sure there's no hurry in that we will eventually update the docs when everything is ready . i will also help in that for sure. |
Don't get too excited though :-) The documentation for the /// The cache file.
final Future<File> cacheFile; |
This fix has landed in 0.9.17. |
@ryanheise |
@SalahAdDin I will need you to file a new bug report and provide details requested in the bug template, because unfortunately just that screenshot is not enough information for me to investigate. |
@ryanheise is here, thank you. |
Hi everyone, the Before I publish the next release, you might like to test the branch and let me know below whether it works or causes problems. If all is well, I will publish it within the next few days. |
Hope this helps |
The |
One thing I am not clear on how it work is the limit size of the cache. Like how does the cache get cleared? Is it automatic? Or do I have to do that myself? I am worried I would use this feature and after sometime the users will have their storage exhausted by our app. Can someone please help explain it to me? Thanks! |
@mhassan772 , this has been documented in the API, and for people who don't want to read the documentation and just want to ask a person for the answer, you can try StackOverflow. It is an organised Q&A database where if your question has already been asked and answered, you don't need to make someone answer the same question more than once. It's a good way to save people from duplicating their effort. |
Hello, I noticed that if I add the header 'range': 'bytes=0-' to get the full response from the host it will throw exceptions when fetching data, had to do the following modification in the function _fetch():
Is that something that can be added in the official release? |
I'm not clear on what you're adding to where to cause the crash, since nowhere in |
Hi, let me give you more context.
I can create a fork and give you a complete working example if you need but basically, I need to use the range header or else the endpoint will throttle my request and the connection will timeout before the file is downloaded, if I send the header, the endpoint server will not throttle my request and the file will download at maximum speed almost instantly. Thanks! |
As mentioned, If you need a feature like this, it needs to be built into the class. However, I would like to be more clear on this before building this into the class. My understanding of the spec is that you should first receive the |
Hi, thanks for the discussion. You are totally right, the spec mentions a inital HEAD request should be performed to check if the host accepts range requests (in my case I know it always does), maybe my use case is a corner case to this, but unless I specify the range for all requests to the audio endpoint (that I don't control) it will serve the file with throttled speed which causes the Thanks for all the work you do! |
Sounds like two changes are in order for
Would that work for you? |
Yes, that would fit my use case perfectly. |
@ryanheise Can I use the
From just_audio.dart: /// Starts the server.
Future<dynamic> start() async {
_running = true;
_server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
_server.listen((request) async {
if (request.method == 'GET') {
final uriPath = _requestKey(request.uri);
final handler = _handlerMap[uriPath]!; // ERROR IS THROWN HERE - LINE 2008
handler(this, request);
}
}, onDone: () {
_running = false;
}, onError: (Object e, StackTrace st) {
_running = false;
});
} |
Any suggestion on how I could play a remote files and store the files in cache for faster playing next time? One option is to use Flutter cache manager to download it too when I play it but this would mean downloading twice i.e one from the remote url (for the audioplayer) and one to store in cache for next time.
How possible is it to play the remote file while caching it for faster playing the next time?
The text was updated successfully, but these errors were encountered: