shaka-project / shaka-player

JavaScript player library / DASH & HLS client / MSE-EME player
Apache License 2.0
7.07k stars 1.33k forks source link

Allow no-cors on fetch request #5959

Closed Robloche closed 9 months ago

Robloche commented 9 months ago

I was looking for a solution to my problem and found the following issue: https://github.com/shaka-project/shaka-player/issues/1286

I think I have indeed found a use case for such a request. I have an HLS manifest in which segments don't have any extension. Then, as shown in code below, the parser does a HEAD request to retrieve the mime type:

https://github.com/shaka-project/shaka-player/blob/678bf2524dae237ca6ec08db35e50e26598d4e63/lib/hls/hls_parser.js#L3754-L3761

And in my case, a CORS error happens. Since I don't have any control on the manifest and I don't care about the anwser (only the response headers matter), a no-cors fetch request would certainly solves my issue.

What do you think?

avelad commented 9 months ago

So what you propose is to use no-cors for HEAD requests? If you can share the manifest with me so I can investigate the issue and provide an appropriate solution. Thanks!

avelad commented 9 months ago

I have been looking and it is not possible, in no-cors mode we do not have access to the headers, so we can not detect the mimetype correctly.

Robloche commented 9 months ago

Oh, you're totally right. I knew I wouldn't be able to access the response's body, but I thought the headers would be OK.

Here's the manifest anyway:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:38405
#EXT-X-TARGETDURATION:6
#EXTINF:6.000,
/beacon/amg01074-fueltv-netgem/147216c6-8f61-11ee-8f06-e2013c1e3b32/1920x1080_6503200?bcn=1&ca=0&cid=FUNGS-2301&dur=6.000000&media_type=C&redirect_url=https%3A%2F%2Famg01074-fueltv-netgem.amagi.tv%2Fmain_1080_2608675.ts&seg_id=2608675&user_id=147216c6-8f61-11ee-8f06-e2013c1e3b32
#EXTINF:6.000,
/beacon/amg01074-fueltv-netgem/147216c6-8f61-11ee-8f06-e2013c1e3b32/1920x1080_6503200?bcn=1&ca=0&cid=FUNGS-2301&dur=6.000000&media_type=C&redirect_url=https%3A%2F%2Famg01074-fueltv-netgem.amagi.tv%2Fmain_1080_2608676.ts&seg_id=2608676&user_id=147216c6-8f61-11ee-8f06-e2013c1e3b32
#EXTINF:6.000,
/beacon/amg01074-fueltv-netgem/147216c6-8f61-11ee-8f06-e2013c1e3b32/1920x1080_6503200?bcn=1&ca=0&cid=FUNGS-2301&dur=6.000000&media_type=C&redirect_url=https%3A%2F%2Famg01074-fueltv-netgem.amagi.tv%2Fmain_1080_2608677.ts&seg_id=2608677&user_id=147216c6-8f61-11ee-8f06-e2013c1e3b32
#EXTINF:6.000,
/beacon/amg01074-fueltv-netgem/147216c6-8f61-11ee-8f06-e2013c1e3b32/1920x1080_6503200?bcn=1&ca=0&cid=FUNGS-2301&dur=6.000000&media_type=C&redirect_url=https%3A%2F%2Famg01074-fueltv-netgem.amagi.tv%2Fmain_1080_2608678.ts&seg_id=2608678&user_id=147216c6-8f61-11ee-8f06-e2013c1e3b32
#EXTINF:6.000,
/beacon/amg01074-fueltv-netgem/147216c6-8f61-11ee-8f06-e2013c1e3b32/1920x1080_6503200?bcn=1&ca=0&cid=FUNGS-2301&dur=6.000000&media_type=C&redirect_url=https%3A%2F%2Famg01074-fueltv-netgem.amagi.tv%2Fmain_1080_2608679.ts&seg_id=2608679&user_id=147216c6-8f61-11ee-8f06-e2013c1e3b32
#EXTINF:6.000,
/beacon/amg01074-fueltv-netgem/147216c6-8f61-11ee-8f06-e2013c1e3b32/1920x1080_6503200?bcn=1&ca=0&cid=FUNGS-2301&dur=6.000000&media_type=C&redirect_url=https%3A%2F%2Famg01074-fueltv-netgem.amagi.tv%2Fmain_1080_2608680.ts&seg_id=2608680&user_id=147216c6-8f61-11ee-8f06-e2013c1e3b32
#EXTINF:6.000,
/beacon/amg01074-fueltv-netgem/147216c6-8f61-11ee-8f06-e2013c1e3b32/1920x1080_6503200?bcn=1&ca=0&cid=FUNGS-2301&dur=6.000000&media_type=C&redirect_url=https%3A%2F%2Famg01074-fueltv-netgem.amagi.tv%2Fmain_1080_2608681.ts&seg_id=2608681&user_id=147216c6-8f61-11ee-8f06-e2013c1e3b32
#EXTINF:6.000,
/beacon/amg01074-fueltv-netgem/147216c6-8f61-11ee-8f06-e2013c1e3b32/1920x1080_6503200?bcn=1&ca=0&cid=FUNGS-2301&dur=6.000000&media_type=C&redirect_url=https%3A%2F%2Famg01074-fueltv-netgem.amagi.tv%2Fmain_1080_2608682.ts&seg_id=2608682&user_id=147216c6-8f61-11ee-8f06-e2013c1e3b32
#EXTINF:6.000,
/beacon/amg01074-fueltv-netgem/147216c6-8f61-11ee-8f06-e2013c1e3b32/1920x1080_6503200?bcn=1&ca=0&cid=FUNGS-2301&dur=6.000000&media_type=C&redirect_url=https%3A%2F%2Famg01074-fueltv-netgem.amagi.tv%2Fmain_1080_2608683.ts&seg_id=2608683&user_id=147216c6-8f61-11ee-8f06-e2013c1e3b32
#EXTINF:6.000,
/beacon/amg01074-fueltv-netgem/147216c6-8f61-11ee-8f06-e2013c1e3b32/1920x1080_6503200?bcn=1&ca=0&cid=FUNGS-2301&dur=6.000000&media_type=C&redirect_url=https%3A%2F%2Famg01074-fueltv-netgem.amagi.tv%2Fmain_1080_2608684.ts&seg_id=2608684&user_id=147216c6-8f61-11ee-8f06-e2013c1e3b32

Thanks for the quick answer.

Robloche commented 9 months ago

In fact, @avelad, I'd like a little help here, if you can. When I load my manifest in your demo player, a GET request is done, as you can see below:

image

https://shaka-player-demo.appspot.com/demo/#audiolang=fr-FR;textlang=fr-FR;uilang=fr-FR;asset=https://amg01074-fueltv-netgem.amagi.tv/playlist/amg01074-fueltv-netgem/ad15140a-8f80-11ee-89ab-3a7f5f935650/27/1920x1080_6503200/index.m3u8;license=https://dev-vodapi.videofutur.fr/apirest/drm/licenseApplication?token=GCmkQphA8QAMeDKT3f1Qw76ewof2Ggu8KZSXriCTQJWt9oMY%2FV3yIQ%3D%3D&drm=widevine;panel=HOME;build=uncompiled;vv

But in my own app, it's a HEAD request:

image

What's the explanation?

avelad commented 9 months ago

I don't have an explanation for this, maybe @theodab can help here.

Robloche commented 9 months ago

Thanks. I'm using the latest version of the player (v4.6.3).

Robloche commented 9 months ago

My bad...

On the demo page, I was providing the manifest's URL for the representation of highest quality: https://amg01074-fueltv-netgem.amagi.tv/playlist/amg01074-fueltv-netgem/d423e0fe-8f96-11ee-9edc-fa70851de8e1/28/1920x1080_6503200/index.m3u8

But in my app (and it's my use case), I'm providing the playlist's URL: https://cdn-ue1-prod.tsv2.amagi.tv/linear/amg01074-fueltv-netgem/playlist.m3u8?did=c9bda167-2609-f2c3-88d8-81b2cd8332c1&dnt=1&genre=sport&app_bundle=com.netgem.netgemtv&app_name=Netgem+TV&us_privacy=0&gdpr=1&gdpr_consent=0&coppa=0

Which leads to downloading this:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Portuguese",DEFAULT=YES,AUTOSELECT=YES,LANGUAGE="por",URI="d423e0fe-8f96-11ee-9edc-fa70851de8e1/28/subs-portuguese-por/subtitle.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="French",DEFAULT=YES,AUTOSELECT=YES,LANGUAGE="fra",URI="d423e0fe-8f96-11ee-9edc-fa70851de8e1/28/subs-french-fra/subtitle.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Finnish",DEFAULT=YES,AUTOSELECT=YES,LANGUAGE="fin",URI="d423e0fe-8f96-11ee-9edc-fa70851de8e1/28/subs-finnish-fin/subtitle.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Spanish",DEFAULT=YES,AUTOSELECT=YES,LANGUAGE="spa",URI="d423e0fe-8f96-11ee-9edc-fa70851de8e1/28/subs-spanish-spa/subtitle.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="English Closed Captions",DEFAULT=YES,AUTOSELECT=YES,LANGUAGE="eng",URI="d423e0fe-8f96-11ee-9edc-fa70851de8e1/28/subs-english-closed-captions-eng/subtitle.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="German",DEFAULT=YES,AUTOSELECT=YES,LANGUAGE="deu",URI="d423e0fe-8f96-11ee-9edc-fa70851de8e1/28/subs-german-deu/subtitle.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Russian",DEFAULT=YES,AUTOSELECT=YES,LANGUAGE="rus",URI="d423e0fe-8f96-11ee-9edc-fa70851de8e1/28/subs-russian-rus/subtitle.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Swedish",DEFAULT=YES,AUTOSELECT=YES,LANGUAGE="swe",URI="d423e0fe-8f96-11ee-9edc-fa70851de8e1/28/subs-swedish-swe/subtitle.m3u8"
#EXT-X-STREAM-INF:PROGRAM-ID=0,BANDWIDTH=6503200,AVERAGE-BANDWIDTH=6261200,CODECS="avc1.640028,mp4a.40.2",RESOLUTION=1920x1080,SUBTITLES="subs",FRAME-RATE=25.000
d423e0fe-8f96-11ee-9edc-fa70851de8e1/28/1920x1080_6503200/index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=0,BANDWIDTH=4919200,AVERAGE-BANDWIDTH=4611200,CODECS="avc1.64001f,mp4a.40.2",RESOLUTION=1280x720,SUBTITLES="subs",FRAME-RATE=25.000
d423e0fe-8f96-11ee-9edc-fa70851de8e1/28/1280x720_4919200/index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=0,BANDWIDTH=2200000,AVERAGE-BANDWIDTH=2120800,CODECS="avc1.77.30,mp4a.40.2",RESOLUTION=640x360,SUBTITLES="subs",FRAME-RATE=25.000
d423e0fe-8f96-11ee-9edc-fa70851de8e1/28/640x360_2200000/index.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=0,BANDWIDTH=1284800,AVERAGE-BANDWIDTH=1240800,CODECS="avc1.4d4014,mp4a.40.2",RESOLUTION=416x234,SUBTITLES="subs",FRAME-RATE=25.000
d423e0fe-8f96-11ee-9edc-fa70851de8e1/28/416x234_1284800/index.m3u8

In conclusion, giving a playlist causes a HEAD in the end, and a CORS error with the demo app, as well as with my app.

avelad commented 9 months ago

The difference is that when you provide the master playlist, since we have all the information, we only need to make a HEAD to obtain the contentType, but when you provide a half playlist we have to obtain all the information, so we download the entire segment.

Robloche commented 9 months ago

OK, I understand the "why", but now, I need to make it work. 😄

I also found this issue which is very similar to mine: https://github.com/shaka-project/shaka-player/issues/3142

And from what I read, it led to a PR that was merged 2 years ago. But the code has changed a bit since that day, and now, when the HEAD request fails, it seems like the execution simply stops instead of going through guessMimeTypeFallback_() and fallback-ing to mp4.

Shouldn't const response = await this.makeNetworkRequest_(headRequest, requestType, {type}); be inside a try/catch?

avelad commented 9 months ago

@Robloche I created https://github.com/shaka-project/shaka-player/pull/5964 to fix it

Robloche commented 9 months ago

Wow, that was fast! Thanks a lot.

Robloche commented 9 months ago

It works like a charm. Thanks again for your swiftness.

Robloche commented 9 months ago

Sorry to bother you again but it seems like the same behavior is needed here as well: https://github.com/shaka-project/shaka-player/blob/7fd99b7c2663903f3fa3991acfbab3782ddb0e07/lib/net/networking_utils.js#L23-L41

I indeed have another case where the playlist itself doesn't have any extension, and redirects to a a .m3u8 file. In this case, a HEAD request is made, which fails.

avelad commented 9 months ago

@Robloche I created https://github.com/shaka-project/shaka-player/pull/5986 to fix it

Robloche commented 9 months ago

Thank you so much.