Skip to content
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

Advanced Video Streaming aka HTTP Range Requests #10

Open
6 of 11 tasks
lastmjs opened this issue Dec 4, 2021 · 19 comments
Open
6 of 11 tasks

Advanced Video Streaming aka HTTP Range Requests #10

lastmjs opened this issue Dec 4, 2021 · 19 comments

Comments

@lastmjs
Copy link

lastmjs commented Dec 4, 2021

I'm attempting to do the work to claim this bounty: https://twitter.com/dominic_w/status/1467144071449915395

It seems like implementing HTTP Range request functionality will achieve video streaming, and beyond that audio streaming and really any kind of file streaming. I'm not exactly sure what is in scope for this bounty, but I hope to receive guidance on what is acceptable along the way.

Tentatively I'll be following this guide: https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests

I'm not sure how much of it needs to be implemented, as some functionality might not be necessary to have excellent video streaming from most clients/browsers

Required functionality

  • Range header
  • 206 partial response
  • Content-Range header
  • Content-Length header
  • 416 response

Possibly optional

  • Accept-Ranges header
  • HEAD requests
  • Multipart ranges
  • If-Range header
  • Certification
  • Protection against denial of service (range numbers that are too big, too many ranges)
@lastmjs
Copy link
Author

lastmjs commented Dec 6, 2021

An update on my progress. I have 206 partial responses somewhat working. I am now able to load a video player into the default Chrome video view and skip around. http range requests are made at any point in the video. The problem is that I now need to stream each partial request, because they could be over the ~3 MB limit. I'm hoping this won't be too hard.

@paulyoung
Copy link

@lastmjs can you clarify if you are only working on streaming response data, or also on streaming request data?

@lastmjs
Copy link
Author

lastmjs commented Jan 18, 2022 via email

@paulyoung
Copy link

I realize that the scope of your work probably relates to the bounty, but it seems like we’ll also need to support streaming uploads as well.

Otherwise, I think the size of the video and audio files involved would be limited by what can be uploaded.

@paulyoung
Copy link

I believe one limitation here is the 2MB message size.

@lastmjs
Copy link
Author

lastmjs commented Feb 5, 2022

Uploads are easily chunked by the client, as can be seen by dfx being able to upload large file sizes

@paulyoung
Copy link

Right, but that means people need to use dfx.

I think the code from the certified assets crate that dfx uses would need to be used by icx-proxy to enable arbitrary-sized file uploads from other clients in general.

For web-based apps that probably needs changes to the service worker as well.

@lastmjs
Copy link
Author

lastmjs commented Feb 5, 2022

What I meant by that is it's easy enough to chunk even from a browser client when uploading. As I understand it the browser client would just need to do what dfx does, which is split the files to be uploaded into appropriate binary chunks and use the update functions on the asset canister. They wouldn't be able to do it all in one http request, but neither does dfx. And this should be possible on the browser, someone just needs to write the code. I've done something similar with my own file example (using a Sudograph canister).

Changes to the asset canister shouldn't be absolutely necessary, but perhaps it would be preferable to implement streaming uploads. But Dfinity is working on increasing the ingress message size limit anyway.

@paulyoung
Copy link

I’m thinking of the use case where an app is trying to (or limited to) make a regular HTTP upload without any special handling.

It also fits into a category of things that could be moved upstream so that every one who wants to do that doesn’t need to implement the same thing.

@lastmjs lastmjs mentioned this issue Feb 5, 2022
@lastmjs
Copy link
Author

lastmjs commented Feb 6, 2022

Yeah I agree that would be great. I think for now it might be best to move this functionality into the JS agent, and then arbitrary sized ingress messages I would hope will provide a true fix.

@lastmjs
Copy link
Author

lastmjs commented Feb 7, 2022

Just ran into a major issue. I've deployed the canister to production and filled it with assets, but partial responses aren't working in production. I wonder if the boundary nodes are filtering out the response headers.

I added the following response headers:

  1. Accept-Ranges
  2. Content-Range

Is there some whitelist in the boundary nodes that needs to be edited? @roman-kashitsyn @nomeata

@lastmjs
Copy link
Author

lastmjs commented Feb 7, 2022

More info in this forum post, @jplevyak has said he will talk to the team and see about getting this addressed: https://forum.dfinity.org/t/boundary-node-http-response-headers/10747

@3cL1p5e7
Copy link

3cL1p5e7 commented Feb 9, 2022

@lastmjs Hi!)
I am testing adding of custom headers (Accept-Ranges and Content-Range) and see that headers are received in production

My case

  • Hard-code headers in certified_assets canister Снимок экрана 2022-02-10 в 01 51 04
  • Deploy and open browser
  • Make .raw. request for some asset Снимок экрана 2022-02-10 в 01 54 06
  • Get headers

Sorry, maybe I misunderstood something in the question, but in my case the headers are returned and it will help :)
It was about boundary node headers filtering or something else.

@lastmjs
Copy link
Author

lastmjs commented Feb 9, 2022 via email

@3cL1p5e7
Copy link

3cL1p5e7 commented Feb 9, 2022

Sorry, I dont know. I just checked if additional headers are filtered or not for .raw. URLs in production and maybe I didn't show anything new

@3cL1p5e7
Copy link

3cL1p5e7 commented Feb 9, 2022

I can assume that in order to have a range streaming, you need to upgrade this place (for .raw. calls)

https://github.com/dfinity/icx-proxy/blob/6cee84ace323c846f670d2eefdd292aa1b986f08/src/main.rs#L279
At this place, the chunks are downloaded sequentially from the certified_assets and possibly sent to the browser. I tried to do something similar in service worker
https://github.com/dfinity/ic/pull/5/files#diff-868be50442ee1d9397fa6910d4627c7a0386365ace603123de7ae169ce2de2e4R220

@lastmjs
Copy link
Author

lastmjs commented Feb 9, 2022 via email

@lastmjs
Copy link
Author

lastmjs commented Feb 10, 2022

@3cL1p5e7 I've done my own testing, and it looks like 206 status codes work in production along with any http response headers I've tried.

It looks like the boundary nodes are filtering out the Range http request header in production. I would love to get the boundary nodes to allow Range headers, because then I could at least use my fork to have range requests until a more scalable solution is implemented at the boundary node level.

@3cL1p5e7
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants