$"""
_NEXT_URL_RE = r'[\?&]next_url=([^&]+)'
# Listed in order of quality
- _available_formats = ['38', '37', '46', '22', '45', '35', '44', '34', '18', '43', '6', '5', '17', '13',
- '95', '94', '93', '92', '132', '151',
+ _available_formats = ['38', '37', '46', '22', '45', '35', '44', '34', '18', '43', '6', '5', '36', '17', '13',
+ # Apple HTTP Live Streaming
+ '96', '95', '94', '93', '92', '132', '151',
# 3D
'85', '84', '102', '83', '101', '82', '100',
# Dash video
# Dash audio
'141', '172', '140', '171', '139',
]
- _available_formats_prefer_free = ['38', '46', '37', '45', '22', '44', '35', '43', '34', '18', '6', '5', '17', '13',
- '95', '94', '93', '92', '132', '151',
+ _available_formats_prefer_free = ['38', '46', '37', '45', '22', '44', '35', '43', '34', '18', '6', '5', '36', '17', '13',
+ # Apple HTTP Live Streaming
+ '96', '95', '94', '93', '92', '132', '151',
+ # 3D
'85', '102', '84', '101', '83', '100', '82',
# Dash video
'138', '248', '137', '247', '136', '246', '245',
# Dash audio
'172', '141', '171', '140', '139',
]
+ _video_formats_map = {
+ 'flv': ['35', '34', '6', '5'],
+ '3gp': ['36', '17', '13'],
+ 'mp4': ['38', '37', '22', '18'],
+ 'webm': ['46', '45', '44', '43'],
+ }
_video_extensions = {
'13': '3gp',
- '17': 'mp4',
+ '17': '3gp',
'18': 'mp4',
'22': 'mp4',
+ '36': '3gp',
'37': 'mp4',
'38': 'mp4',
'43': 'webm',
'101': 'webm',
'102': 'webm',
- # videos that use m3u8
+ # Apple HTTP Live Streaming
'92': 'mp4',
'93': 'mp4',
'94': 'mp4',
'22': '720x1280',
'34': '360x640',
'35': '480x854',
+ '36': '240x320',
'37': '1080x1920',
'38': '3072x4096',
'43': '360x640',
u"info_dict": {
u"upload_date": u"20120506",
u"title": u"Icona Pop - I Love It (feat. Charli XCX) [OFFICIAL VIDEO]",
- u"description": u"md5:b085c9804f5ab69f4adea963a2dceb3c",
+ u"description": u"md5:3e2666e0a55044490499ea45fe9037b7",
u"uploader": u"Icona Pop",
u"uploader_id": u"IconaPop"
}
elif len(s) == 89:
return s[84:78:-1] + s[87] + s[77:60:-1] + s[0] + s[59:3:-1]
elif len(s) == 88:
- return s[48] + s[81:67:-1] + s[82] + s[66:62:-1] + s[85] + s[61:48:-1] + s[67] + s[47:12:-1] + s[3] + s[11:3:-1] + s[2] + s[12]
+ return s[7:28] + s[87] + s[29:45] + s[55] + s[46:55] + s[2] + s[56:87] + s[28]
elif len(s) == 87:
return s[6:27] + s[4] + s[28:39] + s[27] + s[40:59] + s[2] + s[60:]
elif len(s) == 86:
- return s[5:20] + s[2] + s[21:]
+ return s[81:73:-1] + s[84] + s[72:58:-1] + s[0] + s[57:35:-1] + s[85] + s[34:0:-1]
elif len(s) == 85:
return s[83:34:-1] + s[0] + s[33:27:-1] + s[3] + s[26:19:-1] + s[34] + s[18:3:-1] + s[27]
elif len(s) == 84:
- return s[83:27:-1] + s[0] + s[26:5:-1] + s[2:0:-1] + s[27]
+ return s[81:36:-1] + s[0] + s[35:2:-1]
elif len(s) == 83:
return s[81:64:-1] + s[82] + s[63:52:-1] + s[45] + s[51:45:-1] + s[1] + s[44:1:-1] + s[0]
elif len(s) == 82:
def _request_automatic_caption(self, video_id, webpage):
"""We need the webpage for getting the captions url, pass it as an
argument to speed up the process."""
- sub_lang = self._downloader.params.get('subtitleslang') or 'en'
+ sub_lang = (self._downloader.params.get('subtitleslangs') or ['en'])[0]
sub_format = self._downloader.params.get('subtitlesformat')
self.to_screen(u'%s: Looking for automatic captions' % video_id)
mobj = re.search(r';ytplayer.config = ({.*?});', webpage)
Return a dictionary: {language: subtitles} or {} if the subtitles
couldn't be found
"""
- sub_lang_list = self._get_available_subtitles(video_id)
+ available_subs_list = self._get_available_subtitles(video_id)
sub_format = self._downloader.params.get('subtitlesformat')
- if not sub_lang_list: #There was some error, it didn't get the available subtitles
+ if not available_subs_list: #There was some error, it didn't get the available subtitles
return {}
if self._downloader.params.get('allsubtitles', False):
- pass
+ sub_lang_list = available_subs_list
else:
- if self._downloader.params.get('subtitleslang', False):
- sub_lang = self._downloader.params.get('subtitleslang')
- elif 'en' in sub_lang_list:
- sub_lang = 'en'
+ if self._downloader.params.get('subtitleslangs', False):
+ reqested_langs = self._downloader.params.get('subtitleslangs')
+ elif 'en' in available_subs_list:
+ reqested_langs = ['en']
else:
- sub_lang = list(sub_lang_list.keys())[0]
- if not sub_lang in sub_lang_list:
- self._downloader.report_warning(u'no closed captions found in the specified language "%s"' % sub_lang)
- return {}
- sub_lang_list = {sub_lang: sub_lang_list[sub_lang]}
+ reqested_langs = [list(available_subs_list.keys())[0]]
+
+ sub_lang_list = {}
+ for sub_lang in reqested_langs:
+ if not sub_lang in available_subs_list:
+ self._downloader.report_warning(u'no closed captions found in the specified language "%s"' % sub_lang)
+ continue
+ sub_lang_list[sub_lang] = available_subs_list[sub_lang]
subtitles = {}
for sub_lang in sub_lang_list:
subtitle = self._request_subtitle(sub_lang, sub_lang_list[sub_lang].encode('utf-8'), video_id, sub_format)
video_url_list = [(f, url_map[f]) for f in existing_formats] # All formats
else:
# Specific formats. We pick the first in a slash-delimeted sequence.
- # For example, if '1/2/3/4' is requested and '2' and '4' are available, we pick '2'.
+ # Format can be specified as itag or 'mp4' or 'flv' etc. We pick the highest quality
+ # available in the specified format. For example,
+ # if '1/2/3/4' is requested and '2' and '4' are available, we pick '2'.
+ # if '1/mp4/3/4' is requested and '1' and '5' (is a mp4) are available, we pick '1'.
+ # if '1/mp4/3/4' is requested and '4' and '5' (is a mp4) are available, we pick '5'.
req_formats = req_format.split('/')
video_url_list = None
for rf in req_formats:
if rf in url_map:
video_url_list = [(rf, url_map[rf])]
break
+ if rf in self._video_formats_map:
+ for srf in self._video_formats_map[rf]:
+ if srf in url_map:
+ video_url_list = [(srf, url_map[srf])]
+ break
+ else:
+ continue
+ break
if video_url_list is None:
raise ExtractorError(u'requested format not available')
return video_url_list
for entry in response['feed']['entry']:
index = entry['yt$position']['$t']
- if 'media$group' in entry and 'media$player' in entry['media$group']:
- videos.append((index, entry['media$group']['media$player']['url']))
+ if 'media$group' in entry and 'yt$videoid' in entry['media$group']:
+ videos.append((
+ index,
+ 'https://www.youtube.com/watch?v=' + entry['media$group']['yt$videoid']['$t']
+ ))
videos = [v[1] for v in sorted(videos)]
class YoutubeFavouritesIE(YoutubeBaseInfoExtractor):
IE_NAME = u'youtube:favorites'
IE_DESC = u'YouTube.com favourite videos, "ytfav" keyword (requires authentication)'
- _VALID_URL = r'https?://www\.youtube\.com/my_favorites|:ytfav(?:o?rites)?'
+ _VALID_URL = r'https?://www\.youtube\.com/my_favorites|:ytfav(?:ou?rites)?'
_LOGIN_REQUIRED = True
def _real_extract(self, url):