Repository: yt-dlp/yt-dlp

Issue:
peer.tv site request
### Checklist

- [X] I'm reporting a new site support request
- [X] I've verified that I'm running yt-dlp version **2021.11.10.1**. ([update instructions](https://github.com/yt-dlp/yt-dlp#update))
- [X] I've checked that all provided URLs are alive and playable in a browser
- [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)
- [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 am willing to share it if required

### Region

europe

### Example URLs

- Single video: https://www.peer.tv/de/841


### Description

Thank you for considering adding this site. And thank you again for this fantastic tool with its thousands of useful uses.

### Verbose log

```Batchfile
D:\portable programmes\Tools\FFMPEG>yt-dlp.exe -Uv --no-check-certificate https://www.peer.tv/de/841
[debug] Command-line config: ['-Uv', '--no-check-certificate', 'https://www.peer.tv/de/841']
[debug] Encodings: locale cp1252, fs utf-8, out utf-8, err utf-8, pref cp1252
[debug] yt-dlp version 2021.11.10.1 (win_exe)
[debug] Python version 3.8.10 (CPython 64bit) - Windows-10-10.0.19041-SP0
[debug] exe versions: ffmpeg 4.4-essentials_build-www.gyan.dev (setts), ffprobe 4.4-essentials_build-www.gyan.dev
[debug] Optional libraries: Cryptodome, mutagen, sqlite, websockets
[debug] Proxy map: {}
yt-dlp is up to date (2021.11.10.1)
[debug] [generic] Extracting URL: https://www.peer.tv/de/841
[generic] 841: Requesting header
WARNING: [generic] Falling back on generic information extractor.
[generic] 841: Downloading webpage
[generic] 841: Extracting information
[debug] Looking for video embeds
ERROR: Unsupported URL: https://www.peer.tv/de/841
Traceback (most recent call last):
  File "yt_dlp\YoutubeDL.py", line 1311, in wrapper
  File "yt_dlp\YoutubeDL.py", line 1336, in __extract_info
  File "yt_dlp\extractor\common.py", line 595, in extract
  File "yt_dlp\extractor\generic.py", line 3766, in _real_extract
yt_dlp.utils.UnsupportedError: Unsupported URL: https://www.peer.tv/de/841
```



Discussion:
Your verbose log is missing the version. Don't truncate it.
@Ashish0804 Thank you for pointing me and for your work on this issue, sir. The shell output is now replaced in the
above description.

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
@@ -1059,6 +1059,7 @@
     PeerTubeIE,
     PeerTubePlaylistIE,
 )
+from .peertv import PeerTVIE
 from .peloton import (
     PelotonIE,
     PelotonLiveIE
diff --git a/yt_dlp/extractor/peertv.py b/yt_dlp/extractor/peertv.py
new file mode 100644
--- /dev/null
+++ b/yt_dlp/extractor/peertv.py
@@ -0,0 +1,57 @@
+# coding: utf-8
+from __future__ import unicode_literals
+
+from .common import InfoExtractor
+from ..utils import js_to_json
+
+
+class PeerTVIE(InfoExtractor):
+    IE_NAME = 'peer.tv'
+    _VALID_URL = r'https?://(?:www\.)?peer\.tv/(?:de|it|en)/(?P<id>\d+)'
+    _TESTS = [{
+        'url': 'https://www.peer.tv/de/841',
+        'info_dict': {
+            'id': '841',
+            'ext': 'mp4',
+            'title': 'Die Brunnenburg',
+            'description': 'md5:4395f6142b090338340ab88a3aae24ed',
+        },
+    }, {
+        'url': 'https://www.peer.tv/it/404',
+        'info_dict': {
+            'id': '404',
+            'ext': 'mp4',
+            'title': 'Cascate di ghiaccio in Val Gardena',
+            'description': 'md5:e8e5907f236171842674e8090e3577b8',
+        },
+    }]
+
+    def _real_extract(self, url):
+        video_id = self._match_id(url)
+        webpage = self._download_webpage(url, video_id)
+
+        video_key = self._html_search_regex(r'player\.peer\.tv/js/([a-zA-Z0-9]+)', webpage, 'video key')
+
+        js = self._download_webpage(f'https://player.peer.tv/js/{video_key}/', video_id,
+                                    headers={'Referer': 'https://www.peer.tv/'}, note='Downloading session id')
+
+        session_id = self._search_regex(r'["\']session_id["\']:\s*["\']([a-zA-Z0-9]+)["\']', js, 'session id')
+
+        player_webpage = self._download_webpage(
+            f'https://player.peer.tv/jsc/{video_key}/{session_id}?jsr=aHR0cHM6Ly93d3cucGVlci50di9kZS84NDE=&cs=UTF-8&mq=2&ua=0&webm=p&mp4=p&hls=1',
+            video_id, note='Downloading player webpage')
+
+        m3u8_url = self._search_regex(r'["\']playlist_url["\']:\s*(["\'][^"\']+["\'])', player_webpage, 'm3u8 url')
+        m3u8_url = self._parse_json(m3u8_url, video_id, transform_source=js_to_json)
+
+        formats = self._extract_m3u8_formats(m3u8_url, video_id, m3u8_id='hls')
+
+        self._sort_formats(formats)
+
+        return {
+            'id': video_id,
+            'title': self._html_search_regex(r'<h1>(.+?)</h1>', webpage, 'title').replace('\xa0', ' '),
+            'formats': formats,
+            'description': self._html_search_meta(('og:description', 'description'), webpage),
+            'thumbnail': self._html_search_meta(('og:image', 'image'), webpage)
+        }


Test patch: