3 from .common
import InfoExtractor
4 from ..utils
import ExtractorError
5 from ..compat
import compat_urlparse
8 class TuneInBaseIE(InfoExtractor
):
9 _API_BASE_URL
= 'http://tunein.com/tuner/tune/'
12 def _extract_urls(webpage
):
14 r
'<iframe[^>]+src=["\'](?P
<url
>(?
:https?
://)?tunein\
.com
/embed
/player
/[pst
]\d
+)',
17 def _real_extract(self, url):
18 content_id = self._match_id(url)
20 content_info = self._download_json(
21 self._API_BASE_URL + self._API_URL_QUERY % content_id,
22 content_id, note='Downloading JSON metadata
')
24 title = content_info['Title
']
25 thumbnail = content_info.get('Logo
')
26 location = content_info.get('Location
')
27 streams_url = content_info.get('StreamUrl
')
29 raise ExtractorError('No downloadable streams found
', expected=True)
30 if not streams_url.startswith('http
://'):
31 streams_url = compat_urlparse.urljoin(url, streams_url)
33 streams = self._download_json(
34 streams_url, content_id, note='Downloading stream data
',
35 transform_source=lambda s: re.sub(r'^\s
*\
((.*)\
);\s
*$
', r'\
1', s))['Streams
']
39 for stream in streams:
40 if stream.get('Type
') == 'Live
':
42 reliability = stream.get('Reliability
')
44 'Reliability
: %d%%' % reliability
45 if reliability is not None else None)
48 0 if reliability is None or reliability > 90
50 'abr
': stream.get('Bandwidth
'),
51 'ext
': stream.get('MediaType
').lower(),
52 'acodec
': stream.get('MediaType
'),
54 'url
': stream.get('Url
'),
55 'source_preference
': reliability,
56 'format_note
': format_note,
58 self._sort_formats(formats)
64 'thumbnail
': thumbnail,
70 class TuneInClipIE(TuneInBaseIE):
71 IE_NAME = 'tunein
:clip
'
72 _VALID_URL = r'https?
://(?
:www\
.)?tunein\
.com
/station
/.*?audioClipId\
=(?P
<id>\d
+)'
73 _API_URL_QUERY = '?tuneType
=AudioClip
&audioclipId
=%s'
76 'url
': 'http
://tunein
.com
/station
/?stationId
=246119&audioClipId
=816',
77 'md5
': '99f00d772db70efc804385c6b47f4e77
',
86 class TuneInStationIE(TuneInBaseIE):
87 IE_NAME = 'tunein
:station
'
88 _VALID_URL = r'https?
://(?
:www\
.)?tunein\
.com
/(?
:radio
/.*?
-s|station
/.*?StationId
=|embed
/player
/s
)(?P
<id>\d
+)'
89 _API_URL_QUERY = '?tuneType
=Station
&stationId
=%s'
92 def suitable(cls, url):
93 return False if TuneInClipIE.suitable(url) else super(TuneInStationIE, cls).suitable(url)
96 'url
': 'http
://tunein
.com
/radio
/Jazz24
-885-s34682
/',
99 'title
': 'Jazz
24 on
88.5 Jazz24
- KPLU
-HD2
',
101 'location
': 'Tacoma
, WA
',
104 'skip_download
': True, # live stream
107 'url
': 'http
://tunein
.com
/embed
/player
/s6404
/',
108 'only_matching
': True,
112 class TuneInProgramIE(TuneInBaseIE):
113 IE_NAME = 'tunein
:program
'
114 _VALID_URL = r'https?
://(?
:www\
.)?tunein\
.com
/(?
:radio
/.*?
-p|program
/.*?ProgramId
=|embed
/player
/p
)(?P
<id>\d
+)'
115 _API_URL_QUERY = '?tuneType
=Program
&programId
=%s'
118 'url
': 'http
://tunein
.com
/radio
/Jazz
-24-p2506
/',
121 'title
': 'Jazz
24 on
91.3 WUKY
-HD3
',
123 'location
': 'Lexington
, KY
',
126 'skip_download
': True, # live stream
129 'url
': 'http
://tunein
.com
/embed
/player
/p191660
/',
130 'only_matching
': True,
134 class TuneInTopicIE(TuneInBaseIE):
135 IE_NAME = 'tunein
:topic
'
136 _VALID_URL = r'https?
://(?
:www\
.)?tunein\
.com
/(?
:topic
/.*?TopicId
=|embed
/player
/t
)(?P
<id>\d
+)'
137 _API_URL_QUERY = '?tuneType
=Topic
&topicId
=%s'
140 'url
': 'http
://tunein
.com
/topic
/?TopicId
=101830576',
141 'md5
': 'c31a39e6f988d188252eae7af0ef09c9
',
144 'title
': 'Votez pour moi du
29 octobre
2015 (29/10/15)',
146 'location
': 'Belgium
',
149 'url
': 'http
://tunein
.com
/embed
/player
/t101830576
/',
150 'only_matching
': True,
154 class TuneInShortenerIE(InfoExtractor):
155 IE_NAME = 'tunein
:shortener
'
156 IE_DESC = False # Do not list
157 _VALID_URL = r'https?
://tun\
.in/(?P
<id>[A
-Za
-z0
-9]+)'
161 'url
': 'http
://tun
.in/ser7s
',
164 'title
': 'Jazz
24 on
88.5 Jazz24
- KPLU
-HD2
',
166 'location
': 'Tacoma
, WA
',
169 'skip_download
': True, # live stream
173 def _real_extract(self, url):
174 redirect_id = self._match_id(url)
175 # The server doesn't support HEAD requests
176 urlh
= self
._request
_webpage
(
177 url
, redirect_id
, note
='Downloading redirect page')
179 self
.to_screen('Following redirect: %s' % url
)
180 return self
.url_result(url
)