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

Code before:
            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')
                        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'),

Review comment (suggestion):
```suggestion
                    format_id = join_nonempty(
                        stream_type,
                        format_field(stream_response, 'audio_locale', 'audio-%s'),
                        format_field(stream_response, 'hardsub_locale', 'hardsub-%s'))
```

Code after:
            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,
                        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)