Files
CavinHuang-comfyui-nodes-docs/docs/SaveAnimatedWEBP.md
2024-05-15 08:09:49 +08:00

4.9 KiB

Documentation

SaveAnimatedWEBP节点的'save_images'方法旨在高效地将一系列图像保存为动画WEBP文件。它利用PIL库将图像转换为适合动画的格式,允许控制帧速率、无损压缩和质量设置。该节点在图像处理工作流的最终输出阶段扮演着关键角色,能够从一系列静态图像中创建动画视觉效果。

Input types

Required

  • images
    • “images”参数对于节点至关重要,因为它定义了将保存为动画的输入图像。每个图像都构成了最终输出中的一个帧,影响着整个动画序列和其视觉质量。
    • Comfy dtype: IMAGE
    • Python dtype: List[torch.Tensor]
  • fps
    • “fps”参数决定了动画的帧速率,这是影响最终输出在运动感知方面的一个关键因素。它决定了帧的显示速度,影响着整个动画的流畅度。
    • Comfy dtype: FLOAT
    • Python dtype: float
  • lossless
    • “lossless”参数对于控制保存图像时使用的压缩方法很重要。当设置为True时,它确保保存的动画保持最高质量,不会丢失图像数据。
    • Comfy dtype: BOOLEAN
    • Python dtype: bool
  • quality
    • “quality”参数影响保存动画中文件大小和图像质量之间的平衡。较高的值会得到更好的图像质量但文件大小也会增加,而较低的值则相反。
    • Comfy dtype: INT
    • Python dtype: int
  • method
    • “method”参数选择创建动画WEBP文件时使用的压缩算法。不同的方法提供不同程度的压缩效率和速度,影响最终文件大小和保存动画所需的时间。
    • Comfy dtype: COMBO[default, fastest, slowest]
    • Python dtype: Literal['default', 'fastest', 'slowest']

Optional

  • filename_prefix
    • “filename_prefix”参数非常重要,因为它决定了保存文件的命名约定,这对于组织和识别输出至关重要。它提供了一个基础名称,然后与一个唯一标识符结合以创建完整的文件名。
    • Comfy dtype: STRING
    • Python dtype: str

Output types

  • ui
    • 输出中的'ui'参数是一个字典,包含保存的图像的详细信息,包括文件名和子文件夹。它作为节点生成的输出的记录,为用户提供了保存的动画文件的位置和性质的参考。
    • Comfy dtype: DICT
    • Python dtype: Dict[str, Any]

Usage tips

  • Infra type: CPU

Source code

class SaveAnimatedWEBP:

    def __init__(self):
        self.output_dir = folder_paths.get_output_directory()
        self.type = 'output'
        self.prefix_append = ''
    methods = {'default': 4, 'fastest': 0, 'slowest': 6}

    @classmethod
    def INPUT_TYPES(s):
        return {'required': {'images': ('IMAGE',), 'filename_prefix': ('STRING', {'default': 'ComfyUI'}), 'fps': ('FLOAT', {'default': 6.0, 'min': 0.01, 'max': 1000.0, 'step': 0.01}), 'lossless': ('BOOLEAN', {'default': True}), 'quality': ('INT', {'default': 80, 'min': 0, 'max': 100}), 'method': (list(s.methods.keys()),)}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}}
    RETURN_TYPES = ()
    FUNCTION = 'save_images'
    OUTPUT_NODE = True
    CATEGORY = 'image/animation'

    def save_images(self, images, fps, filename_prefix, lossless, quality, method, num_frames=0, prompt=None, extra_pnginfo=None):
        method = self.methods.get(method)
        filename_prefix += self.prefix_append
        (full_output_folder, filename, counter, subfolder, filename_prefix) = folder_paths.get_save_image_path(filename_prefix, self.output_dir, images[0].shape[1], images[0].shape[0])
        results = list()
        pil_images = []
        for image in images:
            i = 255.0 * image.cpu().numpy()
            img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
            pil_images.append(img)
        metadata = pil_images[0].getexif()
        if not args.disable_metadata:
            if prompt is not None:
                metadata[272] = 'prompt:{}'.format(json.dumps(prompt))
            if extra_pnginfo is not None:
                inital_exif = 271
                for x in extra_pnginfo:
                    metadata[inital_exif] = '{}:{}'.format(x, json.dumps(extra_pnginfo[x]))
                    inital_exif -= 1
        if num_frames == 0:
            num_frames = len(pil_images)
        c = len(pil_images)
        for i in range(0, c, num_frames):
            file = f'{filename}_{counter:05}_.webp'
            pil_images[i].save(os.path.join(full_output_folder, file), save_all=True, duration=int(1000.0 / fps), append_images=pil_images[i + 1:i + num_frames], exif=metadata, lossless=lossless, quality=quality, method=method)
            results.append({'filename': file, 'subfolder': subfolder, 'type': self.type})
            counter += 1
        animated = num_frames != 1
        return {'ui': {'images': results, 'animated': (animated,)}}