Repository: yt-dlp/yt-dlp

Issue:
[Crunchyroll] Does not gives all available subtitles
### Checklist

- [X] I'm reporting a broken site
- [X] I've verified that I'm running yt-dlp version **2022.07.18** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/ytdl-org/youtube-dl#video-url-contains-an-ampersand-and-im-getting-some-strange-output-1-2839-or-v-is-not-recognized-as-an-internal-or-external-command)
- [X] I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues **including closed ones**. DO NOT post duplicates
- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)
- [ ] I've read about [sharing account credentials](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#are-you-willing-to-share-account-details-if-needed) and I'm willing to share it if required

### Region

Brazil

### Provide a description that is worded well enough to be understood

Crunchyroll now forces to use the beta website, but yt-dlp can't find any subtitles other than en-us.

By using `https://beta.crunchyroll.com/watch/G8WUN8VKP/the-ruler-of-conspiracy` as example.

yt-dlp first checks the URL `<API>/cms/v2/BR/M3/crunchyroll/episodes/G8WUN8VKP`

Then it fetches the stream data from `playback` URL in API response.

But looking at where the beta website gets the subtitles list and downloads.

Beta website, get the available streams from endpoint `/cms/v2/BR/M3/crunchyroll/videos/GQ9FG10XZ/streams`.

The above URL is avaiable at `episodes` endpoint, at path `'__links__'->'streams'`

The `streams` endpoint, has all the streams available for the video, and also, the subtitles, check print:

![Screenshot_20220726_160040](https://user-images.githubusercontent.com/2255920/181090049-a7f722ec-5d00-453b-900b-08c618306919.png)

---

I hope that was helpful to implement the missing functionality.


### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
[debug] Command-line config: ['--cookies', '/home/jomp16/cookies.txt', '--list-subs', '--skip-download', '-vU', 'https://beta.crunchyroll.com/watch/G8WUN8VKP/the-ruler-of-conspiracy']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version 2022.07.18 [135f05e]
[debug] Python 3.10.5 (CPython 64bit) - Linux-5.18.14-lqx1-1-lqx-x86_64-with-glibc2.35 (glibc 2.35)
[debug] Checking exe version: ffmpeg -bsfs
[debug] Checking exe version: ffprobe -bsfs
[debug] exe versions: ffmpeg 5.0.1 (setts), ffprobe 5.0.1, rtmpdump 2.4
[debug] Optional libraries: Cryptodome-3.12.0, brotlicffi-1.0.9.2, certifi-2022.06.15, secretstorage-3.3.2, sqlite3-2.6.0
[debug] Proxy map: {}
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: 2022.07.18, Current version: 2022.07.18
yt-dlp is up to date (2022.07.18)
[debug] [crunchyroll:beta] Extracting URL: https://beta.crunchyroll.com/watch/G8WUN8VKP/the-ruler-of-conspiracy
[crunchyroll:beta] Retrieving main page
[crunchyroll:beta] Authenticating with cookie
[crunchyroll:beta] Retrieving signed policy
[crunchyroll:beta] the-ruler-of-conspiracy: Retrieving episode metadata
[crunchyroll:beta] the-ruler-of-conspiracy: Retrieving stream info
[crunchyroll:beta] the-ruler-of-conspiracy: Downloading adaptive_hls information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[info] Available subtitles for G8WUN8VKP:
Language Formats
en-US    ass
```

[Crunchyroll] Does not gives all available subtitles
### Checklist

- [X] I'm reporting a broken site
- [X] I've verified that I'm running yt-dlp version **2022.07.18** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/ytdl-org/youtube-dl#video-url-contains-an-ampersand-and-im-getting-some-strange-output-1-2839-or-v-is-not-recognized-as-an-internal-or-external-command)
- [X] I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues **including closed ones**. DO NOT post duplicates
- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)
- [ ] I've read about [sharing account credentials](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#are-you-willing-to-share-account-details-if-needed) and I'm willing to share it if required

### Region

Brazil

### Provide a description that is worded well enough to be understood

Crunchyroll now forces to use the beta website, but yt-dlp can't find any subtitles other than en-us.

By using `https://beta.crunchyroll.com/watch/G8WUN8VKP/the-ruler-of-conspiracy` as example.

yt-dlp first checks the URL `<API>/cms/v2/BR/M3/crunchyroll/episodes/G8WUN8VKP`

Then it fetches the stream data from `playback` URL in API response.

But looking at where the beta website gets the subtitles list and downloads.

Beta website, get the available streams from endpoint `/cms/v2/BR/M3/crunchyroll/videos/GQ9FG10XZ/streams`.

The above URL is avaiable at `episodes` endpoint, at path `'__links__'->'streams'`

The `streams` endpoint, has all the streams available for the video, and also, the subtitles, check print:

![Screenshot_20220726_160040](https://user-images.githubusercontent.com/2255920/181090049-a7f722ec-5d00-453b-900b-08c618306919.png)

---

I hope that was helpful to implement the missing functionality.


### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
[debug] Command-line config: ['--cookies', '/home/jomp16/cookies.txt', '--list-subs', '--skip-download', '-vU', 'https://beta.crunchyroll.com/watch/G8WUN8VKP/the-ruler-of-conspiracy']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version 2022.07.18 [135f05e]
[debug] Python 3.10.5 (CPython 64bit) - Linux-5.18.14-lqx1-1-lqx-x86_64-with-glibc2.35 (glibc 2.35)
[debug] Checking exe version: ffmpeg -bsfs
[debug] Checking exe version: ffprobe -bsfs
[debug] exe versions: ffmpeg 5.0.1 (setts), ffprobe 5.0.1, rtmpdump 2.4
[debug] Optional libraries: Cryptodome-3.12.0, brotlicffi-1.0.9.2, certifi-2022.06.15, secretstorage-3.3.2, sqlite3-2.6.0
[debug] Proxy map: {}
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: 2022.07.18, Current version: 2022.07.18
yt-dlp is up to date (2022.07.18)
[debug] [crunchyroll:beta] Extracting URL: https://beta.crunchyroll.com/watch/G8WUN8VKP/the-ruler-of-conspiracy
[crunchyroll:beta] Retrieving main page
[crunchyroll:beta] Authenticating with cookie
[crunchyroll:beta] Retrieving signed policy
[crunchyroll:beta] the-ruler-of-conspiracy: Retrieving episode metadata
[crunchyroll:beta] the-ruler-of-conspiracy: Retrieving stream info
[crunchyroll:beta] the-ruler-of-conspiracy: Downloading adaptive_hls information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[info] Available subtitles for G8WUN8VKP:
Language Formats
en-US    ass
```



Discussion:
Crunchyroll now forces to use the beta website, same problems for me for `https://beta.crunchyroll.com/fr/watch/GWDU8WM9J/how-to-have-a-wicked-time-in-jinbocho`
Maybe Crunchyroll has done something, because the exact comand right now gives all availables subtitles.

```
[debug] Command-line config: ['--cookies', '/home/jomp16/cookies.txt', '--list-subs', '--skip-download', '-vU', 'https://beta.crunchyroll.com/watch/G8WUN8VKP/the-ruler-of-conspiracy']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version 2022.07.18 [135f05e]
[debug] Python 3.10.5 (CPython 64bit) - Linux-5.18.14-lqx1-1-lqx-x86_64-with-glibc2.35 (glibc 2.35)
[debug] Checking exe version: ffmpeg -bsfs
[debug] Checking exe version: ffprobe -bsfs
[debug] exe versions: ffmpeg 5.0.1 (setts), ffprobe 5.0.1, rtmpdump 2.4
[debug] Optional libraries: Cryptodome-3.12.0, brotlicffi-1.0.9.2, certifi-2022.06.15, secretstorage-3.3.2, sqlite3-2.6.0
[debug] Proxy map: {}
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: 2022.07.18, Current version: 2022.07.18
yt-dlp is up to date (2022.07.18)
[debug] [crunchyroll:beta] Extracting URL: https://beta.crunchyroll.com/watch/G8WUN8VKP/the-ruler-of-conspiracy
[crunchyroll:beta] Retrieving main page
[crunchyroll:beta] Authenticating with cookie
[crunchyroll:beta] Retrieving signed policy
[crunchyroll:beta] the-ruler-of-conspiracy: Retrieving episode metadata
[crunchyroll:beta] the-ruler-of-conspiracy: Retrieving stream info
[crunchyroll:beta] the-ruler-of-conspiracy: Downloading adaptive_hls information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[info] Available subtitles for G8WUN8VKP:
Language Formats
en-US    ass
pt-BR    ass
ru-RU    ass
es-LA    ass
```
Here again this night :

```
[debug] Command-line config: ['--cookies', 'cookies.txt', '-U', 'https://www.crunchyroll.com/fr/lucifer-and-the-biscuit-hammer/episode-4-asahina-hisame-and-shinonome-hangetsu-852956', '--user-agent', 'Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0', '--write-sub', '--no-download', '--list-subs', '--skip-download', '-vU']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version 2022.07.18 [135f05e] (zip)
[debug] Python 3.9.2 (CPython 64bit) - Linux-4.19.0-18-amd64-x86_64-with-glibc2.31 (glibc 2.31)
[debug] Checking exe version: ffmpeg -bsfs
[debug] Checking exe version: ffprobe -bsfs
[debug] exe versions: ffmpeg N-105731-gb14321e307 (fdk,setts), ffprobe N-105731-gb14321e307
[debug] Optional libraries: Crypto-3.14.1, certifi-2020.06.20, sqlite3-2.6.0
[debug] Proxy map: {}
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: 2022.07.18, Current version: 2022.07.18
yt-dlp is up to date (2022.07.18)
[debug] [crunchyroll] Extracting URL: https://www.crunchyroll.com/fr/lucifer-and-the-biscuit-hammer/episode-4-asahina-hisame-and-shinonome-hangetsu-852956
[crunchyroll] 852956: Downloading webpage
[crunchyroll] 852956: Redirected to beta site - https://beta.crunchyroll.com/watch/GN7UD9J3Q/asahina-hisame-and-shinonome-hangetsu
[debug] [crunchyroll:beta] Extracting URL: https://beta.crunchyroll.com/watch/GN7UD9J3Q/asahina-hisame-and-shinonome-hangetsu
[crunchyroll:beta] Retrieving main page
[crunchyroll:beta] Authenticating with cookie
[crunchyroll:beta] Retrieving signed policy
[crunchyroll:beta] asahina-hisame-and-shinonome-hangetsu: Retrieving episode metadata
[crunchyroll:beta] asahina-hisame-and-shinonome-hangetsu: Retrieving stream info
[crunchyroll:beta] asahina-hisame-and-shinonome-hangetsu: Downloading adaptive_hls information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Downloading subtitles: en-US
[info] Available subtitles for GN7UD9J3Q:
Language Formats
en-US    ass
```

but on the website : https://i.imgur.com/R1VlWfA.png
@ArturiaPendragon and now the same command lists all available subtitles.

Maybe Crunchyroll is releasing the incomplete playback stream and then later releasing the subtitles as an alternative stream, and then later merging them into one stream.

I think that YT-DLP should use the `/cms/v2/[...]/videos/<ID>/streams` listed above, that the player uses to list all the available subtitles and hardcoded videos instead of getting the single, playback stream URL that at times doesn't have all the subtitles available.
@jomp16 Yes I think that's probably it, and yes taking `/cms/v2/[...]/videos/<ID>/streams` would be a good idea to get the subtitles directly without waiting sometimes several days for them to realize it.
@tejing1
I could never see any difference between the `playback` url and the `streams` url in testing, but perhaps the difference only appears in non-US regions? Or else the difference is rare and just a result of failure to invalidate a cache somewhere, given that the playback url is hosted on a different server?

Anyway, iirc the data returned by `streams` isn't in quite the same format, so it'd be a bit of work to change it. I should have some time to look into it soon.
According to @jomp16's theory, the difference exists only for new releases
Hmm, the schema is actually close enough to not need to change the code, however the available streams are surprisingly different, given what I remember from when I was writing the extractor. At least for the specific video I'm looking at, the `adaptive_hls` streams look the same, but there are other differences.

Here's a diff of the `gron | grep '= {};'` output:
```
2c2,5
< json.QoS = {};
---
> json.__actions__ = {};
> json.__links__ = {};
> json.__links__.resource = {};
> json.captions = {};
15a19,20
> json.streams.download_dash = {};
> json.streams.download_dash[""] = {};
18,21d22
< json.streams.download_hls["en-US"] = {};
< json.streams.download_hls["es-LA"] = {};
< json.streams.download_hls["pt-BR"] = {};
< json.streams.download_hls["ru-RU"] = {};
33a35,36
> json.streams.drm_download_dash = {};
> json.streams.drm_download_dash[""] = {};
36,51c39,52
< json.streams.drm_download_hls["en-US"] = {};
< json.streams.drm_download_hls["es-LA"] = {};
< json.streams.drm_download_hls["pt-BR"] = {};
< json.streams.drm_download_hls["ru-RU"] = {};
< json.streams.trailer_dash = {};
< json.streams.trailer_dash[""] = {};
< json.streams.trailer_dash["en-US"] = {};
< json.streams.trailer_dash["es-LA"] = {};
< json.streams.trailer_dash["pt-BR"] = {};
< json.streams.trailer_dash["ru-RU"] = {};
< json.streams.trailer_hls = {};
< json.streams.trailer_hls[""] = {};
< json.streams.trailer_hls["en-US"] = {};
< json.streams.trailer_hls["es-LA"] = {};
< json.streams.trailer_hls["pt-BR"] = {};
< json.streams.trailer_hls["ru-RU"] = {};
---
> json.streams.drm_multitrack_adaptive_hls_v2 = {};
> json.streams.drm_multitrack_adaptive_hls_v2[""] = {};
> json.streams.drm_multitrack_adaptive_hls_v2["en-US"] = {};
> json.streams.drm_multitrack_adaptive_hls_v2["es-LA"] = {};
> json.streams.drm_multitrack_adaptive_hls_v2["pt-BR"] = {};
> json.streams.drm_multitrack_adaptive_hls_v2["ru-RU"] = {};
> json.streams.multitrack_adaptive_hls_v2 = {};
> json.streams.multitrack_adaptive_hls_v2[""] = {};
> json.streams.multitrack_adaptive_hls_v2["en-US"] = {};
> json.streams.multitrack_adaptive_hls_v2["es-LA"] = {};
> json.streams.multitrack_adaptive_hls_v2["pt-BR"] = {};
> json.streams.multitrack_adaptive_hls_v2["ru-RU"] = {};
> json.streams.urls = {};
> json.streams.urls[""] = {};
```
`(drm_)?download_hls` loses hardsub versions, `(drm_)?download_dash` appears, `trailer_.+` disappears, and `(drm_)?multitrack_adaptive_hls_v2` appears. Also `urls`, which seems to be completely useless.

Given that probably very few, if any, people are using anything other than the default, `adaptive_hls`, and maybe occasionally `adaptive_dash`, it's probably the right move to change over, especially since that is indeed the endpoint the browser uses, but I guess I should change the "potentially useful values" listed in the docs for the `format` extractor arg.
Crunchyroll now forces to use the beta website, same problems for me for `https://beta.crunchyroll.com/fr/watch/GWDU8WM9J/how-to-have-a-wicked-time-in-jinbocho`
Maybe Crunchyroll has done something, because the exact comand right now gives all availables subtitles.

```
[debug] Command-line config: ['--cookies', '/home/jomp16/cookies.txt', '--list-subs', '--skip-download', '-vU', 'https://beta.crunchyroll.com/watch/G8WUN8VKP/the-ruler-of-conspiracy']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version 2022.07.18 [135f05e]
[debug] Python 3.10.5 (CPython 64bit) - Linux-5.18.14-lqx1-1-lqx-x86_64-with-glibc2.35 (glibc 2.35)
[debug] Checking exe version: ffmpeg -bsfs
[debug] Checking exe version: ffprobe -bsfs
[debug] exe versions: ffmpeg 5.0.1 (setts), ffprobe 5.0.1, rtmpdump 2.4
[debug] Optional libraries: Cryptodome-3.12.0, brotlicffi-1.0.9.2, certifi-2022.06.15, secretstorage-3.3.2, sqlite3-2.6.0
[debug] Proxy map: {}
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: 2022.07.18, Current version: 2022.07.18
yt-dlp is up to date (2022.07.18)
[debug] [crunchyroll:beta] Extracting URL: https://beta.crunchyroll.com/watch/G8WUN8VKP/the-ruler-of-conspiracy
[crunchyroll:beta] Retrieving main page
[crunchyroll:beta] Authenticating with cookie
[crunchyroll:beta] Retrieving signed policy
[crunchyroll:beta] the-ruler-of-conspiracy: Retrieving episode metadata
[crunchyroll:beta] the-ruler-of-conspiracy: Retrieving stream info
[crunchyroll:beta] the-ruler-of-conspiracy: Downloading adaptive_hls information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[info] Available subtitles for G8WUN8VKP:
Language Formats
en-US    ass
pt-BR    ass
ru-RU    ass
es-LA    ass
```
Here again this night :

```
[debug] Command-line config: ['--cookies', 'cookies.txt', '-U', 'https://www.crunchyroll.com/fr/lucifer-and-the-biscuit-hammer/episode-4-asahina-hisame-and-shinonome-hangetsu-852956', '--user-agent', 'Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0', '--write-sub', '--no-download', '--list-subs', '--skip-download', '-vU']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version 2022.07.18 [135f05e] (zip)
[debug] Python 3.9.2 (CPython 64bit) - Linux-4.19.0-18-amd64-x86_64-with-glibc2.31 (glibc 2.31)
[debug] Checking exe version: ffmpeg -bsfs
[debug] Checking exe version: ffprobe -bsfs
[debug] exe versions: ffmpeg N-105731-gb14321e307 (fdk,setts), ffprobe N-105731-gb14321e307
[debug] Optional libraries: Crypto-3.14.1, certifi-2020.06.20, sqlite3-2.6.0
[debug] Proxy map: {}
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: 2022.07.18, Current version: 2022.07.18
yt-dlp is up to date (2022.07.18)
[debug] [crunchyroll] Extracting URL: https://www.crunchyroll.com/fr/lucifer-and-the-biscuit-hammer/episode-4-asahina-hisame-and-shinonome-hangetsu-852956
[crunchyroll] 852956: Downloading webpage
[crunchyroll] 852956: Redirected to beta site - https://beta.crunchyroll.com/watch/GN7UD9J3Q/asahina-hisame-and-shinonome-hangetsu
[debug] [crunchyroll:beta] Extracting URL: https://beta.crunchyroll.com/watch/GN7UD9J3Q/asahina-hisame-and-shinonome-hangetsu
[crunchyroll:beta] Retrieving main page
[crunchyroll:beta] Authenticating with cookie
[crunchyroll:beta] Retrieving signed policy
[crunchyroll:beta] asahina-hisame-and-shinonome-hangetsu: Retrieving episode metadata
[crunchyroll:beta] asahina-hisame-and-shinonome-hangetsu: Retrieving stream info
[crunchyroll:beta] asahina-hisame-and-shinonome-hangetsu: Downloading adaptive_hls information
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), acodec, filesize, fs_approx, tbr, vbr, abr, asr, proto, vext, aext, hasaud, source, id
[debug] Downloading subtitles: en-US
[info] Available subtitles for GN7UD9J3Q:
Language Formats
en-US    ass
```

but on the website : https://i.imgur.com/R1VlWfA.png
@ArturiaPendragon and now the same command lists all available subtitles.

Maybe Crunchyroll is releasing the incomplete playback stream and then later releasing the subtitles as an alternative stream, and then later merging them into one stream.

I think that YT-DLP should use the `/cms/v2/[...]/videos/<ID>/streams` listed above, that the player uses to list all the available subtitles and hardcoded videos instead of getting the single, playback stream URL that at times doesn't have all the subtitles available.
@jomp16 Yes I think that's probably it, and yes taking `/cms/v2/[...]/videos/<ID>/streams` would be a good idea to get the subtitles directly without waiting sometimes several days for them to realize it.
@tejing1
I could never see any difference between the `playback` url and the `streams` url in testing, but perhaps the difference only appears in non-US regions? Or else the difference is rare and just a result of failure to invalidate a cache somewhere, given that the playback url is hosted on a different server?

Anyway, iirc the data returned by `streams` isn't in quite the same format, so it'd be a bit of work to change it. I should have some time to look into it soon.
According to @jomp16's theory, the difference exists only for new releases
Hmm, the schema is actually close enough to not need to change the code, however the available streams are surprisingly different, given what I remember from when I was writing the extractor. At least for the specific video I'm looking at, the `adaptive_hls` streams look the same, but there are other differences.

Here's a diff of the `gron | grep '= {};'` output:
```
2c2,5
< json.QoS = {};
---
> json.__actions__ = {};
> json.__links__ = {};
> json.__links__.resource = {};
> json.captions = {};
15a19,20
> json.streams.download_dash = {};
> json.streams.download_dash[""] = {};
18,21d22
< json.streams.download_hls["en-US"] = {};
< json.streams.download_hls["es-LA"] = {};
< json.streams.download_hls["pt-BR"] = {};
< json.streams.download_hls["ru-RU"] = {};
33a35,36
> json.streams.drm_download_dash = {};
> json.streams.drm_download_dash[""] = {};
36,51c39,52
< json.streams.drm_download_hls["en-US"] = {};
< json.streams.drm_download_hls["es-LA"] = {};
< json.streams.drm_download_hls["pt-BR"] = {};
< json.streams.drm_download_hls["ru-RU"] = {};
< json.streams.trailer_dash = {};
< json.streams.trailer_dash[""] = {};
< json.streams.trailer_dash["en-US"] = {};
< json.streams.trailer_dash["es-LA"] = {};
< json.streams.trailer_dash["pt-BR"] = {};
< json.streams.trailer_dash["ru-RU"] = {};
< json.streams.trailer_hls = {};
< json.streams.trailer_hls[""] = {};
< json.streams.trailer_hls["en-US"] = {};
< json.streams.trailer_hls["es-LA"] = {};
< json.streams.trailer_hls["pt-BR"] = {};
< json.streams.trailer_hls["ru-RU"] = {};
---
> json.streams.drm_multitrack_adaptive_hls_v2 = {};
> json.streams.drm_multitrack_adaptive_hls_v2[""] = {};
> json.streams.drm_multitrack_adaptive_hls_v2["en-US"] = {};
> json.streams.drm_multitrack_adaptive_hls_v2["es-LA"] = {};
> json.streams.drm_multitrack_adaptive_hls_v2["pt-BR"] = {};
> json.streams.drm_multitrack_adaptive_hls_v2["ru-RU"] = {};
> json.streams.multitrack_adaptive_hls_v2 = {};
> json.streams.multitrack_adaptive_hls_v2[""] = {};
> json.streams.multitrack_adaptive_hls_v2["en-US"] = {};
> json.streams.multitrack_adaptive_hls_v2["es-LA"] = {};
> json.streams.multitrack_adaptive_hls_v2["pt-BR"] = {};
> json.streams.multitrack_adaptive_hls_v2["ru-RU"] = {};
> json.streams.urls = {};
> json.streams.urls[""] = {};
```
`(drm_)?download_hls` loses hardsub versions, `(drm_)?download_dash` appears, `trailer_.+` disappears, and `(drm_)?multitrack_adaptive_hls_v2` appears. Also `urls`, which seems to be completely useless.

Given that probably very few, if any, people are using anything other than the default, `adaptive_hls`, and maybe occasionally `adaptive_dash`, it's probably the right move to change over, especially since that is indeed the endpoint the browser uses, but I guess I should change the "potentially useful values" listed in the docs for the `format` extractor arg.

Resolving patch:
diff --git a/yt_dlp/extractor/crunchyroll.py b/yt_dlp/extractor/crunchyroll.py
--- a/yt_dlp/extractor/crunchyroll.py
+++ b/yt_dlp/extractor/crunchyroll.py
@@ -801,7 +801,9 @@ def _real_extract(self, url):
         if episode_response.get('is_premium_only') and not episode_response.get('playback'):
             raise ExtractorError('This video is for premium members only.', expected=True)
 
-        stream_response = self._download_json(episode_response['playback'], display_id, note='Retrieving stream info')
+        stream_response = self._download_json(
+            f'{api_domain}{episode_response["__links__"]["streams"]["href"]}', display_id,
+            note='Retrieving stream info', query=params)
         get_streams = lambda name: (traverse_obj(stream_response, name) or {}).items()
 
         requested_hardsubs = [('' if val == 'none' else val) for val in (self._configuration_arg('hardsub') or ['none'])]


Test patch: