aboutsummaryrefslogtreecommitdiffstats
path: root/yt_dlp
diff options
context:
space:
mode:
Diffstat (limited to 'yt_dlp')
-rw-r--r--yt_dlp/__init__.py2
-rw-r--r--yt_dlp/options.py2
-rw-r--r--yt_dlp/postprocessor/embedthumbnail.py9
-rw-r--r--yt_dlp/postprocessor/ffmpeg.py26
4 files changed, 24 insertions, 15 deletions
diff --git a/yt_dlp/__init__.py b/yt_dlp/__init__.py
index 00a28128d..d014d1e01 100644
--- a/yt_dlp/__init__.py
+++ b/yt_dlp/__init__.py
@@ -227,7 +227,7 @@ def _real_main(argv=None):
if opts.convertsubtitles not in ('srt', 'vtt', 'ass', 'lrc'):
parser.error('invalid subtitle format specified')
if opts.convertthumbnails is not None:
- if opts.convertthumbnails not in ('jpg', ):
+ if opts.convertthumbnails not in ('jpg', 'png'):
parser.error('invalid thumbnail format specified')
if opts.date is not None:
diff --git a/yt_dlp/options.py b/yt_dlp/options.py
index 695e08594..c982dbb84 100644
--- a/yt_dlp/options.py
+++ b/yt_dlp/options.py
@@ -1253,7 +1253,7 @@ def parseOpts(overrideArguments=None):
postproc.add_option(
'--convert-thumbnails',
metavar='FORMAT', dest='convertthumbnails', default=None,
- help='Convert the thumbnails to another format (currently supported: jpg)')
+ help='Convert the thumbnails to another format (currently supported: jpg, png)')
postproc.add_option(
'--split-chapters', '--split-tracks',
dest='split_chapters', action='store_true', default=False,
diff --git a/yt_dlp/postprocessor/embedthumbnail.py b/yt_dlp/postprocessor/embedthumbnail.py
index 2d4f42a20..b0372225a 100644
--- a/yt_dlp/postprocessor/embedthumbnail.py
+++ b/yt_dlp/postprocessor/embedthumbnail.py
@@ -77,11 +77,14 @@ class EmbedThumbnailPP(FFmpegPostProcessor):
original_thumbnail = thumbnail_filename = info['thumbnails'][-1]['filepath']
- # Convert unsupported thumbnail formats to JPEG (see #25687, #25717)
+ # Convert unsupported thumbnail formats to PNG (see #25687, #25717)
+ # Original behavior was to convert to JPG, but since JPG is a lossy
+ # format, there will be some additional data loss.
+ # PNG, on the other hand, is lossless.
thumbnail_ext = os.path.splitext(thumbnail_filename)[1][1:]
if thumbnail_ext not in ('jpg', 'png'):
- thumbnail_filename = convertor.convert_thumbnail(thumbnail_filename, 'jpg')
- thumbnail_ext = 'jpg'
+ thumbnail_filename = convertor.convert_thumbnail(thumbnail_filename, 'png')
+ thumbnail_ext = 'png'
mtime = os.stat(encodeFilename(filename)).st_mtime
diff --git a/yt_dlp/postprocessor/ffmpeg.py b/yt_dlp/postprocessor/ffmpeg.py
index b15610829..f2e3559a5 100644
--- a/yt_dlp/postprocessor/ffmpeg.py
+++ b/yt_dlp/postprocessor/ffmpeg.py
@@ -849,24 +849,30 @@ class FFmpegThumbnailsConvertorPP(FFmpegPostProcessor):
info['__files_to_move'].pop(thumbnail_filename), 'webp')
def convert_thumbnail(self, thumbnail_filename, ext):
- if ext != 'jpg':
- raise FFmpegPostProcessorError('Only conversion to jpg is currently supported')
+ if ext == 'jpg':
+ format_name = 'JPEG'
+ opts = ['-bsf:v', 'mjpeg2jpeg']
+ elif ext == 'png':
+ format_name = 'PNG'
+ opts = []
+ else:
+ raise FFmpegPostProcessorError('Only conversion to either jpg or png is currently supported')
# NB: % is supposed to be escaped with %% but this does not work
# for input files so working around with standard substitution
escaped_thumbnail_filename = thumbnail_filename.replace('%', '#')
os.rename(encodeFilename(thumbnail_filename), encodeFilename(escaped_thumbnail_filename))
- escaped_thumbnail_jpg_filename = replace_extension(escaped_thumbnail_filename, 'jpg')
- self.to_screen('Converting thumbnail "%s" to JPEG' % escaped_thumbnail_filename)
- self.run_ffmpeg(escaped_thumbnail_filename, escaped_thumbnail_jpg_filename, ['-bsf:v', 'mjpeg2jpeg'])
- thumbnail_jpg_filename = replace_extension(thumbnail_filename, 'jpg')
+ escaped_thumbnail_conv_filename = replace_extension(escaped_thumbnail_filename, ext)
+ self.to_screen('Converting thumbnail "%s" to %s' % (escaped_thumbnail_filename, format_name))
+ self.run_ffmpeg(escaped_thumbnail_filename, escaped_thumbnail_conv_filename, opts)
+ thumbnail_conv_filename = replace_extension(thumbnail_filename, ext)
# Rename back to unescaped
os.rename(encodeFilename(escaped_thumbnail_filename), encodeFilename(thumbnail_filename))
- os.rename(encodeFilename(escaped_thumbnail_jpg_filename), encodeFilename(thumbnail_jpg_filename))
- return thumbnail_jpg_filename
+ os.rename(encodeFilename(escaped_thumbnail_conv_filename), encodeFilename(thumbnail_conv_filename))
+ return thumbnail_conv_filename
def run(self, info):
- if self.format != 'jpg':
- raise FFmpegPostProcessorError('Only conversion to jpg is currently supported')
+ if self.format not in ('jpg', 'png'):
+ raise FFmpegPostProcessorError('Only conversion to either jpg or png is currently supported')
files_to_delete = []
has_thumbnail = False