2 from __future__ import unicode_literals
7 from .common import InfoExtractor
8 from ..utils import ExtractorError
11 class TuneInIE(InfoExtractor):
12 _VALID_URL = r'''(?x)https?://(?:www\.)?
17 station/.*?StationId\=
19 |tun\.in/(?P<redirect_id>[A-Za-z0-9]+)
25 'title': 'Jazz 24 on 88.5 Jazz24 - KPLU-HD2',
27 'thumbnail': 're:^https?://.*\.png$',
28 'location': 'Tacoma, WA',
32 'url': 'http://tunein.com/radio/Jazz24-885-s34682/',
33 'info_dict': _INFO_DICT,
35 'skip_download': True, # live stream
39 'url': 'http://tun.in/ser7s',
40 'info_dict': _INFO_DICT,
42 'skip_download': True, # live stream
47 def _real_extract(self, url):
48 mobj = re.match(self._VALID_URL, url)
49 redirect_id = mobj.group('redirect_id')
51 # The server doesn't support HEAD requests
52 urlh = self._request_webpage(
53 url, redirect_id, note='Downloading redirect page')
55 self.to_screen('Following redirect: %s' % url)
56 mobj = re.match(self._VALID_URL, url)
57 station_id = mobj.group('id')
59 webpage = self._download_webpage(
60 url, station_id, note='Downloading station webpage')
62 payload = self._html_search_regex(
63 r'(?m)TuneIn\.payload\s*=\s*(\{[^$]+?)$', webpage, 'JSON data')
64 json_data = json.loads(payload)
65 station_info = json_data['Station']['broadcast']
66 title = station_info['Title']
67 thumbnail = station_info.get('Logo')
68 location = station_info.get('Location')
69 streams_url = station_info.get('StreamUrl')
71 raise ExtractorError('No downloadable streams found',
73 stream_data = self._download_webpage(
74 streams_url, station_id, note='Downloading stream data')
75 streams = json.loads(self._search_regex(
76 r'\((.*)\);', stream_data, 'stream info'))['Streams']
80 for stream in streams:
81 if stream.get('Type') == 'Live':
84 'abr': stream.get('Bandwidth'),
85 'ext': stream.get('MediaType'),
86 'acodec': stream.get('MediaType'),
88 'url': stream.get('Url'),
89 # Sometimes streams with the highest quality do not exist
90 'preference': stream.get('Reliability'),
92 self._sort_formats(formats)
98 'thumbnail': thumbnail,