Repository: yt-dlp/yt-dlp
File: yt_dlp/postprocessor/ffmpeg.py (Python)

Code before:
            thumbnail_ext = thumbnail_ext[1:].lower()
            if thumbnail_ext != 'webp' and self.is_webp(thumbnail_filename):
                self.to_screen('Correcting thumbnail "%s" extension to webp' % thumbnail_filename)
                webp_filename = replace_extension(thumbnail_filename, 'webp')
                if os.path.exists(webp_filename):
                    os.remove(webp_filename)
                os.rename(encodeFilename(thumbnail_filename), encodeFilename(webp_filename))
                info['thumbnails'][idx]['filepath'] = webp_filename
                info['__files_to_move'][webp_filename] = replace_extension(
                    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')
        # 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')
        # 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

    def run(self, info):
        if self.format != 'jpg':
            raise FFmpegPostProcessorError('Only conversion to jpg is currently supported')
        files_to_delete = []
        has_thumbnail = False

        for idx, thumbnail_dict in enumerate(info['thumbnails']):
            if 'filepath' not in thumbnail_dict:
                continue
            has_thumbnail = True
            self.fixup_webp(info, idx)
            original_thumbnail = thumbnail_dict['filepath']
            _, thumbnail_ext = os.path.splitext(original_thumbnail)
            if thumbnail_ext:
                thumbnail_ext = thumbnail_ext[1:].lower()
            if thumbnail_ext == self.format:
                self.to_screen('Thumbnail "%s" is already in the requested format' % original_thumbnail)
                continue
            thumbnail_dict['filepath'] = self.convert_thumbnail(original_thumbnail, self.format)
            files_to_delete.append(original_thumbnail)
            info['__files_to_move'][thumbnail_dict['filepath']] = replace_extension(
                info['__files_to_move'][original_thumbnail], self.format)

        if not has_thumbnail:

Review comment (security):
```suggestion
        self.to_screen('Converting thumbnail "%s" to %s' % (escaped_thumbnail_filename, ext))
```
Using `ext` as the format name will simply the above code. See my other comment

Code after:
            thumbnail_ext = thumbnail_ext[1:].lower()
            if thumbnail_ext != 'webp' and self.is_webp(thumbnail_filename):
                self.to_screen('Correcting thumbnail "%s" extension to webp' % thumbnail_filename)
                webp_filename = replace_extension(thumbnail_filename, 'webp')
                if os.path.exists(webp_filename):
                    os.remove(webp_filename)
                os.rename(encodeFilename(thumbnail_filename), encodeFilename(webp_filename))
                info['thumbnails'][idx]['filepath'] = webp_filename
                info['__files_to_move'][webp_filename] = replace_extension(
                    info['__files_to_move'].pop(thumbnail_filename), 'webp')

    def convert_thumbnail(self, thumbnail_filename, ext):
        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_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_conv_filename), encodeFilename(thumbnail_conv_filename))
        return thumbnail_conv_filename

    def run(self, info):
        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

        for idx, thumbnail_dict in enumerate(info['thumbnails']):
            if 'filepath' not in thumbnail_dict:
                continue
            has_thumbnail = True
            self.fixup_webp(info, idx)
            original_thumbnail = thumbnail_dict['filepath']
            _, thumbnail_ext = os.path.splitext(original_thumbnail)
            if thumbnail_ext:
                thumbnail_ext = thumbnail_ext[1:].lower()
            if thumbnail_ext == self.format:
                self.to_screen('Thumbnail "%s" is already in the requested format' % original_thumbnail)
                continue