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

Code before:
)


class CanvasIE(InfoExtractor):
    _VALID_URL = r'https?://mediazone\.vrt\.be/api/v1/(?P<site_id>canvas|een|ketnet|vrt(?:video|nieuws)|sporza|dako)/assets/(?P<id>[^/?#&]+)'
    _TESTS = [{
        'url': 'https://mediazone.vrt.be/api/v1/ketnet/assets/md-ast-4ac54990-ce66-4d00-a8ca-9eac86f4c475',
        'md5': '37b2b7bb9b3dcaa05b67058dc3a714a9',
        'info_dict': {
            'id': 'md-ast-4ac54990-ce66-4d00-a8ca-9eac86f4c475',
            'display_id': 'md-ast-4ac54990-ce66-4d00-a8ca-9eac86f4c475',
            'ext': 'mp4',
            'title': 'Nachtwacht: De Greystook',
            'description': 'Nachtwacht: De Greystook',
            'thumbnail': r're:^https?://.*\.jpg$',
            'duration': 1468.02,
        },
        'expected_warnings': ['is not a supported codec'],
    }, {
        'url': 'https://mediazone.vrt.be/api/v1/canvas/assets/mz-ast-5e5f90b6-2d72-4c40-82c2-e134f884e93e',
        'only_matching': True,
    }]
    _GEO_BYPASS = False
    _HLS_ENTRY_PROTOCOLS_MAP = {
        'HLS_AES': 'm3u8',
    }
    _REST_API_BASE = 'https://media-services-public.vrt.be/vualto-video-aggregator-web/rest/external/v2'

    def _real_extract(self, url):
        mobj = self._match_valid_url(url)
        site_id, video_id = mobj.group('site_id'), mobj.group('id')

        data = None
        if site_id != 'vrtvideo':
            # Old API endpoint, serves more formats but may fail for some videos
            data = self._download_json(
                'https://mediazone.vrt.be/api/v1/%s/assets/%s'
                % (site_id, video_id), video_id, 'Downloading asset JSON',
                'Unable to download asset JSON', fatal=False)

        # New API endpoint
        if not data:
            vrtnutoken = self._download_json('https://token.vrt.be/refreshtoken',
                                             video_id, note='refreshtoken: Retrieve vrtnutoken',
                                             errnote='refreshtoken failed')['vrtnutoken']
            headers = self.geo_verification_headers()
            headers.update({'Content-Type': 'application/json; charset=utf-8'})
            vrtPlayerToken = self._download_json(
                '%s/tokens' % self._REST_API_BASE, video_id,
                'Downloading token', headers=headers, data=json.dumps({
                    'identityToken': vrtnutoken

Review comment (suggestion):
this seems to be no longer needed. Can you try changing the code to always go through `m3u8_native` and see if it works? (install pycryptodomex when testing)

Code after:
)


class CanvasIE(InfoExtractor):
    _VALID_URL = r'https?://mediazone\.vrt\.be/api/v1/(?P<site_id>canvas|een|ketnet|vrt(?:video|nieuws)|sporza|dako)/assets/(?P<id>[^/?#&]+)'
    _TESTS = [{
        'url': 'https://mediazone.vrt.be/api/v1/ketnet/assets/md-ast-4ac54990-ce66-4d00-a8ca-9eac86f4c475',
        'md5': '37b2b7bb9b3dcaa05b67058dc3a714a9',
        'info_dict': {
            'id': 'md-ast-4ac54990-ce66-4d00-a8ca-9eac86f4c475',
            'display_id': 'md-ast-4ac54990-ce66-4d00-a8ca-9eac86f4c475',
            'ext': 'mp4',
            'title': 'Nachtwacht: De Greystook',
            'description': 'Nachtwacht: De Greystook',
            'thumbnail': r're:^https?://.*\.jpg$',
            'duration': 1468.02,
        },
        'expected_warnings': ['is not a supported codec'],
    }, {
        'url': 'https://mediazone.vrt.be/api/v1/canvas/assets/mz-ast-5e5f90b6-2d72-4c40-82c2-e134f884e93e',
        'only_matching': True,
    }]
    _GEO_BYPASS = False
    _HLS_ENTRY_PROTOCOLS_MAP = {
        'HLS': 'm3u8_native',
        'HLS_AES': 'm3u8_native',
    }
    _REST_API_BASE = 'https://media-services-public.vrt.be/vualto-video-aggregator-web/rest/external/v2'

    def _real_extract(self, url):
        mobj = self._match_valid_url(url)
        site_id, video_id = mobj.group('site_id'), mobj.group('id')

        data = None
        if site_id != 'vrtvideo':
            # Old API endpoint, serves more formats but may fail for some videos
            data = self._download_json(
                'https://mediazone.vrt.be/api/v1/%s/assets/%s'
                % (site_id, video_id), video_id, 'Downloading asset JSON',
                'Unable to download asset JSON', fatal=False)

        # New API endpoint
        if not data:
            vrtnutoken = self._download_json('https://token.vrt.be/refreshtoken',
                                             video_id, note='refreshtoken: Retrieve vrtnutoken',
                                             errnote='refreshtoken failed')['vrtnutoken']
            headers = self.geo_verification_headers()
            headers.update({'Content-Type': 'application/json; charset=utf-8'})
            vrtPlayerToken = self._download_json(
                '%s/tokens' % self._REST_API_BASE, video_id,
                'Downloading token', headers=headers, data=json.dumps({