mirror of
https://github.com/ytdl-org/youtube-dl.git
synced 2024-12-18 14:41:59 +00:00
Compare commits
12 Commits
4fb25ff5a3
...
9f6c03a006
Author | SHA1 | Date | |
---|---|---|---|
|
9f6c03a006 | ||
|
596b26606c | ||
|
f20b505b46 | ||
|
cfee2dfe83 | ||
|
30a3a4c70f | ||
|
a00a7e0cad | ||
|
54558e0baa | ||
|
7c52395479 | ||
|
ea87ed8394 | ||
|
d01e261a15 | ||
|
79e4ccfc4b | ||
|
06159135ef |
6
.github/ISSUE_TEMPLATE/1_broken_site.md
vendored
6
.github/ISSUE_TEMPLATE/1_broken_site.md
vendored
@ -18,7 +18,7 @@ title: ''
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
||||||
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2021.04.07. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2021.04.17. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
||||||
- Make sure that all provided video/audio/playlist URLs (if any) are alive and playable in a browser.
|
- Make sure that all provided video/audio/playlist URLs (if any) are alive and playable in a browser.
|
||||||
- Make sure that all URLs and arguments with special characters are properly quoted or escaped as explained in http://yt-dl.org/escape.
|
- Make sure that all URLs and arguments with special characters are properly quoted or escaped as explained in http://yt-dl.org/escape.
|
||||||
- Search the bugtracker for similar issues: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
- Search the bugtracker for similar issues: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
||||||
@ -26,7 +26,7 @@ Carefully read and work through this check list in order to prevent the most com
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
- [ ] I'm reporting a broken site support
|
- [ ] I'm reporting a broken site support
|
||||||
- [ ] I've verified that I'm running youtube-dl version **2021.04.07**
|
- [ ] I've verified that I'm running youtube-dl version **2021.04.17**
|
||||||
- [ ] I've checked that all provided URLs are alive and playable in a browser
|
- [ ] I've checked that all provided URLs are alive and playable in a browser
|
||||||
- [ ] I've checked that all URLs and arguments with special characters are properly quoted or escaped
|
- [ ] I've checked that all URLs and arguments with special characters are properly quoted or escaped
|
||||||
- [ ] I've searched the bugtracker for similar issues including closed ones
|
- [ ] I've searched the bugtracker for similar issues including closed ones
|
||||||
@ -41,7 +41,7 @@ Add the `-v` flag to your command line you run youtube-dl with (`youtube-dl -v <
|
|||||||
[debug] User config: []
|
[debug] User config: []
|
||||||
[debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj']
|
[debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj']
|
||||||
[debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251
|
[debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251
|
||||||
[debug] youtube-dl version 2021.04.07
|
[debug] youtube-dl version 2021.04.17
|
||||||
[debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2
|
[debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2
|
||||||
[debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
|
[debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
|
||||||
[debug] Proxy map: {}
|
[debug] Proxy map: {}
|
||||||
|
@ -19,7 +19,7 @@ labels: 'site-support-request'
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
||||||
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2021.04.07. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2021.04.17. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
||||||
- Make sure that all provided video/audio/playlist URLs (if any) are alive and playable in a browser.
|
- Make sure that all provided video/audio/playlist URLs (if any) are alive and playable in a browser.
|
||||||
- Make sure that site you are requesting is not dedicated to copyright infringement, see https://yt-dl.org/copyright-infringement. youtube-dl does not support such sites. In order for site support request to be accepted all provided example URLs should not violate any copyrights.
|
- Make sure that site you are requesting is not dedicated to copyright infringement, see https://yt-dl.org/copyright-infringement. youtube-dl does not support such sites. In order for site support request to be accepted all provided example URLs should not violate any copyrights.
|
||||||
- Search the bugtracker for similar site support requests: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
- Search the bugtracker for similar site support requests: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
||||||
@ -27,7 +27,7 @@ Carefully read and work through this check list in order to prevent the most com
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
- [ ] I'm reporting a new site support request
|
- [ ] I'm reporting a new site support request
|
||||||
- [ ] I've verified that I'm running youtube-dl version **2021.04.07**
|
- [ ] I've verified that I'm running youtube-dl version **2021.04.17**
|
||||||
- [ ] I've checked that all provided URLs are alive and playable in a browser
|
- [ ] I've checked that all provided URLs are alive and playable in a browser
|
||||||
- [ ] I've checked that none of provided URLs violate any copyrights
|
- [ ] I've checked that none of provided URLs violate any copyrights
|
||||||
- [ ] I've searched the bugtracker for similar site support requests including closed ones
|
- [ ] I've searched the bugtracker for similar site support requests including closed ones
|
||||||
|
@ -18,13 +18,13 @@ title: ''
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
||||||
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2021.04.07. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2021.04.17. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
||||||
- Search the bugtracker for similar site feature requests: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
- Search the bugtracker for similar site feature requests: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
||||||
- Finally, put x into all relevant boxes (like this [x])
|
- Finally, put x into all relevant boxes (like this [x])
|
||||||
-->
|
-->
|
||||||
|
|
||||||
- [ ] I'm reporting a site feature request
|
- [ ] I'm reporting a site feature request
|
||||||
- [ ] I've verified that I'm running youtube-dl version **2021.04.07**
|
- [ ] I've verified that I'm running youtube-dl version **2021.04.17**
|
||||||
- [ ] I've searched the bugtracker for similar site feature requests including closed ones
|
- [ ] I've searched the bugtracker for similar site feature requests including closed ones
|
||||||
|
|
||||||
|
|
||||||
|
6
.github/ISSUE_TEMPLATE/4_bug_report.md
vendored
6
.github/ISSUE_TEMPLATE/4_bug_report.md
vendored
@ -18,7 +18,7 @@ title: ''
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
||||||
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2021.04.07. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2021.04.17. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
||||||
- Make sure that all provided video/audio/playlist URLs (if any) are alive and playable in a browser.
|
- Make sure that all provided video/audio/playlist URLs (if any) are alive and playable in a browser.
|
||||||
- Make sure that all URLs and arguments with special characters are properly quoted or escaped as explained in http://yt-dl.org/escape.
|
- Make sure that all URLs and arguments with special characters are properly quoted or escaped as explained in http://yt-dl.org/escape.
|
||||||
- Search the bugtracker for similar issues: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
- Search the bugtracker for similar issues: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
||||||
@ -27,7 +27,7 @@ Carefully read and work through this check list in order to prevent the most com
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
- [ ] I'm reporting a broken site support issue
|
- [ ] I'm reporting a broken site support issue
|
||||||
- [ ] I've verified that I'm running youtube-dl version **2021.04.07**
|
- [ ] I've verified that I'm running youtube-dl version **2021.04.17**
|
||||||
- [ ] I've checked that all provided URLs are alive and playable in a browser
|
- [ ] I've checked that all provided URLs are alive and playable in a browser
|
||||||
- [ ] I've checked that all URLs and arguments with special characters are properly quoted or escaped
|
- [ ] I've checked that all URLs and arguments with special characters are properly quoted or escaped
|
||||||
- [ ] I've searched the bugtracker for similar bug reports including closed ones
|
- [ ] I've searched the bugtracker for similar bug reports including closed ones
|
||||||
@ -43,7 +43,7 @@ Add the `-v` flag to your command line you run youtube-dl with (`youtube-dl -v <
|
|||||||
[debug] User config: []
|
[debug] User config: []
|
||||||
[debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj']
|
[debug] Command-line args: [u'-v', u'http://www.youtube.com/watch?v=BaW_jenozKcj']
|
||||||
[debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251
|
[debug] Encodings: locale cp1251, fs mbcs, out cp866, pref cp1251
|
||||||
[debug] youtube-dl version 2021.04.07
|
[debug] youtube-dl version 2021.04.17
|
||||||
[debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2
|
[debug] Python version 2.7.11 - Windows-2003Server-5.2.3790-SP2
|
||||||
[debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
|
[debug] exe versions: ffmpeg N-75573-g1d0487f, ffprobe N-75573-g1d0487f, rtmpdump 2.4
|
||||||
[debug] Proxy map: {}
|
[debug] Proxy map: {}
|
||||||
|
4
.github/ISSUE_TEMPLATE/5_feature_request.md
vendored
4
.github/ISSUE_TEMPLATE/5_feature_request.md
vendored
@ -19,13 +19,13 @@ labels: 'request'
|
|||||||
|
|
||||||
<!--
|
<!--
|
||||||
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of youtube-dl:
|
||||||
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2021.04.07. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
- First of, make sure you are using the latest version of youtube-dl. Run `youtube-dl --version` and ensure your version is 2021.04.17. If it's not, see https://yt-dl.org/update on how to update. Issues with outdated version will be REJECTED.
|
||||||
- Search the bugtracker for similar feature requests: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
- Search the bugtracker for similar feature requests: http://yt-dl.org/search-issues. DO NOT post duplicates.
|
||||||
- Finally, put x into all relevant boxes (like this [x])
|
- Finally, put x into all relevant boxes (like this [x])
|
||||||
-->
|
-->
|
||||||
|
|
||||||
- [ ] I'm reporting a feature request
|
- [ ] I'm reporting a feature request
|
||||||
- [ ] I've verified that I'm running youtube-dl version **2021.04.07**
|
- [ ] I've verified that I'm running youtube-dl version **2021.04.17**
|
||||||
- [ ] I've searched the bugtracker for similar feature requests including closed ones
|
- [ ] I've searched the bugtracker for similar feature requests including closed ones
|
||||||
|
|
||||||
|
|
||||||
|
25
ChangeLog
25
ChangeLog
@ -1,3 +1,28 @@
|
|||||||
|
version 2021.04.17
|
||||||
|
|
||||||
|
Core
|
||||||
|
+ [utils] Add support for experimental HTTP response status code
|
||||||
|
308 Permanent Redirect (#27877, #28768)
|
||||||
|
|
||||||
|
Extractors
|
||||||
|
+ [lbry] Add support for HLS videos (#27877, #28768)
|
||||||
|
* [youtube] Fix stretched ratio calculation
|
||||||
|
* [youtube] Improve stretch extraction (#28769)
|
||||||
|
* [youtube:tab] Improve grid extraction (#28725)
|
||||||
|
+ [youtube:tab] Detect series playlist on playlists page (#28723)
|
||||||
|
+ [youtube] Add more invidious instances (#28706)
|
||||||
|
* [pluralsight] Extend anti-throttling timeout (#28712)
|
||||||
|
* [youtube] Improve URL to extractor routing (#27572, #28335, #28742)
|
||||||
|
+ [maoritv] Add support for maoritelevision.com (#24552)
|
||||||
|
+ [youtube:tab] Pass innertube context and x-goog-visitor-id header along with
|
||||||
|
continuation requests (#28702)
|
||||||
|
* [mtv] Fix Viacom A/B Testing Video Player extraction (#28703)
|
||||||
|
+ [pornhub] Extract DASH and HLS formats from get_media end point (#28698)
|
||||||
|
* [cbssports] Fix extraction (#28682)
|
||||||
|
* [jamendo] Fix track extraction (#28686)
|
||||||
|
* [curiositystream] Fix format extraction (#26845, #28668)
|
||||||
|
|
||||||
|
|
||||||
version 2021.04.07
|
version 2021.04.07
|
||||||
|
|
||||||
Core
|
Core
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
- **20min**
|
- **20min**
|
||||||
- **220.ro**
|
- **220.ro**
|
||||||
- **23video**
|
- **23video**
|
||||||
|
- **247sports**
|
||||||
- **24video**
|
- **24video**
|
||||||
- **3qsdn**: 3Q SDN
|
- **3qsdn**: 3Q SDN
|
||||||
- **3sat**
|
- **3sat**
|
||||||
@ -160,7 +161,8 @@
|
|||||||
- **cbsnews**: CBS News
|
- **cbsnews**: CBS News
|
||||||
- **cbsnews:embed**
|
- **cbsnews:embed**
|
||||||
- **cbsnews:livevideo**: CBS News Live Videos
|
- **cbsnews:livevideo**: CBS News Live Videos
|
||||||
- **CBSSports**
|
- **cbssports**
|
||||||
|
- **cbssports:embed**
|
||||||
- **CCMA**
|
- **CCMA**
|
||||||
- **CCTV**: 央视网
|
- **CCTV**: 央视网
|
||||||
- **CDA**
|
- **CDA**
|
||||||
@ -490,6 +492,7 @@
|
|||||||
- **mangomolo:live**
|
- **mangomolo:live**
|
||||||
- **mangomolo:video**
|
- **mangomolo:video**
|
||||||
- **ManyVids**
|
- **ManyVids**
|
||||||
|
- **MaoriTV**
|
||||||
- **Markiza**
|
- **Markiza**
|
||||||
- **MarkizaPage**
|
- **MarkizaPage**
|
||||||
- **massengeschmack.tv**
|
- **massengeschmack.tv**
|
||||||
|
@ -26,7 +26,7 @@ class CBSNewsEmbedIE(CBSIE):
|
|||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
item = self._parse_json(zlib.decompress(compat_b64decode(
|
item = self._parse_json(zlib.decompress(compat_b64decode(
|
||||||
compat_urllib_parse_unquote(self._match_id(url))),
|
compat_urllib_parse_unquote(self._match_id(url))),
|
||||||
-zlib.MAX_WBITS), None)['video']['items'][0]
|
-zlib.MAX_WBITS).decode('utf-8'), None)['video']['items'][0]
|
||||||
return self._extract_video_info(item['mpxRefId'], 'cbsnews')
|
return self._extract_video_info(item['mpxRefId'], 'cbsnews')
|
||||||
|
|
||||||
|
|
||||||
|
@ -120,6 +120,26 @@ class LBRYIE(LBRYBaseIE):
|
|||||||
'channel_url': 'https://lbry.tv/@LBRYFoundation:0ed629d2b9c601300cacf7eabe9da0be79010212',
|
'channel_url': 'https://lbry.tv/@LBRYFoundation:0ed629d2b9c601300cacf7eabe9da0be79010212',
|
||||||
'vcodec': 'none',
|
'vcodec': 'none',
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
# HLS
|
||||||
|
'url': 'https://odysee.com/@gardeningincanada:b/plants-i-will-never-grow-again.-the:e',
|
||||||
|
'md5': 'fc82f45ea54915b1495dd7cb5cc1289f',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'e51671357333fe22ae88aad320bde2f6f96b1410',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'PLANTS I WILL NEVER GROW AGAIN. THE BLACK LIST PLANTS FOR A CANADIAN GARDEN | Gardening in Canada 🍁',
|
||||||
|
'description': 'md5:9c539c6a03fb843956de61a4d5288d5e',
|
||||||
|
'timestamp': 1618254123,
|
||||||
|
'upload_date': '20210412',
|
||||||
|
'release_timestamp': 1618254002,
|
||||||
|
'release_date': '20210412',
|
||||||
|
'tags': list,
|
||||||
|
'duration': 554,
|
||||||
|
'channel': 'Gardening In Canada',
|
||||||
|
'channel_id': 'b8be0e93b423dad221abe29545fbe8ec36e806bc',
|
||||||
|
'channel_url': 'https://odysee.com/@gardeningincanada:b8be0e93b423dad221abe29545fbe8ec36e806bc',
|
||||||
|
'formats': 'mincount:3',
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
'url': 'https://odysee.com/@BrodieRobertson:5/apple-is-tracking-everything-you-do-on:e',
|
'url': 'https://odysee.com/@BrodieRobertson:5/apple-is-tracking-everything-you-do-on:e',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
@ -163,10 +183,18 @@ class LBRYIE(LBRYBaseIE):
|
|||||||
streaming_url = self._call_api_proxy(
|
streaming_url = self._call_api_proxy(
|
||||||
'get', claim_id, {'uri': uri}, 'streaming url')['streaming_url']
|
'get', claim_id, {'uri': uri}, 'streaming url')['streaming_url']
|
||||||
info = self._parse_stream(result, url)
|
info = self._parse_stream(result, url)
|
||||||
|
urlh = self._request_webpage(
|
||||||
|
streaming_url, display_id, note='Downloading streaming redirect url info')
|
||||||
|
if determine_ext(urlh.geturl()) == 'm3u8':
|
||||||
|
info['formats'] = self._extract_m3u8_formats(
|
||||||
|
urlh.geturl(), display_id, 'mp4', entry_protocol='m3u8_native',
|
||||||
|
m3u8_id='hls')
|
||||||
|
self._sort_formats(info['formats'])
|
||||||
|
else:
|
||||||
|
info['url'] = streaming_url
|
||||||
info.update({
|
info.update({
|
||||||
'id': claim_id,
|
'id': claim_id,
|
||||||
'title': title,
|
'title': title,
|
||||||
'url': streaming_url,
|
|
||||||
})
|
})
|
||||||
return info
|
return info
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ query viewClip {
|
|||||||
# To somewhat reduce the probability of these consequences
|
# To somewhat reduce the probability of these consequences
|
||||||
# we will sleep random amount of time before each call to ViewClip.
|
# we will sleep random amount of time before each call to ViewClip.
|
||||||
self._sleep(
|
self._sleep(
|
||||||
random.randint(2, 5), display_id,
|
random.randint(5, 10), display_id,
|
||||||
'%(video_id)s: Waiting for %(timeout)s seconds to avoid throttling')
|
'%(video_id)s: Waiting for %(timeout)s seconds to avoid throttling')
|
||||||
|
|
||||||
if not viewclip:
|
if not viewclip:
|
||||||
|
@ -46,6 +46,10 @@ from ..utils import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_qs(url):
|
||||||
|
return compat_urlparse.parse_qs(compat_urlparse.urlparse(url).query)
|
||||||
|
|
||||||
|
|
||||||
class YoutubeBaseInfoExtractor(InfoExtractor):
|
class YoutubeBaseInfoExtractor(InfoExtractor):
|
||||||
"""Provide base functions for Youtube extractors"""
|
"""Provide base functions for Youtube extractors"""
|
||||||
_LOGIN_URL = 'https://accounts.google.com/ServiceLogin'
|
_LOGIN_URL = 'https://accounts.google.com/ServiceLogin'
|
||||||
@ -355,21 +359,28 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
r'(?:www\.)?invidious\.mastodon\.host',
|
r'(?:www\.)?invidious\.mastodon\.host',
|
||||||
r'(?:www\.)?invidious\.zapashcanon\.fr',
|
r'(?:www\.)?invidious\.zapashcanon\.fr',
|
||||||
r'(?:www\.)?invidious\.kavin\.rocks',
|
r'(?:www\.)?invidious\.kavin\.rocks',
|
||||||
|
r'(?:www\.)?invidious\.tinfoil-hat\.net',
|
||||||
|
r'(?:www\.)?invidious\.himiko\.cloud',
|
||||||
|
r'(?:www\.)?invidious\.reallyancient\.tech',
|
||||||
r'(?:www\.)?invidious\.tube',
|
r'(?:www\.)?invidious\.tube',
|
||||||
r'(?:www\.)?invidiou\.site',
|
r'(?:www\.)?invidiou\.site',
|
||||||
r'(?:www\.)?invidious\.site',
|
r'(?:www\.)?invidious\.site',
|
||||||
r'(?:www\.)?invidious\.xyz',
|
r'(?:www\.)?invidious\.xyz',
|
||||||
r'(?:www\.)?invidious\.nixnet\.xyz',
|
r'(?:www\.)?invidious\.nixnet\.xyz',
|
||||||
|
r'(?:www\.)?invidious\.048596\.xyz',
|
||||||
r'(?:www\.)?invidious\.drycat\.fr',
|
r'(?:www\.)?invidious\.drycat\.fr',
|
||||||
|
r'(?:www\.)?inv\.skyn3t\.in',
|
||||||
r'(?:www\.)?tube\.poal\.co',
|
r'(?:www\.)?tube\.poal\.co',
|
||||||
r'(?:www\.)?tube\.connect\.cafe',
|
r'(?:www\.)?tube\.connect\.cafe',
|
||||||
r'(?:www\.)?vid\.wxzm\.sx',
|
r'(?:www\.)?vid\.wxzm\.sx',
|
||||||
r'(?:www\.)?vid\.mint\.lgbt',
|
r'(?:www\.)?vid\.mint\.lgbt',
|
||||||
|
r'(?:www\.)?vid\.puffyan\.us',
|
||||||
r'(?:www\.)?yewtu\.be',
|
r'(?:www\.)?yewtu\.be',
|
||||||
r'(?:www\.)?yt\.elukerio\.org',
|
r'(?:www\.)?yt\.elukerio\.org',
|
||||||
r'(?:www\.)?yt\.lelux\.fi',
|
r'(?:www\.)?yt\.lelux\.fi',
|
||||||
r'(?:www\.)?invidious\.ggc-project\.de',
|
r'(?:www\.)?invidious\.ggc-project\.de',
|
||||||
r'(?:www\.)?yt\.maisputain\.ovh',
|
r'(?:www\.)?yt\.maisputain\.ovh',
|
||||||
|
r'(?:www\.)?ytprivate\.com',
|
||||||
r'(?:www\.)?invidious\.13ad\.de',
|
r'(?:www\.)?invidious\.13ad\.de',
|
||||||
r'(?:www\.)?invidious\.toot\.koeln',
|
r'(?:www\.)?invidious\.toot\.koeln',
|
||||||
r'(?:www\.)?invidious\.fdn\.fr',
|
r'(?:www\.)?invidious\.fdn\.fr',
|
||||||
@ -413,16 +424,9 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
|(?:www\.)?cleanvideosearch\.com/media/action/yt/watch\?videoId=
|
|(?:www\.)?cleanvideosearch\.com/media/action/yt/watch\?videoId=
|
||||||
)
|
)
|
||||||
)? # all until now is optional -> you can pass the naked ID
|
)? # all until now is optional -> you can pass the naked ID
|
||||||
(?P<id>[0-9A-Za-z_-]{11}) # here is it! the YouTube video ID
|
(?P<id>[0-9A-Za-z_-]{11}) # here is it! the YouTube video ID
|
||||||
(?!.*?\blist=
|
|
||||||
(?:
|
|
||||||
%(playlist_id)s| # combined list/video URLs are handled by the playlist IE
|
|
||||||
WL # WL are handled by the watch later IE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(?(1).+)? # if we found the ID, everything can follow
|
(?(1).+)? # if we found the ID, everything can follow
|
||||||
$""" % {
|
$""" % {
|
||||||
'playlist_id': YoutubeBaseInfoExtractor._PLAYLIST_ID_RE,
|
|
||||||
'invidious': '|'.join(_INVIDIOUS_SITES),
|
'invidious': '|'.join(_INVIDIOUS_SITES),
|
||||||
}
|
}
|
||||||
_PLAYER_INFO_RE = (
|
_PLAYER_INFO_RE = (
|
||||||
@ -808,6 +812,11 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
},
|
},
|
||||||
'skip': 'This video does not exist.',
|
'skip': 'This video does not exist.',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
# Video with incomplete 'yt:stretch=16:'
|
||||||
|
'url': 'https://www.youtube.com/watch?v=FRhJzUSJbGI',
|
||||||
|
'only_matching': True,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
# Video licensed under Creative Commons
|
# Video licensed under Creative Commons
|
||||||
'url': 'https://www.youtube.com/watch?v=M4gD1WSo5mA',
|
'url': 'https://www.youtube.com/watch?v=M4gD1WSo5mA',
|
||||||
@ -1208,6 +1217,13 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'397': {'acodec': 'none', 'vcodec': 'av01.0.05M.08'},
|
'397': {'acodec': 'none', 'vcodec': 'av01.0.05M.08'},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def suitable(cls, url):
|
||||||
|
qs = parse_qs(url)
|
||||||
|
if qs.get('list', [None])[0]:
|
||||||
|
return False
|
||||||
|
return super(YoutubeIE, cls).suitable(url)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(YoutubeIE, self).__init__(*args, **kwargs)
|
super(YoutubeIE, self).__init__(*args, **kwargs)
|
||||||
self._code_cache = {}
|
self._code_cache = {}
|
||||||
@ -1706,13 +1722,16 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
for m in re.finditer(self._meta_regex('og:video:tag'), webpage)]
|
for m in re.finditer(self._meta_regex('og:video:tag'), webpage)]
|
||||||
for keyword in keywords:
|
for keyword in keywords:
|
||||||
if keyword.startswith('yt:stretch='):
|
if keyword.startswith('yt:stretch='):
|
||||||
w, h = keyword.split('=')[1].split(':')
|
mobj = re.search(r'(\d+)\s*:\s*(\d+)', keyword)
|
||||||
w, h = int(w), int(h)
|
if mobj:
|
||||||
if w > 0 and h > 0:
|
# NB: float is intentional for forcing float division
|
||||||
ratio = w / h
|
w, h = (float(v) for v in mobj.groups())
|
||||||
for f in formats:
|
if w > 0 and h > 0:
|
||||||
if f.get('vcodec') != 'none':
|
ratio = w / h
|
||||||
f['stretched_ratio'] = ratio
|
for f in formats:
|
||||||
|
if f.get('vcodec') != 'none':
|
||||||
|
f['stretched_ratio'] = ratio
|
||||||
|
break
|
||||||
|
|
||||||
thumbnails = []
|
thumbnails = []
|
||||||
for container in (video_details, microformat):
|
for container in (video_details, microformat):
|
||||||
@ -2008,6 +2027,15 @@ class YoutubeTabIE(YoutubeBaseInfoExtractor):
|
|||||||
'title': 'Игорь Клейнер - Playlists',
|
'title': 'Игорь Клейнер - Playlists',
|
||||||
'description': 'md5:be97ee0f14ee314f1f002cf187166ee2',
|
'description': 'md5:be97ee0f14ee314f1f002cf187166ee2',
|
||||||
},
|
},
|
||||||
|
}, {
|
||||||
|
# playlists, series
|
||||||
|
'url': 'https://www.youtube.com/c/3blue1brown/playlists?view=50&sort=dd&shelf_id=3',
|
||||||
|
'playlist_mincount': 5,
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'UCYO_jab_esuFRV4b17AJtAw',
|
||||||
|
'title': '3Blue1Brown - Playlists',
|
||||||
|
'description': 'md5:e1384e8a133307dd10edee76e875d62f',
|
||||||
|
},
|
||||||
}, {
|
}, {
|
||||||
# playlists, singlepage
|
# playlists, singlepage
|
||||||
'url': 'https://www.youtube.com/user/ThirstForScience/playlists',
|
'url': 'https://www.youtube.com/user/ThirstForScience/playlists',
|
||||||
@ -2275,6 +2303,9 @@ class YoutubeTabIE(YoutubeBaseInfoExtractor):
|
|||||||
'title': '#cctv9',
|
'title': '#cctv9',
|
||||||
},
|
},
|
||||||
'playlist_mincount': 350,
|
'playlist_mincount': 350,
|
||||||
|
}, {
|
||||||
|
'url': 'https://www.youtube.com/watch?list=PLW4dVinRY435CBE_JD3t-0SRXKfnZHS1P&feature=youtu.be&v=M9cJMXmQ_ZU',
|
||||||
|
'only_matching': True,
|
||||||
}]
|
}]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -2297,10 +2328,13 @@ class YoutubeTabIE(YoutubeBaseInfoExtractor):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _extract_grid_item_renderer(item):
|
def _extract_grid_item_renderer(item):
|
||||||
for item_kind in ('Playlist', 'Video', 'Channel'):
|
assert isinstance(item, dict)
|
||||||
renderer = item.get('grid%sRenderer' % item_kind)
|
for key, renderer in item.items():
|
||||||
if renderer:
|
if not key.startswith('grid') or not key.endswith('Renderer'):
|
||||||
return renderer
|
continue
|
||||||
|
if not isinstance(renderer, dict):
|
||||||
|
continue
|
||||||
|
return renderer
|
||||||
|
|
||||||
def _grid_entries(self, grid_renderer):
|
def _grid_entries(self, grid_renderer):
|
||||||
for item in grid_renderer['items']:
|
for item in grid_renderer['items']:
|
||||||
@ -2310,7 +2344,8 @@ class YoutubeTabIE(YoutubeBaseInfoExtractor):
|
|||||||
if not isinstance(renderer, dict):
|
if not isinstance(renderer, dict):
|
||||||
continue
|
continue
|
||||||
title = try_get(
|
title = try_get(
|
||||||
renderer, lambda x: x['title']['runs'][0]['text'], compat_str)
|
renderer, (lambda x: x['title']['runs'][0]['text'],
|
||||||
|
lambda x: x['title']['simpleText']), compat_str)
|
||||||
# playlist
|
# playlist
|
||||||
playlist_id = renderer.get('playlistId')
|
playlist_id = renderer.get('playlistId')
|
||||||
if playlist_id:
|
if playlist_id:
|
||||||
@ -2318,10 +2353,12 @@ class YoutubeTabIE(YoutubeBaseInfoExtractor):
|
|||||||
'https://www.youtube.com/playlist?list=%s' % playlist_id,
|
'https://www.youtube.com/playlist?list=%s' % playlist_id,
|
||||||
ie=YoutubeTabIE.ie_key(), video_id=playlist_id,
|
ie=YoutubeTabIE.ie_key(), video_id=playlist_id,
|
||||||
video_title=title)
|
video_title=title)
|
||||||
|
continue
|
||||||
# video
|
# video
|
||||||
video_id = renderer.get('videoId')
|
video_id = renderer.get('videoId')
|
||||||
if video_id:
|
if video_id:
|
||||||
yield self._extract_video(renderer)
|
yield self._extract_video(renderer)
|
||||||
|
continue
|
||||||
# channel
|
# channel
|
||||||
channel_id = renderer.get('channelId')
|
channel_id = renderer.get('channelId')
|
||||||
if channel_id:
|
if channel_id:
|
||||||
@ -2330,6 +2367,17 @@ class YoutubeTabIE(YoutubeBaseInfoExtractor):
|
|||||||
yield self.url_result(
|
yield self.url_result(
|
||||||
'https://www.youtube.com/channel/%s' % channel_id,
|
'https://www.youtube.com/channel/%s' % channel_id,
|
||||||
ie=YoutubeTabIE.ie_key(), video_title=title)
|
ie=YoutubeTabIE.ie_key(), video_title=title)
|
||||||
|
continue
|
||||||
|
# generic endpoint URL support
|
||||||
|
ep_url = urljoin('https://www.youtube.com/', try_get(
|
||||||
|
renderer, lambda x: x['navigationEndpoint']['commandMetadata']['webCommandMetadata']['url'],
|
||||||
|
compat_str))
|
||||||
|
if ep_url:
|
||||||
|
for ie in (YoutubeTabIE, YoutubePlaylistIE, YoutubeIE):
|
||||||
|
if ie.suitable(ep_url):
|
||||||
|
yield self.url_result(
|
||||||
|
ep_url, ie=ie.ie_key(), video_id=ie._match_id(ep_url), video_title=title)
|
||||||
|
break
|
||||||
|
|
||||||
def _shelf_entries_from_content(self, shelf_renderer):
|
def _shelf_entries_from_content(self, shelf_renderer):
|
||||||
content = shelf_renderer.get('content')
|
content = shelf_renderer.get('content')
|
||||||
@ -2764,7 +2812,7 @@ class YoutubeTabIE(YoutubeBaseInfoExtractor):
|
|||||||
url = compat_urlparse.urlunparse(
|
url = compat_urlparse.urlunparse(
|
||||||
compat_urlparse.urlparse(url)._replace(netloc='www.youtube.com'))
|
compat_urlparse.urlparse(url)._replace(netloc='www.youtube.com'))
|
||||||
# Handle both video/playlist URLs
|
# Handle both video/playlist URLs
|
||||||
qs = compat_urlparse.parse_qs(compat_urlparse.urlparse(url).query)
|
qs = parse_qs(url)
|
||||||
video_id = qs.get('v', [None])[0]
|
video_id = qs.get('v', [None])[0]
|
||||||
playlist_id = qs.get('list', [None])[0]
|
playlist_id = qs.get('list', [None])[0]
|
||||||
if video_id and playlist_id:
|
if video_id and playlist_id:
|
||||||
@ -2860,12 +2908,16 @@ class YoutubePlaylistIE(InfoExtractor):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def suitable(cls, url):
|
def suitable(cls, url):
|
||||||
return False if YoutubeTabIE.suitable(url) else super(
|
if YoutubeTabIE.suitable(url):
|
||||||
YoutubePlaylistIE, cls).suitable(url)
|
return False
|
||||||
|
qs = parse_qs(url)
|
||||||
|
if qs.get('v', [None])[0]:
|
||||||
|
return False
|
||||||
|
return super(YoutubePlaylistIE, cls).suitable(url)
|
||||||
|
|
||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
playlist_id = self._match_id(url)
|
playlist_id = self._match_id(url)
|
||||||
qs = compat_urlparse.parse_qs(compat_urlparse.urlparse(url).query)
|
qs = parse_qs(url)
|
||||||
if not qs:
|
if not qs:
|
||||||
qs = {'list': playlist_id}
|
qs = {'list': playlist_id}
|
||||||
return self.url_result(
|
return self.url_result(
|
||||||
|
@ -39,6 +39,7 @@ import zlib
|
|||||||
from .compat import (
|
from .compat import (
|
||||||
compat_HTMLParseError,
|
compat_HTMLParseError,
|
||||||
compat_HTMLParser,
|
compat_HTMLParser,
|
||||||
|
compat_HTTPError,
|
||||||
compat_basestring,
|
compat_basestring,
|
||||||
compat_chr,
|
compat_chr,
|
||||||
compat_cookiejar,
|
compat_cookiejar,
|
||||||
@ -2879,12 +2880,60 @@ class YoutubeDLCookieProcessor(compat_urllib_request.HTTPCookieProcessor):
|
|||||||
|
|
||||||
|
|
||||||
class YoutubeDLRedirectHandler(compat_urllib_request.HTTPRedirectHandler):
|
class YoutubeDLRedirectHandler(compat_urllib_request.HTTPRedirectHandler):
|
||||||
if sys.version_info[0] < 3:
|
"""YoutubeDL redirect handler
|
||||||
def redirect_request(self, req, fp, code, msg, headers, newurl):
|
|
||||||
# On python 2 urlh.geturl() may sometimes return redirect URL
|
The code is based on HTTPRedirectHandler implementation from CPython [1].
|
||||||
# as byte string instead of unicode. This workaround allows
|
|
||||||
# to force it always return unicode.
|
This redirect handler solves two issues:
|
||||||
return compat_urllib_request.HTTPRedirectHandler.redirect_request(self, req, fp, code, msg, headers, compat_str(newurl))
|
- ensures redirect URL is always unicode under python 2
|
||||||
|
- introduces support for experimental HTTP response status code
|
||||||
|
308 Permanent Redirect [2] used by some sites [3]
|
||||||
|
|
||||||
|
1. https://github.com/python/cpython/blob/master/Lib/urllib/request.py
|
||||||
|
2. https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/308
|
||||||
|
3. https://github.com/ytdl-org/youtube-dl/issues/28768
|
||||||
|
"""
|
||||||
|
|
||||||
|
http_error_301 = http_error_303 = http_error_307 = http_error_308 = compat_urllib_request.HTTPRedirectHandler.http_error_302
|
||||||
|
|
||||||
|
def redirect_request(self, req, fp, code, msg, headers, newurl):
|
||||||
|
"""Return a Request or None in response to a redirect.
|
||||||
|
|
||||||
|
This is called by the http_error_30x methods when a
|
||||||
|
redirection response is received. If a redirection should
|
||||||
|
take place, return a new Request to allow http_error_30x to
|
||||||
|
perform the redirect. Otherwise, raise HTTPError if no-one
|
||||||
|
else should try to handle this url. Return None if you can't
|
||||||
|
but another Handler might.
|
||||||
|
"""
|
||||||
|
m = req.get_method()
|
||||||
|
if (not (code in (301, 302, 303, 307, 308) and m in ("GET", "HEAD")
|
||||||
|
or code in (301, 302, 303) and m == "POST")):
|
||||||
|
raise compat_HTTPError(req.full_url, code, msg, headers, fp)
|
||||||
|
# Strictly (according to RFC 2616), 301 or 302 in response to
|
||||||
|
# a POST MUST NOT cause a redirection without confirmation
|
||||||
|
# from the user (of urllib.request, in this case). In practice,
|
||||||
|
# essentially all clients do redirect in this case, so we do
|
||||||
|
# the same.
|
||||||
|
|
||||||
|
# On python 2 urlh.geturl() may sometimes return redirect URL
|
||||||
|
# as byte string instead of unicode. This workaround allows
|
||||||
|
# to force it always return unicode.
|
||||||
|
if sys.version_info[0] < 3:
|
||||||
|
newurl = compat_str(newurl)
|
||||||
|
|
||||||
|
# Be conciliant with URIs containing a space. This is mainly
|
||||||
|
# redundant with the more complete encoding done in http_error_302(),
|
||||||
|
# but it is kept for compatibility with other callers.
|
||||||
|
newurl = newurl.replace(' ', '%20')
|
||||||
|
|
||||||
|
CONTENT_HEADERS = ("content-length", "content-type")
|
||||||
|
# NB: don't use dict comprehension for python 2.6 compatibility
|
||||||
|
newheaders = dict((k, v) for k, v in req.headers.items()
|
||||||
|
if k.lower() not in CONTENT_HEADERS)
|
||||||
|
return compat_urllib_request.Request(
|
||||||
|
newurl, headers=newheaders, origin_req_host=req.origin_req_host,
|
||||||
|
unverifiable=True)
|
||||||
|
|
||||||
|
|
||||||
def extract_timezone(date_str):
|
def extract_timezone(date_str):
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
__version__ = '2021.04.07'
|
__version__ = '2021.04.17'
|
||||||
|
Loading…
Reference in New Issue
Block a user