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/'
11 def _real_extract(self
, url
):
12 content_id
= self
._match
_id
(url
)
14 content_info
= self
._download
_json
(
15 self
._API
_BASE
_URL
+ self
._API
_URL
_QUERY
% content_id
,
16 content_id
, note
='Downloading JSON metadata')
18 title
= content_info
['Title']
19 thumbnail
= content_info
.get('Logo')
20 location
= content_info
.get('Location')
21 streams_url
= content_info
.get('StreamUrl')
23 raise ExtractorError('No downloadable streams found', expected
=True)
24 if not streams_url
.startswith('http://'):
25 streams_url
= compat_urlparse
.urljoin(url
, streams_url
)
27 streams
= self
._download
_json
(
28 streams_url
, content_id
, note
='Downloading stream data',
29 transform_source
=lambda s
: re
.sub(r
'^\s*\((.*)\);\s*$', r
'\1', s
))['Streams']
33 for stream
in streams
:
34 if stream
.get('Type') == 'Live':
36 reliability
= stream
.get('Reliability')
38 'Reliability: %d%%' % reliability
39 if reliability
is not None else None)
42 0 if reliability
is None or reliability
> 90
44 'abr': stream
.get('Bandwidth'),
45 'ext': stream
.get('MediaType').lower(),
46 'acodec': stream
.get('MediaType'),
48 'url': stream
.get('Url'),
49 'source_preference': reliability
,
50 'format_note': format_note
,
52 self
._sort
_formats
(formats
)
58 'thumbnail': thumbnail
,
64 class TuneInClipIE(TuneInBaseIE
):
65 IE_NAME
= 'tunein:clip'
66 _VALID_URL
= r
'https?://(?:www\.)?tunein\.com/station/.*?audioClipId\=(?P<id>\d+)'
67 _API_URL_QUERY
= '?tuneType=AudioClip&audioclipId=%s'
70 'url': 'http://tunein.com/station/?stationId=246119&audioClipId=816',
71 'md5': '99f00d772db70efc804385c6b47f4e77',
80 class TuneInStationIE(TuneInBaseIE
):
81 IE_NAME
= 'tunein:station'
82 _VALID_URL
= r
'https?://(?:www\.)?tunein\.com/(?:radio/.*?-s|station/.*?StationId=|embed/player/s)(?P<id>\d+)'
83 _EMBED_REGEX
= [r
'<iframe[^>]+src=["\'](?P
<url
>(?
:https?
://)?tunein\
.com
/embed
/player
/[pst
]\d
+)']
84 _API_URL_QUERY = '?tuneType
=Station
&stationId
=%s'
87 def suitable(cls, url):
88 return False if TuneInClipIE.suitable(url) else super(TuneInStationIE, cls).suitable(url)
91 'url
': 'http
://tunein
.com
/radio
/Jazz24
-885-s34682
/',
94 'title
': 'Jazz
24 on
88.5 Jazz24
- KPLU
-HD2
',
96 'location
': 'Tacoma
, WA
',
99 'skip_download
': True, # live stream
102 'url
': 'http
://tunein
.com
/embed
/player
/s6404
/',
103 'only_matching
': True,
107 class TuneInProgramIE(TuneInBaseIE):
108 IE_NAME = 'tunein
:program
'
109 _VALID_URL = r'https?
://(?
:www\
.)?tunein\
.com
/(?
:radio
/.*?
-p|program
/.*?ProgramId
=|embed
/player
/p
)(?P
<id>\d
+)'
110 _API_URL_QUERY = '?tuneType
=Program
&programId
=%s'
113 'url
': 'http
://tunein
.com
/radio
/Jazz
-24-p2506
/',
116 'title
': 'Jazz
24 on
91.3 WUKY
-HD3
',
118 'location
': 'Lexington
, KY
',
121 'skip_download
': True, # live stream
124 'url
': 'http
://tunein
.com
/embed
/player
/p191660
/',
125 'only_matching
': True,
129 class TuneInTopicIE(TuneInBaseIE):
130 IE_NAME = 'tunein
:topic
'
131 _VALID_URL = r'https?
://(?
:www\
.)?tunein\
.com
/(?
:topic
/.*?TopicId
=|embed
/player
/t
)(?P
<id>\d
+)'
132 _API_URL_QUERY = '?tuneType
=Topic
&topicId
=%s'
135 'url
': 'http
://tunein
.com
/topic
/?TopicId
=101830576',
136 'md5
': 'c31a39e6f988d188252eae7af0ef09c9
',
139 'title
': 'Votez pour moi du
29 octobre
2015 (29/10/15)',
141 'location
': 'Belgium
',
144 'url
': 'http
://tunein
.com
/embed
/player
/t101830576
/',
145 'only_matching
': True,
149 class TuneInShortenerIE(InfoExtractor):
150 IE_NAME = 'tunein
:shortener
'
151 IE_DESC = False # Do not list
152 _VALID_URL = r'https?
://tun\
.in/(?P
<id>[A
-Za
-z0
-9]+)'
156 'url
': 'http
://tun
.in/ser7s
',
159 'title
': 'Jazz
24 on
88.5 Jazz24
- KPLU
-HD2
',
161 'location
': 'Tacoma
, WA
',
164 'skip_download
': True, # live stream
168 def _real_extract(self, url):
169 redirect_id = self._match_id(url)
170 # The server doesn't support HEAD requests
171 urlh
= self
._request
_webpage
(
172 url
, redirect_id
, note
='Downloading redirect page')
174 self
.to_screen('Following redirect: %s' % url
)
175 return self
.url_result(url
)