3 from .common
import InfoExtractor
11 class PicartoIE(InfoExtractor
):
12 _VALID_URL
= r
'https?://(?:www.)?picarto\.tv/(?P<id>[a-zA-Z0-9]+)'
14 'url': 'https://picarto.tv/Setz',
18 'title': 're:^Setz [0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}$',
22 'skip': 'Stream is offline',
26 def suitable(cls
, url
):
27 return False if PicartoVodIE
.suitable(url
) else super(PicartoIE
, cls
).suitable(url
)
29 def _real_extract(self
, url
):
30 channel_id
= self
._match
_id
(url
)
32 data
= self
._download
_json
(
33 'https://ptvintern.picarto.tv/ptvapi', channel_id
, query
={
42 getLoadBalancerUrl(channel_name: "%s") {
45 }''' % (channel_id
, channel_id
),
47 metadata
= data
['channel']
49 if metadata
.get('online') == 0:
50 raise ExtractorError('Stream is offline', expected
=True)
51 title
= metadata
['title']
53 cdn_data
= self
._download
_json
(
54 data
['getLoadBalancerUrl']['url'] + '/stream/json_' + metadata
['stream_name'] + '.js',
55 channel_id
, 'Downloading load balancing info')
58 for source
in (cdn_data
.get('source') or []):
59 source_url
= source
.get('url')
62 source_type
= source
.get('type')
63 if source_type
== 'html5/application/vnd.apple.mpegurl':
64 formats
.extend(self
._extract
_m
3u8_formats
(
65 source_url
, channel_id
, 'mp4', m3u8_id
='hls', fatal
=False))
66 elif source_type
== 'html5/video/mp4':
71 mature
= metadata
.get('adult')
75 age_limit
= 18 if mature
is True else 0
79 'title': title
.strip(),
81 'channel': channel_id
,
82 'channel_id': metadata
.get('id'),
83 'channel_url': 'https://picarto.tv/%s' % channel_id
,
84 'age_limit': age_limit
,
89 class PicartoVodIE(InfoExtractor
):
90 _VALID_URL
= r
'https?://(?:www\.)?picarto\.tv/(?:videopopout|\w+/videos)/(?P<id>[^/?#&]+)'
92 'url': 'https://picarto.tv/videopopout/ArtofZod_2017.12.12.00.13.23.flv',
93 'md5': '3ab45ba4352c52ee841a28fb73f2d9ca',
95 'id': 'ArtofZod_2017.12.12.00.13.23.flv',
97 'title': 'ArtofZod_2017.12.12.00.13.23.flv',
98 'thumbnail': r
're:^https?://.*\.jpg'
100 'skip': 'The VOD does not exist',
102 'url': 'https://picarto.tv/ArtofZod/videos/772650',
103 'md5': '00067a0889f1f6869cc512e3e79c521b',
107 'title': 'Art of Zod - Drawing and Painting',
108 'thumbnail': r
're:^https?://.*\.jpg',
109 'channel': 'ArtofZod',
113 'url': 'https://picarto.tv/videopopout/Plague',
114 'only_matching': True,
117 def _real_extract(self
, url
):
118 video_id
= self
._match
_id
(url
)
120 data
= self
._download
_json
(
121 'https://ptvintern.picarto.tv/ptvapi', video_id
, query
={
123 video(id: "{video_id}") {{
128 video_recording_image_url
136 file_name
= data
['file_name']
137 netloc
= urllib
.parse
.urlparse(data
['video_recording_image_url']).netloc
139 formats
= self
._extract
_m
3u8_formats
(
140 f
'https://{netloc}/stream/hls/{file_name}/index.m3u8', video_id
, 'mp4', m3u8_id
='hls')
144 **traverse_obj(data
, {
145 'id': ('id', {str_or_none}
),
146 'title': ('title', {str}
),
147 'thumbnail': 'video_recording_image_url',
148 'channel': ('channel', 'name', {str}
),
149 'age_limit': ('adult', {lambda x: 18 if x else 0}
),