Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/crunchyroll.py (Python)

Code before:
        hardsub_preference = qualities((requested_hardsubs or ['', traverse_obj(initial_state, ('localization', 'locale')) or ''])[::-1])

        formats = []
        for stream_type, streams in stream_response.get('streams', {}).items():
            if stream_type in ('adaptive_hls'):
                for stream in streams.values():
                    format_id = join_nonempty(
                        stream_type,
                        'audio-%s' % stream_response.get('audio_locale'),
                        stream.get('hardsub_locale') and 'hardsub-%s' % stream.get('hardsub_locale'))
                    if stream_type.split('_')[-1] == 'hls':
                        adaptive_formats = self._extract_m3u8_formats(
                            stream.get('url'), display_id, 'mp4', m3u8_id=format_id,
                            note='Downloading %s information' % format_id,
                            fatal=False)
                    elif stream_type.split('_')[-1] == 'dash':
                        adaptive_formats = self._extract_mpd_formats(
                            stream.get('url'), display_id, mpd_id=format_id,
                            note='Downloading %s information' % format_id,
                            fatal=False)
                    for f in adaptive_formats:
                        if f.get('acodec') != 'none':
                            f['language'] = stream_response.get('audio_locale')
                        f['language_preference'] = language_preference(stream_response.get('audio_locale'))
                        f['quality'] = hardsub_preference(stream.get('hardsub_locale'))
                    formats.extend(adaptive_formats)
        self._sort_formats(formats)

        return {
            'id': internal_id,
            'title': episode_response.get('season_title') + ' Episode ' + episode_response.get('episode') + ' – ' + episode_response.get('title'),
            'description': episode_response.get('description').replace(r'\r\n', '\n'),
            'duration': float_or_none(episode_response.get('duration_ms'), 1000),
            'thumbnails': thumbnails,
            'series': episode_response.get('series_title'),
            'series_id': episode_response.get('series_id'),
            'season': episode_response.get('season_title'),
            'season_id': episode_response.get('season_id'),
            'season_number': episode_response.get('season_number'),
            'episode': episode_response.get('title'),
            'episode_number': episode_response.get('episode_number'),
            'subtitles': subtitles,
            'formats': formats
        }


class CrunchyrollBetaShowIE(CrunchyrollBaseIE):
    IE_NAME = 'crunchyroll:playlist:beta'
    _VALID_URL = r'https?://beta\.crunchyroll\.com/(?P<lang>(?:\w{1,2}/)?)series/\w+/(?P<id>[\w\-]+)/?(?:\?|$)'
    _TESTS = [{
        'url': 'https://beta.crunchyroll.com/series/GY19NQ2QR/Girl-Friend-BETA',

Review comment (bug):
same as
```py
		streams = stream_response['streams']['adaptive_hls']
        for stream in streams.values():
            ...
```
Or, if you want to add more keys to `adaptive_hls`
```py
		for stream_type, streams in stream_response['streams']:
		    if stream_type not in ('adaptive_hls', ):
		        continue
            for stream in streams.values():
                ...
```
(I didnt bother with making `stream_response['streams']['adaptive_hls']` non-fatal coz if that doesnt exist, extraction will fail anyways)

Code after:
            }]

        requested_hardsubs = [('' if val == 'none' else val) for val in (self._configuration_arg('hardsub') or ['none'])]
        hardsub_preference = qualities(requested_hardsubs[::-1])
        requested_formats = self._configuration_arg('format') or ['adaptive_hls']

        formats = []
        for stream_type, streams in stream_response.get('streams', {}).items():
            if stream_type not in requested_formats:
                continue
            for stream in streams.values():
                hardsub_lang = stream.get('hardsub_locale') or ''
                if hardsub_lang.lower() not in requested_hardsubs:
                    continue
                format_id = join_nonempty(
                    stream_type,
                    format_field(stream, 'hardsub_locale', 'hardsub-%s'))
                if not stream.get('url'):
                    continue
                if stream_type.split('_')[-1] == 'hls':
                    adaptive_formats = self._extract_m3u8_formats(
                        stream['url'], display_id, 'mp4', m3u8_id=format_id,
                        note='Downloading %s information' % format_id,
                        fatal=False)
                elif stream_type.split('_')[-1] == 'dash':
                    adaptive_formats = self._extract_mpd_formats(
                        stream['url'], display_id, mpd_id=format_id,
                        note='Downloading %s information' % format_id,
                        fatal=False)
                for f in adaptive_formats:
                    if f.get('acodec') != 'none':
                        f['language'] = stream_response.get('audio_locale')
                    f['quality'] = hardsub_preference(hardsub_lang.lower())
                formats.extend(adaptive_formats)
        self._sort_formats(formats)

        return {
            'id': internal_id,
            'title': '%s Episode %s – %s' % (episode_response.get('season_title'), episode_response.get('episode'), episode_response.get('title')),
            'description': episode_response.get('description').replace(r'\r\n', '\n'),
            'duration': float_or_none(episode_response.get('duration_ms'), 1000),
            'thumbnails': thumbnails,
            'series': episode_response.get('series_title'),
            'series_id': episode_response.get('series_id'),
            'season': episode_response.get('season_title'),
            'season_id': episode_response.get('season_id'),
            'season_number': episode_response.get('season_number'),
            'episode': episode_response.get('title'),
            'episode_number': episode_response.get('sequence_number'),
            'subtitles': subtitles,
            'formats': formats