'url': thumbnail,
}] if thumbnail else None
- def _extract_twitch_m3u8_formats(self, video_id, token, signature):
- """Subclasses must define _M3U8_PATH"""
- return self._extract_m3u8_formats(
- f'{self._USHER_BASE}/{self._M3U8_PATH}/{video_id}.m3u8', video_id, 'mp4', query={
+ def _extract_twitch_m3u8_formats(self, path, video_id, token, signature):
+ formats = self._extract_m3u8_formats(
+ f'{self._USHER_BASE}/{path}/{video_id}.m3u8', video_id, 'mp4', query={
'allow_source': 'true',
'allow_audio_only': 'true',
'allow_spectre': 'true',
'p': random.randint(1000000, 10000000),
+ 'platform': 'web',
'player': 'twitchweb',
+ 'supported_codecs': 'av1,h265,h264',
'playlist_include_framerate': 'true',
'sig': signature,
'token': token,
})
+ for fmt in formats:
+ if fmt.get('vcodec') and fmt['vcodec'].startswith('av01'):
+ # mpegts does not yet have proper support for av1
+ fmt['downloader_options'] = {'ffmpeg_args_out': ['-f', 'mp4']}
+
+ return formats
class TwitchVodIE(TwitchBaseIE):
)
(?P<id>\d+)
'''
- _M3U8_PATH = 'vod'
_TESTS = [{
'url': 'http://www.twitch.tv/riotgames/v/6528877?t=5m10s',
access_token = self._download_access_token(vod_id, 'video', 'id')
formats = self._extract_twitch_m3u8_formats(
- vod_id, access_token['value'], access_token['signature'])
+ 'vod', vod_id, access_token['value'], access_token['signature'])
formats.extend(self._extract_storyboard(vod_id, video.get('storyboard'), info.get('duration')))
self._prefer_source(formats)
)
(?P<id>[^/#?]+)
'''
- _M3U8_PATH = 'api/channel/hls'
_TESTS = [{
'url': 'http://www.twitch.tv/shroomztv',
stream_id = stream.get('id') or channel_name
formats = self._extract_twitch_m3u8_formats(
- channel_name, access_token['value'], access_token['signature'])
+ 'api/channel/hls', channel_name, access_token['value'], access_token['signature'])
self._prefer_source(formats)
view_count = stream.get('viewers')