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

Code before:
    _TITLE_RE = re.compile('(?P<title>.*?)<[^>]+>(?P<series>[^<]*)')

    def _parse_vue_attributes(self, name, string, video_id):
        attributes = extract_attributes(self._search_regex(rf'(<{name}(?:"[^"]*?"|[^>])*>)', string, name))

        for key, value in attributes.items():
            if key.startswith(':'):
                attributes[key] = self._parse_json(value, video_id, transform_source=js_to_json, fatal=False)

        return attributes

    @staticmethod
    def _process_source(source):
        url = url_or_none(source['src'])
        if not url:
            return None

        source_type = source.get('type', '')
        extension = mimetype2ext(source_type)
        note = url.rpartition('.')[0].rpartition('_')[2] if source_type.startswith('video') else None
        return {
            'url': url,
            'ext': extension,
            'quality': 10 if note == 'high' else 0,
            'format_note': note,
            'format_id': join_nonempty(extension, note),
        }

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)

        title_result = traverse_obj(webpage, ({html_get_element(cls='opening-header__title')}, {self._TITLE_RE.match}))
        json_lds = list(self._yield_json_ld(webpage, video_id, fatal=False))

        return {
            'id': video_id,
            'title': traverse_obj(title_result, ('title', {str.strip})) or None,
            # This metadata could be interpreted otherwise, but it fits "series" the most
            'series': traverse_obj(title_result, ('series', {str.strip})) or None,
            'description': join_nonempty(*traverse_obj(webpage, [(
                {html_get_element(cls='opening-intro')},
                [{html_get_element(tag='bpb-accordion-item')}, {html_get_element(cls='text-content')}],
            ), {clean_html}]), delim='\n\n') or None,
            'creator': self._html_search_meta('author', webpage),
            'uploader': self._html_search_meta('publisher', webpage),
            'release_date': unified_strdate(self._html_search_meta('date', webpage)),
            'tags': traverse_obj(json_lds, (..., 'keywords', {lambda x: x.split(',')}, ...)),
            **traverse_obj(self._parse_vue_attributes('bpb-player', webpage, video_id), {
                'formats': (':sources', ..., {self._process_source}),
                'thumbnail': ('poster', {lambda x: urljoin(self.BASE_URL, x)}),

Review comment (suggestion):
`'vcodec': 'none'` if audio
```suggestion
        source_type = source.get('type', '')
        is_video = source_type.startswith('video')
        extension = mimetype2ext(source_type)
        note = url.rpartition('.')[0].rpartition('_')[2] if is_video else None
        return {
            'url': url,
            'ext': extension,
            'vcodec': None if is_video else 'none',
            'quality': 10 if note == 'high' else 0,
            'format_note': note,
            'format_id': join_nonempty(extension, note),
```

Code after:

    def _parse_vue_attributes(self, name, string, video_id):
        attributes = extract_attributes(self._search_regex(rf'(<{name}(?:"[^"]*?"|[^>])*>)', string, name))

        for key, value in attributes.items():
            if key.startswith(':'):
                attributes[key] = self._parse_json(value, video_id, transform_source=js_to_json, fatal=False)

        return attributes

    @staticmethod
    def _process_source(source):
        url = url_or_none(source['src'])
        if not url:
            return None

        source_type = source.get('type', '')
        extension = mimetype2ext(source_type)
        is_video = source_type.startswith('video')
        note = url.rpartition('.')[0].rpartition('_')[2] if is_video else None

        return {
            'url': url,
            'ext': extension,
            'vcodec': None if is_video else 'none',
            'quality': 10 if note == 'high' else 0,
            'format_note': note,
            'format_id': join_nonempty(extension, note),
        }

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)

        title_result = traverse_obj(webpage, ({html_get_element(cls='opening-header__title')}, {self._TITLE_RE.match}))
        json_lds = list(self._yield_json_ld(webpage, video_id, fatal=False))

        return {
            'id': video_id,
            'title': traverse_obj(title_result, ('title', {str.strip})) or None,
            # This metadata could be interpreted otherwise, but it fits "series" the most
            'series': traverse_obj(title_result, ('series', {str.strip})) or None,
            'description': join_nonempty(*traverse_obj(webpage, [(
                {html_get_element(cls='opening-intro')},
                [{html_get_element(tag='bpb-accordion-item')}, {html_get_element(cls='text-content')}],
            ), {clean_html}]), delim='\n\n') or None,
            'creator': self._html_search_meta('author', webpage),
            'uploader': self._html_search_meta('publisher', webpage),
            'release_date': unified_strdate(self._html_search_meta('date', webpage)),
            'tags': traverse_obj(json_lds, (..., 'keywords', {lambda x: x.split(',')}, ...)),
            **traverse_obj(self._parse_vue_attributes('bpb-player', webpage, video_id), {