|
|
@ -667,6 +667,30 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
|
|
|
|
if text:
|
|
|
|
if text:
|
|
|
|
return text
|
|
|
|
return text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
|
|
|
def _extract_thumbnails(data, *path_list):
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
Extract thumbnails from thumbnails dict
|
|
|
|
|
|
|
|
@param path_list: path list to level that contains 'thumbnails' key
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
thumbnails = []
|
|
|
|
|
|
|
|
for path in path_list or [()]:
|
|
|
|
|
|
|
|
for thumbnail in traverse_obj(data, (*variadic(path), 'thumbnails', ...), default=[]):
|
|
|
|
|
|
|
|
thumbnail_url = url_or_none(thumbnail.get('url'))
|
|
|
|
|
|
|
|
if not thumbnail_url:
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
# Sometimes youtube gives a wrong thumbnail URL. See:
|
|
|
|
|
|
|
|
# https://github.com/yt-dlp/yt-dlp/issues/233
|
|
|
|
|
|
|
|
# https://github.com/ytdl-org/youtube-dl/issues/28023
|
|
|
|
|
|
|
|
if 'maxresdefault' in thumbnail_url:
|
|
|
|
|
|
|
|
thumbnail_url = thumbnail_url.split('?')[0]
|
|
|
|
|
|
|
|
thumbnails.append({
|
|
|
|
|
|
|
|
'url': thumbnail_url,
|
|
|
|
|
|
|
|
'height': int_or_none(thumbnail.get('height')),
|
|
|
|
|
|
|
|
'width': int_or_none(thumbnail.get('width')),
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
return thumbnails
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
@staticmethod
|
|
|
|
def extract_relative_time(relative_time_text):
|
|
|
|
def extract_relative_time(relative_time_text):
|
|
|
|
"""
|
|
|
|
"""
|
|
|
@ -783,6 +807,8 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
|
|
|
|
overlay_style = traverse_obj(
|
|
|
|
overlay_style = traverse_obj(
|
|
|
|
renderer, ('thumbnailOverlays', ..., 'thumbnailOverlayTimeStatusRenderer', 'style'), get_all=False, expected_type=str)
|
|
|
|
renderer, ('thumbnailOverlays', ..., 'thumbnailOverlayTimeStatusRenderer', 'style'), get_all=False, expected_type=str)
|
|
|
|
badges = self._extract_badges(renderer)
|
|
|
|
badges = self._extract_badges(renderer)
|
|
|
|
|
|
|
|
thumbnails = self._extract_thumbnails(renderer, 'thumbnail')
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
'_type': 'url',
|
|
|
|
'_type': 'url',
|
|
|
|
'ie_key': YoutubeIE.ie_key(),
|
|
|
|
'ie_key': YoutubeIE.ie_key(),
|
|
|
@ -794,6 +820,7 @@ class YoutubeBaseInfoExtractor(InfoExtractor):
|
|
|
|
'view_count': view_count,
|
|
|
|
'view_count': view_count,
|
|
|
|
'uploader': uploader,
|
|
|
|
'uploader': uploader,
|
|
|
|
'channel_id': channel_id,
|
|
|
|
'channel_id': channel_id,
|
|
|
|
|
|
|
|
'thumbnails': thumbnails,
|
|
|
|
'upload_date': strftime_or_none(timestamp, '%Y%m%d'),
|
|
|
|
'upload_date': strftime_or_none(timestamp, '%Y%m%d'),
|
|
|
|
'live_status': ('is_upcoming' if scheduled_timestamp is not None
|
|
|
|
'live_status': ('is_upcoming' if scheduled_timestamp is not None
|
|
|
|
else 'was_live' if 'streamed' in time_text.lower()
|
|
|
|
else 'was_live' if 'streamed' in time_text.lower()
|
|
|
@ -2903,25 +2930,7 @@ class YoutubeIE(YoutubeBaseInfoExtractor):
|
|
|
|
if f.get('vcodec') != 'none':
|
|
|
|
if f.get('vcodec') != 'none':
|
|
|
|
f['stretched_ratio'] = ratio
|
|
|
|
f['stretched_ratio'] = ratio
|
|
|
|
break
|
|
|
|
break
|
|
|
|
|
|
|
|
thumbnails = self._extract_thumbnails((video_details, microformats), (..., ..., 'thumbnail'))
|
|
|
|
thumbnails = []
|
|
|
|
|
|
|
|
thumbnail_dicts = traverse_obj(
|
|
|
|
|
|
|
|
(video_details, microformats), (..., ..., 'thumbnail', 'thumbnails', ...),
|
|
|
|
|
|
|
|
expected_type=dict, default=[])
|
|
|
|
|
|
|
|
for thumbnail in thumbnail_dicts:
|
|
|
|
|
|
|
|
thumbnail_url = thumbnail.get('url')
|
|
|
|
|
|
|
|
if not thumbnail_url:
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
# Sometimes youtube gives a wrong thumbnail URL. See:
|
|
|
|
|
|
|
|
# https://github.com/yt-dlp/yt-dlp/issues/233
|
|
|
|
|
|
|
|
# https://github.com/ytdl-org/youtube-dl/issues/28023
|
|
|
|
|
|
|
|
if 'maxresdefault' in thumbnail_url:
|
|
|
|
|
|
|
|
thumbnail_url = thumbnail_url.split('?')[0]
|
|
|
|
|
|
|
|
thumbnails.append({
|
|
|
|
|
|
|
|
'url': thumbnail_url,
|
|
|
|
|
|
|
|
'height': int_or_none(thumbnail.get('height')),
|
|
|
|
|
|
|
|
'width': int_or_none(thumbnail.get('width')),
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
thumbnail_url = search_meta(['og:image', 'twitter:image'])
|
|
|
|
thumbnail_url = search_meta(['og:image', 'twitter:image'])
|
|
|
|
if thumbnail_url:
|
|
|
|
if thumbnail_url:
|
|
|
|
thumbnails.append({
|
|
|
|
thumbnails.append({
|
|
|
@ -3584,7 +3593,6 @@ class YoutubeTabBaseInfoExtractor(YoutubeBaseInfoExtractor):
|
|
|
|
|
|
|
|
|
|
|
|
def _extract_from_tabs(self, item_id, ytcfg, data, tabs):
|
|
|
|
def _extract_from_tabs(self, item_id, ytcfg, data, tabs):
|
|
|
|
playlist_id = title = description = channel_url = channel_name = channel_id = None
|
|
|
|
playlist_id = title = description = channel_url = channel_name = channel_id = None
|
|
|
|
thumbnails_list = []
|
|
|
|
|
|
|
|
tags = []
|
|
|
|
tags = []
|
|
|
|
|
|
|
|
|
|
|
|
selected_tab = self._extract_selected_tab(tabs)
|
|
|
|
selected_tab = self._extract_selected_tab(tabs)
|
|
|
@ -3603,26 +3611,13 @@ class YoutubeTabBaseInfoExtractor(YoutubeBaseInfoExtractor):
|
|
|
|
description = renderer.get('description', '')
|
|
|
|
description = renderer.get('description', '')
|
|
|
|
playlist_id = channel_id
|
|
|
|
playlist_id = channel_id
|
|
|
|
tags = renderer.get('keywords', '').split()
|
|
|
|
tags = renderer.get('keywords', '').split()
|
|
|
|
thumbnails_list = (
|
|
|
|
|
|
|
|
try_get(renderer, lambda x: x['avatar']['thumbnails'], list)
|
|
|
|
|
|
|
|
or try_get(
|
|
|
|
|
|
|
|
self._extract_sidebar_info_renderer(data, 'playlistSidebarPrimaryInfoRenderer'),
|
|
|
|
|
|
|
|
lambda x: x['thumbnailRenderer']['playlistVideoThumbnailRenderer']['thumbnail']['thumbnails'],
|
|
|
|
|
|
|
|
list)
|
|
|
|
|
|
|
|
or [])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
thumbnails = []
|
|
|
|
thumbnails = (
|
|
|
|
for t in thumbnails_list:
|
|
|
|
self._extract_thumbnails(renderer, 'avatar')
|
|
|
|
if not isinstance(t, dict):
|
|
|
|
or self._extract_thumbnails(
|
|
|
|
continue
|
|
|
|
self._extract_sidebar_info_renderer(data, 'playlistSidebarPrimaryInfoRenderer'),
|
|
|
|
thumbnail_url = url_or_none(t.get('url'))
|
|
|
|
('thumbnailRenderer', 'playlistVideoThumbnailRenderer', 'thumbnail')))
|
|
|
|
if not thumbnail_url:
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
thumbnails.append({
|
|
|
|
|
|
|
|
'url': thumbnail_url,
|
|
|
|
|
|
|
|
'width': int_or_none(t.get('width')),
|
|
|
|
|
|
|
|
'height': int_or_none(t.get('height')),
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
if playlist_id is None:
|
|
|
|
if playlist_id is None:
|
|
|
|
playlist_id = item_id
|
|
|
|
playlist_id = item_id
|
|
|
|
if title is None:
|
|
|
|
if title is None:
|
|
|
|