Repository: yt-dlp/yt-dlp

Issue:
medici.tv URLs Not Being Recognized by 'medici' Extractor
### 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 yt-dlp is broken on a **supported** site
- [X] I've verified that I have **updated yt-dlp to nightly or master** ([update instructions](https://github.com/yt-dlp/yt-dlp#update-channels))
- [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

Korea

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

I am experiencing an issue where yt-dlp is not recognizing URLs from medici.tv with the designated 'medici' extractor. Below is a detailed description of the problem:

When attempting to download videos from medici.tv using yt-dlp, the URLs are being treated as generic instead of being processed by the 'medici' extractor.

Example URL: An example of a URL that should be processed by the 'medici' extractor but is not is https://www.medici.tv/en/concerts/concours-de-geneve-international-music-competition-2023-flute-final-and-awards-ceremony

Testing and Debugging Attempts:

Initially, the regular expression for the medici extractor (`r'https?://(?:www\.)?medici\.tv/#!/(?P<id>[^?#&]+)`) did not match certain medici.tv URLs, such as the example URL.  To address this, I modified the regex to `r'https?://(?:www\.)?(?:medici|edu\.medici)\.tv/(?:(?:[a-zA-Z0-9-_\.]+)/)*(?:#!/)?(?P<id>[^?#&]+)'`. This change was intended to make the regex more flexible and inclusive of different URL patterns on medici.tv. Using Python's re module, I confirmed that the modified regex successfully matches the example medici.tv URL. However, when I run yt-dlp with this modified regex, the URLs are still treated as generic, and the medici extractor is not used. Using `--use-extractors medici` didn't help either.

At my current level of Python knowledge, this was the best I could do. Therefore, I would like you to fix the links to medici.tv are correctly recognised by the 'medici' extractor.

### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [ ] 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: ['--cookies-from-browser', 'firefox', 'https://www.medici.tv/en/concerts/concours-de-geneve-international-music-competition-2023-flute-final-and-awards-ceremony', '-vU']
Extracting cookies from firefox
[debug] Extracting cookies from: "C:\Users\ohdor\AppData\Roaming\Mozilla\Firefox\Profiles\69s8cetx.default-release\cookies.sqlite"
Extracted 2427 cookies from firefox
[debug] Encodings: locale cp949, fs utf-8, pref cp949, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.11.16 from yt-dlp/yt-dlp [24f827875] (pip)
[debug] Python 3.11.5 (CPython AMD64 64bit) - Windows-10-10.0.22621-SP0 (OpenSSL 3.0.9 30 May 2023)
[debug] exe versions: ffmpeg 2023-05-08-git-2d43c23b81-full_build-www.gyan.dev (setts), ffprobe 2023-05-08-git-2d43c23b81-full_build-www.gyan.dev
[debug] Optional libraries: Cryptodome-3.18.0, brotli-1.1.0, certifi-2023.07.22, mutagen-1.47.0, requests-2.31.0, sqlite3-3.42.0, urllib3-2.1.0, websockets-11.0.3
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests
[debug] Loaded 1901 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: stable@2023.11.16 from yt-dlp/yt-dlp
yt-dlp is up to date (stable@2023.11.16 from yt-dlp/yt-dlp)
[generic] Extracting URL: https://www.medici.tv/en/concerts/concours-de-geneve-international-music-competition-2023-flute-final-and-awards-ceremony
[generic] concours-de-geneve-international-music-competition-2023-flute-final-and-awards-ceremony: Downloading webpage
WARNING: [generic] Falling back on generic information extractor
[generic] concours-de-geneve-international-music-competition-2023-flute-final-and-awards-ceremony: Extracting information
[debug] Looking for embeds
ERROR: Unsupported URL: https://www.medici.tv/en/concerts/concours-de-geneve-international-music-competition-2023-flute-final-and-awards-ceremony
Traceback (most recent call last):
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\YoutubeDL.py", line 1567, in wrapper
    return func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\YoutubeDL.py", line 1702, in __extract_info
    ie_result = ie.extract(url)
                ^^^^^^^^^^^^^^^
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\common.py", line 715, in extract
    ie_result = self._real_extract(url)
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\generic.py", line 2578, in _real_extract
    raise UnsupportedError(url)
yt_dlp.utils.UnsupportedError: Unsupported URL: https://www.medici.tv/en/concerts/concours-de-geneve-international-music-competition-2023-flute-final-and-awards-ceremony

[debug] Command-line config: ['--cookies-from-browser', 'firefox', 'https://www.medici.tv/en/concerts/concours-de-geneve-international-music-competition-2023-flute-final-and-awards-ceremony', '--use-extractors', 'medici', '-vU']
Extracting cookies from firefox
[debug] Extracting cookies from: "C:\Users\ohdor\AppData\Roaming\Mozilla\Firefox\Profiles\69s8cetx.default-release\cookies.sqlite"
Extracted 2426 cookies from firefox
[debug] Encodings: locale cp949, fs utf-8, pref cp949, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.11.16 from yt-dlp/yt-dlp [24f827875] (pip)
[debug] Python 3.11.5 (CPython AMD64 64bit) - Windows-10-10.0.22621-SP0 (OpenSSL 3.0.9 30 May 2023)
[debug] exe versions: ffmpeg 2023-05-08-git-2d43c23b81-full_build-www.gyan.dev (setts), ffprobe 2023-05-08-git-2d43c23b81-full_build-www.gyan.dev
[debug] Optional libraries: Cryptodome-3.18.0, brotli-1.1.0, certifi-2023.07.22, mutagen-1.47.0, requests-2.31.0, sqlite3-3.42.0, urllib3-2.1.0, websockets-11.0.3
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests
[debug] Loaded 1 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: stable@2023.11.16 from yt-dlp/yt-dlp
yt-dlp is up to date (stable@2023.11.16 from yt-dlp/yt-dlp)
ERROR: No suitable extractor found for URL https://www.medici.tv/en/concerts/concours-de-geneve-international-music-competition-2023-flute-final-and-awards-ceremony
```



Discussion:
> Using Python's re module, I confirmed that the modified regex successfully matches the example [medici.tv](http://medici.tv) URL. However, when I run yt-dlp with this modified regex, the URLs are still treated as generic, and the medici extractor is not used.

`pip` installs are not meant to be editable. It'll work if you delete `extractors/lazy_extractors.py`
Now it is successfully processed by the Medici extractor, but it fails to get `csrftoken` cookie from the website. Here's verbose output:
```
[debug] Command-line config: ['https://www.medici.tv/en/concerts/concours-de-geneve-international-music-competition-2023-flute-final-and-awards-ceremony', '-vU']
[debug] Encodings: locale cp949, fs utf-8, pref cp949, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.11.16 from yt-dlp/yt-dlp [24f827875] (pip)
[debug] Lazy loading extractors is disabled
[debug] Python 3.11.5 (CPython AMD64 64bit) - Windows-10-10.0.22621-SP0 (OpenSSL 3.0.9 30 May 2023)
[debug] exe versions: ffmpeg 2023-05-08-git-2d43c23b81-full_build-www.gyan.dev (setts), ffprobe 2023-05-08-git-2d43c23b81-full_build-www.gyan.dev
[debug] Optional libraries: Cryptodome-3.18.0, brotli-1.1.0, certifi-2023.07.22, mutagen-1.47.0, requests-2.31.0, sqlite3-3.42.0, urllib3-2.1.0, websockets-11.0.3
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests
[debug] Loaded 1901 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: stable@2023.11.16 from yt-dlp/yt-dlp
yt-dlp is up to date (stable@2023.11.16 from yt-dlp/yt-dlp)
[Medici] Extracting URL: https://www.medici.tv/en/concerts/concours-de-geneve-international-music-competition-2023-flute-final-and-awards-ceremony
[Medici] concours-de-geneve-international-music-competition-2023-flute-final-and-awards-ceremony: Downloading webpage
ERROR: concours-de-geneve-international-music-competition-2023-flute-final-and-awards-ceremony: An extractor error has occurred. (caused by KeyError('csrftoken')); please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\common.py", line 715, in extract
    ie_result = self._real_extract(url)
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\medici.py", line 42, in _real_extract
    'X-CSRFToken': self._get_cookies(url)['csrftoken'].value,
                   ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
KeyError: 'csrftoken'
```
Now I found that there's a cookie named `csrftoken_satie`, so I change `'X-CSRFToken': self._get_cookies(url)['csrftoken'].value` into `'X-CSRFToken': self._get_cookies(url)['csrftoken_satie'].value` and now it seems that I overcame that part. However, I encountered another error:

```
[debug] Command-line config: ['--cookies-from-browser', 'firefox', '--write-subs', '--sub-langs', 'all', 'https://edu.medici.tv/en/operas/lady-macbeth-mtsensk-opera-de-paris-2019', '-vU']
Extracting cookies from firefox
[debug] Extracting cookies from: "C:\Users\ohdor\AppData\Roaming\Mozilla\Firefox\Profiles\69s8cetx.default-release\cookies.sqlite"
Extracted 2314 cookies from firefox
[debug] Encodings: locale cp949, fs utf-8, pref cp949, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.11.16 from yt-dlp/yt-dlp [24f827875] (pip)
[debug] Python 3.11.5 (CPython AMD64 64bit) - Windows-10-10.0.22621-SP0 (OpenSSL 3.0.9 30 May 2023)
[debug] exe versions: ffmpeg 2023-05-08-git-2d43c23b81-full_build-www.gyan.dev (setts), ffprobe 2023-05-08-git-2d43c23b81-full_build-www.gyan.dev
[debug] Optional libraries: Cryptodome-3.18.0, brotli-1.1.0, certifi-2023.07.22, mutagen-1.47.0, requests-2.31.0, sqlite3-3.42.0, urllib3-2.1.0, websockets-11.0.3
[debug] Proxy map: {}
[debug] Request Handlers: urllib, requests
[debug] Loaded 1901 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: stable@2023.11.16 from yt-dlp/yt-dlp
yt-dlp is up to date (stable@2023.11.16 from yt-dlp/yt-dlp)
[Medici] Extracting URL: https://edu.medici.tv/en/operas/lady-macbeth-mtsensk-opera-de-paris-2019
[Medici] lady-macbeth-mtsensk-opera-de-paris-2019: Downloading webpage
[Medici] lady-macbeth-mtsensk-opera-de-paris-2019: Downloading JSON metadata
ERROR: [Medici] lady-macbeth-mtsensk-opera-de-paris-2019: lady-macbeth-mtsensk-opera-de-paris-2019: Failed to parse JSON (caused by JSONDecodeError("Expecting value in '': line 1 column 1 (char 0)")); please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\common.py", line 715, in extract
    ie_result = self._real_extract(url)
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\medici.py", line 35, in _real_extract
    data = self._download_json(
           ^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\common.py", line 1069, in download_content
    res = getattr(self, download_handle.__name__)(url_or_request, video_id, **kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\common.py", line 1039, in download_handle
    return parse(self, content, video_id, transform_source=transform_source, fatal=fatal, errnote=errnote), urlh
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\common.py", line 1029, in parse
    return getattr(ie, parser)(content, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\common.py", line 1016, in _parse_json
    self.__print_error('Failed to parse JSON' if errnote is None else errnote, fatal, video_id, ve)
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\common.py", line 999, in __print_error
    raise ExtractorError(f'{video_id}: {errnote}', cause=err)

  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\utils\_utils.py", line 555, in decode
    return super().decode(s)
           ^^^^^^^^^^^^^^^^^
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\extractor\common.py", line 1013, in _parse_json
    return json.loads(
           ^^^^^^^^^^^
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\json\__init__.py", line 359, in loads
    return cls(**kw).decode(s)
           ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\ohdor\AppData\Local\Programs\Python\Python311\Lib\site-packages\yt_dlp\utils\_utils.py", line 563, in decode
    raise type(e)(f'{e.msg} in {s[e.pos-10:e.pos+10]!r}', s, e.pos)
json.decoder.JSONDecodeError: Expecting value in '': line 1 column 1 (char 0)
```

Resolving patch:
diff --git a/yt_dlp/extractor/generic.py b/yt_dlp/extractor/generic.py
--- a/yt_dlp/extractor/generic.py
+++ b/yt_dlp/extractor/generic.py
@@ -2104,22 +2104,6 @@ class GenericIE(InfoExtractor):
                 'age_limit': 0,
             },
         },
-        {
-            'note': 'JW Player embed with unicode-escape sequences in URL',
-            'url': 'https://www.medici.tv/en/concerts/lahav-shani-mozart-mahler-israel-philharmonic-abu-dhabi-classics',
-            'info_dict': {
-                'id': 'm',
-                'ext': 'mp4',
-                'title': 'Lahav Shani conducts the Israel Philharmonic\'s first-ever concert in Abu Dhabi',
-                'description': 'Mahler\'s ',
-                'uploader': 'www.medici.tv',
-                'age_limit': 0,
-                'thumbnail': r're:^https?://.+\.jpg',
-            },
-            'params': {
-                'skip_download': True,
-            },
-        },
         {
             'url': 'https://shooshtime.com/videos/284002/just-out-of-the-shower-joi/',
             'md5': 'e2f0a4c329f7986280b7328e24036d60',
diff --git a/yt_dlp/extractor/medici.py b/yt_dlp/extractor/medici.py
--- a/yt_dlp/extractor/medici.py
+++ b/yt_dlp/extractor/medici.py
@@ -1,67 +1,153 @@
+import urllib.parse
+
 from .common import InfoExtractor
 from ..utils import (
-    unified_strdate,
-    update_url_query,
-    urlencode_postdata,
+    filter_dict,
+    parse_iso8601,
+    traverse_obj,
+    try_call,
+    url_or_none,
 )
 
 
 class MediciIE(InfoExtractor):
-    _VALID_URL = r'https?://(?:www\.)?medici\.tv/#!/(?P<id>[^?#&]+)'
-    _TEST = {
-        'url': 'http://www.medici.tv/#!/daniel-harding-frans-helmerson-verbier-festival-music-camp',
-        'md5': '004c21bb0a57248085b6ff3fec72719d',
+    _VALID_URL = r'https?://(?:(?P<sub>www|edu)\.)?medici\.tv/[a-z]{2}/[\w.-]+/(?P<id>[^/?#&]+)'
+    _TESTS = [{
+        'url': 'https://www.medici.tv/en/operas/thomas-ades-the-exterminating-angel-calixto-bieito-opera-bastille-paris',
+        'md5': 'd483f74e7a7a9eac0dbe152ab189050d',
+        'info_dict': {
+            'id': '8032',
+            'ext': 'mp4',
+            'title': 'Thomas Adès\'s The Exterminating Angel',
+            'description': 'md5:708ae6350dadc604225b4a6e32482bab',
+            'thumbnail': r're:https://.+/.+\.jpg',
+            'upload_date': '20240304',
+            'timestamp': 1709561766,
+            'display_id': 'thomas-ades-the-exterminating-angel-calixto-bieito-opera-bastille-paris',
+        },
+        'expected_warnings': [r'preview'],
+    }, {
+        'url': 'https://edu.medici.tv/en/operas/wagner-lohengrin-paris-opera-kirill-serebrennikov-piotr-beczala-kwangchul-youn-johanni-van-oostrum',
+        'md5': '4ef3f4079a6e1c617584463a9eb84f99',
+        'info_dict': {
+            'id': '7900',
+            'ext': 'mp4',
+            'title': 'Wagner\'s Lohengrin',
+            'description': 'md5:a384a62937866101f86902f21752cd89',
+            'thumbnail': r're:https://.+/.+\.jpg',
+            'upload_date': '20231017',
+            'timestamp': 1697554771,
+            'display_id': 'wagner-lohengrin-paris-opera-kirill-serebrennikov-piotr-beczala-kwangchul-youn-johanni-van-oostrum',
+        },
+        'expected_warnings': [r'preview'],
+    }, {
+        'url': 'https://www.medici.tv/en/concerts/sergey-smbatyan-conducts-mansurian-chouchane-siranossian-mario-brunello',
+        'md5': '9dd757e53b22b2511e85ea9ea60e4815',
+        'info_dict': {
+            'id': '5712',
+            'ext': 'mp4',
+            'title': 'Sergey Smbatyan conducts Tigran Mansurian — With Chouchane Siranossian and Mario Brunello',
+            'thumbnail': r're:https://.+/.+\.jpg',
+            'description': 'md5:9411fe44c874bb10e9af288c65816e41',
+            'upload_date': '20200323',
+            'timestamp': 1584975600,
+            'display_id': 'sergey-smbatyan-conducts-mansurian-chouchane-siranossian-mario-brunello',
+        },
+        'expected_warnings': [r'preview'],
+    }, {
+        'url': 'https://www.medici.tv/en/ballets/carmen-ballet-choregraphie-de-jiri-bubenicek-teatro-dellopera-di-roma',
+        'md5': '40f5e76cb701a97a6d7ba23b62c49990',
+        'info_dict': {
+            'id': '7857',
+            'ext': 'mp4',
+            'title': 'Carmen by Jiří Bubeníček after Roland Petit, music by Bizet, de Falla, Castelnuovo-Tedesco, and Bonolis',
+            'thumbnail': r're:https://.+/.+\.jpg',
+            'description': 'md5:0f15a15611ed748020c769873e10a8bb',
+            'upload_date': '20240223',
+            'timestamp': 1708707600,
+            'display_id': 'carmen-ballet-choregraphie-de-jiri-bubenicek-teatro-dellopera-di-roma',
+        },
+        'expected_warnings': [r'preview'],
+    }, {
+        'url': 'https://www.medici.tv/en/documentaries/la-sonnambula-liege-2023-documentaire',
+        'md5': '87ff198018ce79a34757ab0dd6f21080',
+        'info_dict': {
+            'id': '7513',
+            'ext': 'mp4',
+            'title': 'La Sonnambula',
+            'thumbnail': r're:https://.+/.+\.jpg',
+            'description': 'md5:0caf9109a860fd50cd018df062a67f34',
+            'upload_date': '20231103',
+            'timestamp': 1699010830,
+            'display_id': 'la-sonnambula-liege-2023-documentaire',
+        },
+        'expected_warnings': [r'preview'],
+    }, {
+        'url': 'https://edu.medici.tv/en/masterclasses/yvonne-loriod-olivier-messiaen',
+        'md5': 'fb5dcec46d76ad20fbdbaabb01da191d',
+        'info_dict': {
+            'id': '3024',
+            'ext': 'mp4',
+            'title': 'Olivier Messiaen and Yvonne Loriod, pianists and teachers',
+            'thumbnail': r're:https://.+/.+\.jpg',
+            'description': 'md5:aab948e2f7690214b5c28896c83f1fc1',
+            'upload_date': '20150223',
+            'timestamp': 1424706608,
+            'display_id': 'yvonne-loriod-olivier-messiaen',
+        },
+        'skip': 'Requires authentication; preview starts in the middle',
+    }, {
+        'url': 'https://www.medici.tv/en/jazz/makaya-mccraven-la-rochelle',
+        'md5': '4cc279a8b06609782747c8f50beea2b3',
         'info_dict': {
-            'id': '3059',
-            'ext': 'flv',
-            'title': 'Daniel Harding conducts the Verbier Festival Music Camp \u2013 With Frans Helmerson',
-            'description': 'md5:322a1e952bafb725174fd8c1a8212f58',
-            'thumbnail': r're:^https?://.*\.jpg$',
-            'upload_date': '20170408',
+            'id': '7922',
+            'ext': 'mp4',
+            'title': 'NEW: Makaya McCraven in La Rochelle',
+            'thumbnail': r're:https://.+/.+\.jpg',
+            'description': 'md5:b5a8aaeb6993d8ccb18bde8abb8aa8d2',
+            'upload_date': '20231228',
+            'timestamp': 1703754863,
+            'display_id': 'makaya-mccraven-la-rochelle',
         },
-    }
+        'expected_warnings': [r'preview'],
+    }]
 
     def _real_extract(self, url):
-        video_id = self._match_id(url)
-
-        # Sets csrftoken cookie
-        self._download_webpage(url, video_id)
+        display_id, subdomain = self._match_valid_url(url).group('id', 'sub')
+        self._request_webpage(url, display_id, 'Requesting CSRF token cookie')
 
-        MEDICI_URL = 'http://www.medici.tv/'
+        subdomain = 'edu-' if subdomain == 'edu' else ''
+        origin = f'https://{urllib.parse.urlparse(url).hostname}'
 
         data = self._download_json(
-            MEDICI_URL, video_id,
-            data=urlencode_postdata({
-                'json': 'true',
-                'page': '/%s' % video_id,
-                'timezone_offset': -420,
-            }), headers={
-                'X-CSRFToken': self._get_cookies(url)['csrftoken'].value,
-                'X-Requested-With': 'XMLHttpRequest',
-                'Referer': MEDICI_URL,
-                'Content-Type': 'application/x-www-form-urlencoded',
-            })
-
-        video = data['video']['videos']['video1']
-
-        title = video.get('nom') or data['title']
+            f'https://api.medici.tv/{subdomain}satie/edito/movie-file/{display_id}/', display_id,
+            headers=filter_dict({
+                'Authorization': try_call(
+                    lambda: urllib.parse.unquote(self._get_cookies(url)['auth._token.mAuth'].value)),
+                'Device-Type': 'web',
+                'Origin': origin,
+                'Referer': f'{origin}/',
+                'Accept': 'application/json, text/plain, */*',
+            }))
 
-        video_id = video.get('id') or video_id
-        formats = self._extract_f4m_formats(
-            update_url_query(video['url_akamai'], {
-                'hdcore': '3.1.0',
-                'plugin=aasp': '3.1.0.43.124',
-            }), video_id, f4m_id='hds')
+        if not traverse_obj(data, ('video', 'is_full_video')) and traverse_obj(
+                data, ('video', 'is_limited_by_user_access')):
+            self.report_warning(
+                'The full video is for subscribers only. Only previews will be downloaded. If you '
+                'have used the --cookies-from-browser option, try using the --cookies option instead')
 
-        description = data.get('meta_description')
-        thumbnail = video.get('url_thumbnail') or data.get('main_image')
-        upload_date = unified_strdate(data['video'].get('date'))
+        formats, subtitles = self._extract_m3u8_formats_and_subtitles(
+            data['video']['video_url'], display_id, 'mp4')
 
         return {
-            'id': video_id,
-            'title': title,
-            'description': description,
-            'thumbnail': thumbnail,
-            'upload_date': upload_date,
+            'id': str(data['id']),
+            'display_id': display_id,
             'formats': formats,
+            'subtitles': subtitles,
+            **traverse_obj(data, {
+                'title': ('title', {str}),
+                'description': ('subtitle', {str}),
+                'thumbnail': ('picture', {url_or_none}),
+                'timestamp': ('date_publish', {parse_iso8601}),
+            }),
         }


Test patch: