mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-10-31 06:35:12 +00:00 
			
		
		
		
	[ThumbnailsConvertor] Support conversion to png and make it the default (#333)
				
					
				
			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
This commit is contained in:
		| @@ -752,7 +752,7 @@ Then simply run `make`. You can also run `make yt-dlp` instead to compile only t | |||||||
|                                      (currently supported: srt|ass|vtt|lrc) |                                      (currently supported: srt|ass|vtt|lrc) | ||||||
|                                      (Alias: --convert-subtitles) |                                      (Alias: --convert-subtitles) | ||||||
|     --convert-thumbnails FORMAT      Convert the thumbnails to another format |     --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 |     --split-chapters                 Split video into multiple files based on | ||||||
|                                      internal chapters. The "chapter:" prefix |                                      internal chapters. The "chapter:" prefix | ||||||
|                                      can be used with "--paths" and "--output" |                                      can be used with "--paths" and "--output" | ||||||
|   | |||||||
| @@ -227,7 +227,7 @@ def _real_main(argv=None): | |||||||
|         if opts.convertsubtitles not in ('srt', 'vtt', 'ass', 'lrc'): |         if opts.convertsubtitles not in ('srt', 'vtt', 'ass', 'lrc'): | ||||||
|             parser.error('invalid subtitle format specified') |             parser.error('invalid subtitle format specified') | ||||||
|     if opts.convertthumbnails is not None: |     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') |             parser.error('invalid thumbnail format specified') | ||||||
|  |  | ||||||
|     if opts.date is not None: |     if opts.date is not None: | ||||||
|   | |||||||
| @@ -1253,7 +1253,7 @@ def parseOpts(overrideArguments=None): | |||||||
|     postproc.add_option( |     postproc.add_option( | ||||||
|         '--convert-thumbnails', |         '--convert-thumbnails', | ||||||
|         metavar='FORMAT', dest='convertthumbnails', default=None, |         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( |     postproc.add_option( | ||||||
|         '--split-chapters', '--split-tracks', |         '--split-chapters', '--split-tracks', | ||||||
|         dest='split_chapters', action='store_true', default=False, |         dest='split_chapters', action='store_true', default=False, | ||||||
|   | |||||||
| @@ -77,11 +77,14 @@ class EmbedThumbnailPP(FFmpegPostProcessor): | |||||||
|  |  | ||||||
|         original_thumbnail = thumbnail_filename = info['thumbnails'][-1]['filepath'] |         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:] |         thumbnail_ext = os.path.splitext(thumbnail_filename)[1][1:] | ||||||
|         if thumbnail_ext not in ('jpg', 'png'): |         if thumbnail_ext not in ('jpg', 'png'): | ||||||
|             thumbnail_filename = convertor.convert_thumbnail(thumbnail_filename, 'jpg') |             thumbnail_filename = convertor.convert_thumbnail(thumbnail_filename, 'png') | ||||||
|             thumbnail_ext = 'jpg' |             thumbnail_ext = 'png' | ||||||
|  |  | ||||||
|         mtime = os.stat(encodeFilename(filename)).st_mtime |         mtime = os.stat(encodeFilename(filename)).st_mtime | ||||||
|  |  | ||||||
|   | |||||||
| @@ -849,24 +849,30 @@ class FFmpegThumbnailsConvertorPP(FFmpegPostProcessor): | |||||||
|                     info['__files_to_move'].pop(thumbnail_filename), 'webp') |                     info['__files_to_move'].pop(thumbnail_filename), 'webp') | ||||||
|  |  | ||||||
|     def convert_thumbnail(self, thumbnail_filename, ext): |     def convert_thumbnail(self, thumbnail_filename, ext): | ||||||
|         if ext != 'jpg': |         if ext == 'jpg': | ||||||
|             raise FFmpegPostProcessorError('Only conversion to jpg is currently supported') |             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 |         # NB: % is supposed to be escaped with %% but this does not work | ||||||
|         # for input files so working around with standard substitution |         # for input files so working around with standard substitution | ||||||
|         escaped_thumbnail_filename = thumbnail_filename.replace('%', '#') |         escaped_thumbnail_filename = thumbnail_filename.replace('%', '#') | ||||||
|         os.rename(encodeFilename(thumbnail_filename), encodeFilename(escaped_thumbnail_filename)) |         os.rename(encodeFilename(thumbnail_filename), encodeFilename(escaped_thumbnail_filename)) | ||||||
|         escaped_thumbnail_jpg_filename = replace_extension(escaped_thumbnail_filename, 'jpg') |         escaped_thumbnail_conv_filename = replace_extension(escaped_thumbnail_filename, ext) | ||||||
|         self.to_screen('Converting thumbnail "%s" to JPEG' % escaped_thumbnail_filename) |         self.to_screen('Converting thumbnail "%s" to %s' % (escaped_thumbnail_filename, format_name)) | ||||||
|         self.run_ffmpeg(escaped_thumbnail_filename, escaped_thumbnail_jpg_filename, ['-bsf:v', 'mjpeg2jpeg']) |         self.run_ffmpeg(escaped_thumbnail_filename, escaped_thumbnail_conv_filename, opts) | ||||||
|         thumbnail_jpg_filename = replace_extension(thumbnail_filename, 'jpg') |         thumbnail_conv_filename = replace_extension(thumbnail_filename, ext) | ||||||
|         # Rename back to unescaped |         # Rename back to unescaped | ||||||
|         os.rename(encodeFilename(escaped_thumbnail_filename), encodeFilename(thumbnail_filename)) |         os.rename(encodeFilename(escaped_thumbnail_filename), encodeFilename(thumbnail_filename)) | ||||||
|         os.rename(encodeFilename(escaped_thumbnail_jpg_filename), encodeFilename(thumbnail_jpg_filename)) |         os.rename(encodeFilename(escaped_thumbnail_conv_filename), encodeFilename(thumbnail_conv_filename)) | ||||||
|         return thumbnail_jpg_filename |         return thumbnail_conv_filename | ||||||
|  |  | ||||||
|     def run(self, info): |     def run(self, info): | ||||||
|         if self.format != 'jpg': |         if self.format not in ('jpg', 'png'): | ||||||
|             raise FFmpegPostProcessorError('Only conversion to jpg is currently supported') |             raise FFmpegPostProcessorError('Only conversion to either jpg or png is currently supported') | ||||||
|         files_to_delete = [] |         files_to_delete = [] | ||||||
|         has_thumbnail = False |         has_thumbnail = False | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 louie-github
					louie-github