8000 fix(service-worker): update service worker to handle seeking better for videos by Beanminchild · Pull Request #60029 · angular/angular · GitHub
[go: up one dir, main page]

Skip to content

fix(service-worker): update service worker to handle seeking better for videos #60029

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Beanminchild
Copy link
Contributor
@Beanminchild Beanminchild commented Feb 20, 2025

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.dev application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

"If you ng run app:build:production and your pwa comes with a

Issue Number: #25865

What is the new behavior?

Added logic to driver.ts in the worker src folder that does the following:

The onFetch method now:

  • Checks for Range headers in incoming requests.

  • Calls the handleRangeRequest function if a Range header is present.

The newly added handleRangeRequest function:

  • Parses the Range header to determine the requested byte range.

  • Fetches the full content and extracts the requested byte range.

  • Constructs a response with the appropriate Content-Range and Content-Length headers.

  • Returns a 206 Partial Content response with the requested byte range.

These changes ensure that the service worker can handle Range requests, allowing videos to start at the specified currentTime when delivered by the service worker as well as fixing seeking.

Does this PR introduce a breaking change?

  • Yes
  • No

Should not be a breaking change

@angular-robot angular-robot bot added the area: service-worker Issues related to the @angular/service-worker package label Feb 20, 2025
@ngbot ngbot bot added this to the Backlog milestone Feb 20, 2025
@Beanminchild Beanminchild marked this pull request as ready for review February 21, 2025 13:16
@pullapprove pullapprove bot requested a review from alxhub February 21, 2025 13:16
@Beanminchild
Copy link
Contributor Author

@alxhub can you please review when you get a chance? Thank you.

@Beanminchild
Copy link
Contributor Author

@kirjs can I get this reviewed please?

Copy link
Contributor
@thePunderWoman thePunderWoman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks!

@thePunderWoman thePunderWoman removed the request for review from alxhub June 3, 2025 11:11
@thePunderWoman thePunderWoman added action: merge The PR is ready for merge by the caretaker target: patch This PR is targeted for the next patch release labels Jun 3, 2025
@kirjs kirjs added target: patch This PR is targeted for the next patch release and removed target: patch This PR is targeted for the next patch release labels Jun 3, 2025
@kirjs kirjs closed this Jun 3, 2025
@kirjs kirjs reopened this Jun 3, 2025
@thePunderWoman
Copy link
Contributor

@Beanminchild Can you sign the CLA? Once you do that, this should be ok to merge. Thanks!

@Beanminchild
Copy link
Contributor Author

@Beanminchild Can you sign the CLA? Once you do that, this should be ok to merge. Thanks!

sure thing ill do that right now

@Beanminchild
Copy link
Contributor Author
Beanminchild commented Jun 3, 2025

@Beanminchild Can you sign the CLA? Once you do that, this should be ok to merge. Thanks!

@thePunderWoman okay i updated the cla

…or videos

This update ensures that the service worker can handle range requests, allowing video seeking to work correctly when videos are delivered by the service worker.
@Beanminchild
Copy link
Contributor Author

@thePunderWoman everything looks good, do you need anything else from me?

@kirjs
Copy link
Contributor
kirjs commented Jun 3, 2025

This PR was merged into the repository by commit c663277.

The changes were merged into the following branches: main, 20.0.x

@kirjs kirjs closed this in c663277 Jun 3, 2025
kirjs pushed a commit that referenced this pull request Jun 3, 2025
…or videos (#60029)

This update ensures that the service worker can handle range requests, allowing video seeking to work correctly when videos are delivered by the service worker.

PR Close #60029
@anisabboud
Copy link

This was released in v20.0.1 and caused a major regression in our platform, causing videos to stop working completely.

We use shaka-player to play DASH videos hosted in Firebase Cloud Storage.

Shaka-player started showing this warning: Payload length does not match range requested bytes,
along with status 206 "Partial Content" matching the description of this PR:

  • Returns a 206 Partial Content response with the requested byte range.

image

Reverting back to @angular/service-worker 20.0.0 resolved the video playback issue for now.
Please revert or re-review this change!

@thePunderWoman
Copy link
Contributor

@anisabboud Please file an issue with a reproduction so we can verify and we can proceed from there.

@anisabboud
Copy link

Might be related, but not identical: #62333 (issue from 4 days ago by @Benny739 streaming video via hls.js with Range: bytes=... header, where this PR modified the behavior.)

@anisabboud
Copy link

I think there should be tests in place for this tricky piece of code...

const start = Number(rangeMatch[1]);
const end = rangeMatch[2] ? Number(rangeMatch[2]) : undefined;
const buffer = await response.arrayBuffer();
const contentLength = buffer.byteLength;
const chunk = buffer.slice(start, end ? end + 1 : contentLength);
const chunkLength = chunk.byteLength;
const headers = new Headers(response.headers);
headers.set(
'Content-Range',
`bytes ${start}-${end ? end : contentLength - 1}/${contentLength}`,
);
headers.set('Content-Length', chunkLength.toString());
headers.set('Accept-Ranges', 'bytes');

This is the shaka-player console error with some additional information (playing DASH video stream encoded by Google Cloud Transcoder and hosted on Firebase Storage):
image

The request range in this example is 673-1785602 while the arrayBuffer.byteLength is 1784257.
shaka-player expects arrayBuffer.byteLength to be equal to (range[1] - range[0] + 1) which is 1784930.
In this case, arrayBuffer.byteLength is smaller than (range[1] - range[0] + 1) by exactly 673 which is the start value.

https://github.com/shaka-project/shaka-player/blob/b1579eb75d89f5bb00ee155fa05b3c05314d34d2/lib/net/http_fetch_plugin.js#L221-L230

Perhaps in some cases the response.arrayBuffer() is already sliced and we shouldn't do buffer.slice(start.

Hope this helps. In any case, I appended ?ngsw-bypass=true query param to all video segment URLs to workaround this bug our my code (as per the https://angular.dev/ecosystem/service-workers/devops#bypassing-the-service-worker).

@anisabboud
Copy link

BTW in the reference implementation by @philnash (blogpost referenced by @gkalpak), he eventually updated his sw.js code to skip slicing it if response.status === 206 ("Partial Content") and just returns it as is. See commit: philnash/philna.sh@2702651.
image
https://github.com/philnash/philna.sh/blob/d0737c37725378a6874dd25d3170ca05db41591e/sw.js#L68-L91


In the other reference implementation by the Chrome workbox-range-requests, they also return the response as is if the status is 206 (Partial Content):
image
https://github.com/GoogleChrome/workbox/blob/e26d8d7507f9412ba029922f3d9920e68710f2cf/packages/workbox-range-requests/src/createPartialResponse.ts#L53-L57

    if (originalResponse.status === 206) {
      // If we already have a 206, then just pass it through as-is;
      // see https://github.com/GoogleChrome/workbox/issues/1720
      return originalResponse;
    }

See this commit: GoogleChrome/workbox@cd5ef34 by @jeffposnick "Return a HTTP 206 response as-is" (to avoid "double-slice").

Perhaps someone from the Chrome/Workbox team could review this PR?

@thePunderWoman
Copy link
Contributor

@anisabboud The Angular service worker does not use workbox. I think we'll just revert this pr for now.

thePunderWoman added a commit to thePunderWoman/angular that referenced this pull request Jul 2, 2025
thePunderWoman added a commit that referenced this pull request Jul 2, 2025
thePunderWoman added a commit that referenced this pull request Jul 2, 2025
thePunderWoman added a commit that referenced this pull request Jul 2, 2025
@thePunderWoman
Copy link
Contributor

@Beanminchild We've reverted this PR in #62422 due to reported regressions.

@thePunderWoman thePunderWoman reopened this Jul 2, 2025
@thePunderWoman thePunderWoman added action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews and removed action: merge The PR is ready for merge by the caretaker labels Jul 2, 2025
@anisabboud
Copy link

@anisabboud The Angular service worker does not use workbox. I think we'll just revert this pr for now.

@thePunderWoman Thank you for the attention to this issue.

I referenced Workbox since they implemented a similar feature, as mentioned in #25865 (comment), which could be used as a basis for this PR / code review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
action: cleanup The PR is in need of cleanup, either due to needing a rebase or in response to comments from reviews area: service-worker Issues related to the @angular/service-worker package target: patch This PR is targeted for the next patch release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
0