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

Code before:
            self._merge_subtitles(subs, target=subtitles)

        for f in formats:
            f['http_headers'] = headers

        return {
            'id': f'{urllib.parse.urlparse(api_base).hostname}_{video_id}',
            **traverse_obj(traverse_obj(video_info, ('blocks', 0)), {
                'display_id': ('slug',),
                'title': ('title',),
                'episode': ('title',),
                'description': ('description',),
                'series': ('program_title',),
                'season_number': ('season_number',),
                'episode_number': ('episode',),
                'thumbnail': ('image',),
                'duration': ('duration', 'total'),
                'age_limit': ('age_rating',),
            }),
            'formats': formats,
            'subtitles': subtitles,
            'is_live': False,
        }


class FaulioLiveIE(FaulioBase):
    _VALID_URL = fr'https?://(?:{"|".join(map(re.escape, _DOMAINS))})/(?:(?:{"|".join(map(re.escape, _LANGUAGES))})/)?live/(?P<id>[a-zA-Z0-9-]+)'
    _TESTS = [{
        'url': 'https://aloula.sba.sa/live/saudiatv',
        'info_dict': {
            'id': 'aloula.faulio.com_saudiatv',
            'title': str,
            'description': str,
            'ext': 'mp4',
            'live_status': 'is_live',
        },
        'params': {
            'skip_download': 'Livestream',
        },
    }, {
        'url': 'https://bahry.com/live/1',
        'info_dict': {
            'id': 'bahry.faulio.com_1',
            'title': str,
            'description': str,
            'ext': 'mp4',
            'live_status': 'is_live',
        },
        'params': {
            'skip_download': 'Livestream',
        },

Review comment (suggestion):
```suggestion
class FaulioLiveIE(FaulioBaseIE):
```

Code after:
            'thumbnail': r're:^https?://.*\.jpg$',
            'duration': 2492,
            'age_limit': 0,
        },
    }, {
        'url': 'https://aloula.sba.sa/en/episode/0',
        'only_matching': True,
    }]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        api_base = self._get_api_base(url, video_id)
        video_info = self._download_json(f'{api_base}/video/{video_id}', video_id, fatal=False)
        player_info = self._download_json(f'{api_base}/video/{video_id}/player', video_id)

        headers = self._get_headers(url)
        formats = []
        subtitles = {}
        if hls_url := traverse_obj(player_info, ('settings', 'protocols', 'hls', {url_or_none})):
            fmts, subs = self._extract_m3u8_formats_and_subtitles(
                hls_url, video_id, 'mp4', m3u8_id='hls', fatal=False, headers=headers)
            formats.extend(fmts)
            self._merge_subtitles(subs, target=subtitles)

        if mpd_url := traverse_obj(player_info, ('settings', 'protocols', 'dash', {url_or_none})):
            fmts, subs = self._extract_mpd_formats_and_subtitles(
                mpd_url, video_id, mpd_id='dash', fatal=False, headers=headers)
            formats.extend(fmts)
            self._merge_subtitles(subs, target=subtitles)

        return {
            'id': f'{urllib.parse.urlparse(api_base).hostname}_{video_id}',
            **traverse_obj(traverse_obj(video_info, ('blocks', 0)), {
                'display_id': ('slug', {str}),
                'title': ('title', {str}),
                'episode': ('title', {str}),
                'description': ('description', {str}),
                'series': ('program_title', {str}),
                'season_number': ('season_number', {int_or_none}),
                'episode_number': ('episode', {int_or_none}),
                'thumbnail': ('image', {url_or_none}),
                'duration': ('duration', 'total', {int_or_none}),
                'age_limit': ('age_rating', {int_or_none}),
            }),
            'formats': formats,
            'subtitles': subtitles,
            'http_headers': headers,
        }


class FaulioLiveIE(FaulioBaseIE):