Skip to content

Commit

Permalink
Mixcloud IE
Browse files Browse the repository at this point in the history
  • Loading branch information
sh!zeeg committed Nov 24, 2011
1 parent fa2672f commit b158a1d
Showing 1 changed file with 120 additions and 0 deletions.
120 changes: 120 additions & 0 deletions youtube-dl
Expand Up @@ -3608,7 +3608,126 @@ class InfoQIE(InfoExtractor):
except UnavailableVideoError, err:
self._downloader.trouble(u'\nERROR: unable to download ' + video_url)

class MixcloudIE(InfoExtractor):
"""Information extractor for www.mixcloud.com"""
_VALID_URL = r'^(?:https?://)?(?:www\.)?mixcloud\.com/([\w\d-]+)/([\w\d-]+)'
IE_NAME = u'mixcloud'

def __init__(self, downloader=None):
InfoExtractor.__init__(self, downloader)

def report_download_json(self, file_id):
"""Report JSON download."""
self._downloader.to_screen(u'[%s] Downloading json' % self.IE_NAME)

def report_extraction(self, file_id):
"""Report information extraction."""
self._downloader.to_screen(u'[%s] %s: Extracting information' % (self.IE_NAME, file_id))

def get_urls(self, jsonData, fmt, bitrate='best'):
"""Get urls from 'audio_formats' section in json"""
file_url = None
try:
bitrate_list = jsonData[fmt]
if bitrate is None or bitrate == 'best' or bitrate not in bitrate_list:
bitrate = max(bitrate_list) # select highest

url_list = jsonData[fmt][bitrate]
except TypeError: # we have no bitrate info.
url_list = jsonData[fmt]

return url_list

def check_urls(self, url_list):
"""Returns 1st active url from list"""
for url in url_list:
try:
urllib2.urlopen(url)
return url
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
url = None

return None

def _print_formats(self, formats):
print 'Available formats:'
for fmt in formats.keys():
for b in formats[fmt]:
try:
ext = formats[fmt][b][0]
print '%s\t%s\t[%s]' % (fmt, b, ext.split('.')[-1])
except TypeError: # we have no bitrate info
ext = formats[fmt][0]
print '%s\t%s\t[%s]' % (fmt, '??', ext.split('.')[-1])
break

def _real_extract(self, url):
mobj = re.match(self._VALID_URL, url)
if mobj is None:
self._downloader.trouble(u'ERROR: invalid URL: %s' % url)
return
# extract uploader & filename from url
uploader = mobj.group(1).decode('utf-8')
file_id = uploader + "-" + mobj.group(2).decode('utf-8')

# construct API request
file_url = 'http://www.mixcloud.com/api/1/cloudcast/' + '/'.join(url.split('/')[-3:-1]) + '.json'
# retrieve .json file with links to files
request = urllib2.Request(file_url)
try:
self.report_download_json(file_url)
jsonData = urllib2.urlopen(request).read()
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
self._downloader.trouble(u'ERROR: Unable to retrieve file: %s' % str(err))
return

# parse JSON
json_data = json.loads(jsonData)
player_url = json_data['player_swf_url']
formats = dict(json_data['audio_formats'])

req_format = self._downloader.params.get('format', None)
bitrate = None

if self._downloader.params.get('listformats', None):
self._print_formats(formats)
return

if req_format is None or req_format == 'best':
for format_param in formats.keys():
url_list = self.get_urls(formats, format_param)
# check urls
file_url = self.check_urls(url_list)
if file_url is not None:
break # got it!
else:
if req_format not in formats.keys():
self._downloader.trouble(u'ERROR: format is not available')
return

url_list = self.get_urls(formats, req_format)
file_url = self.check_urls(url_list)
format_param = req_format

# We have audio
self._downloader.increment_downloads()
try:
# Process file information
self._downloader.process_info({
'id': file_id.decode('utf-8'),
'url': file_url.decode('utf-8'),
'uploader': uploader.decode('utf-8'),
'upload_date': u'NA',
'title': json_data['name'],
'stitle': _simplify_title(json_data['name']),
'ext': file_url.split('.')[-1].decode('utf-8'),
'format': (format_param is None and u'NA' or format_param.decode('utf-8')),
'thumbnail': json_data['thumbnail_url'],
'description': json_data['description'],
'player_url': player_url.decode('utf-8'),
})
except UnavailableVideoError, err:
self._downloader.trouble(u'ERROR: unable to download file')

class PostProcessor(object):
"""Post Processor class.
Expand Down Expand Up @@ -4008,6 +4127,7 @@ def gen_extractors():
XVideosIE(),
SoundcloudIE(),
InfoQIE(),
MixcloudIE(),

GenericIE()
]
Expand Down

0 comments on commit b158a1d

Please sign in to comment.