aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--youtube_dl/YoutubeDL.py10
-rw-r--r--youtube_dl/__init__.py4
-rw-r--r--youtube_dl/extractor/soundcloud.py66
3 files changed, 55 insertions, 25 deletions
diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py
index a1ef3a94a..50f750593 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