3 from .common
import InfoExtractor
4 from ..networking
.exceptions
import HTTPError
14 class ZypeIE(InfoExtractor
):
15 _ID_RE
= r
'[\da-fA-F]+'
16 _COMMON_RE
= r
'//player\.zype\.com/embed/%s\.(?:js|json|html)\?.*?(?:access_token|(?:ap[ip]|player)_key)='
17 _VALID_URL
= r
'https?:%s[^&]+' % (_COMMON_RE
% (f
'(?P<id>{_ID_RE})'))
18 _EMBED_REGEX
= [fr
'<script[^>]+\bsrc=(["\'])(?P
<url
>(?
:https?
:)?
{_COMMON_RE
% _ID_RE
}.+?
)\
1']
20 'url
': 'https
://player
.zype
.com
/embed
/5b400b834b32992a310622b9
.js?api_key
=jZ9GUhRmxcPvX7M3SlfejB6Hle9jyHTdk2jVxG7wOHPLODgncEKVdPYBhuz9iWXQ
&autoplay
=false
&controls
=true
&da
=false
',
21 'md5
': 'eaee31d474c76a955bdaba02a505c595
',
23 'id': '5b400b834b32992a310622b9
',
25 'title
': 'Smoky Barbecue Favorites
',
26 'thumbnail
': r're
:^https?
://.*\
.jpe?g
',
27 'description
': 'md5
:5ff01e76316bd8d46508af26dc86023b
',
28 'timestamp
': 1504915200,
29 'upload_date
': '20170909',
33 def _real_extract(self, url):
34 video_id = self._match_id(url)
37 response = self._download_json(re.sub(
38 r'\
.(?
:js|html
)\?', '.json?
', url), video_id)['response
']
39 except ExtractorError as e:
40 if isinstance(e.cause, HTTPError) and e.cause.status in (400, 401, 403):
41 raise ExtractorError(self._parse_json(
42 e.cause.response.read().decode(), video_id)['message
'], expected=True)
45 body = response['body
']
46 video = response['video
']
47 title = video['title
']
51 if isinstance(body, dict):
53 for output in body.get('outputs
', []):
54 output_url = output.get('url
')
57 name = output.get('name
')
59 formats, subtitles = self._extract_m3u8_formats_and_subtitles(
60 output_url, video_id, 'mp4
',
61 'm3u8_native
', m3u8_id='hls
', fatal=False)
65 'tbr
': int_or_none(output.get('bitrate
')),
68 if name in ('m4a
', 'mp3
'):
72 'height
': int_or_none(output.get('height
')),
73 'width
': int_or_none(output.get('width
')),
76 text_tracks = body.get('subtitles
') or []
78 m3u8_url = self._search_regex(
79 r'(["\'])(?P<url>(?:(?!\1).)+\.m3u8(?:(?!\1).)*)\1',
80 body, 'm3u8 url', group='url', default=None)
82 source = self._search_regex(
83 r'(?s)sources\s*:\s*\[\s*({.+?})\s*\]', body, 'source')
86 return self._search_regex(
87 rf'\b{key}\s*:\s*([\'"])(?P
<val
>(?
:(?
!\
1).)+)\
1',
88 source, key, group='val
')
90 if get_attr('integration
') == 'verizon
-media
':
91 m3u8_url = 'https
://content
.uplynk
.com
/{}.m3u8
'.format(get_attr('id'))
92 formats, subtitles = self._extract_m3u8_formats_and_subtitles(
93 m3u8_url, video_id, 'mp4
', 'm3u8_native
', m3u8_id='hls
')
94 text_tracks = self._search_regex(
95 r'textTracks\s
*:\s
*(\
[[^
]]+\
])',
96 body, 'text tracks
', default=None)
98 text_tracks = self._parse_json(
99 text_tracks, video_id, js_to_json, False)
102 for text_track in text_tracks:
103 tt_url = dict_get(text_track, ('file', 'src
'))
106 subtitles.setdefault(text_track.get('label
') or 'English
', []).append({
111 for thumbnail in video.get('thumbnails
', []):
112 thumbnail_url = thumbnail.get('url
')
113 if not thumbnail_url:
116 'url
': thumbnail_url,
117 'width
': int_or_none(thumbnail.get('width
')),
118 'height
': int_or_none(thumbnail.get('height
')),
123 'display_id
': video.get('friendly_title
'),
125 'thumbnails
': thumbnails,
126 'description
': dict_get(video, ('description
', 'ott_description
', 'short_description
')),
127 'timestamp
': parse_iso8601(video.get('published_at
')),
128 'duration
': int_or_none(video.get('duration
')),
129 'view_count
': int_or_none(video.get('request_count
')),
130 'average_rating
': int_or_none(video.get('rating
')),
131 'season_number
': int_or_none(video.get('season
')),
132 'episode_number
': int_or_none(video.get('episode
')),
134 'subtitles
': subtitles,