-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Offline storage silently failing on Safari #6228
Comments
When using your sample code, I actually am hanging on an earlier part of the storage process on Safari. Specifically, the part where the DRM engine is created: shaka-player/lib/offline/storage.js Lines 361 to 364 in 36b7367
So I can't confirm that that line you highlighted in specific is the problem. That aside...
So I don't think this is actually a bug, per se. Though we could probably fail in a more informative manner than having a promise hang without resolving... |
Persisted licenses and offline storage are two different things. You can use offline storage without persisted licenses. Since Safari supports IndexedDb, it should be compatible with offline storage without persisted licenses. |
We’ve recently changed our DRM proxy server to do the base64 transformations for FairPlay so we don’t need the Shaka request and response filters anymore, which is probably why you ran into this issue with running this sample code. I’ll post a newer version of the code here shortly. |
Here's an updated html+js page that reproduces the issue. The code is cross-platform, so you can see offline storage working correctly on Chrome and Edge and hanging at the first storage attempt on Safari. If you uncomment the code section that talks about this github issue, you basically avoid using offline storage in Safari.
|
I'm getting the same result with that code; the drm engine fails to load, and we never even get to that call to Looking into the setup process of the drm engine, it looks like the loading process gets confused by the empty init data we generate for That change is presumably not a fix for this problem though. At no point have I managed to reproduce the issue you are reporting, and you haven't reported seeing the issue I am experiencing either. I am testing this on Safari on macOS 13.6.4, so perhaps there could be platform differences at play? |
I'm using Safari Version 17.2.1 (19617.1.17.11.12) on MacOS 14.2.1 (23C71) |
To start, we should never be failing silently. Thank you for your report. As an aside, I see a couple small change you can/should make to your code to optimize a little. You don't need to list the stored contents again to get the offline URI. Metadata of the stored content is returned to you after the storage operation. You can also use for-of instead of forEach to return early without iterating through each item. So this: let alreadyStored = false;
await this.storage.list().then(function(content) {
console.log('Stored offline content', content);
content.forEach(function(line) {
if (line.originalManifestUri == uri) {
alreadyStored = true;
}
});
});
if (!alreadyStored) {
console.log('URI not already stored, storing now', uri);
await this.storage.store(uri).promise;
console.log('URI stored', uri);
player.getMediaElement().play();
}
let offlineURIList = [];
await this.storage.list().then(function(content) {
console.log('Stored offline content', content);
content.forEach(function(line) {
// Offline storage will keep things from previous code iterations as well
// We only want offline manifests that correspond to the current target manifest URI
if (line.originalManifestUri == uri) {
offlineURIList.push(line.offlineUri);
}
});
});
if (offlineURIList.length) {
console.log('Found offline content, play it', offlineURIList[0]);
return offlineURIList[0];
}
return uri; Could simplify to this: const items = await this.storage.list();
console.log('Stored offline content', items);
for (const item of items) {
if (item.originalManifestUri == uri) {
return item.offlineUri;
}
}
console.log('URI not already stored, storing now', uri);
const newItem = await this.storage.store(uri).promise;
console.log('URI stored', uri, 'as', newItem.offlineUri);
return newItem.offlineUri; I don't expect this will change the shape of your problem, but could you try it and confirm that you still see Thanks! |
I've updated the code to use your snippet, you can test it live here: https://layerproject.github.io/shaka-predownload-pallycon.html Here's a screen recording of the issue experienced in Safari: https://drive.google.com/file/d/1r6iHcL3oBzBUuQr17TqziQFY8F0aA9vN/view?usp=sharing |
Even with that uploaded code snippet, I still see it hanging on the DRM engine creation. |
Oh, right, my macbook is too old to run macOS Sonoma. In the meantime, I uploaded the change I mentioned that fixed the problem I was running into, just in case. |
I got a new work MacBook that can run MacOS 14.4, and I am still seeing your demo hang on the creation of the DRM engine rather than the line you highlighted. That suggests this isn't a platform-specific issue. |
I saw your access to our system in the logs earlier today and you only hit our DRM proxy URL with Widevine as the requested DRM type, FYI. Here's an updated version of our self-contained repro case: https://layerproject.github.io/shaka-issue-6228-repro.html please use that one for further testing, as the old code will fire some alerts on our system. For our own project we gave up on Shaka's offline storage for now, instead we switched to using a service worker of our own. It works great, including on Safari. |
I opened the page in Chrome once by accident that day, and when loading the page on Safari it doesn't even get to requesting DRM info, which probably is why you are only seeing a Widevine request. According to the info logs it has chosen com.apple.fps on Safari. |
Yes, that's correct, it's the same behaviour I'm seeing. The last log message is |
@gi11es I've tried our FairPlay example from the Demo, and I've modified your url to include https://nightly-dot-shaka-player-demo.appspot.com/dist/shaka-player.compiled.debug.js and everything works correctly. This week we are going to release 4.8.0 that includes all the main changes, so the problem would be resolved. Note: I used Safari 17.3 (19617.2.4.11.8) |
Have you read the FAQ and checked for duplicate open issues?
Yes
If the problem is related to FairPlay, have you read the tutorial?
Yes
What version of Shaka Player are you using?
4.7.9
Can you reproduce the issue with our latest release version?
Yes
Can you reproduce the issue with the latest code from
main
?Haven't tried, but nothing in the 7 commits since the 4.7.9 tag touches the offline code.
Are you using the demo app or your own custom app?
Custom app
If custom app, can you reproduce the issue using our demo app?
The demo app doesn't support custom response rewriting without modifying the code, which is necessary for the DRM provider I'm using (PallyCon).
What browser and OS are you using?
MacOS 14.2.1 Safari
For embedded devices (smart TVs, etc.), what model and firmware version are you using?
n/a
What are the manifest and license server URIs?
See below, I'll share the entire repro case
What configuration are you using? What is the output of
player.getConfiguration()
?See below, I'll share the entire repro case
What did you do?
Here's the entire code to repro this. It will attempt to put a random video from our catalogue into offline storage and play it back.
What did you expect to happen?
The request manifest and streams are stored offline
What actually happened?
Execution gets stuck on:
await window.storage.store(manifestURI).promise;
By tracing execution with breakpoints, I was able to track it down to the following async call seemingly never completing:
shaka-player/lib/offline/storage.js
Line 389 in 36b7367
It seems to be the first attempt to store something in IndexedDB.
There are no errors, execution just stays stuck there.
The text was updated successfully, but these errors were encountered: