+ initials = self._parse_json(
+ self._search_regex(
+ r'window\.initials\s*=\s*({.+?})\s*;\s*\n', webpage, 'initials',
+ default='{}'),
+ video_id, fatal=False)
+ if initials:
+ video = initials['videoModel']
+ title = video['title']
+ formats = []
+ for format_id, formats_dict in video['sources'].items():
+ if not isinstance(formats_dict, dict):
+ continue
+ for quality, format_item in formats_dict.items():
+ if format_id == 'download':
+ # Download link takes some time to be generated,
+ # skipping for now
+ continue
+ if not isinstance(format_item, dict):
+ continue
+ format_url = format_item.get('link')
+ filesize = int_or_none(
+ format_item.get('size'), invscale=1000000)
+ else:
+ format_url = format_item
+ filesize = None
+ format_url = url_or_none(format_url)
+ if not format_url:
+ continue
+ formats.append({
+ 'format_id': '%s-%s' % (format_id, quality),
+ 'url': format_url,
+ 'ext': determine_ext(format_url, 'mp4'),
+ 'height': get_height(quality),
+ 'filesize': filesize,
+ })
+ self._sort_formats(formats)
+
+ categories_list = video.get('categories')
+ if isinstance(categories_list, list):
+ categories = []
+ for c in categories_list:
+ if not isinstance(c, dict):
+ continue
+ c_name = c.get('name')
+ if isinstance(c_name, compat_str):
+ categories.append(c_name)
+ else:
+ categories = None
+
+ return {
+ 'id': video_id,
+ 'display_id': display_id,
+ 'title': title,
+ 'description': video.get('description'),
+ 'timestamp': int_or_none(video.get('created')),
+ 'uploader': try_get(
+ video, lambda x: x['author']['name'], compat_str),
+ 'thumbnail': video.get('thumbURL'),
+ 'duration': int_or_none(video.get('duration')),
+ 'view_count': int_or_none(video.get('views')),
+ 'like_count': int_or_none(try_get(
+ video, lambda x: x['rating']['likes'], int)),
+ 'dislike_count': int_or_none(try_get(
+ video, lambda x: x['rating']['dislikes'], int)),
+ 'comment_count': int_or_none(video.get('views')),
+ 'age_limit': age_limit,
+ 'categories': categories,
+ 'formats': formats,
+ }
+
+ # Old layout fallback