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]+)
22 _API_URL_TEMPLATE = 'http://tunein.com/tuner/tune/?stationId={0:}&tuneType=Station'
26 'title': 'Jazz 24 on 88.5 Jazz24 - KPLU-HD2',
28 'thumbnail': 're:^https?://.*\.png$',
29 'location': 'Tacoma, WA',
33 'url': 'http://tunein.com/radio/Jazz24-885-s34682/',
34 'info_dict': _INFO_DICT,
36 'skip_download': True, # live stream
40 'url': 'http://tun.in/ser7s',
41 'info_dict': _INFO_DICT,
43 'skip_download': True, # live stream
48 def _real_extract(self, url):
49 mobj = re.match(self._VALID_URL, url)
50 redirect_id = mobj.group('redirect_id')
52 # The server doesn't support HEAD requests
53 urlh = self._request_webpage(
54 url, redirect_id, note='Downloading redirect page')
56 self.to_screen('Following redirect: %s' % url)
57 mobj = re.match(self._VALID_URL, url)
58 station_id = mobj.group('id')
60 station_info = self._download_json(
61 self._API_URL_TEMPLATE.format(station_id),
62 station_id, note='Downloading station JSON')
64 title = station_info['Title']
65 thumbnail = station_info.get('Logo')
66 location = station_info.get('Location')
67 streams_url = station_info.get('StreamUrl')
69 raise ExtractorError('No downloadable streams found',
71 stream_data = self._download_webpage(
72 streams_url, station_id, note='Downloading stream data')
73 streams = json.loads(self._search_regex(
74 r'\((.*)\);', stream_data, 'stream info'))['Streams']
78 for stream in streams:
79 if stream.get('Type') == 'Live':
81 reliability = stream.get('Reliability')
83 'Reliability: %d%%' % reliability
84 if reliability is not None else None)
87 0 if reliability is None or reliability > 90
89 'abr': stream.get('Bandwidth'),
90 'ext': stream.get('MediaType').lower(),
91 'acodec': stream.get('MediaType'),
93 'url': stream.get('Url'),
94 'source_preference': reliability,
95 'format_note': format_note,
97 self._sort_formats(formats)
103 'thumbnail': thumbnail,
104 'location': location,