diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py index 8790b326b..f3b216b62 100644 --- a/yt_dlp/YoutubeDL.py +++ b/yt_dlp/YoutubeDL.py @@ -304,6 +304,7 @@ class YoutubeDL: unless writeinfojson is also given writeannotations: Write the video annotations to a .annotations.xml file writethumbnail: Write the thumbnail image to a file + thumbnail_format: Format code of thumbnail to write allow_playlist_files: Whether to write playlists' description, infojson etc also to disk when using the 'write*' options write_all_thumbnails: Write all thumbnail formats to files @@ -4385,9 +4386,24 @@ def _write_subtitles(self, info_dict, filename): def _write_thumbnails(self, label, info_dict, filename, thumb_filename_base=None): """ Write thumbnails to file and return list of (thumb_filename, final_thumb_filename); or None if error """ write_all = self.params.get('write_all_thumbnails', False) + write_any = write_all or self.params.get('writethumbnail', False) thumbnails, ret = [], [] - if write_all or self.params.get('writethumbnail', False): - thumbnails = info_dict.get('thumbnails') or [] + + if write_any: + all_thumbnails = info_dict.get('thumbnails') or [] + thumbnail_id = self.params.get('thumbnail_format') + if thumbnail_id and not write_all: + for t in all_thumbnails: + if t.get('id') == thumbnail_id: + thumbnails.append(t) + break + else: + self.raise_no_formats( + info_dict, msg=('Invalid thumbnail ID specified. Use --list-thumbnails to see available IDs'), + ) + else: + thumbnails = all_thumbnails + if not thumbnails: self.to_screen(f'[info] There are no {label} thumbnails to download') return ret diff --git a/yt_dlp/__init__.py b/yt_dlp/__init__.py index 7d8f10047..84a2cb03e 100644 --- a/yt_dlp/__init__.py +++ b/yt_dlp/__init__.py @@ -877,6 +877,7 @@ def parse_options(argv=None): 'clean_infojson': opts.clean_infojson, 'getcomments': opts.getcomments, 'writethumbnail': opts.writethumbnail is True, + 'thumbnail_format': opts.thumbnail_format, 'write_all_thumbnails': opts.writethumbnail == 'all', 'writelink': opts.writelink, 'writeurllink': opts.writeurllink, diff --git a/yt_dlp/options.py b/yt_dlp/options.py index 91c2635a7..410286c2e 100644 --- a/yt_dlp/options.py +++ b/yt_dlp/options.py @@ -1533,6 +1533,10 @@ def _alias_callback(option, opt_str, value, parser, opts, nargs): '--no-write-thumbnail', action='store_false', dest='writethumbnail', help='Do not write thumbnail image to disk (default)') + thumbnail.add_option( + '--thumbnail-format', + metavar='format', dest='thumbnail_format', + help='Format code of thumbnail to write to disk') thumbnail.add_option( '--write-all-thumbnails', action='store_const', dest='writethumbnail', const='all', diff --git a/yt_dlp/postprocessor/embedthumbnail.py b/yt_dlp/postprocessor/embedthumbnail.py index d8ba220ca..42d381269 100644 --- a/yt_dlp/postprocessor/embedthumbnail.py +++ b/yt_dlp/postprocessor/embedthumbnail.py @@ -62,7 +62,10 @@ def run(self, info): self.to_screen('There aren\'t any thumbnails to embed') return [], info - idx = next((-i for i, t in enumerate(info['thumbnails'][::-1], 1) if t.get('filepath')), None) + if self._downloader and (fmt := self._downloader.params.get('thumbnail_format')): + idx = next((i for i, t in enumerate(info['thumbnails']) if t.get('id') == fmt and t.get('filepath')), None) + else: + idx = next((-i for i, t in enumerate(info['thumbnails'][::-1], 1) if t.get('filepath')), None) if idx is None: self.to_screen('There are no thumbnails on disk') return [], info