We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Genius.com now throws unsupported url
### DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE

- [X] I understand that I will be **blocked** if I *intentionally* remove or skip any mandatory\* field

### Checklist

- [X] I'm reporting that a **supported** site is broken
- [X] I've verified that I'm running yt-dlp version **2023.03.04** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#video-url-contains-an-ampersand--and-im-getting-some-strange-output-1-2839-or-v-is-not-recognized-as-an-internal-or-external-command)
- [X] I've searched [known issues](https://github.com/yt-dlp/yt-dlp/issues/3766) and the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues **including closed ones**. DO NOT post duplicates
- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)
- [X] I've read about [sharing account credentials](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#are-you-willing-to-share-account-details-if-needed) and I'm willing to share it if required

### Region

Colombia

### Provide a description that is worded well enough to be understood

The genius extractor currently doesn't work

### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [X] If using API, add `'verbose': True` to `YoutubeDL` params instead
- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
[debug] Command-line config: ['-vU', 'https://genius.com/a/cordae-anderson-paak-break-down-the-meaning-of-two-tens']
[debug] Encodings: locale cp1252, fs utf-8, pref cp1252, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version nightly@2023.03.06.190223 [d4e6ef407] (win_exe)
[debug] Python 3.8.10 (CPython AMD64 64bit) - Windows-10-10.0.19045-SP0 (OpenSSL 1.1.1k  25 Mar 2021)
[debug] exe versions: ffmpeg N-109920-gac6eec1fc2-20230224 (setts), ffprobe N-109920-gac6eec1fc2-20230224
[debug] Optional libraries: Cryptodome-3.17, brotli-1.0.9, certifi-2022.12.07, mutagen-1.46.0, sqlite3-2.6.0, websockets-10.4
[debug] Proxy map: {}
[debug] Loaded 1788 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp-nightly-builds/releases/latest
Available version: nightly@2023.03.06.190223, Current version: nightly@2023.03.06.190223
Current Build Hash: 7c51ebf2a7a9e1f199547cd8dad7df7713655f1c91a95f7e49764a513c52d6b1
yt-dlp is up to date (nightly@2023.03.06.190223)
[generic] Extracting URL: https://genius.com/a/cordae-anderson-paak-break-down-the-meaning-of-two-tens
[generic] cordae-anderson-paak-break-down-the-meaning-of-two-tens: Downloading webpage
WARNING: [generic] Falling back on generic information extractor
[generic] cordae-anderson-paak-break-down-the-meaning-of-two-tens: Extracting information
[debug] Looking for embeds
ERROR: Unsupported URL: https://genius.com/a/cordae-anderson-paak-break-down-the-meaning-of-two-tens
Traceback (most recent call last):
  File "yt_dlp\YoutubeDL.py", line 1518, in wrapper
  File "yt_dlp\YoutubeDL.py", line 1594, in __extract_info
  File "yt_dlp\extractor\common.py", line 694, in extract
  File "yt_dlp\extractor\generic.py", line 2510, in _real_extract
yt_dlp.utils.UnsupportedError: Unsupported URL: https://genius.com/a/cordae-anderson-paak-break-down-the-meaning-of-two-tens
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `yt_dlp/extractor/genius.py`
Content:
```
1 from .common import InfoExtractor
2 from ..utils import (
3     ExtractorError,
4     js_to_json,
5     smuggle_url,
6     str_or_none,
7     traverse_obj,
8     unescapeHTML,
9 )
10 
11 
12 class GeniusIE(InfoExtractor):
13     _VALID_URL = r'https?://(?:www\.)?genius\.com/videos/(?P<id>[^?/#]+)'
14     _TESTS = [{
15         'url': 'https://genius.com/videos/Vince-staples-breaks-down-the-meaning-of-when-sparks-fly',
16         'md5': '64c2ad98cfafcfda23bfa0ad0c512f4c',
17         'info_dict': {
18             'id': '6313303597112',
19             'ext': 'mp4',
20             'title': 'Vince Staples Breaks Down The Meaning Of “When Sparks Fly”',
21             'description': 'md5:bc15e00342c537c0039d414423ae5752',
22             'tags': 'count:1',
23             'uploader_id': '4863540648001',
24             'duration': 388.416,
25             'upload_date': '20221005',
26             'timestamp': 1664982341,
27             'thumbnail': r're:^https?://.*\.jpg$',
28         },
29     }, {
30         'url': 'https://genius.com/videos/Breaking-down-drakes-certified-lover-boy-kanye-beef-way-2-sexy-cudi',
31         'md5': 'b8ed87a5efd1473bd027c20a969d4060',
32         'info_dict': {
33             'id': '6271792014001',
34             'ext': 'mp4',
35             'title': 'md5:c6355f7fa8a70bc86492a3963919fc15',
36             'description': 'md5:1774638c31548b31b037c09e9b821393',
37             'tags': 'count:3',
38             'uploader_id': '4863540648001',
39             'duration': 2685.099,
40             'upload_date': '20210909',
41             'timestamp': 1631209167,
42             'thumbnail': r're:^https?://.*\.jpg$',
43         },
44     }]
45 
46     def _real_extract(self, url):
47         display_id = self._match_id(url)
48         webpage = self._download_webpage(url, display_id)
49 
50         metadata = self._search_json(
51             r'<meta content="', webpage, 'metadata', display_id, transform_source=unescapeHTML)
52         video_id = traverse_obj(
53             metadata, ('video', 'provider_id'),
54             ('dfp_kv', lambda _, x: x['name'] == 'brightcove_video_id', 'values', 0), get_all=False)
55         if not video_id:
56             raise ExtractorError('Brightcove video id not found in webpage')
57 
58         config = self._search_json(r'var\s*APP_CONFIG\s*=', webpage, 'config', video_id, default={})
59         account_id = config.get('brightcove_account_id', '4863540648001')
60         player_id = traverse_obj(
61             config, 'brightcove_standard_web_player_id', 'brightcove_standard_no_autoplay_web_player_id',
62             'brightcove_modal_web_player_id', 'brightcove_song_story_web_player_id', default='S1ZcmcOC1x')
63 
64         return self.url_result(
65             smuggle_url(
66                 f'https://players.brightcove.net/{account_id}/{player_id}_default/index.html?videoId={video_id}',
67                 {'referrer': url}), 'BrightcoveNew', video_id)
68 
69 
70 class GeniusLyricsIE(InfoExtractor):
71     _VALID_URL = r'https?://(?:www\.)?genius\.com/(?P<id>[^?/#]+)-lyrics[?/#]?'
72     _TESTS = [{
73         'url': 'https://genius.com/Lil-baby-heyy-lyrics',
74         'playlist_mincount': 2,
75         'info_dict': {
76             'id': '8454545',
77             'title': 'Heyy',
78             'description': 'Heyy by Lil Baby',
79         },
80     }, {
81         'url': 'https://genius.com/Outkast-two-dope-boyz-in-a-cadillac-lyrics',
82         'playlist_mincount': 1,
83         'info_dict': {
84             'id': '36239',
85             'title': 'Two Dope Boyz (In a Cadillac)',
86             'description': 'Two Dope Boyz (In a Cadillac) by OutKast',
87         },
88     }, {
89         'url': 'https://genius.com/Playboi-carti-rip-lyrics',
90         'playlist_mincount': 1,
91         'info_dict': {
92             'id': '3710582',
93             'title': 'R.I.P.',
94             'description': 'R.I.P. by Playboi Carti',
95         },
96     }]
97 
98     def _real_extract(self, url):
99         display_id = self._match_id(url)
100         webpage = self._download_webpage(url, display_id)
101 
102         json_string = self._search_json(
103             r'window\.__PRELOADED_STATE__\s*=\s*JSON\.parse\(', webpage, 'json string',
104             display_id, transform_source=js_to_json, contains_pattern=r'\'{(?s:.+)}\'')
105         song_info = self._parse_json(json_string, display_id)
106         song_id = str_or_none(traverse_obj(song_info, ('songPage', 'song')))
107         if not song_id:
108             raise ExtractorError('Song id not found in webpage')
109 
110         title = traverse_obj(
111             song_info, ('songPage', 'trackingData', lambda _, x: x['key'] == 'Title', 'value'),
112             get_all=False, default='untitled')
113         artist = traverse_obj(
114             song_info, ('songPage', 'trackingData', lambda _, x: x['key'] == 'Primary Artist', 'value'),
115             get_all=False, default='unknown artist')
116         media = traverse_obj(
117             song_info, ('entities', 'songs', song_id, 'media'), expected_type=list, default=[])
118 
119         entries = []
120         for m in media:
121             if m.get('type') in ('video', 'audio') and m.get('url'):
122                 if m.get('provider') == 'spotify':
123                     self.to_screen(f'{song_id}: Skipping Spotify audio embed')
124                 else:
125                     entries.append(self.url_result(m['url']))
126 
127         return self.playlist_result(entries, song_id, title, f'{title} by {artist}')
128
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/yt_dlp/extractor/genius.py b/yt_dlp/extractor/genius.py
--- a/yt_dlp/extractor/genius.py
+++ b/yt_dlp/extractor/genius.py
@@ -10,7 +10,7 @@
 
 
 class GeniusIE(InfoExtractor):
-    _VALID_URL = r'https?://(?:www\.)?genius\.com/videos/(?P<id>[^?/#]+)'
+    _VALID_URL = r'https?://(?:www\.)?genius\.com/(?:videos|(?P<article>a))/(?P<id>[^?/#]+)'
     _TESTS = [{
         'url': 'https://genius.com/videos/Vince-staples-breaks-down-the-meaning-of-when-sparks-fly',
         'md5': '64c2ad98cfafcfda23bfa0ad0c512f4c',
@@ -41,19 +41,37 @@
             'timestamp': 1631209167,
             'thumbnail': r're:^https?://.*\.jpg$',
         },
+    }, {
+        'url': 'https://genius.com/a/cordae-anderson-paak-break-down-the-meaning-of-two-tens',
+        'md5': 'f98a4e03b16b0a2821bd6e52fb3cc9d7',
+        'info_dict': {
+            'id': '6321509903112',
+            'ext': 'mp4',
+            'title': 'Cordae & Anderson .Paak Breaks Down The Meaning Of “Two Tens”',
+            'description': 'md5:1255f0e1161d07342ce56a8464ac339d',
+            'tags': ['song id: 5457554'],
+            'uploader_id': '4863540648001',
+            'duration': 361.813,
+            'upload_date': '20230301',
+            'timestamp': 1677703908,
+            'thumbnail': r're:^https?://.*\.jpg$',
+        },
     }]
 
     def _real_extract(self, url):
-        display_id = self._match_id(url)
+        display_id, is_article = self._match_valid_url(url).group('id', 'article')
         webpage = self._download_webpage(url, display_id)
 
         metadata = self._search_json(
-            r'<meta content="', webpage, 'metadata', display_id, transform_source=unescapeHTML)
-        video_id = traverse_obj(
-            metadata, ('video', 'provider_id'),
-            ('dfp_kv', lambda _, x: x['name'] == 'brightcove_video_id', 'values', 0), get_all=False)
+            r'<meta content="', webpage, 'metadata', display_id,
+            end_pattern=r'"\s+itemprop="page_data"', transform_source=unescapeHTML)
+        video_id = traverse_obj(metadata, (
+            (('article', 'media', ...), ('video', None)),
+            ('provider_id', ('dfp_kv', lambda _, v: v['name'] == 'brightcove_video_id', 'values', ...))),
+            get_all=False)
         if not video_id:
-            raise ExtractorError('Brightcove video id not found in webpage')
+            # Not all article pages have videos, expect the error
+            raise ExtractorError('Brightcove video ID not found in webpage', expected=bool(is_article))
 
         config = self._search_json(r'var\s*APP_CONFIG\s*=', webpage, 'config', video_id, default={})
         account_id = config.get('brightcove_account_id', '4863540648001')
@@ -68,7 +86,7 @@
 
 
 class GeniusLyricsIE(InfoExtractor):
-    _VALID_URL = r'https?://(?:www\.)?genius\.com/(?P<id>[^?/#]+)-lyrics[?/#]?'
+    _VALID_URL = r'https?://(?:www\.)?genius\.com/(?P<id>[^?/#]+)-lyrics(?:[?/#]|$)'
     _TESTS = [{
         'url': 'https://genius.com/Lil-baby-heyy-lyrics',
         'playlist_mincount': 2,

{"golden_diff": "diff --git a/yt_dlp/extractor/genius.py b/yt_dlp/extractor/genius.py\n--- a/yt_dlp/extractor/genius.py\n+++ b/yt_dlp/extractor/genius.py\n@@ -10,7 +10,7 @@\n \n \n class GeniusIE(InfoExtractor):\n-    _VALID_URL = r'https?://(?:www\\.)?genius\\.com/videos/(?P<id>[^?/#]+)'\n+    _VALID_URL = r'https?://(?:www\\.)?genius\\.com/(?:videos|(?P<article>a))/(?P<id>[^?/#]+)'\n     _TESTS = [{\n         'url': 'https://genius.com/videos/Vince-staples-breaks-down-the-meaning-of-when-sparks-fly',\n         'md5': '64c2ad98cfafcfda23bfa0ad0c512f4c',\n@@ -41,19 +41,37 @@\n             'timestamp': 1631209167,\n             'thumbnail': r're:^https?://.*\\.jpg$',\n         },\n+    }, {\n+        'url': 'https://genius.com/a/cordae-anderson-paak-break-down-the-meaning-of-two-tens',\n+        'md5': 'f98a4e03b16b0a2821bd6e52fb3cc9d7',\n+        'info_dict': {\n+            'id': '6321509903112',\n+            'ext': 'mp4',\n+            'title': 'Cordae & Anderson .Paak Breaks Down The Meaning Of \u201cTwo Tens\u201d',\n+            'description': 'md5:1255f0e1161d07342ce56a8464ac339d',\n+            'tags': ['song id: 5457554'],\n+            'uploader_id': '4863540648001',\n+            'duration': 361.813,\n+            'upload_date': '20230301',\n+            'timestamp': 1677703908,\n+            'thumbnail': r're:^https?://.*\\.jpg$',\n+        },\n     }]\n \n     def _real_extract(self, url):\n-        display_id = self._match_id(url)\n+        display_id, is_article = self._match_valid_url(url).group('id', 'article')\n         webpage = self._download_webpage(url, display_id)\n \n         metadata = self._search_json(\n-            r'<meta content=\"', webpage, 'metadata', display_id, transform_source=unescapeHTML)\n-        video_id = traverse_obj(\n-            metadata, ('video', 'provider_id'),\n-            ('dfp_kv', lambda _, x: x['name'] == 'brightcove_video_id', 'values', 0), get_all=False)\n+            r'<meta content=\"', webpage, 'metadata', display_id,\n+            end_pattern=r'\"\\s+itemprop=\"page_data\"', transform_source=unescapeHTML)\n+        video_id = traverse_obj(metadata, (\n+            (('article', 'media', ...), ('video', None)),\n+            ('provider_id', ('dfp_kv', lambda _, v: v['name'] == 'brightcove_video_id', 'values', ...))),\n+            get_all=False)\n         if not video_id:\n-            raise ExtractorError('Brightcove video id not found in webpage')\n+            # Not all article pages have videos, expect the error\n+            raise ExtractorError('Brightcove video ID not found in webpage', expected=bool(is_article))\n \n         config = self._search_json(r'var\\s*APP_CONFIG\\s*=', webpage, 'config', video_id, default={})\n         account_id = config.get('brightcove_account_id', '4863540648001')\n@@ -68,7 +86,7 @@\n \n \n class GeniusLyricsIE(InfoExtractor):\n-    _VALID_URL = r'https?://(?:www\\.)?genius\\.com/(?P<id>[^?/#]+)-lyrics[?/#]?'\n+    _VALID_URL = r'https?://(?:www\\.)?genius\\.com/(?P<id>[^?/#]+)-lyrics(?:[?/#]|$)'\n     _TESTS = [{\n         'url': 'https://genius.com/Lil-baby-heyy-lyrics',\n         'playlist_mincount': 2,\n", "issue": "Genius.com now throws unsupported url\n### DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE\n\n- [X] I understand that I will be **blocked** if I *intentionally* remove or skip any mandatory\\* field\n\n### Checklist\n\n- [X] I'm reporting that a **supported** site is broken\n- [X] I've verified that I'm running yt-dlp version **2023.03.04** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)\n- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details\n- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#video-url-contains-an-ampersand--and-im-getting-some-strange-output-1-2839-or-v-is-not-recognized-as-an-internal-or-external-command)\n- [X] I've searched [known issues](https://github.com/yt-dlp/yt-dlp/issues/3766) and the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues **including closed ones**. DO NOT post duplicates\n- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)\n- [X] I've read about [sharing account credentials](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#are-you-willing-to-share-account-details-if-needed) and I'm willing to share it if required\n\n### Region\n\nColombia\n\n### Provide a description that is worded well enough to be understood\n\nThe genius extractor currently doesn't work\n\n### Provide verbose output that clearly demonstrates the problem\n\n- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)\n- [X] If using API, add `'verbose': True` to `YoutubeDL` params instead\n- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below\n\n### Complete Verbose Output\n\n```shell\n[debug] Command-line config: ['-vU', 'https://genius.com/a/cordae-anderson-paak-break-down-the-meaning-of-two-tens']\r\n[debug] Encodings: locale cp1252, fs utf-8, pref cp1252, out utf-8, error utf-8, screen utf-8\r\n[debug] yt-dlp version nightly@2023.03.06.190223 [d4e6ef407] (win_exe)\r\n[debug] Python 3.8.10 (CPython AMD64 64bit) - Windows-10-10.0.19045-SP0 (OpenSSL 1.1.1k  25 Mar 2021)\r\n[debug] exe versions: ffmpeg N-109920-gac6eec1fc2-20230224 (setts), ffprobe N-109920-gac6eec1fc2-20230224\r\n[debug] Optional libraries: Cryptodome-3.17, brotli-1.0.9, certifi-2022.12.07, mutagen-1.46.0, sqlite3-2.6.0, websockets-10.4\r\n[debug] Proxy map: {}\r\n[debug] Loaded 1788 extractors\r\n[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp-nightly-builds/releases/latest\r\nAvailable version: nightly@2023.03.06.190223, Current version: nightly@2023.03.06.190223\r\nCurrent Build Hash: 7c51ebf2a7a9e1f199547cd8dad7df7713655f1c91a95f7e49764a513c52d6b1\r\nyt-dlp is up to date (nightly@2023.03.06.190223)\r\n[generic] Extracting URL: https://genius.com/a/cordae-anderson-paak-break-down-the-meaning-of-two-tens\r\n[generic] cordae-anderson-paak-break-down-the-meaning-of-two-tens: Downloading webpage\r\nWARNING: [generic] Falling back on generic information extractor\r\n[generic] cordae-anderson-paak-break-down-the-meaning-of-two-tens: Extracting information\r\n[debug] Looking for embeds\r\nERROR: Unsupported URL: https://genius.com/a/cordae-anderson-paak-break-down-the-meaning-of-two-tens\r\nTraceback (most recent call last):\r\n  File \"yt_dlp\\YoutubeDL.py\", line 1518, in wrapper\r\n  File \"yt_dlp\\YoutubeDL.py\", line 1594, in __extract_info\r\n  File \"yt_dlp\\extractor\\common.py\", line 694, in extract\r\n  File \"yt_dlp\\extractor\\generic.py\", line 2510, in _real_extract\r\nyt_dlp.utils.UnsupportedError: Unsupported URL: https://genius.com/a/cordae-anderson-paak-break-down-the-meaning-of-two-tens\n```\n\n", "before_files": [{"content": "from .common import InfoExtractor\nfrom ..utils import (\n    ExtractorError,\n    js_to_json,\n    smuggle_url,\n    str_or_none,\n    traverse_obj,\n    unescapeHTML,\n)\n\n\nclass GeniusIE(InfoExtractor):\n    _VALID_URL = r'https?://(?:www\\.)?genius\\.com/videos/(?P<id>[^?/#]+)'\n    _TESTS = [{\n        'url': 'https://genius.com/videos/Vince-staples-breaks-down-the-meaning-of-when-sparks-fly',\n        'md5': '64c2ad98cfafcfda23bfa0ad0c512f4c',\n        'info_dict': {\n            'id': '6313303597112',\n            'ext': 'mp4',\n            'title': 'Vince Staples Breaks Down The Meaning Of \u201cWhen Sparks Fly\u201d',\n            'description': 'md5:bc15e00342c537c0039d414423ae5752',\n            'tags': 'count:1',\n            'uploader_id': '4863540648001',\n            'duration': 388.416,\n            'upload_date': '20221005',\n            'timestamp': 1664982341,\n            'thumbnail': r're:^https?://.*\\.jpg$',\n        },\n    }, {\n        'url': 'https://genius.com/videos/Breaking-down-drakes-certified-lover-boy-kanye-beef-way-2-sexy-cudi',\n        'md5': 'b8ed87a5efd1473bd027c20a969d4060',\n        'info_dict': {\n            'id': '6271792014001',\n            'ext': 'mp4',\n            'title': 'md5:c6355f7fa8a70bc86492a3963919fc15',\n            'description': 'md5:1774638c31548b31b037c09e9b821393',\n            'tags': 'count:3',\n            'uploader_id': '4863540648001',\n            'duration': 2685.099,\n            'upload_date': '20210909',\n            'timestamp': 1631209167,\n            'thumbnail': r're:^https?://.*\\.jpg$',\n        },\n    }]\n\n    def _real_extract(self, url):\n        display_id = self._match_id(url)\n        webpage = self._download_webpage(url, display_id)\n\n        metadata = self._search_json(\n            r'<meta content=\"', webpage, 'metadata', display_id, transform_source=unescapeHTML)\n        video_id = traverse_obj(\n            metadata, ('video', 'provider_id'),\n            ('dfp_kv', lambda _, x: x['name'] == 'brightcove_video_id', 'values', 0), get_all=False)\n        if not video_id:\n            raise ExtractorError('Brightcove video id not found in webpage')\n\n        config = self._search_json(r'var\\s*APP_CONFIG\\s*=', webpage, 'config', video_id, default={})\n        account_id = config.get('brightcove_account_id', '4863540648001')\n        player_id = traverse_obj(\n            config, 'brightcove_standard_web_player_id', 'brightcove_standard_no_autoplay_web_player_id',\n            'brightcove_modal_web_player_id', 'brightcove_song_story_web_player_id', default='S1ZcmcOC1x')\n\n        return self.url_result(\n            smuggle_url(\n                f'https://players.brightcove.net/{account_id}/{player_id}_default/index.html?videoId={video_id}',\n                {'referrer': url}), 'BrightcoveNew', video_id)\n\n\nclass GeniusLyricsIE(InfoExtractor):\n    _VALID_URL = r'https?://(?:www\\.)?genius\\.com/(?P<id>[^?/#]+)-lyrics[?/#]?'\n    _TESTS = [{\n        'url': 'https://genius.com/Lil-baby-heyy-lyrics',\n        'playlist_mincount': 2,\n        'info_dict': {\n            'id': '8454545',\n            'title': 'Heyy',\n            'description': 'Heyy by Lil Baby',\n        },\n    }, {\n        'url': 'https://genius.com/Outkast-two-dope-boyz-in-a-cadillac-lyrics',\n        'playlist_mincount': 1,\n        'info_dict': {\n            'id': '36239',\n            'title': 'Two Dope Boyz (In a Cadillac)',\n            'description': 'Two Dope Boyz (In a Cadillac) by OutKast',\n        },\n    }, {\n        'url': 'https://genius.com/Playboi-carti-rip-lyrics',\n        'playlist_mincount': 1,\n        'info_dict': {\n            'id': '3710582',\n            'title': 'R.I.P.',\n            'description': 'R.I.P. by Playboi Carti',\n        },\n    }]\n\n    def _real_extract(self, url):\n        display_id = self._match_id(url)\n        webpage = self._download_webpage(url, display_id)\n\n        json_string = self._search_json(\n            r'window\\.__PRELOADED_STATE__\\s*=\\s*JSON\\.parse\\(', webpage, 'json string',\n            display_id, transform_source=js_to_json, contains_pattern=r'\\'{(?s:.+)}\\'')\n        song_info = self._parse_json(json_string, display_id)\n        song_id = str_or_none(traverse_obj(song_info, ('songPage', 'song')))\n        if not song_id:\n            raise ExtractorError('Song id not found in webpage')\n\n        title = traverse_obj(\n            song_info, ('songPage', 'trackingData', lambda _, x: x['key'] == 'Title', 'value'),\n            get_all=False, default='untitled')\n        artist = traverse_obj(\n            song_info, ('songPage', 'trackingData', lambda _, x: x['key'] == 'Primary Artist', 'value'),\n            get_all=False, default='unknown artist')\n        media = traverse_obj(\n            song_info, ('entities', 'songs', song_id, 'media'), expected_type=list, default=[])\n\n        entries = []\n        for m in media:\n            if m.get('type') in ('video', 'audio') and m.get('url'):\n                if m.get('provider') == 'spotify':\n                    self.to_screen(f'{song_id}: Skipping Spotify audio embed')\n                else:\n                    entries.append(self.url_result(m['url']))\n\n        return self.playlist_result(entries, song_id, title, f'{title} by {artist}')\n", "path": "yt_dlp/extractor/genius.py"}], "after_files": [{"content": "from .common import InfoExtractor\nfrom ..utils import (\n    ExtractorError,\n    js_to_json,\n    smuggle_url,\n    str_or_none,\n    traverse_obj,\n    unescapeHTML,\n)\n\n\nclass GeniusIE(InfoExtractor):\n    _VALID_URL = r'https?://(?:www\\.)?genius\\.com/(?:videos|(?P<article>a))/(?P<id>[^?/#]+)'\n    _TESTS = [{\n        'url': 'https://genius.com/videos/Vince-staples-breaks-down-the-meaning-of-when-sparks-fly',\n        'md5': '64c2ad98cfafcfda23bfa0ad0c512f4c',\n        'info_dict': {\n            'id': '6313303597112',\n            'ext': 'mp4',\n            'title': 'Vince Staples Breaks Down The Meaning Of \u201cWhen Sparks Fly\u201d',\n            'description': 'md5:bc15e00342c537c0039d414423ae5752',\n            'tags': 'count:1',\n            'uploader_id': '4863540648001',\n            'duration': 388.416,\n            'upload_date': '20221005',\n            'timestamp': 1664982341,\n            'thumbnail': r're:^https?://.*\\.jpg$',\n        },\n    }, {\n        'url': 'https://genius.com/videos/Breaking-down-drakes-certified-lover-boy-kanye-beef-way-2-sexy-cudi',\n        'md5': 'b8ed87a5efd1473bd027c20a969d4060',\n        'info_dict': {\n            'id': '6271792014001',\n            'ext': 'mp4',\n            'title': 'md5:c6355f7fa8a70bc86492a3963919fc15',\n            'description': 'md5:1774638c31548b31b037c09e9b821393',\n            'tags': 'count:3',\n            'uploader_id': '4863540648001',\n            'duration': 2685.099,\n            'upload_date': '20210909',\n            'timestamp': 1631209167,\n            'thumbnail': r're:^https?://.*\\.jpg$',\n        },\n    }, {\n        'url': 'https://genius.com/a/cordae-anderson-paak-break-down-the-meaning-of-two-tens',\n        'md5': 'f98a4e03b16b0a2821bd6e52fb3cc9d7',\n        'info_dict': {\n            'id': '6321509903112',\n            'ext': 'mp4',\n            'title': 'Cordae & Anderson .Paak Breaks Down The Meaning Of \u201cTwo Tens\u201d',\n            'description': 'md5:1255f0e1161d07342ce56a8464ac339d',\n            'tags': ['song id: 5457554'],\n            'uploader_id': '4863540648001',\n            'duration': 361.813,\n            'upload_date': '20230301',\n            'timestamp': 1677703908,\n            'thumbnail': r're:^https?://.*\\.jpg$',\n        },\n    }]\n\n    def _real_extract(self, url):\n        display_id, is_article = self._match_valid_url(url).group('id', 'article')\n        webpage = self._download_webpage(url, display_id)\n\n        metadata = self._search_json(\n            r'<meta content=\"', webpage, 'metadata', display_id,\n            end_pattern=r'\"\\s+itemprop=\"page_data\"', transform_source=unescapeHTML)\n        video_id = traverse_obj(metadata, (\n            (('article', 'media', ...), ('video', None)),\n            ('provider_id', ('dfp_kv', lambda _, v: v['name'] == 'brightcove_video_id', 'values', ...))),\n            get_all=False)\n        if not video_id:\n            # Not all article pages have videos, expect the error\n            raise ExtractorError('Brightcove video ID not found in webpage', expected=bool(is_article))\n\n        config = self._search_json(r'var\\s*APP_CONFIG\\s*=', webpage, 'config', video_id, default={})\n        account_id = config.get('brightcove_account_id', '4863540648001')\n        player_id = traverse_obj(\n            config, 'brightcove_standard_web_player_id', 'brightcove_standard_no_autoplay_web_player_id',\n            'brightcove_modal_web_player_id', 'brightcove_song_story_web_player_id', default='S1ZcmcOC1x')\n\n        return self.url_result(\n            smuggle_url(\n                f'https://players.brightcove.net/{account_id}/{player_id}_default/index.html?videoId={video_id}',\n                {'referrer': url}), 'BrightcoveNew', video_id)\n\n\nclass GeniusLyricsIE(InfoExtractor):\n    _VALID_URL = r'https?://(?:www\\.)?genius\\.com/(?P<id>[^?/#]+)-lyrics(?:[?/#]|$)'\n    _TESTS = [{\n        'url': 'https://genius.com/Lil-baby-heyy-lyrics',\n        'playlist_mincount': 2,\n        'info_dict': {\n            'id': '8454545',\n            'title': 'Heyy',\n            'description': 'Heyy by Lil Baby',\n        },\n    }, {\n        'url': 'https://genius.com/Outkast-two-dope-boyz-in-a-cadillac-lyrics',\n        'playlist_mincount': 1,\n        'info_dict': {\n            'id': '36239',\n            'title': 'Two Dope Boyz (In a Cadillac)',\n            'description': 'Two Dope Boyz (In a Cadillac) by OutKast',\n        },\n    }, {\n        'url': 'https://genius.com/Playboi-carti-rip-lyrics',\n        'playlist_mincount': 1,\n        'info_dict': {\n            'id': '3710582',\n            'title': 'R.I.P.',\n            'description': 'R.I.P. by Playboi Carti',\n        },\n    }]\n\n    def _real_extract(self, url):\n        display_id = self._match_id(url)\n        webpage = self._download_webpage(url, display_id)\n\n        json_string = self._search_json(\n            r'window\\.__PRELOADED_STATE__\\s*=\\s*JSON\\.parse\\(', webpage, 'json string',\n            display_id, transform_source=js_to_json, contains_pattern=r'\\'{(?s:.+)}\\'')\n        song_info = self._parse_json(json_string, display_id)\n        song_id = str_or_none(traverse_obj(song_info, ('songPage', 'song')))\n        if not song_id:\n            raise ExtractorError('Song id not found in webpage')\n\n        title = traverse_obj(\n            song_info, ('songPage', 'trackingData', lambda _, x: x['key'] == 'Title', 'value'),\n            get_all=False, default='untitled')\n        artist = traverse_obj(\n            song_info, ('songPage', 'trackingData', lambda _, x: x['key'] == 'Primary Artist', 'value'),\n            get_all=False, default='unknown artist')\n        media = traverse_obj(\n            song_info, ('entities', 'songs', song_id, 'media'), expected_type=list, default=[])\n\n        entries = []\n        for m in media:\n            if m.get('type') in ('video', 'audio') and m.get('url'):\n                if m.get('provider') == 'spotify':\n                    self.to_screen(f'{song_id}: Skipping Spotify audio embed')\n                else:\n                    entries.append(self.url_result(m['url']))\n\n        return self.playlist_result(entries, song_id, title, f'{title} by {artist}')\n", "path": "yt_dlp/extractor/genius.py"}]}