Repository: yt-dlp/yt-dlp

Issue:
European Parliament Multimedia Centre (multimedia.europarl.europa.eu)
### DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE

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

### Checklist

- [X] I'm reporting a new site support request
- [X] I've verified that I'm running yt-dlp version **2022.09.01** ([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 none of provided URLs [violate any copyrights](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#is-the-website-primarily-used-for-piracy) or contain any [DRM](https://en.wikipedia.org/wiki/Digital_rights_management) to the best of my knowledge
- [X] I've searched 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)
- [ ] 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 am willing to share it if required

### Region

at least European Union, probably worldwide

### Example URLs

- full session: https://multimedia.europarl.europa.eu/pl/webstreaming/plenary-session_20220914-0900-PLENARY
- fragments: https://multimedia.europarl.europa.eu/en/event_20220914-0900-PLENARY_vd?start=20220914122648&end=20220914122800
- embed: https://webstreaming.europarl.europa.eu/ep/embed/embed.html?event=20220914-0900-PLENARY&language=en&autoplay=true&logo=true


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

DRM is asked by the website but not required, I successfully downloaded videos with a url I found in my browser's network logs: `yt-dlp https://d1asa0nzfd3bqt.cloudfront.net/groupc/live/bcaa1db4-76ef-7e06-8da7-839bd0ad1dbe/live.isml/.mpd\?t\=2022-09-14T12:26:48-2022-09-14T12:28:00 -f 'bestvideo+bestaudio[language=en]'`

### 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] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
[debug] Command-line config: ['-vU', 'https://multimedia.europarl.europa.eu/en/event_20220914-0900-PLENARY_vd?start=20220914122648&end=20220914122800']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version 2022.09.01 [5d7c7d6]
[debug] Python 3.10.7 (CPython 64bit) - Linux-5.15.67-0-lts-x86_64-with 
[debug] Checking exe version: ffmpeg -bsfs
[debug] Checking exe version: ffprobe -bsfs
[debug] exe versions: ffmpeg 5.1.1 (setts), ffprobe 5.1.1
[debug] Optional libraries: Crypto-3.15.0, brotli-1.0.9, certifi-2022.06.15, sqlite3-2.6.0
[debug] Proxy map: {}
[debug] Loaded 1670 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: 2022.09.01, Current version: 2022.09.01
yt-dlp is up to date (2022.09.01)
[debug] [generic] Extracting URL: https://multimedia.europarl.europa.eu/en/event_20220914-0900-PLENARY_vd?start=20220914122648&end=20220914122800
[generic] event_20220914-0900-PLENARY_vd?start=20220914122648&end=20220914122800: Downloading webpage
[redirect] Following redirect to https://multimedia.europarl.europa.eu/en/webstreaming/event_20220914-0900-PLENARY?start=20220914122648&end=20220914122800
[debug] [generic] Extracting URL: https://multimedia.europarl.europa.eu/en/webstreaming/event_20220914-0900-PLENARY?start=20220914122648&end=20220914122800
[generic] event_20220914-0900-PLENARY?start=20220914122648&end=20220914122800: Downloading webpage
WARNING: [generic] Falling back on generic information extractor
[generic] event_20220914-0900-PLENARY?start=20220914122648&end=20220914122800: Extracting information
[debug] Looking for Brightcove embeds
[debug] Looking for embeds
ERROR: Unsupported URL: https://multimedia.europarl.europa.eu/en/webstreaming/event_20220914-0900-PLENARY?start=20220914122648&end=20220914122800
Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/yt_dlp/YoutubeDL.py", line 1459, in wrapper
    return func(self, *args, **kwargs)
  File "/usr/lib/python3.10/site-packages/yt_dlp/YoutubeDL.py", line 1535, in __extract_info
    ie_result = ie.extract(url)
  File "/usr/lib/python3.10/site-packages/yt_dlp/extractor/common.py", line 670, in extract
    ie_result = self._real_extract(url)
  File "/usr/lib/python3.10/site-packages/yt_dlp/extractor/generic.py", line 3078, in _real_extract
    raise UnsupportedError(url)
yt_dlp.utils.UnsupportedError: Unsupported URL: https://multimedia.europarl.europa.eu/en/webstreaming/event_20220914-0900-PLENARY?start=20220914122648&end=20220914122800
```



Discussion:
> at least European Union, probably worldwide

I can access it here in Australia, so it's definitely not geoblocked


> DRM is asked by the website but not required

I can confirm
@pukkandan Oh, that message wasn't meant to be me triaging this (also, I didn't attempt to reproduce the issue)
it's a site support request, it's simply not implemented, and not a bug, I don't think there is anything to reproduce here
1. I'm not sure what the process of triaging an issue even involves (just that it involves reproducing the issue)
2. Theoretically I could check if I can reproduce the generic extractor not supporting that site
@gamer191 Triaging site request involve:
1. Try to confirm if it's actually a site request. Often site-bug tends to get reported as site request. Though, there are also circumstances where it can be difficult for even devs to distinguish them.
2. Check if the video is playable in browser (without DRM)
3. Make sure the site is not for piracy
4. Add relevant labels for geo-blocked and account-needed

Trying to reproduce isn't often needed when the log is properly filled up. I'm only looking for user errors and tend to assume lack of any malicious intend. So when the posted log has updated yt-dlp and says unsupported URL, it is blindly trusted

So yes, you did triage it even if that wasn't your intention

PS: Besides, selfisekai is a contributor and I have trust they know what they are doing - so I can skip some of these steps 😉 

Resolving patch:
diff --git a/yt_dlp/extractor/_extractors.py b/yt_dlp/extractor/_extractors.py
--- a/yt_dlp/extractor/_extractors.py
+++ b/yt_dlp/extractor/_extractors.py
@@ -531,7 +531,7 @@
     ESPNCricInfoIE,
 )
 from .esri import EsriVideoIE
-from .europa import EuropaIE
+from .europa import EuropaIE, EuroParlWebstreamIE
 from .europeantour import EuropeanTourIE
 from .eurosport import EurosportIE
 from .euscreen import EUScreenIE
diff --git a/yt_dlp/extractor/europa.py b/yt_dlp/extractor/europa.py
--- a/yt_dlp/extractor/europa.py
+++ b/yt_dlp/extractor/europa.py
@@ -3,6 +3,7 @@
     int_or_none,
     orderedSet,
     parse_duration,
+    parse_iso8601,
     parse_qs,
     qualities,
     unified_strdate,
@@ -88,3 +89,86 @@ def get_item(type_, preference):
             'view_count': view_count,
             'formats': formats
         }
+
+
+class EuroParlWebstreamIE(InfoExtractor):
+    _VALID_URL = r'''(?x)
+        https?://(?:multimedia|webstreaming)\.europarl\.europa\.eu/[^/#?]+/
+        (?:embed/embed\.html\?event=|(?!video)[^/#?]+/[\w-]+_)(?P<id>[\w-]+)
+    '''
+    _TESTS = [{
+        'url': 'https://multimedia.europarl.europa.eu/pl/webstreaming/plenary-session_20220914-0900-PLENARY',
+        'info_dict': {
+            'id': 'bcaa1db4-76ef-7e06-8da7-839bd0ad1dbe',
+            'ext': 'mp4',
+            'release_timestamp': 1663137900,
+            'title': 'Plenary session',
+            'release_date': '20220914',
+        },
+        'params': {
+            'skip_download': True,
+        }
+    }, {
+        'url': 'https://multimedia.europarl.europa.eu/pl/webstreaming/eu-cop27-un-climate-change-conference-in-sharm-el-sheikh-egypt-ep-delegation-meets-with-ngo-represen_20221114-1600-SPECIAL-OTHER',
+        'info_dict': {
+            'id': 'a8428de8-b9cd-6a2e-11e4-3805d9c9ff5c',
+            'ext': 'mp4',
+            'release_timestamp': 1668434400,
+            'release_date': '20221114',
+            'title': 'md5:d3550280c33cc70e0678652e3d52c028',
+        },
+        'params': {
+            'skip_download': True,
+        }
+    }, {
+        # embed webpage
+        'url': 'https://webstreaming.europarl.europa.eu/ep/embed/embed.html?event=20220914-0900-PLENARY&language=en&autoplay=true&logo=true',
+        'info_dict': {
+            'id': 'bcaa1db4-76ef-7e06-8da7-839bd0ad1dbe',
+            'ext': 'mp4',
+            'title': 'Plenary session',
+            'release_date': '20220914',
+            'release_timestamp': 1663137900,
+        },
+        'params': {
+            'skip_download': True,
+        }
+    }, {
+        # live webstream
+        'url': 'https://multimedia.europarl.europa.eu/en/webstreaming/euroscola_20221115-1000-SPECIAL-EUROSCOLA',
+        'info_dict': {
+            'ext': 'mp4',
+            'id': '510eda7f-ba72-161b-7ee7-0e836cd2e715',
+            'release_timestamp': 1668502800,
+            'title': 'Euroscola 2022-11-15 19:21',
+            'release_date': '20221115',
+            'live_status': 'is_live',
+        },
+        'skip': 'not live anymore'
+    }]
+
+    def _real_extract(self, url):
+        display_id = self._match_id(url)
+
+        json_info = self._download_json(
+            'https://vis-api.vuplay.co.uk/event/external', display_id,
+            query={
+                'player_key': 'europarl|718f822c-a48c-4841-9947-c9cb9bb1743c',
+                'external_id': display_id,
+            })
+
+        formats, subtitles = self._extract_mpd_formats_and_subtitles(json_info['streaming_url'], display_id)
+        fmts, subs = self._extract_m3u8_formats_and_subtitles(
+            json_info['streaming_url'].replace('.mpd', '.m3u8'), display_id)
+
+        formats.extend(fmts)
+        self._merge_subtitles(subs, target=subtitles)
+
+        return {
+            'id': json_info['id'],
+            'title': json_info.get('title'),
+            'formats': formats,
+            'subtitles': subtitles,
+            'release_timestamp': parse_iso8601(json_info.get('published_start')),
+            'is_live': 'LIVE' in json_info.get('state', '')
+        }


Test patch: