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

Code before:
        if live_status:
            info_dict['live_status'] = live_status
            for key in live_keys:
                if info_dict.get(key) is None:
                    info_dict[key] = (live_status == key)
        if live_status == 'post_live':
            info_dict['was_live'] = True

        # Auto generate title fields corresponding to the *_number fields when missing
        # in order to always have clean titles. This is very common for TV series.
        for field in ('chapter', 'season', 'episode'):
            if final and info_dict.get('%s_number' % field) is not None and not info_dict.get(field):
                info_dict[field] = '%s %d' % (field.capitalize(), info_dict['%s_number' % field])

        multivalue_fields = {
            'album_artist': 'album_artists',
            'artist': 'artists',
            'composer': 'composers',
            'creator': 'creators',
            'genre': 'genres',
        }
        for old_key, new_key in multivalue_fields.items():
            if old_value := info_dict.get(old_key):
                info_dict[new_key] = re.split(r', ?', old_value)
            elif new_value := info_dict.get(new_key):
                info_dict[old_key] = ', '.join(new_value)

    def _raise_pending_errors(self, info):
        err = info.pop('__pending_error', None)
        if err:
            self.report_error(err, tb=False)

    def sort_formats(self, info_dict):
        formats = self._get_formats(info_dict)
        formats.sort(key=FormatSorter(
            self, info_dict.get('_format_sort_fields') or []).calculate_preference)

    def process_video_result(self, info_dict, download=True):
        assert info_dict.get('_type', 'video') == 'video'
        self._num_videos += 1

        if 'id' not in info_dict:
            raise ExtractorError('Missing "id" field in extractor result', ie=info_dict['extractor'])
        elif not info_dict.get('id'):
            raise ExtractorError('Extractor failed to obtain "id"', ie=info_dict['extractor'])

        def report_force_conversion(field, field_not, conversion):
            self.report_warning(
                '"%s" field is not %s - forcing %s conversion, there is an error in extractor'
                % (field, field_not, conversion))


Review comment (suggestion):
We could perhaps do (remove space):
```suggestion
                info_dict[old_key] = ', '.join(re.replace(', +', ',', v) for v in new_value)
```
or maybe (unicode):
```suggestion
                info_dict[old_key] = ', '.join(v.replace(', ', '， ') for v in new_value)
```

as partial workaround to https://github.com/yt-dlp/yt-dlp/issues/3944#issuecomment-1686854709 for those who don't have mutagen

Opinions?

We don't have to do it in this PR. Just asking

Code after:
                if info_dict.get(key) is False:
                    continue
                if info_dict.get(key):
                    live_status = key
                break
            if all(info_dict.get(key) is False for key in live_keys):
                live_status = 'not_live'
        if live_status:
            info_dict['live_status'] = live_status
            for key in live_keys:
                if info_dict.get(key) is None:
                    info_dict[key] = (live_status == key)
        if live_status == 'post_live':
            info_dict['was_live'] = True

        # Auto generate title fields corresponding to the *_number fields when missing
        # in order to always have clean titles. This is very common for TV series.
        for field in ('chapter', 'season', 'episode'):
            if final and info_dict.get('%s_number' % field) is not None and not info_dict.get(field):
                info_dict[field] = '%s %d' % (field.capitalize(), info_dict['%s_number' % field])

        for old_key, new_key in self._deprecated_multivalue_fields.items():
            if new_key in info_dict and old_key in info_dict:
                self.deprecation_warning(f'Do not return {old_key!r} when {new_key!r} is present')
            elif old_value := info_dict.get(old_key):
                info_dict[new_key] = old_value.split(', ')
            elif new_value := info_dict.get(new_key):
                info_dict[old_key] = ', '.join(v.replace(',', '\N{FULLWIDTH COMMA}') for v in new_value)

    def _raise_pending_errors(self, info):
        err = info.pop('__pending_error', None)
        if err:
            self.report_error(err, tb=False)

    def sort_formats(self, info_dict):
        formats = self._get_formats(info_dict)
        formats.sort(key=FormatSorter(
            self, info_dict.get('_format_sort_fields') or []).calculate_preference)

    def process_video_result(self, info_dict, download=True):
        assert info_dict.get('_type', 'video') == 'video'
        self._num_videos += 1

        if 'id' not in info_dict:
            raise ExtractorError('Missing "id" field in extractor result', ie=info_dict['extractor'])
        elif not info_dict.get('id'):
            raise ExtractorError('Extractor failed to obtain "id"', ie=info_dict['extractor'])

        def report_force_conversion(field, field_not, conversion):
            self.report_warning(
                '"%s" field is not %s - forcing %s conversion, there is an error in extractor'