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

Code before:
            'locale': traverse_obj(initial_state, ('localization', 'locale'))
        }
        episode_response = self._download_json(
            api_domain + '/cms/v2' + bucket + '/episodes/' + internal_id, display_id,
            note='Retrieving episode metadata',
            query=params)
        stream_response = self._download_json(
            episode_response.get('playback'), display_id,
            note='Retrieving stream info')

        thumbnails = []
        for thumbnails_data in traverse_obj(episode_response, ('images', 'thumbnail')):
            for thumbnail_data in thumbnails_data:
                thumbnails.append({
                    'url': thumbnail_data.get('source'),
                    'width': thumbnail_data.get('width'),
                    'height': thumbnail_data.get('height'),
                })
        subtitles = {}
        for lang, subtitle_data in stream_response.get('subtitles').items():
            subtitles[lang] = [{
                'url': subtitle_data.get('url'),
                'ext': subtitle_data.get('format')
            }]

        requested_languages = self._configuration_arg('language')
        requested_hardsubs = [('' if val == 'none' else val) for val in self._configuration_arg('hardsub')]
        language_preference = qualities((requested_languages or [traverse_obj(initial_state, ('localization', 'locale')) or ''])[::-1])
        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')

Review comment (suggestion):
Either document the configuration args in README or imo just take it from crunchyroll
```suggestion
        requested_languages = self._configuration_arg('language', ie_key=CrunchyrollIE.ie_key())
```
same for subs

Code after:
            'Key-Pair-Id': policy_response['cms']['key_pair_id']
        }
        locale = traverse_obj(initial_state, ('localization', 'locale'))
        if locale:
            params['locale'] = locale
        episode_response = self._download_json(
            f'{api_domain}/cms/v2{bucket}/episodes/{internal_id}', display_id,
            note='Retrieving episode metadata',
            query=params)
        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')

        thumbnails = []
        for thumbnails_data in traverse_obj(episode_response, ('images', 'thumbnail')):
            for thumbnail_data in thumbnails_data:
                thumbnails.append({
                    'url': thumbnail_data.get('source'),
                    'width': thumbnail_data.get('width'),
                    'height': thumbnail_data.get('height'),
                })
        subtitles = {}
        for lang, subtitle_data in stream_response.get('subtitles').items():
            subtitles[lang] = [{
                'url': subtitle_data.get('url'),
                'ext': subtitle_data.get('format')
            }]

        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,