# Documentation - Class name: SaveAnimatedWEBP - Category: image/animation - Output node: True - Repo Ref: https://github.com/comfyanonymous/ComfyUI 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,)}} ```