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

Code before:
                href
                distributionType
                audioBitrate
                audioCodec
            }
            show {
              title
            }
            image {
              url1X1
            }
            programSet {
              publicationService {
                organizationName
              }
            }
            description
            title
            duration
            startDate
            episodeNumber
        }
    }'''

    def _real_extract(self, url):
        urn = self._match_valid_url(url).group('id')
        item = self._graphql_query(urn, self._QUERY_ITEM)['item']
        return {
            'formats': traverse_obj(item, (
                'audioList', lambda _, v: url_or_none(v['href']), {
                    'url': 'href',
                    'format_id': ('distributionType', {str}),
                    'abr': ('audioBitrate', {int}),
                    'acodec': ('audioCodec', {str}),
                })),
            'id': urn,
            **traverse_obj(item, {
                'channel': ('programSet', 'publicationService', 'organizationName', {str}),
                'description': ('description', {str}),
                'duration': ('duration', {int_or_none}),
                'series': ('show', 'title', {str}),
                'episode_number': ('episodeNumber', {int_or_none}),
                'thumbnail': ('image', 'url1X1', {lambda v: v.split('?')[0] if isinstance(v, str) else None}),
                'timestamp': ('startDate', {parse_iso8601}),
                'title': ('title', {str}),
            }),
        }


class ARDAudiothekPlaylistIE(ARDAudiothekBaseIE):
    _VALID_URL = r'''(?x)https:?//

Review comment (suggestion):
```suggestion
        urn = self._match_id(url)
```

Code after:
            description
            title
            duration
            startDate
            episodeNumber
        }
    }'''

    def _real_extract(self, url):
        urn = self._match_id(url)
        item = self._graphql_query(urn, self._QUERY_ITEM)['item']
        return {
            'id': urn,
            **traverse_obj(item, {
                'formats': ('audioList', lambda _, v: url_or_none(v['href']), {
                    'url': 'href',
                    'format_id': ('distributionType', {str}),
                    'abr': ('audioBitrate', {int_or_none}),
                    'acodec': ('audioCodec', {str}),
                    'vcodec': {value('none')},
                }),
                'channel': ('programSet', 'publicationService', 'organizationName', {str}),
                'description': ('description', {str}),
                'duration': ('duration', {int_or_none}),
                'series': ('show', 'title', {str}),
                'episode_number': ('episodeNumber', {int_or_none}),
                'thumbnail': ('image', 'url1X1', {url_or_none}, {update_url(query=None)}),
                'timestamp': ('startDate', {parse_iso8601}),
                'title': ('title', {str}),
            }),
        }


class ARDAudiothekPlaylistIE(ARDAudiothekBaseIE):
    _VALID_URL = r'https:?//(?:www\.)?ardaudiothek\.de/sendung/(?P<playlist>[\w-]+)/(?P<id>urn:ard:show:[a-f0-9]{16})'

    _TESTS = [{
        'url': 'https://www.ardaudiothek.de/sendung/mia-insomnia/urn:ard:show:c405aa26d9a4060a/',
        'info_dict': {
            'display_id': 'mia-insomnia',
            'title': 'Mia Insomnia',
            'id': 'urn:ard:show:c405aa26d9a4060a',
            'description': 'md5:d9ceb7a6b4d26a4db3316573bb564292',
        },
        'playlist_mincount': 37,
    }, {
        'url': 'https://www.ardaudiothek.de/sendung/100-berlin/urn:ard:show:4d248e0806ce37bc/',
        'only_matching': True,
    }]

    _QUERY_PLAYLIST = '''