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

Code before:
            },
            'params': {'skip_download': True},
            'skip': 'Live might have ended',
        },
        {
            'url': 'https://gem.cbc.ca/live-event/10835',
            'info_dict': {
                'id': 'live-event/10835',
                'ext': 'mp4',
                'is_live': True,
                'title': r're:^The National \| Biden’s trip wraps up, Paltrow testifies, Bird flu [0-9\-: ]+',
                'description': 'March 24, 2023 | President Biden’s Ottawa visit ends with big pledges from both countries. Plus, Gwyneth Paltrow testifies in her ski collision trial.',
                'live_status': 'is_live',
                'thumbnail': r're:https://images.gem.cbc.ca/v1/cbc-gem/live/.*',
                'timestamp': 1679706000,
                'upload_date': '20230325',
            },
            'params': {'skip_download': True},
            'skip': 'Live might have ended',
        }
    ]

    def _real_extract(self, url):
        match = self._match_valid_url(url)
        video_id = match.group('id')
        video_key = match.group('key')
        webpage = self._download_webpage(url, video_key)
        video_info = self._search_nextjs_data(webpage, video_key)['props']['pageProps']['data']

        # Two types of metadata JSON
        if not video_info.get('formattedIdMedia'):
            video_info = traverse_obj(
                video_info, ('freeTv', 'items', lambda _, v: v['key'] == video_key, {dict}),
                get_all=False, default={})

        video_stream_id = video_info.get('formattedIdMedia')
        if not video_stream_id:
            raise ExtractorError('Couldn\'t find video metadata, maybe this livestream is now offline', expected=True)

        stream_data = self._download_json(
            'https://services.radio-canada.ca/media/validation/v2/', video_key, query={
                'appCode': 'mpx',
                'connectionType': 'hd',
                'deviceType': 'ipad',
                'idMedia': video_stream_id,
                'multibitrate': 'true',
                'output': 'json',
                'tech': 'hls',
                'manifestType': 'desktop',
            })


Review comment (suggestion):
```suggestion
        video_id, video_key = self._match_valid_url(url).group('id', 'key')
```

Code after:
                'description': 'The live TV channel and local programming from Ottawa',
                'live_status': 'is_live',
                'thumbnail': r're:https://images.gem.cbc.ca/v1/cbc-gem/live/.*'
            },
            'params': {'skip_download': True},
            'skip': 'Live might have ended',
        },
        {
            'url': 'https://gem.cbc.ca/live-event/10835',
            'info_dict': {
                'id': '10835',
                'ext': 'mp4',
                'is_live': True,
                'title': r're:^The National \| Biden’s trip wraps up, Paltrow testifies, Bird flu [0-9\-: ]+',
                'description': 'March 24, 2023 | President Biden’s Ottawa visit ends with big pledges from both countries. Plus, Gwyneth Paltrow testifies in her ski collision trial.',
                'live_status': 'is_live',
                'thumbnail': r're:https://images.gem.cbc.ca/v1/cbc-gem/live/.*',
                'timestamp': 1679706000,
                'upload_date': '20230325',
            },
            'params': {'skip_download': True},
            'skip': 'Live might have ended',
        }
    ]

    def _real_extract(self, url):
        video_id = self._match_id(url)
        webpage = self._download_webpage(url, video_id)
        video_info = self._search_nextjs_data(webpage, video_id)['props']['pageProps']['data']

        # Two types of metadata JSON
        if not video_info.get('formattedIdMedia'):
            video_info = traverse_obj(
                video_info, (('freeTv', ('streams', ...)), 'items', lambda _, v: v['key'] == video_id, {dict}),
                get_all=False, default={})

        video_stream_id = video_info.get('formattedIdMedia')
        if not video_stream_id:
            raise ExtractorError('Couldn\'t find video metadata, maybe this livestream is now offline', expected=True)

        stream_data = self._download_json(
            'https://services.radio-canada.ca/media/validation/v2/', video_id, query={
                'appCode': 'mpx',
                'connectionType': 'hd',
                'deviceType': 'ipad',
                'idMedia': video_stream_id,
                'multibitrate': 'true',
                'output': 'json',
                'tech': 'hls',
                'manifestType': 'desktop',
            })