Merge remote-tracking branch 'upstream/master' into yourporn
This commit is contained in:
commit
bd2f55db56
6
.github/ISSUE_TEMPLATE.md
vendored
6
.github/ISSUE_TEMPLATE.md
vendored
@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Make sure you are using the *latest* version: run `youtube-dl --version` and ensure your version is *2019.01.10*. If it's not, read [this FAQ entry](https://github.com/rg3/youtube-dl/blob/master/README.md#how-do-i-update-youtube-dl) and update. Issues with outdated version will be rejected.
|
### Make sure you are using the *latest* version: run `youtube-dl --version` and ensure your version is *2019.01.17*. If it's not, read [this FAQ entry](https://github.com/rg3/youtube-dl/blob/master/README.md#how-do-i-update-youtube-dl) and update. Issues with outdated version will be rejected.
|
||||||
- [ ] I've **verified** and **I assure** that I'm running youtube-dl **2019.01.10**
|
- [ ] I've **verified** and **I assure** that I'm running youtube-dl **2019.01.17**
|
||||||
|
|
||||||
### Before submitting an *issue* make sure you have:
|
### Before submitting an *issue* make sure you have:
|
||||||
- [ ] At least skimmed through the [README](https://github.com/rg3/youtube-dl/blob/master/README.md), **most notably** the [FAQ](https://github.com/rg3/youtube-dl#faq) and [BUGS](https://github.com/rg3/youtube-dl#bugs) sections
|
- [ ] At least skimmed through the [README](https://github.com/rg3/youtube-dl/blob/master/README.md), **most notably** the [FAQ](https://github.com/rg3/youtube-dl#faq) and [BUGS](https://github.com/rg3/youtube-dl#bugs) sections
|
||||||
@ -36,7 +36,7 @@ Add the `-v` flag to **your command line** you run youtube-dl with (`youtube-dl
|
|||||||
[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 2019.01.10
|
[debug] youtube-dl version 2019.01.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: {}
|
||||||
|
25
ChangeLog
25
ChangeLog
@ -1,3 +1,28 @@
|
|||||||
|
version 2019.01.17
|
||||||
|
|
||||||
|
Extractors
|
||||||
|
* [youtube] Extend JS player signature function name regular expressions
|
||||||
|
(#18890, #18891, #18893)
|
||||||
|
|
||||||
|
|
||||||
|
version 2019.01.16
|
||||||
|
|
||||||
|
Core
|
||||||
|
+ [test/helper] Add support for maxcount and count collection len checkers
|
||||||
|
* [downloader/hls] Fix uplynk ad skipping (#18824)
|
||||||
|
* [postprocessor/ffmpeg] Improve ffmpeg version parsing (#18813)
|
||||||
|
|
||||||
|
Extractors
|
||||||
|
* [youtube] Skip unsupported adaptive stream type (#18804)
|
||||||
|
+ [youtube] Extract DASH formats from player response (#18804)
|
||||||
|
* [funimation] Fix extraction (#14089)
|
||||||
|
* [skylinewebcams] Fix extraction (#18853)
|
||||||
|
+ [curiositystream] Add support for non app URLs
|
||||||
|
+ [bitchute] Check formats (#18833)
|
||||||
|
* [wistia] Extend URL regular expression (#18823)
|
||||||
|
+ [playplustv] Add support for playplus.com (#18789)
|
||||||
|
|
||||||
|
|
||||||
version 2019.01.10
|
version 2019.01.10
|
||||||
|
|
||||||
Core
|
Core
|
||||||
|
@ -153,15 +153,27 @@ def expect_value(self, got, expected, field):
|
|||||||
isinstance(got, compat_str),
|
isinstance(got, compat_str),
|
||||||
'Expected field %s to be a unicode object, but got value %r of type %r' % (field, got, type(got)))
|
'Expected field %s to be a unicode object, but got value %r of type %r' % (field, got, type(got)))
|
||||||
got = 'md5:' + md5(got)
|
got = 'md5:' + md5(got)
|
||||||
elif isinstance(expected, compat_str) and expected.startswith('mincount:'):
|
elif isinstance(expected, compat_str) and re.match(r'^(?:min|max)?count:\d+', expected):
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
isinstance(got, (list, dict)),
|
isinstance(got, (list, dict)),
|
||||||
'Expected field %s to be a list or a dict, but it is of type %s' % (
|
'Expected field %s to be a list or a dict, but it is of type %s' % (
|
||||||
field, type(got).__name__))
|
field, type(got).__name__))
|
||||||
expected_num = int(expected.partition(':')[2])
|
op, _, expected_num = expected.partition(':')
|
||||||
assertGreaterEqual(
|
expected_num = int(expected_num)
|
||||||
|
if op == 'mincount':
|
||||||
|
assert_func = assertGreaterEqual
|
||||||
|
msg_tmpl = 'Expected %d items in field %s, but only got %d'
|
||||||
|
elif op == 'maxcount':
|
||||||
|
assert_func = assertLessEqual
|
||||||
|
msg_tmpl = 'Expected maximum %d items in field %s, but got %d'
|
||||||
|
elif op == 'count':
|
||||||
|
assert_func = assertEqual
|
||||||
|
msg_tmpl = 'Expected exactly %d items in field %s, but got %d'
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
assert_func(
|
||||||
self, len(got), expected_num,
|
self, len(got), expected_num,
|
||||||
'Expected %d items in field %s, but only got %d' % (expected_num, field, len(got)))
|
msg_tmpl % (expected_num, field, len(got)))
|
||||||
return
|
return
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
expected, got,
|
expected, got,
|
||||||
@ -237,6 +249,20 @@ def assertGreaterEqual(self, got, expected, msg=None):
|
|||||||
self.assertTrue(got >= expected, msg)
|
self.assertTrue(got >= expected, msg)
|
||||||
|
|
||||||
|
|
||||||
|
def assertLessEqual(self, got, expected, msg=None):
|
||||||
|
if not (got <= expected):
|
||||||
|
if msg is None:
|
||||||
|
msg = '%r not less than or equal to %r' % (got, expected)
|
||||||
|
self.assertTrue(got <= expected, msg)
|
||||||
|
|
||||||
|
|
||||||
|
def assertEqual(self, got, expected, msg=None):
|
||||||
|
if not (got == expected):
|
||||||
|
if msg is None:
|
||||||
|
msg = '%r not equal to %r' % (got, expected)
|
||||||
|
self.assertTrue(got == expected, msg)
|
||||||
|
|
||||||
|
|
||||||
def expect_warnings(ydl, warnings_re):
|
def expect_warnings(ydl, warnings_re):
|
||||||
real_warning = ydl.report_warning
|
real_warning = ydl.report_warning
|
||||||
|
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
from .turner import TurnerBaseIE
|
from .turner import TurnerBaseIE
|
||||||
|
from ..utils import int_or_none
|
||||||
|
|
||||||
|
|
||||||
class CartoonNetworkIE(TurnerBaseIE):
|
class CartoonNetworkIE(TurnerBaseIE):
|
||||||
_VALID_URL = r'https?://(?:www\.)?cartoonnetwork\.com/video/(?:[^/]+/)+(?P<id>[^/?#]+)-(?:clip|episode)\.html'
|
_VALID_URL = r'https?://(?:www\.)?cartoonnetwork\.com/video/(?:[^/]+/)+(?P<id>[^/?#]+)-(?:clip|episode)\.html'
|
||||||
_TEST = {
|
_TEST = {
|
||||||
'url': 'http://www.cartoonnetwork.com/video/teen-titans-go/starfire-the-cat-lady-clip.html',
|
'url': 'https://www.cartoonnetwork.com/video/ben-10/how-to-draw-upgrade-episode.html',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '8a250ab04ed07e6c014ef3f1e2f9016c',
|
'id': '6e3375097f63874ebccec7ef677c1c3845fa850e',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'title': 'Starfire the Cat Lady',
|
'title': 'How to Draw Upgrade',
|
||||||
'description': 'Robin decides to become a cat so that Starfire will finally love him.',
|
'description': 'md5:2061d83776db7e8be4879684eefe8c0f',
|
||||||
},
|
},
|
||||||
'params': {
|
'params': {
|
||||||
# m3u8 download
|
# m3u8 download
|
||||||
@ -25,18 +24,39 @@ class CartoonNetworkIE(TurnerBaseIE):
|
|||||||
def _real_extract(self, url):
|
def _real_extract(self, url):
|
||||||
display_id = self._match_id(url)
|
display_id = self._match_id(url)
|
||||||
webpage = self._download_webpage(url, display_id)
|
webpage = self._download_webpage(url, display_id)
|
||||||
id_type, video_id = re.search(r"_cnglobal\.cvp(Video|Title)Id\s*=\s*'([^']+)';", webpage).groups()
|
|
||||||
query = ('id' if id_type == 'Video' else 'titleId') + '=' + video_id
|
def find_field(global_re, name, content_re=None, value_re='[^"]+', fatal=False):
|
||||||
return self._extract_cvp_info(
|
metadata_re = ''
|
||||||
'http://www.cartoonnetwork.com/video-seo-svc/episodeservices/getCvpPlaylist?networkName=CN2&' + query, video_id, {
|
if content_re:
|
||||||
'secure': {
|
metadata_re = r'|video_metadata\.content_' + content_re
|
||||||
'media_src': 'http://androidhls-secure.cdn.turner.com/toon/big',
|
return self._search_regex(
|
||||||
'tokenizer_src': 'https://token.vgtf.net/token/token_mobile',
|
r'(?:_cnglobal\.currentVideo\.%s%s)\s*=\s*"(%s)";' % (global_re, metadata_re, value_re),
|
||||||
},
|
webpage, name, fatal=fatal)
|
||||||
}, {
|
|
||||||
|
media_id = find_field('mediaId', 'media id', 'id', '[0-9a-f]{40}', True)
|
||||||
|
title = find_field('episodeTitle', 'title', '(?:episodeName|name)', fatal=True)
|
||||||
|
|
||||||
|
info = self._extract_ngtv_info(
|
||||||
|
media_id, {'networkId': 'cartoonnetwork'}, {
|
||||||
'url': url,
|
'url': url,
|
||||||
'site_name': 'CartoonNetwork',
|
'site_name': 'CartoonNetwork',
|
||||||
'auth_required': self._search_regex(
|
'auth_required': find_field('authType', 'auth type') != 'unauth',
|
||||||
r'_cnglobal\.cvpFullOrPreviewAuth\s*=\s*(true|false);',
|
|
||||||
webpage, 'auth required', default='false') == 'true',
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
series = find_field(
|
||||||
|
'propertyName', 'series', 'showName') or self._html_search_meta('partOfSeries', webpage)
|
||||||
|
info.update({
|
||||||
|
'id': media_id,
|
||||||
|
'display_id': display_id,
|
||||||
|
'title': title,
|
||||||
|
'description': self._html_search_meta('description', webpage),
|
||||||
|
'series': series,
|
||||||
|
'episode': title,
|
||||||
|
})
|
||||||
|
|
||||||
|
for field in ('season', 'episode'):
|
||||||
|
field_name = field + 'Number'
|
||||||
|
info[field + '_number'] = int_or_none(find_field(
|
||||||
|
field_name, field + ' number', value_re=r'\d+') or self._html_search_meta(field_name, webpage))
|
||||||
|
|
||||||
|
return info
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
|
||||||
from .common import InfoExtractor
|
from .common import InfoExtractor
|
||||||
from ..compat import compat_HTTPError
|
from ..compat import compat_HTTPError
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
@ -87,7 +90,7 @@ class FunimationIE(InfoExtractor):
|
|||||||
|
|
||||||
video_id = title_data.get('id') or self._search_regex([
|
video_id = title_data.get('id') or self._search_regex([
|
||||||
r"KANE_customdimensions.videoID\s*=\s*'(\d+)';",
|
r"KANE_customdimensions.videoID\s*=\s*'(\d+)';",
|
||||||
r'<iframe[^>]+src="/player/(\d+)"',
|
r'<iframe[^>]+src="/player/(\d+)',
|
||||||
], webpage, 'video_id', default=None)
|
], webpage, 'video_id', default=None)
|
||||||
if not video_id:
|
if not video_id:
|
||||||
player_url = self._html_search_meta([
|
player_url = self._html_search_meta([
|
||||||
@ -108,8 +111,10 @@ class FunimationIE(InfoExtractor):
|
|||||||
if self._TOKEN:
|
if self._TOKEN:
|
||||||
headers['Authorization'] = 'Token %s' % self._TOKEN
|
headers['Authorization'] = 'Token %s' % self._TOKEN
|
||||||
sources = self._download_json(
|
sources = self._download_json(
|
||||||
'https://prod-api-funimationnow.dadcdigital.com/api/source/catalog/video/%s/signed/' % video_id,
|
'https://www.funimation.com/api/showexperience/%s/' % video_id,
|
||||||
video_id, headers=headers)['items']
|
video_id, headers=headers, query={
|
||||||
|
'pinst_id': ''.join([random.choice(string.digits + string.ascii_letters) for _ in range(8)]),
|
||||||
|
})['items']
|
||||||
except ExtractorError as e:
|
except ExtractorError as e:
|
||||||
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403:
|
if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403:
|
||||||
error = self._parse_json(e.cause.read(), video_id)['errors'][0]
|
error = self._parse_json(e.cause.read(), video_id)['errors'][0]
|
||||||
|
@ -26,7 +26,7 @@ class SkylineWebcamsIE(InfoExtractor):
|
|||||||
webpage = self._download_webpage(url, video_id)
|
webpage = self._download_webpage(url, video_id)
|
||||||
|
|
||||||
stream_url = self._search_regex(
|
stream_url = self._search_regex(
|
||||||
r'url\s*:\s*(["\'])(?P<url>(?:https?:)?//.+?\.m3u8.*?)\1', webpage,
|
r'(?:url|source)\s*:\s*(["\'])(?P<url>(?:https?:)?//.+?\.m3u8.*?)\1', webpage,
|
||||||
'stream url', group='url')
|
'stream url', group='url')
|
||||||
|
|
||||||
title = self._og_search_title(webpage)
|
title = self._og_search_title(webpage)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import base64
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import itertools
|
import itertools
|
||||||
@ -392,6 +393,22 @@ class VimeoIE(VimeoBaseInfoExtractor):
|
|||||||
'skip_download': True,
|
'skip_download': True,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'url': 'http://player.vimeo.com/video/68375962',
|
||||||
|
'md5': 'aaf896bdb7ddd6476df50007a0ac0ae7',
|
||||||
|
'info_dict': {
|
||||||
|
'id': '68375962',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'youtube-dl password protected test video',
|
||||||
|
'uploader_url': r're:https?://(?:www\.)?vimeo\.com/user18948128',
|
||||||
|
'uploader_id': 'user18948128',
|
||||||
|
'uploader': 'Jaime Marquínez Ferrándiz',
|
||||||
|
'duration': 10,
|
||||||
|
},
|
||||||
|
'params': {
|
||||||
|
'videopassword': 'youtube-dl',
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'url': 'http://vimeo.com/moogaloop.swf?clip_id=2539741',
|
'url': 'http://vimeo.com/moogaloop.swf?clip_id=2539741',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
@ -452,7 +469,9 @@ class VimeoIE(VimeoBaseInfoExtractor):
|
|||||||
password = self._downloader.params.get('videopassword')
|
password = self._downloader.params.get('videopassword')
|
||||||
if password is None:
|
if password is None:
|
||||||
raise ExtractorError('This video is protected by a password, use the --video-password option')
|
raise ExtractorError('This video is protected by a password, use the --video-password option')
|
||||||
data = urlencode_postdata({'password': password})
|
data = urlencode_postdata({
|
||||||
|
'password': base64.b64encode(password.encode()),
|
||||||
|
})
|
||||||
pass_url = url + '/check-password'
|
pass_url = url + '/check-password'
|
||||||
password_request = sanitized_Request(pass_url, data)
|
password_request = sanitized_Request(pass_url, data)
|
||||||
password_request.add_header('Content-Type', 'application/x-www-form-urlencoded')
|
password_request.add_header('Content-Type', 'application/x-www-form-urlencoded')
|
||||||
|
@ -498,7 +498,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'channel_id': 'UCLqxVugv74EIW3VWh2NOa3Q',
|
'channel_id': 'UCLqxVugv74EIW3VWh2NOa3Q',
|
||||||
'channel_url': r're:https?://(?:www\.)?youtube\.com/channel/UCLqxVugv74EIW3VWh2NOa3Q',
|
'channel_url': r're:https?://(?:www\.)?youtube\.com/channel/UCLqxVugv74EIW3VWh2NOa3Q',
|
||||||
'upload_date': '20121002',
|
'upload_date': '20121002',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'description': 'test chars: "\'/\\ä↭𝕐\ntest URL: https://github.com/rg3/youtube-dl/issues/1892\n\nThis is a test video for youtube-dl.\n\nFor more information, contact phihag@phihag.de .',
|
'description': 'test chars: "\'/\\ä↭𝕐\ntest URL: https://github.com/rg3/youtube-dl/issues/1892\n\nThis is a test video for youtube-dl.\n\nFor more information, contact phihag@phihag.de .',
|
||||||
'categories': ['Science & Technology'],
|
'categories': ['Science & Technology'],
|
||||||
'tags': ['youtube-dl'],
|
'tags': ['youtube-dl'],
|
||||||
@ -527,7 +526,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'uploader': 'Icona Pop',
|
'uploader': 'Icona Pop',
|
||||||
'uploader_id': 'IconaPop',
|
'uploader_id': 'IconaPop',
|
||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/IconaPop',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/IconaPop',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'creator': 'Icona Pop',
|
'creator': 'Icona Pop',
|
||||||
'track': 'I Love It (feat. Charli XCX)',
|
'track': 'I Love It (feat. Charli XCX)',
|
||||||
'artist': 'Icona Pop',
|
'artist': 'Icona Pop',
|
||||||
@ -540,14 +538,13 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'id': '07FYdnEawAQ',
|
'id': '07FYdnEawAQ',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'upload_date': '20130703',
|
'upload_date': '20130703',
|
||||||
'title': 'Justin Timberlake - Tunnel Vision (Explicit)',
|
'title': 'Justin Timberlake - Tunnel Vision (Official Music Video) (Explicit)',
|
||||||
'alt_title': 'Tunnel Vision',
|
'alt_title': 'Tunnel Vision',
|
||||||
'description': 'md5:64249768eec3bc4276236606ea996373',
|
'description': 'md5:07dab3356cde4199048e4c7cd93471e1',
|
||||||
'duration': 419,
|
'duration': 419,
|
||||||
'uploader': 'justintimberlakeVEVO',
|
'uploader': 'justintimberlakeVEVO',
|
||||||
'uploader_id': 'justintimberlakeVEVO',
|
'uploader_id': 'justintimberlakeVEVO',
|
||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/justintimberlakeVEVO',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/justintimberlakeVEVO',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'creator': 'Justin Timberlake',
|
'creator': 'Justin Timberlake',
|
||||||
'track': 'Tunnel Vision',
|
'track': 'Tunnel Vision',
|
||||||
'artist': 'Justin Timberlake',
|
'artist': 'Justin Timberlake',
|
||||||
@ -566,7 +563,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'uploader': 'SET India',
|
'uploader': 'SET India',
|
||||||
'uploader_id': 'setindia',
|
'uploader_id': 'setindia',
|
||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/setindia',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/setindia',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'age_limit': 18,
|
'age_limit': 18,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -581,7 +577,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'uploader_id': 'phihag',
|
'uploader_id': 'phihag',
|
||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/phihag',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/phihag',
|
||||||
'upload_date': '20121002',
|
'upload_date': '20121002',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'description': 'test chars: "\'/\\ä↭𝕐\ntest URL: https://github.com/rg3/youtube-dl/issues/1892\n\nThis is a test video for youtube-dl.\n\nFor more information, contact phihag@phihag.de .',
|
'description': 'test chars: "\'/\\ä↭𝕐\ntest URL: https://github.com/rg3/youtube-dl/issues/1892\n\nThis is a test video for youtube-dl.\n\nFor more information, contact phihag@phihag.de .',
|
||||||
'categories': ['Science & Technology'],
|
'categories': ['Science & Technology'],
|
||||||
'tags': ['youtube-dl'],
|
'tags': ['youtube-dl'],
|
||||||
@ -605,7 +600,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/8KVIDEO',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/8KVIDEO',
|
||||||
'description': '',
|
'description': '',
|
||||||
'uploader': '8KVIDEO',
|
'uploader': '8KVIDEO',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'title': 'UHDTV TEST 8K VIDEO.mp4'
|
'title': 'UHDTV TEST 8K VIDEO.mp4'
|
||||||
},
|
},
|
||||||
'params': {
|
'params': {
|
||||||
@ -620,13 +614,12 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': 'IB3lcPjvWLA',
|
'id': 'IB3lcPjvWLA',
|
||||||
'ext': 'm4a',
|
'ext': 'm4a',
|
||||||
'title': 'Afrojack, Spree Wilson - The Spark ft. Spree Wilson',
|
'title': 'Afrojack, Spree Wilson - The Spark (Official Music Video) ft. Spree Wilson',
|
||||||
'description': 'md5:1900ed86ee514927b9e00fbead6969a5',
|
'description': 'md5:8f5e2b82460520b619ccac1f509d43bf',
|
||||||
'duration': 244,
|
'duration': 244,
|
||||||
'uploader': 'AfrojackVEVO',
|
'uploader': 'AfrojackVEVO',
|
||||||
'uploader_id': 'AfrojackVEVO',
|
'uploader_id': 'AfrojackVEVO',
|
||||||
'upload_date': '20131011',
|
'upload_date': '20131011',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
},
|
},
|
||||||
'params': {
|
'params': {
|
||||||
'youtube_include_dash_manifest': True,
|
'youtube_include_dash_manifest': True,
|
||||||
@ -640,13 +633,11 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'id': 'nfWlot6h_JM',
|
'id': 'nfWlot6h_JM',
|
||||||
'ext': 'm4a',
|
'ext': 'm4a',
|
||||||
'title': 'Taylor Swift - Shake It Off',
|
'title': 'Taylor Swift - Shake It Off',
|
||||||
'alt_title': 'Shake It Off',
|
'description': 'md5:bec2185232c05479482cb5a9b82719bf',
|
||||||
'description': 'md5:95f66187cd7c8b2c13eb78e1223b63c3',
|
|
||||||
'duration': 242,
|
'duration': 242,
|
||||||
'uploader': 'TaylorSwiftVEVO',
|
'uploader': 'TaylorSwiftVEVO',
|
||||||
'uploader_id': 'TaylorSwiftVEVO',
|
'uploader_id': 'TaylorSwiftVEVO',
|
||||||
'upload_date': '20140818',
|
'upload_date': '20140818',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'creator': 'Taylor Swift',
|
'creator': 'Taylor Swift',
|
||||||
},
|
},
|
||||||
'params': {
|
'params': {
|
||||||
@ -662,10 +653,9 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'duration': 219,
|
'duration': 219,
|
||||||
'upload_date': '20100909',
|
'upload_date': '20100909',
|
||||||
'uploader': 'TJ Kirk',
|
'uploader': 'Amazing Atheist',
|
||||||
'uploader_id': 'TheAmazingAtheist',
|
'uploader_id': 'TheAmazingAtheist',
|
||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/TheAmazingAtheist',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/TheAmazingAtheist',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'title': 'Burning Everyone\'s Koran',
|
'title': 'Burning Everyone\'s Koran',
|
||||||
'description': 'SUBSCRIBE: http://www.youtube.com/saturninefilms\n\nEven Obama has taken a stand against freedom on this issue: http://www.huffingtonpost.com/2010/09/09/obama-gma-interview-quran_n_710282.html',
|
'description': 'SUBSCRIBE: http://www.youtube.com/saturninefilms\n\nEven Obama has taken a stand against freedom on this issue: http://www.huffingtonpost.com/2010/09/09/obama-gma-interview-quran_n_710282.html',
|
||||||
}
|
}
|
||||||
@ -683,7 +673,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'uploader_id': 'WitcherGame',
|
'uploader_id': 'WitcherGame',
|
||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/WitcherGame',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/WitcherGame',
|
||||||
'upload_date': '20140605',
|
'upload_date': '20140605',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'age_limit': 18,
|
'age_limit': 18,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -692,7 +681,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'url': 'https://www.youtube.com/watch?v=6kLq3WMV1nU',
|
'url': 'https://www.youtube.com/watch?v=6kLq3WMV1nU',
|
||||||
'info_dict': {
|
'info_dict': {
|
||||||
'id': '6kLq3WMV1nU',
|
'id': '6kLq3WMV1nU',
|
||||||
'ext': 'webm',
|
'ext': 'mp4',
|
||||||
'title': 'Dedication To My Ex (Miss That) (Lyric Video)',
|
'title': 'Dedication To My Ex (Miss That) (Lyric Video)',
|
||||||
'description': 'md5:33765bb339e1b47e7e72b5490139bb41',
|
'description': 'md5:33765bb339e1b47e7e72b5490139bb41',
|
||||||
'duration': 246,
|
'duration': 246,
|
||||||
@ -700,7 +689,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'uploader_id': 'LloydVEVO',
|
'uploader_id': 'LloydVEVO',
|
||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/LloydVEVO',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/LloydVEVO',
|
||||||
'upload_date': '20110629',
|
'upload_date': '20110629',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'age_limit': 18,
|
'age_limit': 18,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -718,7 +706,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'creator': 'deadmau5',
|
'creator': 'deadmau5',
|
||||||
'description': 'md5:12c56784b8032162bb936a5f76d55360',
|
'description': 'md5:12c56784b8032162bb936a5f76d55360',
|
||||||
'uploader': 'deadmau5',
|
'uploader': 'deadmau5',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'title': 'Deadmau5 - Some Chords (HD)',
|
'title': 'Deadmau5 - Some Chords (HD)',
|
||||||
'alt_title': 'Some Chords',
|
'alt_title': 'Some Chords',
|
||||||
},
|
},
|
||||||
@ -736,7 +723,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'upload_date': '20150827',
|
'upload_date': '20150827',
|
||||||
'uploader_id': 'olympic',
|
'uploader_id': 'olympic',
|
||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/olympic',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/olympic',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'description': 'HO09 - Women - GER-AUS - Hockey - 31 July 2012 - London 2012 Olympic Games',
|
'description': 'HO09 - Women - GER-AUS - Hockey - 31 July 2012 - London 2012 Olympic Games',
|
||||||
'uploader': 'Olympic',
|
'uploader': 'Olympic',
|
||||||
'title': 'Hockey - Women - GER-AUS - London 2012 Olympic Games',
|
'title': 'Hockey - Women - GER-AUS - London 2012 Olympic Games',
|
||||||
@ -758,7 +744,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/AllenMeow',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/AllenMeow',
|
||||||
'description': 'made by Wacom from Korea | 字幕&加油添醋 by TY\'s Allen | 感謝heylisa00cavey1001同學熱情提供梗及翻譯',
|
'description': 'made by Wacom from Korea | 字幕&加油添醋 by TY\'s Allen | 感謝heylisa00cavey1001同學熱情提供梗及翻譯',
|
||||||
'uploader': '孫ᄋᄅ',
|
'uploader': '孫ᄋᄅ',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'title': '[A-made] 變態妍字幕版 太妍 我就是這樣的人',
|
'title': '[A-made] 變態妍字幕版 太妍 我就是這樣的人',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -792,7 +777,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'uploader_id': 'dorappi2000',
|
'uploader_id': 'dorappi2000',
|
||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/dorappi2000',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/dorappi2000',
|
||||||
'uploader': 'dorappi2000',
|
'uploader': 'dorappi2000',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'formats': 'mincount:31',
|
'formats': 'mincount:31',
|
||||||
},
|
},
|
||||||
'skip': 'not actual anymore',
|
'skip': 'not actual anymore',
|
||||||
@ -808,7 +792,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'uploader': 'Airtek',
|
'uploader': 'Airtek',
|
||||||
'description': 'Retransmisión en directo de la XVIII media maratón de Zaragoza.',
|
'description': 'Retransmisión en directo de la XVIII media maratón de Zaragoza.',
|
||||||
'uploader_id': 'UCzTzUmjXxxacNnL8I3m4LnQ',
|
'uploader_id': 'UCzTzUmjXxxacNnL8I3m4LnQ',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'title': 'Retransmisión XVIII Media maratón Zaragoza 2015',
|
'title': 'Retransmisión XVIII Media maratón Zaragoza 2015',
|
||||||
},
|
},
|
||||||
'params': {
|
'params': {
|
||||||
@ -881,6 +864,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'params': {
|
'params': {
|
||||||
'skip_download': True,
|
'skip_download': True,
|
||||||
},
|
},
|
||||||
|
'skip': 'This video is not available.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
# Multifeed video with comma in title (see https://github.com/rg3/youtube-dl/issues/8536)
|
# Multifeed video with comma in title (see https://github.com/rg3/youtube-dl/issues/8536)
|
||||||
@ -917,7 +901,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'uploader_id': 'IronSoulElf',
|
'uploader_id': 'IronSoulElf',
|
||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/IronSoulElf',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/IronSoulElf',
|
||||||
'uploader': 'IronSoulElf',
|
'uploader': 'IronSoulElf',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'creator': 'Todd Haberman, Daniel Law Heath and Aaron Kaplan',
|
'creator': 'Todd Haberman, Daniel Law Heath and Aaron Kaplan',
|
||||||
'track': 'Dark Walk - Position Music',
|
'track': 'Dark Walk - Position Music',
|
||||||
'artist': 'Todd Haberman, Daniel Law Heath and Aaron Kaplan',
|
'artist': 'Todd Haberman, Daniel Law Heath and Aaron Kaplan',
|
||||||
@ -1021,13 +1004,12 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'id': 'iqKdEhx-dD4',
|
'id': 'iqKdEhx-dD4',
|
||||||
'ext': 'mp4',
|
'ext': 'mp4',
|
||||||
'title': 'Isolation - Mind Field (Ep 1)',
|
'title': 'Isolation - Mind Field (Ep 1)',
|
||||||
'description': 'md5:25b78d2f64ae81719f5c96319889b736',
|
'description': 'md5:46a29be4ceffa65b92d277b93f463c0f',
|
||||||
'duration': 2085,
|
'duration': 2085,
|
||||||
'upload_date': '20170118',
|
'upload_date': '20170118',
|
||||||
'uploader': 'Vsauce',
|
'uploader': 'Vsauce',
|
||||||
'uploader_id': 'Vsauce',
|
'uploader_id': 'Vsauce',
|
||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/Vsauce',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/user/Vsauce',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
'series': 'Mind Field',
|
'series': 'Mind Field',
|
||||||
'season_number': 1,
|
'season_number': 1,
|
||||||
'episode_number': 1,
|
'episode_number': 1,
|
||||||
@ -1053,7 +1035,6 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
'uploader': 'New Century Foundation',
|
'uploader': 'New Century Foundation',
|
||||||
'uploader_id': 'UCEJYpZGqgUob0zVVEaLhvVg',
|
'uploader_id': 'UCEJYpZGqgUob0zVVEaLhvVg',
|
||||||
'uploader_url': r're:https?://(?:www\.)?youtube\.com/channel/UCEJYpZGqgUob0zVVEaLhvVg',
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/channel/UCEJYpZGqgUob0zVVEaLhvVg',
|
||||||
'license': 'Standard YouTube License',
|
|
||||||
},
|
},
|
||||||
'params': {
|
'params': {
|
||||||
'skip_download': True,
|
'skip_download': True,
|
||||||
@ -1081,6 +1062,26 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
# DRM protected
|
# DRM protected
|
||||||
'url': 'https://www.youtube.com/watch?v=s7_qI6_mIXc',
|
'url': 'https://www.youtube.com/watch?v=s7_qI6_mIXc',
|
||||||
'only_matching': True,
|
'only_matching': True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
# Video with unsupported adaptive stream type formats
|
||||||
|
'url': 'https://www.youtube.com/watch?v=Z4Vy8R84T1U',
|
||||||
|
'info_dict': {
|
||||||
|
'id': 'Z4Vy8R84T1U',
|
||||||
|
'ext': 'mp4',
|
||||||
|
'title': 'saman SMAN 53 Jakarta(Sancety) opening COFFEE4th at SMAN 53 Jakarta',
|
||||||
|
'description': 'md5:d41d8cd98f00b204e9800998ecf8427e',
|
||||||
|
'duration': 433,
|
||||||
|
'upload_date': '20130923',
|
||||||
|
'uploader': 'Amelia Putri Harwita',
|
||||||
|
'uploader_id': 'UCpOxM49HJxmC1qCalXyB3_Q',
|
||||||
|
'uploader_url': r're:https?://(?:www\.)?youtube\.com/channel/UCpOxM49HJxmC1qCalXyB3_Q',
|
||||||
|
'formats': 'maxcount:10',
|
||||||
|
},
|
||||||
|
'params': {
|
||||||
|
'skip_download': True,
|
||||||
|
'youtube_include_dash_manifest': False,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1197,8 +1198,8 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
funcname = self._search_regex(
|
funcname = self._search_regex(
|
||||||
(r'(["\'])signature\1\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
(r'(["\'])signature\1\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
||||||
r'\.sig\|\|(?P<sig>[a-zA-Z0-9$]+)\(',
|
r'\.sig\|\|(?P<sig>[a-zA-Z0-9$]+)\(',
|
||||||
r'yt\.akamaized\.net/\)\s*\|\|\s*.*?\s*c\s*&&\s*d\.set\([^,]+\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
r'yt\.akamaized\.net/\)\s*\|\|\s*.*?\s*c\s*&&\s*d\.set\([^,]+\s*,\s*(?:encodeURIComponent\s*\()?(?P<sig>[a-zA-Z0-9$]+)\(',
|
||||||
r'\bc\s*&&\s*d\.set\([^,]+\s*,\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
r'\bc\s*&&\s*d\.set\([^,]+\s*,\s*(?:encodeURIComponent\s*\()?\s*(?P<sig>[a-zA-Z0-9$]+)\(',
|
||||||
r'\bc\s*&&\s*d\.set\([^,]+\s*,\s*\([^)]*\)\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\('),
|
r'\bc\s*&&\s*d\.set\([^,]+\s*,\s*\([^)]*\)\s*\(\s*(?P<sig>[a-zA-Z0-9$]+)\('),
|
||||||
jscode, 'Initial JS player signature function name', group='sig')
|
jscode, 'Initial JS player signature function name', group='sig')
|
||||||
|
|
||||||
@ -1545,6 +1546,13 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
if dash_mpd and dash_mpd[0] not in dash_mpds:
|
if dash_mpd and dash_mpd[0] not in dash_mpds:
|
||||||
dash_mpds.append(dash_mpd[0])
|
dash_mpds.append(dash_mpd[0])
|
||||||
|
|
||||||
|
def add_dash_mpd_pr(pl_response):
|
||||||
|
dash_mpd = url_or_none(try_get(
|
||||||
|
pl_response, lambda x: x['streamingData']['dashManifestUrl'],
|
||||||
|
compat_str))
|
||||||
|
if dash_mpd and dash_mpd not in dash_mpds:
|
||||||
|
dash_mpds.append(dash_mpd)
|
||||||
|
|
||||||
is_live = None
|
is_live = None
|
||||||
view_count = None
|
view_count = None
|
||||||
|
|
||||||
@ -1602,6 +1610,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
if isinstance(pl_response, dict):
|
if isinstance(pl_response, dict):
|
||||||
player_response = pl_response
|
player_response = pl_response
|
||||||
if not video_info or self._downloader.params.get('youtube_include_dash_manifest', True):
|
if not video_info or self._downloader.params.get('youtube_include_dash_manifest', True):
|
||||||
|
add_dash_mpd_pr(player_response)
|
||||||
# We also try looking in get_video_info since it may contain different dashmpd
|
# We also try looking in get_video_info since it may contain different dashmpd
|
||||||
# URL that points to a DASH manifest with possibly different itag set (some itags
|
# URL that points to a DASH manifest with possibly different itag set (some itags
|
||||||
# are missing from DASH manifest pointed by webpage's dashmpd, some - from DASH
|
# are missing from DASH manifest pointed by webpage's dashmpd, some - from DASH
|
||||||
@ -1633,6 +1642,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
pl_response = get_video_info.get('player_response', [None])[0]
|
pl_response = get_video_info.get('player_response', [None])[0]
|
||||||
if isinstance(pl_response, dict):
|
if isinstance(pl_response, dict):
|
||||||
player_response = pl_response
|
player_response = pl_response
|
||||||
|
add_dash_mpd_pr(player_response)
|
||||||
add_dash_mpd(get_video_info)
|
add_dash_mpd(get_video_info)
|
||||||
if view_count is None:
|
if view_count is None:
|
||||||
view_count = extract_view_count(get_video_info)
|
view_count = extract_view_count(get_video_info)
|
||||||
@ -1818,6 +1828,10 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|||||||
url_data = compat_parse_qs(url_data_str)
|
url_data = compat_parse_qs(url_data_str)
|
||||||
if 'itag' not in url_data or 'url' not in url_data:
|
if 'itag' not in url_data or 'url' not in url_data:
|
||||||
continue
|
continue
|
||||||
|
stream_type = int_or_none(try_get(url_data, lambda x: x['stream_type'][0]))
|
||||||
|
# Unsupported FORMAT_STREAM_TYPE_OTF
|
||||||
|
if stream_type == 3:
|
||||||
|
continue
|
||||||
format_id = url_data['itag'][0]
|
format_id = url_data['itag'][0]
|
||||||
url = url_data['url'][0]
|
url = url_data['url'][0]
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
__version__ = '2019.01.10'
|
__version__ = '2019.01.17'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user