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

Code before:

    _STATION_RE = 'noe|wie|bgl|ooe|stm|ktn|sbg|tir|vbg|oe3|oe1|fm4|tv'

    _VALID_URL = rf'https?://sound\.orf\.at/podcast/(?P<station>{_STATION_RE})/(?P<show>[\w-]+)/(?P<id>[\w-]+)'

    _TESTS = [{
        'url': 'https://sound.orf.at/podcast/oe3/fruehstueck-bei-mir/nicolas-stockhammer-15102023',
        'md5': '526a5700e03d271a1505386a8721ab9b',
        'info_dict': {
            'id': 'nicolas-stockhammer-15102023',
            'ext': 'mp3',
            'title': 'Nicolas Stockhammer (15.10.2023)',
            'duration': 3396.0,
            'series': 'Frühstück bei mir',
        },
        'skip': 'ORF podcasts are only available for a limited time'
    }]

    def _real_extract(self, url):
        station, show, show_id = self._match_valid_url(url).group('station', 'show', 'id')
        data = self._download_json(
            f'https://audioapi.orf.at/radiothek/api/2.0/podcast/{station}/{show}/{show_id}', show_id)

        return {
            'id': show_id,
            'ext': 'mp3',
            'vcodec': 'none',
            **traverse_obj(data, ('payload', {
                'url': ('enclosures', 0, 'url'),
                'title': 'title',
                'description': ('description', {clean_html}),
                'duration': ('duration', {functools.partial(float_or_none, scale=1000)}),
                'series': ('podcast', 'title'),
            })),
        }


class ORFIPTVIE(InfoExtractor):
    IE_NAME = 'orf:iptv'
    IE_DESC = 'iptv.ORF.at'
    _VALID_URL = r'https?://iptv\.orf\.at/(?:#/)?stories/(?P<id>\d+)'

    _TEST = {
        'url': 'http://iptv.orf.at/stories/2275236/',
        'md5': 'c8b22af4718a4b4af58342529453e3e5',
        'info_dict': {
            'id': '350612',
            'ext': 'flv',
            'title': 'Weitere Evakuierungen um Vulkan Calbuco',
            'description': 'md5:d689c959bdbcf04efeddedbf2299d633',
            'duration': 68.197,

Review comment (refactor):
Are we sure that it is always an mp3?
In the API response JSON there is a mimetype given in the `payload.enclosures.0.type` field

So you could keep `'ext': 'mp3'` here as a default, but then also add

```diff
             **traverse_obj(data, ('payload', {
                 'url': ('enclosures', 0, 'url'),
+                'ext': ('enclosures', 0, 'type', {mimetype2ext}),
```
to extract actual extension when available

Code after:
    IE_NAME = 'orf:podcast'
    _STATION_RE = '|'.join(map(re.escape, (
        'bgl', 'fm4', 'ktn', 'noe', 'oe1', 'oe3',
        'ooe', 'sbg', 'stm', 'tir', 'tv', 'vbg', 'wie')))
    _VALID_URL = rf'https?://sound\.orf\.at/podcast/(?P<station>{_STATION_RE})/(?P<show>[\w-]+)/(?P<id>[\w-]+)'
    _TESTS = [{
        'url': 'https://sound.orf.at/podcast/oe3/fruehstueck-bei-mir/nicolas-stockhammer-15102023',
        'md5': '526a5700e03d271a1505386a8721ab9b',
        'info_dict': {
            'id': 'nicolas-stockhammer-15102023',
            'ext': 'mp3',
            'title': 'Nicolas Stockhammer (15.10.2023)',
            'duration': 3396.0,
            'series': 'Frühstück bei mir',
        },
        'skip': 'ORF podcasts are only available for a limited time'
    }]

    def _real_extract(self, url):
        station, show, show_id = self._match_valid_url(url).group('station', 'show', 'id')
        data = self._download_json(
            f'https://audioapi.orf.at/radiothek/api/2.0/podcast/{station}/{show}/{show_id}', show_id)

        return {
            'id': show_id,
            'ext': 'mp3',
            'vcodec': 'none',
            **traverse_obj(data, ('payload', {
                'url': ('enclosures', 0, 'url'),
                'ext': ('enclosures', 0, 'type', {mimetype2ext}),
                'title': 'title',
                'description': ('description', {clean_html}),
                'duration': ('duration', {functools.partial(float_or_none, scale=1000)}),
                'series': ('podcast', 'title'),
            })),
        }


class ORFIPTVIE(InfoExtractor):
    IE_NAME = 'orf:iptv'
    IE_DESC = 'iptv.ORF.at'
    _VALID_URL = r'https?://iptv\.orf\.at/(?:#/)?stories/(?P<id>\d+)'

    _TEST = {
        'url': 'http://iptv.orf.at/stories/2275236/',
        'md5': 'c8b22af4718a4b4af58342529453e3e5',
        'info_dict': {
            'id': '350612',
            'ext': 'flv',
            'title': 'Weitere Evakuierungen um Vulkan Calbuco',
            'description': 'md5:d689c959bdbcf04efeddedbf2299d633',