-
Notifications
You must be signed in to change notification settings - Fork 6k
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
Generalize/enhance persistent caching functionality #420
Comments
It also should be able to cache mp3, mp4 files distributed through plain http. In my use case app plays media file from server, but URL and CDN server may change everytime file is requested. I think we should use key based caching. |
I'm making my own cache for now, should I modify DataSource interface or create CacheableDataSource instead? |
I did some work, please check it. https://github.com/nzer/ExoPlayer/commit/6c3c89073e25b7af97fc7c55e6a7d15d308a9fbc |
One question about the indexes (key), why not just use a hashing function of the DataSpec info, like uri+position+length? Would be unique enough for the caching structure and would also avoid having another segments chunk index overlap with some other. |
Because if you've cached the whole of a media stream under some hash h(uri, 0, length_of_stream), then you'll get a cache miss for every request to for the same uri unless you happen to be requesting from position 0 for the whole stream, even though you have this data cached already. |
Hmmm, right, however I've managed to get the cache working using a simple hash function of uri+offset+length, which works great currently because it is pretty much unique to that stream and to its requests so if a user seeks he immediately gets the stream playing if it is cached. Only a small hick up happens if the video has switched to a higher resolution meanwhile and you seek back to the stream, than it has to reload that part in another variant, but I guess that is more of a feature/expected than a bug. Also in my tests so far, it doesn't impede any streams at all, live works well with it too - it doesn't cache it. I think that it can be easily leveraged to implement additional functionality like live seeking and similar I just need to extend it to support these more or less unbounded requests. |
The point of this bug is to generalize support for all use cases. What you're doing only optimizes for a subset of cases (from your description, I'm assuming either HLS or a particular variant of DASH/SmoothStreaming). It likely also breaks if a read error occurs part way through a request (subsequent read attempts probably get a cache hit to the incomplete data). |
Yes, I'm currently using the existing implementation and only testing from my HLS use cases. I should definitely take a look what happens with incomplete data and how it handles. |
Question - just to be clear, this enhancement when done will include the capability to save mp4 from http source to the device as it's playing? our use case is to play the video from http the first time and if the file download completes as it's playing, then the file gets saved to our app cache and next time it can be played from disk instead. I have sort of a working solution but I'm not sure it's really the correct approach. Essentially the http data source passes the bytes (readInternal method) to a custom transfer listener which writes the bytes to a file output stream as the video downloads/plays. When the download is complete/ file is done being written, that video is marked as saved in our app. This seems to be working as expected except when I ask the player to seek during download - it looks like the connection and input stream are closed and re-opened with a new request and the file output gets hosed. Couple of questions: Is there another approach I might take in the meantime? Is it currently possible to create my own downloader and play the video from a file input stream as it downloads? Is it possible to create an internal http proxy server and pass the internal url to the httpdatasource? |
Anyone have a dev branch currently working on this? @Arqu @42footPaul @ojw28 |
@cmdkhh Agreed. An update on the status of Exo caching would be most appreciated. Has anyone else found any type of success with caching? I'm currently attempting to cache mp4 files served from a URL with CacheDataSource, but it doesn't seem to be actually cache anything from what I can tell (powering off/on the screen, releasing the player and reinitializing it, still redownloads the mp4 from the network again). |
If there is a current roadmap of tasks that need to be done to implement caching, or if anyone has an official development branch started, that would be better then starting from scratch. If any of these are available do let us know. We plan to start implementing caching ourselves but would love to provide support back to Exo. |
Would like to share my investigations in this way. I have spent some time to implement cache for exo player in my app. Requirements for my app: Issues that I have faced with:
1: 2: Let me know if I am unclear or missed something. 2015-11-10 20:15 GMT+02:00 John Shelley [email protected]:
|
I will just add my interaction with the caching issue. |
If you setup OkHttp it's pretty straight forward to get files to cache. I can provide details if needed. |
@laurencedawson an example or some direction would be awesome! I'm thoroughly lost after attempting it for a while now. Even getting something relatively simple like the ExoPlayer Demo to cache with OkHttp would be tremendously helpful. I swapped in OkHttp and added a cache for it, but the demo still seems to re-download when that activity is recreated (rotation for example). |
@laurencedawson I'm using okhttpdatasource and still no luck trying to download the audio stream to disk. Any input you can provide will be greatly appreciated. Thanks |
Check this: Using CacheControl to set max stale, and OkHttp's Cache will honor them |
Thanks for the prompt reply. I've followed your suggestion and included the On Fri, Jan 29, 2016 at 11:01 AM, Yu-Hsuan Lin [email protected]
|
@zhangvb the link you gave is dead. |
@kinsleykajiva the link is fine if you copy and paste the URL as text (it's just that it's linked incorrectly). |
@qqli007 great example... caching seems to work but now seeking backward or forward is not working any more. I'm working with mp3 files. |
Appending my code, it worked for me. If play without seeking cache works.
|
Hello by using dev-v2 am able to create local cache of stream video. Now its showing multiple files in following format "xxxxx.v2.exo" is there any way by which i can create .mp4 file. |
@Anshumansharma12 it isn't possible but you can always download the file yourself and play it using a FileDataSource. |
Can somebody please explain how the CacheDataSource is supposed to be setup ? All I can see is code like this but no idea how to integrate back into the demo application. ie
The demo application has code like this, so where does CacheDataSource go here ?
I'm hoping this will work as an offline cache ? Why is it not integrated into it already ? offline playback seems to be a common request. |
I've got this but I can't seem to debug if it's working. There is zero documentation and I've resorted to dev-v2-id3 as it seems the most up to date with all the refactoring. If I start playing a dash source. Turn off remote connection and try and replay it fails to load the mpd file from the cache.
The dash source stays the same
The event logger implements this event method but nothing.
|
Confirming this to be working. It is causing audio buffer underruns when playing from the cache so dropping frames. Turning off connection the fragments can play back from the cache but the main manifest still wants a connection and is not being stored into the cache. Perhaps this solution can be used for providing an offline downloader without having to re-engineer one. Just run the caching in the background ? |
I have both caching and persistent widevine dash working. However it's not caching the Mpd yet perhaps there is still a setup problem there ? |
The cache gets messed up with adaptive switching. Still can't figure out why its not caching the Mpd file. It is possible not setting the key correctly for the Dash segments. Need to now figure out how to turn Adaptive off and choose the largest bitrate while trying to build a cached offline file. There has been zero proper documentation, even code commenting for any of it sadly. As I mentioned FairPlay has a downloader and offline playback feature for AVPlayer out of the box with the current SDK. It would be nice to match it. |
This code is so convoluted. I was able to track down why the mpd is not being cached. It's because of a content length being -1. I can't work out right now where or why it's returning -1. Really hard work. You have other options than to use the cache directory I believe like these. One will clear content when the app is removed, the other will not.
|
As far as I can see the manifest loader runs through a parser. No content length is given before it's opened. It will fail to store in the cache because no content length is given. |
This provides no length therefore the issue. the length can't be set after reading bytes. Requires some hacking elsewhere to allow writing the cache without checking for length possibly. |
@erdemguven - Do we cache data if even the resolved length is unknown (this is likely a result of the mpd response being gzip'd) and/or have a solution to this? @danrossi - I think it would be fairer to call the code necessarily complex ;). There are many small nuances to caching media properly, particularly when considering things like caching of non-completed requests. As an aside, you probably shouldn't be using the caching components as-is to build a proper DASH offlining solution. A proper DASH offlining solution would more than likely involve explicitly downloading only a single representation (and not the manifest, although you might optionally recreate an offline manifest containing only the single representation downloaded). The caching components can be used as part of an implementation for this, but the actual downloading bit should probably not be implemented using a player instance. |
@ojw28 ok. I was hoping to use this then play the locally stored sources ? I have the custom offline widevine manager working and will load the keys. I could be interested to upload that to github. The last past of course was hoping to switch to the largest bitrate and turn abr off and just let the internals do the downloading without having to re-engineer anything. I couldn't even find documentation how to do that sadly. I wouldn't know where to start to. Im assuming the entire DashDataSource needs to be duplicated and modified to use a filedatasource for playback like the cache system does. |
I thought the latest changes were intended to deal with lack of content length issues. It still won't cache the mpd file sadly. It seems this system is not designed for and not adequate for offline storage purposes, and an offline concurrent downloader feature needs to be built on top of the dash parser feature possibly. Then another system like the cachedatasource to play back those local files. None of this readily available. |
Is there an internal feature like the cachedatasource, to download parsed dash manifests and fragments then use the FileDataSource to play it back ? It would be easier if it just concurrently downloaded everything into the cache path and CacheDataSource played them back ? |
@danrossi We're working on full DASH offlining solution but there isn't anything for downloading yet. I don't know when it'll be ready. |
@erdemguven Any idea when this is likely to land? We need this functionality so might end up building it in the mean time, but it would be fantastic to not have to! |
@matclayton if you mean the DASH downloader, basic functionality should be in github in 2 weeks time. |
Yes I did, fantastic! |
Hey @erdemguven was the DASH downloader released? Can't seem to find it. |
ExoCache is designed specifically for DASH implementations where every request can be in the form of a bounded range request (which in practice means single-segment on-demand streams containing sidx boxes). It doesn't work for anything else (DASH where streams are segmented in the manifest, SmoothStreaming, HLS, ExtractorSampleSource). There are three things to fix:
The text was updated successfully, but these errors were encountered: