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

Code before:
            'https://www.rtbf.be/auvio/embed/' + ('direct' if live else 'media'),
            media_id, query={'id': media_id})

        media_data = self._html_search_regex(r'data-media="([^"]+)"', embed_page, 'media data', fatal=False)
        if not media_data:
            if re.findall(r'<div[^>]+id="[^"]*js-error-expired[^"]*"[^>]+class="(?![^"]*hidden)', embed_page):
                raise ExtractorError('Livestream has ended.', expected=True)
            if re.findall(r'<div[^>]+id="[^"]*js-sso-connect[^"]*"[^>]+class="(?![^"]*hidden)', embed_page):
                self.raise_login_required()

            raise ExtractorError('Could not find media data')

        data = self._parse_json(media_data, media_id, fatal=False)

        error = data.get('error')
        if error:
            raise ExtractorError('%s said: %s' % (self.IE_NAME, error), expected=True)

        provider = data.get('provider')
        if provider in self._PROVIDERS:
            return self.url_result(data['url'], self._PROVIDERS[provider])

        # In general, we prefer the 'subtitle' because it's a lot more specific than the 'title',
        # but we need to fallback to 'title' in case 'subtitle' doesn't exist, like for livestreams.
        # https://github.com/yt-dlp/yt-dlp/issues/4656
        title = data.get('subtitle') or data['title']
        is_live = data.get('isLive')
        height_re = r'-(\d+)p\.'
        formats, subtitles = [], {}

        m3u8_url = data.get('urlHlsAes128') or data.get('urlHls')
        # The old api still returns m3u8 and mpd manifest for livestreams, but these are 'fake'
        # since all they contain is a 20s video that is completely unrelated.
        # https://github.com/yt-dlp/yt-dlp/issues/4656#issuecomment-1214461092
        if not is_live:
            if m3u8_url:
                fmts, subs = self._extract_m3u8_formats_and_subtitles(
                    m3u8_url, media_id, 'mp4', m3u8_id='hls', fatal=False)
                formats.extend(fmts)
                self._merge_subtitles(subs, target=subtitles)

            fix_url = lambda x: x.replace('//rtbf-vod.', '//rtbf.') if '/geo/drm/' in x else x
            http_url = data.get('url')
            if formats and http_url and re.search(height_re, http_url):
                http_url = fix_url(http_url)
                for m3u8_f in formats[:]:
                    height = m3u8_f.get('height')
                    if not height:
                        continue
                    f = m3u8_f.copy()
                    del f['protocol']

Review comment (suggestion):
```suggestion
        title = traverse_obj(data, 'subtitle', 'title')
```

Code after:
        embed_page = self._download_webpage(
            'https://www.rtbf.be/auvio/embed/' + ('direct' if live else 'media'),
            media_id, query={'id': media_id})

        media_data = self._html_search_regex(r'data-media="([^"]+)"', embed_page, 'media data', fatal=False)
        if not media_data:
            if re.search(r'<div[^>]+id="js-error-expired"[^>]+class="(?![^"]*hidden)', embed_page):
                raise ExtractorError('Livestream has ended.', expected=True)
            if re.search(r'<div[^>]+id="js-sso-connect"[^>]+class="(?![^"]*hidden)', embed_page):
                self.raise_login_required()

            raise ExtractorError('Could not find media data')

        data = self._parse_json(media_data, media_id)

        error = data.get('error')
        if error:
            raise ExtractorError('%s said: %s' % (self.IE_NAME, error), expected=True)

        provider = data.get('provider')
        if provider in self._PROVIDERS:
            return self.url_result(data['url'], self._PROVIDERS[provider])

        title = traverse_obj(data, 'subtitle', 'title')
        is_live = data.get('isLive')
        height_re = r'-(\d+)p\.'
        formats, subtitles = [], {}

        # The old api still returns m3u8 and mpd manifest for livestreams, but these are 'fake'
        # since all they contain is a 20s video that is completely unrelated.
        # https://github.com/yt-dlp/yt-dlp/issues/4656#issuecomment-1214461092
        m3u8_url = None if data.get('isLive') else traverse_obj(data, 'urlHlsAes128', 'urlHls')
        if m3u8_url:
            fmts, subs = self._extract_m3u8_formats_and_subtitles(
                m3u8_url, media_id, 'mp4', m3u8_id='hls', fatal=False)
            formats.extend(fmts)
            self._merge_subtitles(subs, target=subtitles)

        fix_url = lambda x: x.replace('//rtbf-vod.', '//rtbf.') if '/geo/drm/' in x else x
        http_url = data.get('url')
        if formats and http_url and re.search(height_re, http_url):
            http_url = fix_url(http_url)
            for m3u8_f in formats[:]:
                height = m3u8_f.get('height')
                if not height:
                    continue
                f = m3u8_f.copy()
                del f['protocol']
                f.update({
                    'format_id': m3u8_f['format_id'].replace('hls-', 'http-'),
                    'url': re.sub(height_re, '-%dp.' % height, http_url),