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
Query download size before storing offline #2900
Comments
I really like this idea. The async callback would also allow integration with an app's UI to present a prompt to the user. There are a few wrinkles, though, to be worked out first:
In fact, the more I think about this latter issue, the more I think it would be ideal for applications to have some way to get size metadata from their catalog directly, so that they can make size-based decisions without hammering their servers with HEAD requests. A two-hour film with 10-second segments (which is on the high end of segment size, but common enough for VOD) would be 720 segments x 2 streams (video + audio) = 1440 segments. Do app developers really want us to make 1440 HEAD requests before we start downloading content? |
One thing we could do is have a flag to select between making HEAD requests and estimating it based on the manifest. We could estimate the size based on the bandwidth. This would allow apps to have a ballpark estimate without requests, or to have us make a bunch of requests if they need a more exact answer. |
You make a good point. If we are clear in the API that the size in the callback is only an estimate, we could simply always use average bandwidth x time to compute that size estimate. I feel as though that should be accurate enough for storage decisions, but also extremely efficient in terms of time and server resources. What do you think? |
Hi @TheModMaker and @joeyparrish, I don't know about what other apps do but we launch two HEAD request (one for video data and other one for audio) for each content after track selection. Then, since we're allowing to create a queue, we store that content size for all elements in the queue and check that adding a new one is going to fit in the device. Given that and taking into account that we use to add a margin (100 MB right now) to content size, I think an estimation should be enough for checking if the download fits in the device and can continue or not. |
So now we have three competing ideas:
I feel like option 2 would skew badly if we used the first segments of each, since the opening may involve many black or nearly-black frames in a row, which would compress really well. Same for audio, which may involve a lot of silence early on. If the manifest is relatively accurate, option 3 could actually be the best choice. Apps could make decisions with some safety margin, and we could document recommendations for that that app developers could start with if they like. This would also allow us to put download size estimates on the tracks themselves so that apps could use that info in selecting tracks. @OmarPedraza, what do you think? |
Hi @joeyparrish, The content we used for this test has a 2623204 ms duration and selected track bandwidths were 97690 bps for audio and 1225627 bps for video. Combining those number we obtain the following estimations: Audio: 256260798.76 bits -> 32032599.845 bytes Then we proceed to download the content using an iOS simulator resulting in files with the following sizes: Audio: 32033338 bytes As you can see, it seems like these calculation is very accurate so I think that option 3 should be the winner. |
Okay, sounds like a plan. Thanks for your input! So, we would add a size estimate to the Track API, for use in selecting tracks: track.sizeEstimate = track.bandwidth * duration / 8; Repeating @TheModMaker's API proposal, we would add storage.configure('offline.downloadSizeCallback', async (sizeEstimate) => {
const estimate = await navigator.storage.estimate();
// Limit to 75% of quota.
return (estimate.quota - estimate.usage) * 0.75 > sizeEstimate;
}); Where Should the sample |
The fallback to prefixed methods is really helpful, but the final fallback in that article just returns NaN, so we would still need some behavior in the callback for when a storage estimate is unavailable. Should we allow by default in those cases? Or reject by default? |
If we fall back to "allow", that will preserve prior behavior on older platforms. However, if we fall back to "reject", we will force app developers using those platforms to write their own callback. This may prompt them to look for and leverage platform-specific APIs in that callback, or it may cause them to mistakenly assume offline storage is no longer supported on that device. :-/ Thoughts? |
By default, we should allow downloading in case the apis are not available. |
Have you read the FAQ and checked for duplicate open issues?
Yes
Is your feature request related to a problem? Please describe.
When downloading content for storage, it's useful to know how much storage space will be needed before storing. This is extremely important for mobile devices that have limited space. See shaka-project/shaka-player-embedded#167.
Describe the solution you'd like
We could use the info in the manifest and make HEAD requests to determine the size of the content we're downloading. This would only include the segments themselves, not the manifest since it's small and we can't determine how large that will be in IndexedDB.
We would have an extra callback (like the track-selection callback) that will be called with the size once we know it. The callback can return a boolean for whether we want to continue or cancel. The method could be asynchronous to allow using the Storage API:
Describe alternatives you've considered
Additional context
The text was updated successfully, but these errors were encountered: