From 77d0f05f714eec81f076025f309d5d39325d5d0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Fri, 21 Jun 2013 19:28:23 +0200 Subject: [PATCH 1/3] YoutubeIE: Detect new Vevo style videos The url_encoded_fmt_stream_map can be found in the video page, but the signature must be decrypted, we get it from the webpage instead of the `get_video_info` pages because we have only discover the algorithm for keys with both sub keys of size 43. --- youtube_dl/InfoExtractors.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/youtube_dl/InfoExtractors.py b/youtube_dl/InfoExtractors.py index 8d228d40d..a12bffbe3 100755 --- a/youtube_dl/InfoExtractors.py +++ b/youtube_dl/InfoExtractors.py @@ -724,6 +724,16 @@ class YoutubeIE(InfoExtractor): # Decide which formats to download req_format = self._downloader.params.get('format', None) + try: + mobj = re.search(r';ytplayer.config = ({.*?});', video_webpage) + info = json.loads(mobj.group(1)) + if 'dashmpd' in info['args']: + # Vevo videos with encrypted signatures + self.to_screen(u'Vevo video detected.') + video_info['url_encoded_fmt_stream_map'] = [info['args']['url_encoded_fmt_stream_map']] + except ValueError: + pass + if 'conn' in video_info and video_info['conn'][0].startswith('rtmp'): self.report_rtmp_download() video_url_list = [(None, video_info['conn'][0])] @@ -735,6 +745,16 @@ class YoutubeIE(InfoExtractor): url = url_data['url'][0] if 'sig' in url_data: url += '&signature=' + url_data['sig'][0] + if 's' in url_data: + def k(s): + """Decrypt the key the two subkeys must have a length of 43""" + (a,b) = s.split('.') + b = ''.join([b[:8],a[0],b[9:18],b[-4],b[19:39], b[18]])[0:40] + a = a[-40:] + s_dec = '.'.join((a,b))[::-1] + return s_dec + key = k(url_data['s'][0]) + url += '&signature=' + key if 'ratebypass' not in url: url += '&ratebypass=yes' url_map[url_data['itag'][0]] = url From ef75f76f5c0704bc5d91a436c724630b6aa9b7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sat, 22 Jun 2013 13:13:40 +0200 Subject: [PATCH 2/3] Detect more vevo videos --- youtube_dl/InfoExtractors.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/youtube_dl/InfoExtractors.py b/youtube_dl/InfoExtractors.py index a12bffbe3..2a748b175 100755 --- a/youtube_dl/InfoExtractors.py +++ b/youtube_dl/InfoExtractors.py @@ -727,10 +727,11 @@ class YoutubeIE(InfoExtractor): try: mobj = re.search(r';ytplayer.config = ({.*?});', video_webpage) info = json.loads(mobj.group(1)) - if 'dashmpd' in info['args']: + args = info['args'] + if args.get('ptk','') == 'vevo' or 'dashmpd': # Vevo videos with encrypted signatures self.to_screen(u'Vevo video detected.') - video_info['url_encoded_fmt_stream_map'] = [info['args']['url_encoded_fmt_stream_map']] + video_info['url_encoded_fmt_stream_map'] = [args['url_encoded_fmt_stream_map']] except ValueError: pass From b37fbb990bd29521f5891b0874bb485eb72981fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Marqui=CC=81nez=20Ferra=CC=81ndiz?= Date: Sat, 22 Jun 2013 13:20:06 +0200 Subject: [PATCH 3/3] Move the decrypting function to a static method --- youtube_dl/InfoExtractors.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/youtube_dl/InfoExtractors.py b/youtube_dl/InfoExtractors.py index 2a748b175..af11333d1 100755 --- a/youtube_dl/InfoExtractors.py +++ b/youtube_dl/InfoExtractors.py @@ -379,6 +379,17 @@ class YoutubeIE(InfoExtractor): """Indicate the download will use the RTMP protocol.""" self.to_screen(u'RTMP download detected') + @staticmethod + def _decrypt_signature(s): + """Decrypt the key the two subkeys must have a length of 43""" + (a,b) = s.split('.') + if len(a) != 43 or len(b) != 43: + raise ExtractorError(u'Unable to decrypt signature, subkeys lengths not valid') + b = ''.join([b[:8],a[0],b[9:18],b[-4],b[19:39], b[18]])[0:40] + a = a[-40:] + s_dec = '.'.join((a,b))[::-1] + return s_dec + def _get_available_subtitles(self, video_id): self.report_video_subtitles_download(video_id) request = compat_urllib_request.Request('http://video.google.com/timedtext?hl=en&type=list&v=%s' % video_id) @@ -747,15 +758,8 @@ class YoutubeIE(InfoExtractor): if 'sig' in url_data: url += '&signature=' + url_data['sig'][0] if 's' in url_data: - def k(s): - """Decrypt the key the two subkeys must have a length of 43""" - (a,b) = s.split('.') - b = ''.join([b[:8],a[0],b[9:18],b[-4],b[19:39], b[18]])[0:40] - a = a[-40:] - s_dec = '.'.join((a,b))[::-1] - return s_dec - key = k(url_data['s'][0]) - url += '&signature=' + key + signature = self._decrypt_signature(url_data['s'][0]) + url += '&signature=' + signature if 'ratebypass' not in url: url += '&ratebypass=yes' url_map[url_data['itag'][0]] = url