|
|
@ -22,6 +22,7 @@ from ..utils import ( |
|
|
|
parse_duration, |
|
|
|
parse_iso8601, |
|
|
|
qualities, |
|
|
|
str_or_none, |
|
|
|
try_get, |
|
|
|
unified_timestamp, |
|
|
|
update_url_query, |
|
|
@ -591,10 +592,18 @@ class TwitchStreamIE(TwitchBaseIE): |
|
|
|
else super(TwitchStreamIE, cls).suitable(url)) |
|
|
|
|
|
|
|
def _real_extract(self, url): |
|
|
|
channel_id = self._match_id(url) |
|
|
|
channel_name = self._match_id(url) |
|
|
|
|
|
|
|
access_token = self._call_api( |
|
|
|
'api/channels/%s/access_token' % channel_name, channel_name, |
|
|
|
'Downloading access token JSON') |
|
|
|
|
|
|
|
token = access_token['token'] |
|
|
|
channel_id = compat_str(self._parse_json( |
|
|
|
token, channel_name)['channel_id']) |
|
|
|
|
|
|
|
stream = self._call_api( |
|
|
|
'kraken/streams/%s?stream_type=all' % channel_id.lower(), |
|
|
|
'kraken/streams/%s?stream_type=all' % channel_id, |
|
|
|
channel_id, 'Downloading stream JSON').get('stream') |
|
|
|
|
|
|
|
if not stream: |
|
|
@ -604,11 +613,9 @@ class TwitchStreamIE(TwitchBaseIE): |
|
|
|
# (e.g. http://www.twitch.tv/TWITCHPLAYSPOKEMON) that will lead to constructing |
|
|
|
# an invalid m3u8 URL. Working around by use of original channel name from stream |
|
|
|
# JSON and fallback to lowercase if it's not available. |
|
|
|
channel_id = stream.get('channel', {}).get('name') or channel_id.lower() |
|
|
|
|
|
|
|
access_token = self._call_api( |
|
|
|
'api/channels/%s/access_token' % channel_id, channel_id, |
|
|
|
'Downloading channel access token') |
|
|
|
channel_name = try_get( |
|
|
|
stream, lambda x: x['channel']['name'], |
|
|
|
compat_str) or channel_name.lower() |
|
|
|
|
|
|
|
query = { |
|
|
|
'allow_source': 'true', |
|
|
@ -619,11 +626,11 @@ class TwitchStreamIE(TwitchBaseIE): |
|
|
|
'playlist_include_framerate': 'true', |
|
|
|
'segment_preference': '4', |
|
|
|
'sig': access_token['sig'].encode('utf-8'), |
|
|
|
'token': access_token['token'].encode('utf-8'), |
|
|
|
'token': token.encode('utf-8'), |
|
|
|
} |
|
|
|
formats = self._extract_m3u8_formats( |
|
|
|
'%s/api/channel/hls/%s.m3u8?%s' |
|
|
|
% (self._USHER_BASE, channel_id, compat_urllib_parse_urlencode(query)), |
|
|
|
% (self._USHER_BASE, channel_name, compat_urllib_parse_urlencode(query)), |
|
|
|
channel_id, 'mp4') |
|
|
|
self._prefer_source(formats) |
|
|
|
|
|
|
@ -646,8 +653,8 @@ class TwitchStreamIE(TwitchBaseIE): |
|
|
|
}) |
|
|
|
|
|
|
|
return { |
|
|
|
'id': compat_str(stream['_id']), |
|
|
|
'display_id': channel_id, |
|
|
|
'id': str_or_none(stream.get('_id')) or channel_id, |
|
|
|
'display_id': channel_name, |
|
|
|
'title': title, |
|
|
|
'description': description, |
|
|
|
'thumbnails': thumbnails, |
|
|
|