diff options
| -rw-r--r-- | youtube_dl/YoutubeDL.py | 10 | ||||
| -rw-r--r-- | youtube_dl/__init__.py | 4 | ||||
| -rw-r--r-- | youtube_dl/extractor/soundcloud.py | 66 | 
3 files changed, 55 insertions, 25 deletions
| diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index 46635bce1..d0aab1bbd 100644 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -258,10 +258,6 @@ class YoutubeDL(object):          if self.params.get('cookiefile') is not None:              self.cookiejar.save() -    def fixed_template(self): -        """Checks if the output template is fixed.""" -        return (re.search(u'(?u)%\\(.+?\\)s', self.params['outtmpl']) is None) -      def trouble(self, message=None, tb=None):          """Determine action to take when a download problem appears. @@ -798,7 +794,9 @@ class YoutubeDL(object):      def download(self, url_list):          """Download a given list of URLs.""" -        if len(url_list) > 1 and self.fixed_template(): +        if (len(url_list) > 1 and +                '%' not in self.params['outtmpl'] +                and self.params.get('max_downloads') != 1):              raise SameFileError(self.params['outtmpl'])          for url in url_list: @@ -968,7 +966,7 @@ class YoutubeDL(object):                  proxy_map.update(handler.proxies)          write_string(u'[debug] Proxy map: ' + compat_str(proxy_map) + u'\n') -    def _setup_opener(self, timeout=300): +    def _setup_opener(self, timeout=20):          opts_cookiefile = self.params.get('cookiefile')          opts_proxy = self.params.get('proxy') diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 1f15c7eaa..102508cf9 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -206,7 +206,9 @@ def parseOpts(overrideArguments=None):              dest='playlistend', metavar='NUMBER', help='playlist video to end at (default is last)', default=-1)      selection.add_option('--match-title', dest='matchtitle', metavar='REGEX',help='download only matching titles (regex or caseless sub-string)')      selection.add_option('--reject-title', dest='rejecttitle', metavar='REGEX',help='skip download for matching titles (regex or caseless sub-string)') -    selection.add_option('--max-downloads', metavar='NUMBER', dest='max_downloads', help='Abort after downloading NUMBER files', default=None) +    selection.add_option('--max-downloads', metavar='NUMBER', +                         dest='max_downloads', type=int, default=None, +                         help='Abort after downloading NUMBER files')      selection.add_option('--min-filesize', metavar='SIZE', dest='min_filesize', help="Do not download any videos smaller than SIZE (e.g. 50k or 44.6m)", default=None)      selection.add_option('--max-filesize', metavar='SIZE', dest='max_filesize', help="Do not download any videos larger than SIZE (e.g. 50k or 44.6m)", default=None)      selection.add_option('--date', metavar='DATE', dest='date', help='download only videos uploaded in this date', default=None) diff --git a/youtube_dl/extractor/soundcloud.py b/youtube_dl/extractor/soundcloud.py index 67b2dff9c..ee8da227e 100644 --- a/youtube_dl/extractor/soundcloud.py +++ b/youtube_dl/extractor/soundcloud.py @@ -76,44 +76,74 @@ class SoundcloudIE(InfoExtractor):      def _extract_info_dict(self, info, full_title=None, quiet=False):          track_id = compat_str(info['id'])          name = full_title or track_id -        if quiet == False: +        if quiet:              self.report_extraction(name)          thumbnail = info['artwork_url']          if thumbnail is not None:              thumbnail = thumbnail.replace('-large', '-t500x500') +        ext = info.get('original_format', u'mp3')          result = { -            'id':       track_id, +            'id': track_id,              'uploader': info['user']['username'],              'upload_date': unified_strdate(info['created_at']), -            'title':    info['title'], -            'ext':      info.get('original_format', u'mp3'), +            'title': info['title'],              'description': info['description'],              'thumbnail': thumbnail,          }          if info.get('downloadable', False):              # We can build a direct link to the song -            result['url'] = 'https://api.soundcloud.com/tracks/{0}/download?client_id={1}'.format(track_id, self._CLIENT_ID) +            format_url = ( +                u'https://api.soundcloud.com/tracks/{0}/download?client_id={1}'.format( +                    track_id, self._CLIENT_ID)) +            result['formats'] = [{ +                'format_id': 'download', +                'ext': ext, +                'url': format_url, +            }]          else:              # We have to retrieve the url              stream_json = self._download_webpage(                  'http://api.soundcloud.com/i1/tracks/{0}/streams?client_id={1}'.format(track_id, self._IPHONE_CLIENT_ID),                  track_id, u'Downloading track url') -            # There should be only one entry in the dictionary -            key, stream_url = list(json.loads(stream_json).items())[0] -            if key.startswith(u'http'): -                result['url'] = stream_url -            elif key.startswith(u'rtmp'): -                # The url doesn't have an rtmp app, we have to extract the playpath -                url, path = stream_url.split('mp3:', 1) -                result.update({ -                    'url': url, -                    'play_path': 'mp3:' + path, -                }) -            else: + +            formats = [] +            format_dict = json.loads(stream_json) +            for key, stream_url in format_dict.items(): +                if key.startswith(u'http'): +                    formats.append({ +                        'format_id': key, +                        'ext': ext, +                        'url': stream_url, +                    }) +                elif key.startswith(u'rtmp'): +                    # The url doesn't have an rtmp app, we have to extract the playpath +                    url, path = stream_url.split('mp3:', 1) +                    formats.append({ +                        'format_id': key, +                        'url': url, +                        'play_path': 'mp3:' + path, +                        'ext': ext, +                    }) + +            if not formats:                  # We fallback to the stream_url in the original info, this                  # cannot be always used, sometimes it can give an HTTP 404 error -                result['url'] = info['stream_url'] + '?client_id=' + self._CLIENT_ID, +                formats.append({ +                    'format_id': u'fallback', +                    'url': info['stream_url'] + '?client_id=' + self._CLIENT_ID, +                    'ext': ext, +                }) + +            def format_pref(f): +                if f['format_id'].startswith('http'): +                    return 2 +                if f['format_id'].startswith('rtmp'): +                    return 1 +                return 0 + +            formats.sort(key=format_pref) +            result['formats'] = formats          return result | 
