Repository: yt-dlp/yt-dlp

Issue:
[RFE] Support arbeitsagentur.de / BerufeTV
### 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.08.08** ([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/ytdl-org/youtube-dl#can-you-add-support-for-this-anime-video-site-or-site-which-shows-current-movies-for-free) 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

Worldwide

### Example URLs

https://web.arbeitsagentur.de/berufetv/studienberufe/wirtschaftswissenschaften/wirtschaftswissenschaften-volkswirtschaft/film;filmId=DvKC3DUpMKvUZ_6fEnfg3u

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

This site is currently unsupported, and videos cannot be downloaded using the generic extractor. It would be nice if support could be added. Thank you!

### 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
$ yt-dlp -vU 'https://web.arbeitsagentur.de/berufetv/studienberufe/wirtschaftswissenschaften/wirtschaftswissenschaften-volkswirtschaft/film;filmId=DvKC3DUpMKvUZ_6fEnfg3u'
[debug] Command-line config: ['-vU', 'https://web.arbeitsagentur.de/berufetv/studienberufe/wirtschaftswissenschaften/wirtschaftswissenschaften-volkswirtschaft/film;filmId=DvKC3DUpMKvUZ_6fEnfg3u']
[debug] Encodings: locale cp1252, fs utf-8, pref cp1252, out cp1252 (No VT), error cp1252 (No VT), screen cp1252 (No VT)
[debug] yt-dlp version 2022.08.08 [3157158] (win32_exe)
[debug] Python 3.8.10 (CPython 64bit)
[debug] Checking exe version: ffmpeg -bsfs
[debug] Checking exe version: ffprobe -bsfs
[debug] exe versions: ffmpeg N-107213-gfed07efcde-20220622 (setts), ffprobe N-107213-gfed07efcde-20220622
[debug] Optional libraries: Cryptodome-3.15.0, brotli-1.0.9, certifi-2022.06.15, mutagen-1.45.1, sqlite3-2.6.0, websockets-10.3
[debug] Proxy map: {}
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: 2022.08.08, Current version: 2022.08.08
yt-dlp is up to date (2022.08.08)
[debug] [generic] Extracting URL: https://web.arbeitsagentur.de/berufetv/studienberufe/wirtschaftswissenschaften/wirtschaftswissenschaften-volkswirtschaft/film;filmId=DvKC3DUpMKvUZ_6fEnfg3u
[generic] film;filmId=DvKC3DUpMKvUZ_6fEnfg3u: Downloading webpage
WARNING: [generic] Falling back on generic information extractor
[generic] film;filmId=DvKC3DUpMKvUZ_6fEnfg3u: Extracting information
[debug] Looking for Brightcove embeds
[debug] Looking for embeds
ERROR: Unsupported URL: https://web.arbeitsagentur.de/berufetv/studienberufe/wirtschaftswissenschaften/wirtschaftswissenschaften-volkswirtschaft/film;filmId=DvKC3DUpMKvUZ_6fEnfg3u
Traceback (most recent call last):
  File "yt_dlp\YoutubeDL.py", line 1441, in wrapper
  File "yt_dlp\YoutubeDL.py", line 1517, in __extract_info
  File "yt_dlp\extractor\common.py", line 666, in extract
  File "yt_dlp\extractor\generic.py", line 3077, in _real_extract
yt_dlp.utils.UnsupportedError: Unsupported URL: https://web.arbeitsagentur.de/berufetv/studienberufe/wirtschaftswissenschaften/wirtschaftswissenschaften-volkswirtschaft/film;filmId=DvKC3DUpMKvUZ_6fEnfg3u
```



Discussion:

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
@@ -172,6 +172,7 @@
 from .behindkink import BehindKinkIE
 from .bellmedia import BellMediaIE
 from .beatport import BeatportIE
+from .berufetv import BerufeTVIE
 from .bet import BetIE
 from .bfi import BFIPlayerIE
 from .bfmtv import (
diff --git a/yt_dlp/extractor/berufetv.py b/yt_dlp/extractor/berufetv.py
new file mode 100644
--- /dev/null
+++ b/yt_dlp/extractor/berufetv.py
@@ -0,0 +1,70 @@
+from .common import InfoExtractor
+from ..utils import float_or_none, mimetype2ext, traverse_obj
+
+
+class BerufeTVIE(InfoExtractor):
+    _VALID_URL = r'https?://(?:www\.)?web\.arbeitsagentur\.de/berufetv/[^?#]+/film;filmId=(?P<id>[\w-]+)'
+    _TESTS = [{
+        'url': 'https://web.arbeitsagentur.de/berufetv/studienberufe/wirtschaftswissenschaften/wirtschaftswissenschaften-volkswirtschaft/film;filmId=DvKC3DUpMKvUZ_6fEnfg3u',
+        'md5': '041b6432ec8e6838f84a5c30f31cc795',
+        'info_dict': {
+            'id': 'DvKC3DUpMKvUZ_6fEnfg3u',
+            'ext': 'mp4',
+            'title': 'Volkswirtschaftslehre',
+            'description': 'md5:6bd87d0c63163480a6489a37526ee1c1',
+            'categories': ['Studien&shy;beruf'],
+            'tags': ['Studienfilm'],
+            'duration': 602.440,
+            'thumbnail': r're:^https://asset-out-cdn\.video-cdn\.net/private/videos/DvKC3DUpMKvUZ_6fEnfg3u/thumbnails/793063\?quality=thumbnail&__token__=[^\s]+$',
+        }
+    }]
+
+    def _real_extract(self, url):
+        video_id = self._match_id(url)
+
+        movie_metadata = self._download_json(
+            'https://rest.arbeitsagentur.de/infosysbub/berufetv/pc/v1/film-metadata',
+            video_id, 'Downloading JSON metadata',
+            headers={'X-API-Key': '79089773-4892-4386-86e6-e8503669f426'}, fatal=False)
+
+        meta = traverse_obj(
+            movie_metadata, ('metadaten', lambda _, i: video_id == i['miId']),
+            get_all=False, default={})
+
+        video = self._download_json(
+            f'https://d.video-cdn.net/play/player/8YRzUk6pTzmBdrsLe9Y88W/video/{video_id}',
+            video_id, 'Downloading video JSON')
+
+        formats, subtitles = [], {}
+        for key, source in video['videoSources']['html'].items():
+            if key == 'auto':
+                fmts, subs = self._extract_m3u8_formats_and_subtitles(source[0]['source'], video_id)
+                formats += fmts
+                subtitles = subs
+            else:
+                formats.append({
+                    'url': source[0]['source'],
+                    'ext': mimetype2ext(source[0]['mimeType']),
+                    'format_id': key,
+                })
+
+        for track in video.get('videoTracks') or []:
+            if track.get('type') != 'SUBTITLES':
+                continue
+            subtitles.setdefault(track['language'], []).append({
+                'url': track['source'],
+                'name': track.get('label'),
+                'ext': 'vtt'
+            })
+
+        return {
+            'id': video_id,
+            'title': meta.get('titel') or traverse_obj(video, ('videoMetaData', 'title')),
+            'description': meta.get('beschreibung'),
+            'thumbnail': meta.get('thumbnail') or f'https://asset-out-cdn.video-cdn.net/private/videos/{video_id}/thumbnails/active',
+            'duration': float_or_none(video.get('duration'), scale=1000),
+            'categories': [meta['kategorie']] if meta.get('kategorie') else None,
+            'tags': meta.get('themengebiete'),
+            'subtitles': subtitles,
+            'formats': formats,
+        }


Test patch: