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

Code before:
        'url': 'https://www.dr.dk/lyd/p4kbh/regionale-nyheder-kh4/regionale-nyheder-2023-03-14-10-30-9',
        'info_dict': {
            'ext': 'mp4',
            'id': '14802310112',
            'timestamp': 1678786200,
            'duration': 120.043,
            'season_id': 'urn:dr:mu:bundle:63a4f7c87140143504b6710f',
            'series': 'P4 København regionale nyheder',
            'upload_date': '20230314',
            'release_year': 0,
            'description': 'Hør seneste regionale nyheder fra P4 København.',
            'season': 'Regionale nyheder',
            'title': 'Regionale nyheder',
        },
    }]

    def _real_extract(self, url):
        raw_video_id, is_radio_url = self._match_valid_url(url).group('id', 'radio')
        webpage = self._download_webpage(url, raw_video_id)
        if '>Programmet er ikke længere tilgængeligt' in webpage:
            raise ExtractorError(
                'Video %s is not available' % raw_video_id, expected=True)
        json_data = self._search_json(r'window\.__data\s*=', webpage, 'data', raw_video_id)
        item = traverse_obj(json_data, ('cache', 'page', Ellipsis, (None, ('entries', 0)), 'item'), get_all=False)
        itemId = item.get('id')
        videoId = item['customId'].split(':')[-1]
        deviceId = uuid.uuid1()
        token = self._download_json('https://isl.dr-massive.com/api/authorization/anonymous-sso?device=web_browser&ff=idp%2Cldp&lang=da', videoId, headers={'Content-Type': 'application/json'}, data=json.dumps({'deviceId': str(deviceId), 'scopes': ['Catalog'], 'optout': True}).encode('utf-8'))[0]['value']
        data = self._download_json('https://production.dr-massive.com/api/account/items/{0}/videos?delivery=stream&device=web_browser&ff=idp%2Cldp%2Crpt&lang=da&resolution=HD-1080&sub=Anonymous'.format(itemId), videoId, headers={'authorization': 'Bearer {0}'.format(token)})
        formats = []
        subtitles = {}
        for fmt in data:
            formatId = fmt['format'] or 'na'
            accessService = fmt['accessService']
            preference = None
            if accessService in ('SpokenSubtitles', 'SignLanguage', 'VisuallyInterpreted'):
                preference = -1
                formatId += '-%s' % accessService
            elif accessService == 'StandardVideo':
                preference = 1
            fmts, subs = self._extract_m3u8_formats_and_subtitles(fmt['url'], videoId, 'mp4', entry_protocol='m3u8_native', preference=preference, m3u8_id=formatId, fatal=False)
            formats.extend(fmts)
            self._merge_subtitles(subs, target=subtitles)
            LANGS = {
                'Danish': 'da',
            }
            for subs in fmt['subtitles']:
                if not isinstance(subs, dict):
                    continue
                sub_uri = url_or_none(subs.get('link'))
                if not sub_uri:

Review comment (refactor):
I wonder if the regular id could be used as the video instead of this one.
From the URLs posted in #8298 the new URL format seems to have the regular id as part of the URL. Is this always the case and the could the id be extracted from there?

Code after:
                'ff': 'idp,ldp,rpt',
                'lang': 'da',
                'supportFallbackToken': 'true',
            }, data=json.dumps({
                'deviceId': str(uuid.uuid4()),
                'scopes': ['Catalog'],
                'optout': True,
            }).encode())

        self._TOKEN = traverse_obj(
            token_response, (lambda _, x: x['type'] == 'UserAccount', 'value', {str}), get_all=False)
        if not self._TOKEN:
            raise ExtractorError('Unable to get anonymous token')

    def _real_extract(self, url):
        url_slug = self._match_id(url)
        webpage = self._download_webpage(url, url_slug)

        json_data = self._search_json(
            r'window\.__data\s*=', webpage, 'data', url_slug, fatal=False) or {}
        item = traverse_obj(
            json_data, ('cache', 'page', ..., (None, ('entries', 0)), 'item', {dict}), get_all=False)
        if item:
            item_id = item.get('id')
        else:
            item_id = url_slug.rsplit('_', 1)[-1]
            item = self._download_json(
                f'https://production-cdn.dr-massive.com/api/items/{item_id}', item_id,
                note='Attempting to download backup item data', query={
                    'device': 'web_browser',
                    'expand': 'all',
                    'ff': 'idp,ldp,rpt',
                    'geoLocation': 'dk',
                    'isDeviceAbroad': 'false',
                    'lang': 'da',
                    'segments': 'drtv,optedout',
                    'sub': 'Anonymous',
                })

        video_id = try_call(lambda: item['customId'].rsplit(':', 1)[-1]) or item_id
        stream_data = self._download_json(
            f'https://production.dr-massive.com/api/account/items/{item_id}/videos', video_id,
            note='Downloading stream data', query={
                'delivery': 'stream',
                'device': 'web_browser',
                'ff': 'idp,ldp,rpt',
                'lang': 'da',
                'resolution': 'HD-1080',
                'sub': 'Anonymous',
            }, headers={'authorization': f'Bearer {self._TOKEN}'})