]>
Raphaƫl G. Git Repositories - youtubedl/blob - youtube_dl/extractor/beampro.py
   2 from __future__ 
import unicode_literals
 
   4 from .common 
import InfoExtractor
 
  17 class BeamProBaseIE(InfoExtractor
): 
  18     _API_BASE 
= 'https://mixer.com/api/v1' 
  19     _RATINGS 
= {'family': 0, 'teen': 13, '18+': 18} 
  21     def _extract_channel_info(self
, chan
): 
  22         user_id 
= chan
.get('userId') or try_get(chan
, lambda x
: x
['user']['id']) 
  24             'uploader': chan
.get('token') or try_get( 
  25                 chan
, lambda x
: x
['user']['username'], compat_str
), 
  26             'uploader_id': compat_str(user_id
) if user_id 
else None, 
  27             'age_limit': self
._RATINGS
.get(chan
.get('audience')), 
  31 class BeamProLiveIE(BeamProBaseIE
): 
  32     IE_NAME 
= 'Mixer:live' 
  33     _VALID_URL 
= r
'https?://(?:\w+\.)?(?:beam\.pro|mixer\.com)/(?P<id>[^/?#&]+)' 
  35         'url': 'http://mixer.com/niterhayven', 
  39             'title': 'Introducing The Witcher 3 //  The Grind Starts Now!', 
  40             'description': 'md5:0b161ac080f15fe05d18a07adb44a74d', 
  41             'thumbnail': r
're:https://.*\.jpg$', 
  42             'timestamp': 1483477281, 
  43             'upload_date': '20170103', 
  44             'uploader': 'niterhayven', 
  45             'uploader_id': '373396', 
  50         'skip': 'niterhayven is offline', 
  52             'skip_download': True, 
  56     _MANIFEST_URL_TEMPLATE 
= '%s/channels/%%s/manifest.%%s' % BeamProBaseIE
._API
_BASE
 
  59     def suitable(cls
, url
): 
  60         return False if BeamProVodIE
.suitable(url
) else super(BeamProLiveIE
, cls
).suitable(url
) 
  62     def _real_extract(self
, url
): 
  63         channel_name 
= self
._match
_id
(url
) 
  65         chan 
= self
._download
_json
( 
  66             '%s/channels/%s' % (self
._API
_BASE
, channel_name
), channel_name
) 
  68         if chan
.get('online') is False: 
  70                 '{0} is offline'.format(channel_name
), expected
=True) 
  72         channel_id 
= chan
['id'] 
  74         def manifest_url(kind
): 
  75             return self
._MANIFEST
_URL
_TEMPLATE 
% (channel_id
, kind
) 
  77         formats 
= self
._extract
_m
3u8_formats
( 
  78             manifest_url('m3u8'), channel_name
, ext
='mp4', m3u8_id
='hls', 
  80         formats
.extend(self
._extract
_smil
_formats
( 
  81             manifest_url('smil'), channel_name
, fatal
=False)) 
  82         self
._sort
_formats
(formats
) 
  85             'id': compat_str(chan
.get('id') or channel_name
), 
  86             'title': self
._live
_title
(chan
.get('name') or channel_name
), 
  87             'description': clean_html(chan
.get('description')), 
  89                 chan
, lambda x
: x
['thumbnail']['url'], compat_str
), 
  90             'timestamp': parse_iso8601(chan
.get('updatedAt')), 
  92             'view_count': int_or_none(chan
.get('viewersTotal')), 
  95         info
.update(self
._extract
_channel
_info
(chan
)) 
 100 class BeamProVodIE(BeamProBaseIE
): 
 101     IE_NAME 
= 'Mixer:vod' 
 102     _VALID_URL 
= r
'https?://(?:\w+\.)?(?:beam\.pro|mixer\.com)/[^/?#&]+\?.*?\bvod=(?P<id>\d+)' 
 104         'url': 'https://mixer.com/willow8714?vod=2259830', 
 105         'md5': 'b2431e6e8347dc92ebafb565d368b76b', 
 109             'title': 'willow8714\'s Channel', 
 111             'thumbnail': r
're:https://.*source\.png$', 
 112             'timestamp': 1494046474, 
 113             'upload_date': '20170506', 
 114             'uploader': 'willow8714', 
 115             'uploader_id': '6085379', 
 120             'skip_download': True, 
 125     def _extract_format(vod
, vod_type
): 
 126         if not vod
.get('baseUrl'): 
 129         if vod_type 
== 'hls': 
 130             filename
, protocol 
= 'manifest.m3u8', 'm3u8_native' 
 131         elif vod_type 
== 'raw': 
 132             filename
, protocol 
= 'source.mp4', 'https' 
 136         data 
= vod
.get('data') if isinstance(vod
.get('data'), dict) else {} 
 138         format_id 
= [vod_type
] 
 139         if isinstance(data
.get('Height'), compat_str
): 
 140             format_id
.append('%sp' % data
['Height']) 
 143             'url': urljoin(vod
['baseUrl'], filename
), 
 144             'format_id': '-'.join(format_id
), 
 146             'protocol': protocol
, 
 147             'width': int_or_none(data
.get('Width')), 
 148             'height': int_or_none(data
.get('Height')), 
 149             'fps': int_or_none(data
.get('Fps')), 
 150             'tbr': int_or_none(data
.get('Bitrate'), 1000), 
 153     def _real_extract(self
, url
): 
 154         vod_id 
= self
._match
_id
(url
) 
 156         vod_info 
= self
._download
_json
( 
 157             '%s/recordings/%s' % (self
._API
_BASE
, vod_id
), vod_id
) 
 159         state 
= vod_info
.get('state') 
 160         if state 
!= 'AVAILABLE': 
 161             raise ExtractorError( 
 162                 'VOD %s is not available (state: %s)' % (vod_id
, state
), 
 168         for vod 
in vod_info
['vods']: 
 169             vod_type 
= vod
.get('format') 
 170             if vod_type 
in ('hls', 'raw'): 
 171                 formats
.extend(self
._extract
_format
(vod
, vod_type
)) 
 172             elif vod_type 
== 'thumbnail': 
 173                 thumbnail_url 
= urljoin(vod
.get('baseUrl'), 'source.png') 
 175         self
._sort
_formats
(formats
) 
 179             'title': vod_info
.get('name') or vod_id
, 
 180             'duration': float_or_none(vod_info
.get('duration')), 
 181             'thumbnail': thumbnail_url
, 
 182             'timestamp': parse_iso8601(vod_info
.get('createdAt')), 
 183             'view_count': int_or_none(vod_info
.get('viewsTotal')), 
 186         info
.update(self
._extract
_channel
_info
(vod_info
.get('channel') or {}))