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

Code before:
        # Note: DLF's mp3 recordings are in two distinct locations on the web:
        # A direct download location, https://download.deutschlandfunk.de/ ... .mp3
        # A stream with playback controls, https://ondemand-mp3.dradio.de/ ... .mp3
        url = url_or_none(
            attrs.get('data-audio-download-src')
            or attrs.get('data-audio')
            or attrs.get('data-audioreference')
            or attrs['data-audio-src'])

        return {
            'id': id,
            'title': (
                attrs.get('data-audiotitle')
                or attrs.get('data-audio-title')
                or attrs.get('data-audio-download-tracking-title')),
            'url': url,
            'formats': (
                self._extract_m3u8_formats(url, id) if determine_ext(url) == 'm3u8'
                else None),
            'duration': int_or_none(
                attrs.get('data-audioduration')
                or attrs.get('data-audio-duration')),
            'thumbnail': attrs.get('data-audioimage'),
            'uploader': attrs.get('data-audio-producer'),
            'series': attrs.get('data-audio-series'),
            'channel': attrs.get('data-audio-origin-site-name'),
        }


class DLFIE(DLFBaseIE):
    _VALID_URL = DLFBaseIE._VALID_URL_BASE + r'(?:\w+-)+(?P<id>[^-]*\d[^-]*)-100\.html'

    IE_NAME = 'dlf'
    _TESTS = [
        # Audio as an HLS stream
        {
            'url': 'https://www.deutschlandfunk.de/tanz-der-saiteninstrumente-das-wild-strings-trio-aus-slowenien-dlf-03a3eb19-100.html',
            'info_dict': {
                'id': '03a3eb19',
                'title': r're:Tanz der Saiteninstrumente [-/] Das Wild Strings Trio aus Slowenien',
                'url': 'https://dradiohls.akamaized.net/hls/2023/03/03/tanz_der_saiteninstrumente_das_wild_strings_trio_aus_dlf_20230303_2105_03a3eb19/128/seglist.m3u8',
                'ext': 'm4a',
                'duration': 3298,
                'thumbnail': 'https://assets.deutschlandfunk.de/FALLBACK-IMAGE-AUDIO/512x512.png?t=1603714364673',
                'uploader': 'Deutschlandfunk',
                'series': 'On Stage',
                'channel': 'deutschlandfunk'
            },
            'params': {
                'skip_download': 'm3u8'
            },

Review comment (refactor):
 - We need to add `'vcodec': 'none'` if it's audio-only.
 - Using `formats` for both m3u8 and mp3 formats seems simpler to me
 - `traverse_obj` makes this less grueling to read/write
 - Like how I suggested to add `extractor` and `extractor_key` above, we want to extract the `webpage_url` for individual media here too:
```suggestion
            **traverse_obj(attrs, {
                'title': (('data-audiotitle', 'data-audio-title', 'data-audio-download-tracking-title'), {str}),
                'duration': (('data-audioduration', 'data-audio-duration'), {int_or_none}),
                'thumbnail': ('data-audioimage', {url_or_none}),
                'uploader': 'data-audio-producer',
                'series': 'data-audio-series',
                'channel': 'data-audio-origin-site-name',
                'webpage_url': 'data-audio-download-tracking-path',
            }, get_all=False),
            'formats': (self._extract_m3u8_formats(url, id_, fatal=False)
                        if ext == 'm3u8' else [{'url': url, 'ext': ext, 'vcodec': 'none'}])
```

Code after:
        audio_id = audio_id or attrs['data-audio-diraid']

        url = traverse_obj(
            attrs, 'data-audio-download-src', 'data-audio', 'data-audioreference',
            'data-audio-src', expected_type=url_or_none)
        ext = determine_ext(url)

        return {
            'id': audio_id,
            'extractor_key': DLFIE.ie_key(),
            'extractor': DLFIE.IE_NAME,
            **traverse_obj(attrs, {
                'title': (('data-audiotitle', 'data-audio-title', 'data-audio-download-tracking-title'), {str}),
                'duration': (('data-audioduration', 'data-audio-duration'), {int_or_none}),
                'thumbnail': ('data-audioimage', {url_or_none}),
                'uploader': 'data-audio-producer',
                'series': 'data-audio-series',
                'channel': 'data-audio-origin-site-name',
                'webpage_url': ('data-audio-download-tracking-path', {url_or_none}),
            }, get_all=False),
            'formats': (self._extract_m3u8_formats(url, audio_id, fatal=False)
                        if ext == 'm3u8' else [{'url': url, 'ext': ext, 'vcodec': 'none'}])
        }


class DLFIE(DLFBaseIE):
    IE_NAME = 'dlf'
    _VALID_URL = DLFBaseIE._VALID_URL_BASE + r'[\w-]+-dlf-(?P<id>[\da-f]{8})-100\.html'
    _TESTS = [
        # Audio as an HLS stream
        {
            'url': 'https://www.deutschlandfunk.de/tanz-der-saiteninstrumente-das-wild-strings-trio-aus-slowenien-dlf-03a3eb19-100.html',
            'info_dict': {
                'id': '03a3eb19',
                'title': r're:Tanz der Saiteninstrumente [-/] Das Wild Strings Trio aus Slowenien',
                'ext': 'm4a',
                'duration': 3298,
                'thumbnail': 'https://assets.deutschlandfunk.de/FALLBACK-IMAGE-AUDIO/512x512.png?t=1603714364673',
                'uploader': 'Deutschlandfunk',
                'series': 'On Stage',
                'channel': 'deutschlandfunk'
            },
            'params': {
                'skip_download': 'm3u8'
            },
            'skip': 'This webpage no longer exists'
        }, {
            'url': 'https://www.deutschlandfunk.de/russische-athleten-kehren-zurueck-auf-die-sportbuehne-ein-gefaehrlicher-tueroeffner-dlf-d9cc1856-100.html',
            'info_dict': {
                'id': 'd9cc1856',
                'title': 'Russische Athleten kehren zurück auf die Sportbühne: Ein gefährlicher Türöffner',