-
Notifications
You must be signed in to change notification settings - Fork 25.9k
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
Service worker doesn't support seeking in videos #25865
Comments
We hit this issue, because requests to video needed to be
|
@mordka Thank you for your suggested fix. I was having a slightly different issue where range requests were breaking audio in Safari due to the SW failing to apply the |
Turns out this is actually fixed now by appending ngsw-ignore to your querystring or as a header. |
That is just another workaround to ignore videos (though it is one of the best workarounds in that regard so far). |
As mentioned in #25865 (comment), if someone wants to take a stub at incorporating range handling into the SW, I'd be happy to help/review. How do other implementations (e.g. workbox) handle this? |
We are having the same issue now. Was there any progress on that? |
Hopefully, this issue gets solved soon. We are using a nasty hack, after building, in the build script we're adding a line to ignore the video:
This way we're avoiding a new fork from the main repo. |
I have also been facing an issue with this. I have been using EDIT: |
One way to do this is to create a patched First copy a onFetch(event) {
if (event.request.headers.get("range")) {
// You need to grab the cache name. On my version of ngsw-worker.js:
const cacheName = `${this.adapter.cacheNamePrefix}:${this.latestHash}:assets:app:cache`;
// note: adjust assets:app with where you put the videos (could be assets:assets group).
// do respondWith with the promise returned from returnRangeRequest()
event.respondWith(returnRangeRequest(event.request, cacheName));
// @philnash code:
function returnRangeRequest(request, cacheName) {
return caches
.open(cacheName)
.then(function (cache) {
return cache.match(request.url);
})
.then(function (res) {
if (!res) {
return fetch(request)
.then((res) => {
const clonedRes = res.clone();
return caches
.open(cacheName)
.then((cache) => cache.put(request, clonedRes))
.then(() => res);
})
.then((res) => {
return res.arrayBuffer();
});
}
return res.arrayBuffer();
})
.then(function (arrayBuffer) {
const bytes = /^bytes\=(\d+)\-(\d+)?$/g.exec(
request.headers.get("range")
);
if (bytes) {
const start = Number(bytes[1]);
const end = Number(bytes[2]) || arrayBuffer.byteLength - 1;
return new Response(arrayBuffer.slice(start, end + 1), {
status: 206,
statusText: "Partial Content",
headers: [
[
"Content-Range",
`bytes ${start}-${end}/${arrayBuffer.byteLength}`,
],
],
});
} else {
return new Response(null, {
status: 416,
statusText: "Range Not Satisfiable",
headers: [["Content-Range", `*/${arrayBuffer.byteLength}`]],
});
}
});
}
return;
}
... // rest of codes onFetch codes Then on your npm postbuild script you can just cp the file back to your dist folder: "scripts": {
"build": "ng build --prod",
"postbuild": "cp ngsw-worker-patched.js ./dist/ngsw-worker.js", If your videos are small and you want to avoid doing manual patch of |
Hello, I actually had to update that SW code recently (turned out the caches API didn't like storing 206 responses), so I'd check the latest from here: https://github.com/philnash/philna.sh/blob/master/sw.js#L49-L100. |
To sum up (for future reference):
BTW, Workbox has a module to handle range requests: Workbox Range Requests (source code) If anyone is interested in trying to incorporate the fix into the SW and submit a pull request, I would be happy to help/review. |
@gkalpak what king of a fix are we looking into should we add another property in SW-config file. Which if made true add code which handles it |
No, we don't need a config option. We just need to teach the SW how to handle range requests (by incorporating code similar to this and potentially making other necessary adjustments). |
It seems that we have a lot of workarounds in order to fix the video issues in Safari iOS, but I wonder why the fix is not yet implemented ? |
As mentioned in #25865 (comment) (and other comments), implementing the fix is up for grabs if anyone is interested. I would be happy to help out. Otherwise, I will hopefully get to it at some point, but this is not high in priority, so no timeline and no promises 😁 |
No timeline, no promise, not high in priority. However this issue is open since June 2018 Of course there is a lot of people interested to see a fix in order to have video working with Safari without having to extand manually the ngsw. I'm one of them :) |
My issue was that the videos of my PWA (Angular + NGSW) simply wouldn´t play on iOS using Safari. I finally found the solution in this answer: https://stackoverflow.com/a/58966397/8581106. The solution for me was to bypass the Angular Service Worker with Example: <video muted preload="metadata" controls playsinline>
<source src="assets/vid/tutorial_invoice.mp4?ngsw-bypass=true" type="video/mp4">
</video> |
Is it possible to add it to :src that renders dynamically? |
Hm, what is needed here to get this to work properly? In our case, we load many PDFs, each must be cached for offline usage, which works, but range requests do not. Weirdly, it only does not work for giant PDFs, above 6 MB. |
Same issue here with range requests and the service worker. We're using @philnash's patch, but we shouldn't have to. Any updates on this? |
I would like this issue to be resolved, which is why I have posted a $60 reward. I would like to contribute but I don't have time to solve it and that's why I thought that a monetary contribution could help attract people who want to help (especially seeing that it is an issue that has been open for quite some time) |
If the video file is still being served by the Service Worker, you can force the video to load directly from the network by appending a unique parameter to the video URL, such as a timestamp or identifier: const videoElement = document.getElementById('myVideo'); If you need to serve large videos, consider configuring a web server with range request support, such as Nginx or Apache. This ensures that the browser can handle seeking (currentTime) properly. |
Hey i took a stab at it ... is this looking like what you all wanted to do? I just made a quick draft to confirm if this is the solution desired since there was a lot of discussion over this. Open to any and all feedback or requested changes. |
can anyone take a look and tell me if im missing anything ? i think this is all we need to do. |
I'm submitting a...
Current behavior
If you
ng run app:build:production
and your pwa comes with a<video>
element where you also utilize seeking (settingcurrentTime
depending on your app logic and/or user input) it will not work or only very inconsistently. Most videos will simply run from start and not at the settedcurrentTime
position. This is only the case when videos are delivered/fetched by the service worker. So it works in development mode.Expected behavior
Videos should start at the setted
currentTime
.Minimal reproduction of the problem with instructions
Environment
Angular version: 6.1.2
Browser:
Chrome (desktop) version 69
Others:
This seems to be a known problem since service workers don't know Range requests. However it also looks like very easily fixable if I understand this thread comment correctly: https://bugs.chromium.org/p/chromium/issues/detail?id=575357#c10
A workaround would be a convenient way to completely exclude requests from service worker (not just set strategies for them). But obviously it would be better if we also could cache some videos. For exclusion also this issue may be relevant : #21191
EDIT(gkalpak): Issue summary in #25865 (comment).
The text was updated successfully, but these errors were encountered: