mirror of https://github.com/yt-dlp/yt-dlp.git
[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:
parent
09f1580e2d
commit
a927acb1ec
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue