]> jfr.im git - yt-dlp.git/commitdiff
[ThumbnailsConvertor] Support conversion to `png` and make it the default (#333)
authorlouie-github <redacted>
Fri, 21 May 2021 18:09:48 +0000 (02:09 +0800)
committerGitHub <redacted>
Fri, 21 May 2021 18:09:48 +0000 (23:39 +0530)
PNG, being a lossless format, should be a better default here compared to JPG since we won't be compressing to a lossy format and losing some of the original image data
PNG is also supported for embedding in all the formats similar to JPEG

Authored by: louie-github

README.md
yt_dlp/__init__.py
yt_dlp/options.py
yt_dlp/postprocessor/embedthumbnail.py
yt_dlp/postprocessor/ffmpeg.py

index b1ad224162d3c6b302a7c7fe6d5a8ec737636b26..9d77f9735d9b6097e48d7183b3e20691826263dd 100644 (file)
--- a/README.md
+++ b/README.md
@@ -752,7 +752,7 @@ ## Post-Processing Options:
                                      (currently supported: srt|ass|vtt|lrc)
                                      (Alias: --convert-subtitles)
     --convert-thumbnails FORMAT      Convert the thumbnails to another format
-                                     (currently supported: jpg)
+                                     (currently supported: jpg, png)
     --split-chapters                 Split video into multiple files based on
                                      internal chapters. The "chapter:" prefix
                                      can be used with "--paths" and "--output"
index 00a28128d2cfdde66a81a5326ae5f47fdd5d678a..d014d1e0106c4103d1390d8ce7106e0c980ded79 100644 (file)
@@ -227,7 +227,7 @@ def parse_retries(retries, name=''):
         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:
index 695e085940f41a45ef72a0ff19887f4693db53c2..c982dbb846fdc1322cf6c9026d3ae54eea54d66b 100644 (file)
@@ -1253,7 +1253,7 @@ def _dict_from_options_callback(
     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,
index 2d4f42a20066f87f8678942e177934e3f40288bf..b0372225a80482e2d61dcc926ca42097c16be384 100644 (file)
@@ -77,11 +77,14 @@ def run(self, info):
 
         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
 
index b156108293ba92806fba457e7333aa46b095fea6..f2e3559a5ee896529f5feda317935fd7717f4e60 100644 (file)
@@ -849,24 +849,30 @@ def fixup_webp(self, info, idx=-1):
                     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