We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
RedTube DL don't work any more
### Checklist

- [X] I'm reporting a broken site
- [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 all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/ytdl-org/youtube-dl#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 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

_No response_

### Description

only downloaded a small file (893 btyes) which is obviously not the real video file...
sample url:
https://www.redtube.com/39016781

### Verbose log

```shell
Download Log for url: https://www.redtube.com/39016781

Waiting
[RedTube] 39016781: Downloading webpage
[RedTube] 39016781: Downloading m3u8 information
[info] 39016781: Downloading 1 format(s): 1
[download] Destination: C:\Users\Sony\xxx\Youtube-Dl\Cute Asian is fucked & creampied!-39016781.mp4
[download] 893.00B at 436.07KiB/s (00:02)
[download] 100% of 893.00B in 00:02
Download Worker Finished.
```


--- 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/redtube.py`
Content:
```
1 from __future__ import unicode_literals
2 
3 import re
4 
5 from .common import InfoExtractor
6 from ..utils import (
7     determine_ext,
8     ExtractorError,
9     int_or_none,
10     merge_dicts,
11     str_to_int,
12     unified_strdate,
13     url_or_none,
14 )
15 
16 
17 class RedTubeIE(InfoExtractor):
18     _VALID_URL = r'https?://(?:(?:\w+\.)?redtube\.com/|embed\.redtube\.com/\?.*?\bid=)(?P<id>[0-9]+)'
19     _TESTS = [{
20         'url': 'http://www.redtube.com/66418',
21         'md5': 'fc08071233725f26b8f014dba9590005',
22         'info_dict': {
23             'id': '66418',
24             'ext': 'mp4',
25             'title': 'Sucked on a toilet',
26             'upload_date': '20110811',
27             'duration': 596,
28             'view_count': int,
29             'age_limit': 18,
30         }
31     }, {
32         'url': 'http://embed.redtube.com/?bgcolor=000000&id=1443286',
33         'only_matching': True,
34     }, {
35         'url': 'http://it.redtube.com/66418',
36         'only_matching': True,
37     }]
38 
39     @staticmethod
40     def _extract_urls(webpage):
41         return re.findall(
42             r'<iframe[^>]+?src=["\'](?P<url>(?:https?:)?//embed\.redtube\.com/\?.*?\bid=\d+)',
43             webpage)
44 
45     def _real_extract(self, url):
46         video_id = self._match_id(url)
47         webpage = self._download_webpage(
48             'http://www.redtube.com/%s' % video_id, video_id)
49 
50         ERRORS = (
51             (('video-deleted-info', '>This video has been removed'), 'has been removed'),
52             (('private_video_text', '>This video is private', '>Send a friend request to its owner to be able to view it'), 'is private'),
53         )
54 
55         for patterns, message in ERRORS:
56             if any(p in webpage for p in patterns):
57                 raise ExtractorError(
58                     'Video %s %s' % (video_id, message), expected=True)
59 
60         info = self._search_json_ld(webpage, video_id, default={})
61 
62         if not info.get('title'):
63             info['title'] = self._html_search_regex(
64                 (r'<h(\d)[^>]+class="(?:video_title_text|videoTitle|video_title)[^"]*">(?P<title>(?:(?!\1).)+)</h\1>',
65                  r'(?:videoTitle|title)\s*:\s*(["\'])(?P<title>(?:(?!\1).)+)\1',),
66                 webpage, 'title', group='title',
67                 default=None) or self._og_search_title(webpage)
68 
69         formats = []
70         sources = self._parse_json(
71             self._search_regex(
72                 r'sources\s*:\s*({.+?})', webpage, 'source', default='{}'),
73             video_id, fatal=False)
74         if sources and isinstance(sources, dict):
75             for format_id, format_url in sources.items():
76                 if format_url:
77                     formats.append({
78                         'url': format_url,
79                         'format_id': format_id,
80                         'height': int_or_none(format_id),
81                     })
82         medias = self._parse_json(
83             self._search_regex(
84                 r'mediaDefinition["\']?\s*:\s*(\[.+?}\s*\])', webpage,
85                 'media definitions', default='{}'),
86             video_id, fatal=False)
87         if medias and isinstance(medias, list):
88             for media in medias:
89                 format_url = url_or_none(media.get('videoUrl'))
90                 if not format_url:
91                     continue
92                 if media.get('format') == 'hls' or determine_ext(format_url) == 'm3u8':
93                     formats.extend(self._extract_m3u8_formats(
94                         format_url, video_id, 'mp4',
95                         entry_protocol='m3u8_native', m3u8_id='hls',
96                         fatal=False))
97                     continue
98                 format_id = media.get('quality')
99                 formats.append({
100                     'url': format_url,
101                     'ext': 'mp4',
102                     'format_id': format_id,
103                     'height': int_or_none(format_id),
104                 })
105         if not formats:
106             video_url = self._html_search_regex(
107                 r'<source src="(.+?)" type="video/mp4">', webpage, 'video URL')
108             formats.append({'url': video_url, 'ext': 'mp4'})
109         self._sort_formats(formats)
110 
111         thumbnail = self._og_search_thumbnail(webpage)
112         upload_date = unified_strdate(self._search_regex(
113             r'<span[^>]+>(?:ADDED|Published on) ([^<]+)<',
114             webpage, 'upload date', default=None))
115         duration = int_or_none(self._og_search_property(
116             'video:duration', webpage, default=None) or self._search_regex(
117                 r'videoDuration\s*:\s*(\d+)', webpage, 'duration', default=None))
118         view_count = str_to_int(self._search_regex(
119             (r'<div[^>]*>Views</div>\s*<div[^>]*>\s*([\d,.]+)',
120              r'<span[^>]*>VIEWS</span>\s*</td>\s*<td>\s*([\d,.]+)',
121              r'<span[^>]+\bclass=["\']video_view_count[^>]*>\s*([\d,.]+)'),
122             webpage, 'view count', default=None))
123 
124         # No self-labeling, but they describe themselves as
125         # "Home of Videos Porno"
126         age_limit = 18
127 
128         return merge_dicts(info, {
129             'id': video_id,
130             'ext': 'mp4',
131             'thumbnail': thumbnail,
132             'upload_date': upload_date,
133             'duration': duration,
134             'view_count': view_count,
135             'age_limit': age_limit,
136             'formats': formats,
137         })
138
```
--- 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/redtube.py b/yt_dlp/extractor/redtube.py
--- a/yt_dlp/extractor/redtube.py
+++ b/yt_dlp/extractor/redtube.py
@@ -17,17 +17,20 @@
 class RedTubeIE(InfoExtractor):
     _VALID_URL = r'https?://(?:(?:\w+\.)?redtube\.com/|embed\.redtube\.com/\?.*?\bid=)(?P<id>[0-9]+)'
     _TESTS = [{
-        'url': 'http://www.redtube.com/66418',
-        'md5': 'fc08071233725f26b8f014dba9590005',
+        'url': 'https://www.redtube.com/38864951',
+        'md5': '4fba70cbca3aefd25767ab4b523c9878',
         'info_dict': {
-            'id': '66418',
+            'id': '38864951',
             'ext': 'mp4',
-            'title': 'Sucked on a toilet',
-            'upload_date': '20110811',
-            'duration': 596,
+            'title': 'Public Sex on the Balcony in Freezing Paris! Amateur Couple LeoLulu',
+            'description': 'Watch video Public Sex on the Balcony in Freezing Paris! Amateur Couple LeoLulu on Redtube, home of free Blowjob porn videos and Blonde sex movies online. Video length: (10:46) - Uploaded by leolulu - Verified User - Starring Pornstar: Leolulu',
+            'upload_date': '20210111',
+            'timestamp': 1610343109,
+            'duration': 646,
             'view_count': int,
             'age_limit': 18,
-        }
+            'thumbnail': r're:https://\wi-ph\.rdtcdn\.com/videos/.+/.+\.jpg',
+        },
     }, {
         'url': 'http://embed.redtube.com/?bgcolor=000000&id=1443286',
         'only_matching': True,
@@ -84,15 +87,25 @@
                 r'mediaDefinition["\']?\s*:\s*(\[.+?}\s*\])', webpage,
                 'media definitions', default='{}'),
             video_id, fatal=False)
-        if medias and isinstance(medias, list):
-            for media in medias:
+        for media in medias if isinstance(medias, list) else []:
+            format_url = url_or_none(media.get('videoUrl'))
+            if not format_url:
+                continue
+            format_id = media.get('format')
+            quality = media.get('quality')
+            if format_id == 'hls' or (format_id == 'mp4' and not quality):
+                more_media = self._download_json(format_url, video_id, fatal=False)
+            else:
+                more_media = [media]
+            for media in more_media if isinstance(more_media, list) else []:
                 format_url = url_or_none(media.get('videoUrl'))
                 if not format_url:
                     continue
-                if media.get('format') == 'hls' or determine_ext(format_url) == 'm3u8':
+                format_id = media.get('format')
+                if format_id == 'hls' or determine_ext(format_url) == 'm3u8':
                     formats.extend(self._extract_m3u8_formats(
                         format_url, video_id, 'mp4',
-                        entry_protocol='m3u8_native', m3u8_id='hls',
+                        entry_protocol='m3u8_native', m3u8_id=format_id or 'hls',
                         fatal=False))
                     continue
                 format_id = media.get('quality')

{"golden_diff": "diff --git a/yt_dlp/extractor/redtube.py b/yt_dlp/extractor/redtube.py\n--- a/yt_dlp/extractor/redtube.py\n+++ b/yt_dlp/extractor/redtube.py\n@@ -17,17 +17,20 @@\n class RedTubeIE(InfoExtractor):\n     _VALID_URL = r'https?://(?:(?:\\w+\\.)?redtube\\.com/|embed\\.redtube\\.com/\\?.*?\\bid=)(?P<id>[0-9]+)'\n     _TESTS = [{\n-        'url': 'http://www.redtube.com/66418',\n-        'md5': 'fc08071233725f26b8f014dba9590005',\n+        'url': 'https://www.redtube.com/38864951',\n+        'md5': '4fba70cbca3aefd25767ab4b523c9878',\n         'info_dict': {\n-            'id': '66418',\n+            'id': '38864951',\n             'ext': 'mp4',\n-            'title': 'Sucked on a toilet',\n-            'upload_date': '20110811',\n-            'duration': 596,\n+            'title': 'Public Sex on the Balcony in Freezing Paris! Amateur Couple LeoLulu',\n+            'description': 'Watch video Public Sex on the Balcony in Freezing Paris! Amateur Couple LeoLulu on Redtube, home of free Blowjob porn videos and Blonde sex movies online. Video length: (10:46) - Uploaded by leolulu - Verified User - Starring Pornstar: Leolulu',\n+            'upload_date': '20210111',\n+            'timestamp': 1610343109,\n+            'duration': 646,\n             'view_count': int,\n             'age_limit': 18,\n-        }\n+            'thumbnail': r're:https://\\wi-ph\\.rdtcdn\\.com/videos/.+/.+\\.jpg',\n+        },\n     }, {\n         'url': 'http://embed.redtube.com/?bgcolor=000000&id=1443286',\n         'only_matching': True,\n@@ -84,15 +87,25 @@\n                 r'mediaDefinition[\"\\']?\\s*:\\s*(\\[.+?}\\s*\\])', webpage,\n                 'media definitions', default='{}'),\n             video_id, fatal=False)\n-        if medias and isinstance(medias, list):\n-            for media in medias:\n+        for media in medias if isinstance(medias, list) else []:\n+            format_url = url_or_none(media.get('videoUrl'))\n+            if not format_url:\n+                continue\n+            format_id = media.get('format')\n+            quality = media.get('quality')\n+            if format_id == 'hls' or (format_id == 'mp4' and not quality):\n+                more_media = self._download_json(format_url, video_id, fatal=False)\n+            else:\n+                more_media = [media]\n+            for media in more_media if isinstance(more_media, list) else []:\n                 format_url = url_or_none(media.get('videoUrl'))\n                 if not format_url:\n                     continue\n-                if media.get('format') == 'hls' or determine_ext(format_url) == 'm3u8':\n+                format_id = media.get('format')\n+                if format_id == 'hls' or determine_ext(format_url) == 'm3u8':\n                     formats.extend(self._extract_m3u8_formats(\n                         format_url, video_id, 'mp4',\n-                        entry_protocol='m3u8_native', m3u8_id='hls',\n+                        entry_protocol='m3u8_native', m3u8_id=format_id or 'hls',\n                         fatal=False))\n                     continue\n                 format_id = media.get('quality')\n", "issue": "RedTube DL don't work any more\n### Checklist\n\n- [X] I'm reporting a broken site\n- [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))\n- [X] I've checked that all provided URLs are alive and playable in a browser\n- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/ytdl-org/youtube-dl#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 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\n_No response_\n\n### Description\n\nonly downloaded a small file (893 btyes) which is obviously not the real video file...\r\nsample url:\r\nhttps://www.redtube.com/39016781\n\n### Verbose log\n\n```shell\nDownload Log for url: https://www.redtube.com/39016781\r\n\r\nWaiting\r\n[RedTube] 39016781: Downloading webpage\r\n[RedTube] 39016781: Downloading m3u8 information\r\n[info] 39016781: Downloading 1 format(s): 1\r\n[download] Destination: C:\\Users\\Sony\\xxx\\Youtube-Dl\\Cute Asian is fucked & creampied!-39016781.mp4\r\n[download] 893.00B at 436.07KiB/s (00:02)\r\n[download] 100% of 893.00B in 00:02\r\nDownload Worker Finished.\n```\n\n", "before_files": [{"content": "from __future__ import unicode_literals\n\nimport re\n\nfrom .common import InfoExtractor\nfrom ..utils import (\n    determine_ext,\n    ExtractorError,\n    int_or_none,\n    merge_dicts,\n    str_to_int,\n    unified_strdate,\n    url_or_none,\n)\n\n\nclass RedTubeIE(InfoExtractor):\n    _VALID_URL = r'https?://(?:(?:\\w+\\.)?redtube\\.com/|embed\\.redtube\\.com/\\?.*?\\bid=)(?P<id>[0-9]+)'\n    _TESTS = [{\n        'url': 'http://www.redtube.com/66418',\n        'md5': 'fc08071233725f26b8f014dba9590005',\n        'info_dict': {\n            'id': '66418',\n            'ext': 'mp4',\n            'title': 'Sucked on a toilet',\n            'upload_date': '20110811',\n            'duration': 596,\n            'view_count': int,\n            'age_limit': 18,\n        }\n    }, {\n        'url': 'http://embed.redtube.com/?bgcolor=000000&id=1443286',\n        'only_matching': True,\n    }, {\n        'url': 'http://it.redtube.com/66418',\n        'only_matching': True,\n    }]\n\n    @staticmethod\n    def _extract_urls(webpage):\n        return re.findall(\n            r'<iframe[^>]+?src=[\"\\'](?P<url>(?:https?:)?//embed\\.redtube\\.com/\\?.*?\\bid=\\d+)',\n            webpage)\n\n    def _real_extract(self, url):\n        video_id = self._match_id(url)\n        webpage = self._download_webpage(\n            'http://www.redtube.com/%s' % video_id, video_id)\n\n        ERRORS = (\n            (('video-deleted-info', '>This video has been removed'), 'has been removed'),\n            (('private_video_text', '>This video is private', '>Send a friend request to its owner to be able to view it'), 'is private'),\n        )\n\n        for patterns, message in ERRORS:\n            if any(p in webpage for p in patterns):\n                raise ExtractorError(\n                    'Video %s %s' % (video_id, message), expected=True)\n\n        info = self._search_json_ld(webpage, video_id, default={})\n\n        if not info.get('title'):\n            info['title'] = self._html_search_regex(\n                (r'<h(\\d)[^>]+class=\"(?:video_title_text|videoTitle|video_title)[^\"]*\">(?P<title>(?:(?!\\1).)+)</h\\1>',\n                 r'(?:videoTitle|title)\\s*:\\s*([\"\\'])(?P<title>(?:(?!\\1).)+)\\1',),\n                webpage, 'title', group='title',\n                default=None) or self._og_search_title(webpage)\n\n        formats = []\n        sources = self._parse_json(\n            self._search_regex(\n                r'sources\\s*:\\s*({.+?})', webpage, 'source', default='{}'),\n            video_id, fatal=False)\n        if sources and isinstance(sources, dict):\n            for format_id, format_url in sources.items():\n                if format_url:\n                    formats.append({\n                        'url': format_url,\n                        'format_id': format_id,\n                        'height': int_or_none(format_id),\n                    })\n        medias = self._parse_json(\n            self._search_regex(\n                r'mediaDefinition[\"\\']?\\s*:\\s*(\\[.+?}\\s*\\])', webpage,\n                'media definitions', default='{}'),\n            video_id, fatal=False)\n        if medias and isinstance(medias, list):\n            for media in medias:\n                format_url = url_or_none(media.get('videoUrl'))\n                if not format_url:\n                    continue\n                if media.get('format') == 'hls' or determine_ext(format_url) == 'm3u8':\n                    formats.extend(self._extract_m3u8_formats(\n                        format_url, video_id, 'mp4',\n                        entry_protocol='m3u8_native', m3u8_id='hls',\n                        fatal=False))\n                    continue\n                format_id = media.get('quality')\n                formats.append({\n                    'url': format_url,\n                    'ext': 'mp4',\n                    'format_id': format_id,\n                    'height': int_or_none(format_id),\n                })\n        if not formats:\n            video_url = self._html_search_regex(\n                r'<source src=\"(.+?)\" type=\"video/mp4\">', webpage, 'video URL')\n            formats.append({'url': video_url, 'ext': 'mp4'})\n        self._sort_formats(formats)\n\n        thumbnail = self._og_search_thumbnail(webpage)\n        upload_date = unified_strdate(self._search_regex(\n            r'<span[^>]+>(?:ADDED|Published on) ([^<]+)<',\n            webpage, 'upload date', default=None))\n        duration = int_or_none(self._og_search_property(\n            'video:duration', webpage, default=None) or self._search_regex(\n                r'videoDuration\\s*:\\s*(\\d+)', webpage, 'duration', default=None))\n        view_count = str_to_int(self._search_regex(\n            (r'<div[^>]*>Views</div>\\s*<div[^>]*>\\s*([\\d,.]+)',\n             r'<span[^>]*>VIEWS</span>\\s*</td>\\s*<td>\\s*([\\d,.]+)',\n             r'<span[^>]+\\bclass=[\"\\']video_view_count[^>]*>\\s*([\\d,.]+)'),\n            webpage, 'view count', default=None))\n\n        # No self-labeling, but they describe themselves as\n        # \"Home of Videos Porno\"\n        age_limit = 18\n\n        return merge_dicts(info, {\n            'id': video_id,\n            'ext': 'mp4',\n            'thumbnail': thumbnail,\n            'upload_date': upload_date,\n            'duration': duration,\n            'view_count': view_count,\n            'age_limit': age_limit,\n            'formats': formats,\n        })\n", "path": "yt_dlp/extractor/redtube.py"}], "after_files": [{"content": "from __future__ import unicode_literals\n\nimport re\n\nfrom .common import InfoExtractor\nfrom ..utils import (\n    determine_ext,\n    ExtractorError,\n    int_or_none,\n    merge_dicts,\n    str_to_int,\n    unified_strdate,\n    url_or_none,\n)\n\n\nclass RedTubeIE(InfoExtractor):\n    _VALID_URL = r'https?://(?:(?:\\w+\\.)?redtube\\.com/|embed\\.redtube\\.com/\\?.*?\\bid=)(?P<id>[0-9]+)'\n    _TESTS = [{\n        'url': 'https://www.redtube.com/38864951',\n        'md5': '4fba70cbca3aefd25767ab4b523c9878',\n        'info_dict': {\n            'id': '38864951',\n            'ext': 'mp4',\n            'title': 'Public Sex on the Balcony in Freezing Paris! Amateur Couple LeoLulu',\n            'description': 'Watch video Public Sex on the Balcony in Freezing Paris! Amateur Couple LeoLulu on Redtube, home of free Blowjob porn videos and Blonde sex movies online. Video length: (10:46) - Uploaded by leolulu - Verified User - Starring Pornstar: Leolulu',\n            'upload_date': '20210111',\n            'timestamp': 1610343109,\n            'duration': 646,\n            'view_count': int,\n            'age_limit': 18,\n            'thumbnail': r're:https://\\wi-ph\\.rdtcdn\\.com/videos/.+/.+\\.jpg',\n        },\n    }, {\n        'url': 'http://embed.redtube.com/?bgcolor=000000&id=1443286',\n        'only_matching': True,\n    }, {\n        'url': 'http://it.redtube.com/66418',\n        'only_matching': True,\n    }]\n\n    @staticmethod\n    def _extract_urls(webpage):\n        return re.findall(\n            r'<iframe[^>]+?src=[\"\\'](?P<url>(?:https?:)?//embed\\.redtube\\.com/\\?.*?\\bid=\\d+)',\n            webpage)\n\n    def _real_extract(self, url):\n        video_id = self._match_id(url)\n        webpage = self._download_webpage(\n            'http://www.redtube.com/%s' % video_id, video_id)\n\n        ERRORS = (\n            (('video-deleted-info', '>This video has been removed'), 'has been removed'),\n            (('private_video_text', '>This video is private', '>Send a friend request to its owner to be able to view it'), 'is private'),\n        )\n\n        for patterns, message in ERRORS:\n            if any(p in webpage for p in patterns):\n                raise ExtractorError(\n                    'Video %s %s' % (video_id, message), expected=True)\n\n        info = self._search_json_ld(webpage, video_id, default={})\n\n        if not info.get('title'):\n            info['title'] = self._html_search_regex(\n                (r'<h(\\d)[^>]+class=\"(?:video_title_text|videoTitle|video_title)[^\"]*\">(?P<title>(?:(?!\\1).)+)</h\\1>',\n                 r'(?:videoTitle|title)\\s*:\\s*([\"\\'])(?P<title>(?:(?!\\1).)+)\\1',),\n                webpage, 'title', group='title',\n                default=None) or self._og_search_title(webpage)\n\n        formats = []\n        sources = self._parse_json(\n            self._search_regex(\n                r'sources\\s*:\\s*({.+?})', webpage, 'source', default='{}'),\n            video_id, fatal=False)\n        if sources and isinstance(sources, dict):\n            for format_id, format_url in sources.items():\n                if format_url:\n                    formats.append({\n                        'url': format_url,\n                        'format_id': format_id,\n                        'height': int_or_none(format_id),\n                    })\n        medias = self._parse_json(\n            self._search_regex(\n                r'mediaDefinition[\"\\']?\\s*:\\s*(\\[.+?}\\s*\\])', webpage,\n                'media definitions', default='{}'),\n            video_id, fatal=False)\n        for media in medias if isinstance(medias, list) else []:\n            format_url = url_or_none(media.get('videoUrl'))\n            if not format_url:\n                continue\n            format_id = media.get('format')\n            quality = media.get('quality')\n            if format_id == 'hls' or (format_id == 'mp4' and not quality):\n                more_media = self._download_json(format_url, video_id, fatal=False)\n            else:\n                more_media = [media]\n            for media in more_media if isinstance(more_media, list) else []:\n                format_url = url_or_none(media.get('videoUrl'))\n                if not format_url:\n                    continue\n                format_id = media.get('format')\n                if format_id == 'hls' or determine_ext(format_url) == 'm3u8':\n                    formats.extend(self._extract_m3u8_formats(\n                        format_url, video_id, 'mp4',\n                        entry_protocol='m3u8_native', m3u8_id=format_id or 'hls',\n                        fatal=False))\n                    continue\n                format_id = media.get('quality')\n                formats.append({\n                    'url': format_url,\n                    'ext': 'mp4',\n                    'format_id': format_id,\n                    'height': int_or_none(format_id),\n                })\n        if not formats:\n            video_url = self._html_search_regex(\n                r'<source src=\"(.+?)\" type=\"video/mp4\">', webpage, 'video URL')\n            formats.append({'url': video_url, 'ext': 'mp4'})\n        self._sort_formats(formats)\n\n        thumbnail = self._og_search_thumbnail(webpage)\n        upload_date = unified_strdate(self._search_regex(\n            r'<span[^>]+>(?:ADDED|Published on) ([^<]+)<',\n            webpage, 'upload date', default=None))\n        duration = int_or_none(self._og_search_property(\n            'video:duration', webpage, default=None) or self._search_regex(\n                r'videoDuration\\s*:\\s*(\\d+)', webpage, 'duration', default=None))\n        view_count = str_to_int(self._search_regex(\n            (r'<div[^>]*>Views</div>\\s*<div[^>]*>\\s*([\\d,.]+)',\n             r'<span[^>]*>VIEWS</span>\\s*</td>\\s*<td>\\s*([\\d,.]+)',\n             r'<span[^>]+\\bclass=[\"\\']video_view_count[^>]*>\\s*([\\d,.]+)'),\n            webpage, 'view count', default=None))\n\n        # No self-labeling, but they describe themselves as\n        # \"Home of Videos Porno\"\n        age_limit = 18\n\n        return merge_dicts(info, {\n            'id': video_id,\n            'ext': 'mp4',\n            'thumbnail': thumbnail,\n            'upload_date': upload_date,\n            'duration': duration,\n            'view_count': view_count,\n            'age_limit': age_limit,\n            'formats': formats,\n        })\n", "path": "yt_dlp/extractor/redtube.py"}]}