3 from .common
import InfoExtractor
4 from ..compat
import compat_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
% ('(?P<id>%s)' % _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, compat_HTTPError) and e.cause.code in (400, 401, 403):
41 raise ExtractorError(self._parse_json(
42 e.cause.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 r'\b%s\s*:\s*([\'"])(?P
<val
>(?
:(?
!\
1).)+)\
1' % key,
88 source, key, group='val
')
90 if get_attr('integration
') == 'verizon
-media
':
91 m3u8_url = 'https
://content
.uplynk
.com
/%s.m3u8
' % 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)
100 self._sort_formats(formats)
103 for text_track in text_tracks:
104 tt_url = dict_get(text_track, ('file', 'src
'))
107 subtitles.setdefault(text_track.get('label
') or 'English
', []).append({
112 for thumbnail in video.get('thumbnails
', []):
113 thumbnail_url = thumbnail.get('url
')
114 if not thumbnail_url:
117 'url
': thumbnail_url,
118 'width
': int_or_none(thumbnail.get('width
')),
119 'height
': int_or_none(thumbnail.get('height
')),
124 'display_id
': video.get('friendly_title
'),
126 'thumbnails
': thumbnails,
127 'description
': dict_get(video, ('description
', 'ott_description
', 'short_description
')),
128 'timestamp
': parse_iso8601(video.get('published_at
')),
129 'duration
': int_or_none(video.get('duration
')),
130 'view_count
': int_or_none(video.get('request_count
')),
131 'average_rating
': int_or_none(video.get('rating
')),
132 'season_number
': int_or_none(video.get('season
')),
133 'episode_number
': int_or_none(video.get('episode
')),
135 'subtitles
': subtitles,