[soundcloud] Prefer HTTP over RTMP (#1798)
authorPhilipp Hagemeister <phihag@phihag.de>
Mon, 25 Nov 2013 19:30:41 +0000 (20:30 +0100)
committerPhilipp Hagemeister <phihag@phihag.de>
Mon, 25 Nov 2013 19:30:41 +0000 (20:30 +0100)
youtube_dl/extractor/soundcloud.py

index 67b2dff9c9ec431bb7ddd501bb804f6cc572cb61..ee8da227e4e6f40d37f9b837b04c9e84cc6e7e56 100644 (file)
@@ -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