1 Star 0 Fork 0

ComfyUI CustomNodes Clone/ComfyUI_FizzNodes

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
ScheduledNodes.py 35.75 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
#These nodes were made using code from the Deforum extension for A1111 webui
#You can find the project here: https://github.com/deforum-art/sd-webui-deforum
import comfy
import numexpr
import torch
import numpy as np
import pandas as pd
import re
import json
from .ScheduleFuncs import (
check_is_number, interpolate_prompts_SDXL, PoolAnimConditioning,
interpolate_string, addWeighted, reverseConcatenation, split_weighted_subprompts
)
from .BatchFuncs import interpolate_prompt_series, BatchPoolAnimConditioning, BatchInterpolatePromptsSDXL, batch_split_weighted_subprompts #, BatchGLIGENConditioning
from .ValueFuncs import batch_get_inbetweens, batch_parse_key_frames, parse_key_frames, get_inbetweens, sanitize_value
#Max resolution value for Gligen area calculation.
MAX_RESOLUTION=8192
defaultPrompt=""""0" :"",
"12" :"",
"24" :"",
"36" :"",
"48" :"",
"60" :"",
"72" :"",
"84" :"",
"96" :"",
"108" :"",
"120" :""
"""
defaultValue="""0:(0),
12:(0),
24:(0),
36:(0),
48:(0),
60:(0),
72:(0),
84:(0),
96:(0),
108:(0),
120:(0)
"""
#This node parses the user's formatted prompt,
#sequences the current prompt,next prompt, and
#conditioning strength, evaluates expressions in
#the prompts, and then returns either current,
#next or averaged conditioning.
class PromptSchedule:
@classmethod
def INPUT_TYPES(s):
return {"required": {"text": ("STRING", {"multiline": True, "default":defaultPrompt}),
"clip": ("CLIP", ),
"max_frames": ("INT", {"default": 120.0, "min": 1.0, "max": 999999.0, "step": 1.0}),
"current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 999999.0, "step": 1.0,}),
"print_output":("BOOLEAN", {"default": False}),},# "forceInput": True}),},
"optional": {"pre_text": ("STRING", {"multiline": True,}),# "forceInput": True}),
"app_text": ("STRING", {"multiline": True,}),# "forceInput": True}),
"pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
"pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
"pw_c": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
"pw_d": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
}}
RETURN_TYPES = ("CONDITIONING", "CONDITIONING",)
RETURN_NAMES = ("POS", "NEG",)
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/ScheduleNodes"
def animate(self, text, max_frames, print_output, current_frame, clip, pw_a=0, pw_b=0, pw_c=0, pw_d=0, pre_text='', app_text=''):
current_frame = current_frame % max_frames
inputText = str("{" + text + "}")
inputText = re.sub(r',\s*}', '}', inputText)
animation_prompts = json.loads(inputText.strip())
start_frame = 0
pos, neg = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text)
pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a,
pw_b, pw_c, pw_d, print_output)
pc = PoolAnimConditioning(pos_cur_prompt[current_frame], pos_nxt_prompt[current_frame], weight[current_frame], clip)
neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a,
pw_b, pw_c, pw_d, print_output)
nc = PoolAnimConditioning(neg_cur_prompt[current_frame], neg_nxt_prompt[current_frame], weight[current_frame], clip)
return (pc, nc,)
class BatchPromptSchedule:
@classmethod
def INPUT_TYPES(s):
return {"required": {"text": ("STRING", {"multiline": True, "default": defaultPrompt}),
"clip": ("CLIP",),
"max_frames": ("INT", {"default": 120.0, "min": 1.0, "max": 999999.0, "step": 1.0}),
"print_output":("BOOLEAN", {"default": False}),},
# "forceInput": True}),},
"optional": {"pre_text": ("STRING", {"multiline": True, "default": "PRE" }), # "forceInput": True}),
"app_text": ("STRING", {"multiline": True, "default": "APP" }), # "forceInput": True}),
"start_frame": ("INT", {"default": 0, "min": 0, "max": 9999, "step": 1, }),
"pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_c": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_d": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
}}
RETURN_TYPES = ("CONDITIONING", "CONDITIONING",)
RETURN_NAMES = ("POS", "NEG",)
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/BatchScheduleNodes"
def animate(self, text, max_frames, print_output, clip, start_frame, pw_a, pw_b, pw_c, pw_d, pre_text='', app_text=''):
inputText = str("{" + text + "}")
inputText = re.sub(r',\s*}', '}', inputText)
max_frames += start_frame
animation_prompts = json.loads(inputText.strip())
pos, neg = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text)
pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output)
pc = BatchPoolAnimConditioning( pos_cur_prompt, pos_nxt_prompt, weight, clip,)
neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output)
nc = BatchPoolAnimConditioning(neg_cur_prompt, neg_nxt_prompt, weight, clip, )
return (pc, nc, )
class BatchPromptScheduleLatentInput:
@classmethod
def INPUT_TYPES(s):
return {"required": {"text": ("STRING", {"multiline": True, "default": defaultPrompt}),
"clip": ("CLIP",),
"num_latents": ("LATENT", ),
"print_output":("BOOLEAN", {"default": False}),},
# "forceInput": True}),},
"optional": {"pre_text": ("STRING", {"multiline": True, "default": "PRE", }), # "forceInput": True}),
"app_text": ("STRING", {"multiline": True, "default": "APP", }), # "forceInput": True}),
"start_frame": ("INT", {"default": 0.0, "min": 0, "max": 9999, "step": 1, }),
"pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_c": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_d": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
}}
RETURN_TYPES = ("CONDITIONING", "CONDITIONING", "LATENT", )
RETURN_NAMES = ("POS", "NEG", "INPUT_LATENTS",)
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/BatchScheduleNodes"
def animate(self, text, num_latents, print_output, clip, start_frame, pw_a, pw_b, pw_c, pw_d, pre_text='', app_text=''):
max_frames = sum(tensor.size(0) for tensor in num_latents.values())
max_frames += start_frame
inputText = str("{" + text + "}")
inputText = re.sub(r',\s*}', '}', inputText)
animation_prompts = json.loads(inputText.strip())
pos, neg = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text)
pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, start_frame, pre_text,
app_text, pw_a, pw_b, pw_c, pw_d,
print_output)
pc = BatchPoolAnimConditioning(pos_cur_prompt, pos_nxt_prompt, weight, clip, )
neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, start_frame, pre_text,
app_text, pw_a, pw_b, pw_c, pw_d,
print_output)
nc = BatchPoolAnimConditioning(neg_cur_prompt, neg_nxt_prompt, weight, clip, )
return (pc, nc, num_latents,)
class StringSchedule:
@classmethod
def INPUT_TYPES(s):
return {"required": {"text": ("STRING", {"multiline": True, "default": defaultPrompt}),
"max_frames": ("INT", {"default": 120.0, "min": 1.0, "max": 999999.0, "step": 1.0}),
"current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 999999.0, "step": 1.0, })},
# "forceInput": True}),},
"optional": {"pre_text": ("STRING", {"multiline": True, "default": "PRE", }), # "forceInput": True}),
"app_text": ("STRING", {"multiline": True, "default": "APP", }), # "forceInput": True}),
"pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_c": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_d": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
}}
RETURN_TYPES = ("STRING",)
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/ScheduleNodes"
def animate(self, text, max_frames, current_frame, pw_a=0, pw_b=0, pw_c=0, pw_d=0, pre_text='', app_text=''):
current_frame = current_frame % max_frames
inputText = str("{" + text + "}")
inputText = re.sub(r',\s*}', '}', inputText)
animation_prompts = json.loads(inputText.strip())
cur_prompt = interpolate_string(animation_prompts, max_frames, current_frame, pre_text,
app_text, pw_a, pw_b, pw_c, pw_d)
#c = PoolAnimConditioning(cur_prompt, nxt_prompt, weight, clip, )
return (cur_prompt,)
class PromptScheduleSDXLRefiner:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"ascore": ("FLOAT", {"default": 6.0, "min": 0.0, "max": 1000.0, "step": 0.01}),
"width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"text": ("STRING", {"multiline": True, "default":defaultPrompt}), "clip": ("CLIP", ),
}}
RETURN_TYPES = ("CONDITIONING",)
FUNCTION = "encode"
CATEGORY = "advanced/conditioning"
def encode(self, clip, ascore, width, height, text):
tokens = clip.tokenize(text)
cond, pooled = clip.encode_from_tokens(tokens, return_pooled=True)
return ([[cond, {"pooled_output": pooled, "aesthetic_score": ascore, "width": width,"height": height}]], )
class BatchStringSchedule:
@classmethod
def INPUT_TYPES(s):
return {"required": {"text": ("STRING", {"multiline": True, "default": defaultPrompt}),
"max_frames": ("INT", {"default": 120.0, "min": 1.0, "max": 999999.0, "step": 1.0}),},
# "forceInput": True}),},
"optional": {"pre_text": ("STRING", {"multiline": True, "default": "PRE", }), # "forceInput": True}),
"app_text": ("STRING", {"multiline": True, "default": "APP", }), # "forceInput": True}),
"pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_c": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_d": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
}}
RETURN_TYPES = ("STRING",)
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/BatchScheduleNodes"
def animate(self, text, max_frames, pw_a=0, pw_b=0, pw_c=0, pw_d=0, pre_text='', app_text=''):
inputText = str("{" + text + "}")
inputText = re.sub(r',\s*}', '}', inputText)
start_frame = 0
animation_prompts = json.loads(inputText.strip())
cur_prompt_series, nxt_prompt_series, weight_series = interpolate_prompt_series(animation_prompts, max_frames, start_frame, pre_text,
app_text, pw_a, pw_b, pw_c, pw_d)
return (cur_prompt_series,)
class BatchPromptScheduleEncodeSDXL:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"crop_w": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
"crop_h": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
"target_width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"target_height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"text_g": ("STRING", {"multiline": True, "default": "CLIP_G"}), "clip": ("CLIP", ),
"text_l": ("STRING", {"multiline": True, "default": "CLIP_L"}), "clip": ("CLIP", ),
"max_frames": ("INT", {"default": 120.0, "min": 1.0, "max": 999999.0, "step": 1.0}),
"print_output":("BOOLEAN", {"default": False}),},
"optional": {"pre_text_G": ("STRING", {"multiline": True, "default": "PRE_G"}),# "forceInput": True}),
"app_text_G": ("STRING", {"multiline": True, "default": "APP_G"}),# "forceInput": True}),
"pre_text_L": ("STRING", {"multiline": True, "default": "PRE_L"}),# "forceInput": True}),
"app_text_L": ("STRING", {"multiline": True, "default": "APP_L"}),# "forceInput": True}),
"pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
"pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
"pw_c": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
"pw_d": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
}}
RETURN_TYPES = ("CONDITIONING",)
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/BatchScheduleNodes"
def animate(self, clip, width, height, crop_w, crop_h, target_width, target_height, text_g, text_l, app_text_G, app_text_L, pre_text_G, pre_text_L, max_frames, print_output, pw_a, pw_b, pw_c, pw_d):
inputTextG = str("{" + text_g + "}")
inputTextL = str("{" + text_l + "}")
inputTextG = re.sub(r',\s*}', '}', inputTextG)
inputTextL = re.sub(r',\s*}', '}', inputTextL)
animation_promptsG = json.loads(inputTextG.strip())
animation_promptsL = json.loads(inputTextL.strip())
return (BatchInterpolatePromptsSDXL(animation_promptsG, animation_promptsL, max_frames, clip, app_text_G, app_text_L, pre_text_G, pre_text_L, pw_a, pw_b, pw_c, pw_d, width, height, crop_w, crop_h, target_width, target_height, print_output,),)
class BatchPromptScheduleEncodeSDXLLatentInput:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"crop_w": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
"crop_h": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
"target_width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"target_height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"text_g": ("STRING", {"multiline": True, "default": "CLIP_G"}), "clip": ("CLIP", ),
"text_l": ("STRING", {"multiline": True, "default": "CLIP_L"}), "clip": ("CLIP", ),
"num_latents": ("LATENT", ),
"print_output":("BOOLEAN", {"default": False}),},
"optional": {"pre_text_G": ("STRING", {"multiline": True, "default": "PRE_G",}),# "forceInput": True}),
"app_text_G": ("STRING", {"multiline": True, "default": "APP_G",}),# "forceInput": True}),
"pre_text_L": ("STRING", {"multiline": True, "default": "PRE_L",}),# "forceInput": True}),
"app_text_L": ("STRING", {"multiline": True, "default": "APP_L",}),# "forceInput": True}),
"pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
"pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
"pw_c": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
"pw_d": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
}}
RETURN_TYPES = ("CONDITIONING", "LATENT",)
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/BatchScheduleNodes"
def animate(self, clip, width, height, crop_w, crop_h, target_width, target_height, text_g, text_l, app_text_G, app_text_L, pre_text_G, pre_text_L, num_latents, print_output, pw_a, pw_b, pw_c, pw_d):
max_frames = sum(tensor.size(0) for tensor in num_latents.values())
inputTextG = str("{" + text_g + "}")
inputTextL = str("{" + text_l + "}")
inputTextG = re.sub(r',\s*}', '}', inputTextG)
inputTextL = re.sub(r',\s*}', '}', inputTextL)
animation_promptsG = json.loads(inputTextG.strip())
animation_promptsL = json.loads(inputTextL.strip())
return (BatchInterpolatePromptsSDXL(animation_promptsG, animation_promptsL, max_frames, clip, app_text_G, app_text_L, pre_text_G, pre_text_L, pw_a, pw_b, pw_c, pw_d, width, height, crop_w, crop_h, target_width, target_height, print_output, ), num_latents, )
class PromptScheduleEncodeSDXL:
@classmethod
def INPUT_TYPES(s):
return {"required": {
"width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"crop_w": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
"crop_h": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION}),
"target_width": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"target_height": ("INT", {"default": 1024.0, "min": 0, "max": MAX_RESOLUTION}),
"text_g": ("STRING", {"multiline": True, "default": "CLIP_G"}), "clip": ("CLIP", ),
"text_l": ("STRING", {"multiline": True, "default": "CLIP_L"}), "clip": ("CLIP", ),
"max_frames": ("INT", {"default": 120.0, "min": 1.0, "max": 999999.0, "step": 1.0}),
"current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 999999.0, "step": 1.0}),
"print_output":("BOOLEAN", {"default": False})},
"optional": {"pre_text_G": ("STRING", {"multiline": True, "default": "PRE_G",}),# "forceInput": True}),
"app_text_G": ("STRING", {"multiline": True, "default": "APP_G",}),# "forceInput": True}),
"pre_text_L": ("STRING", {"multiline": True, "default": "PRE_L",}),# "forceInput": True}),
"app_text_L": ("STRING", {"multiline": True, "default": "APP_L",}),# "forceInput": True}),
"pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
"pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
"pw_c": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
"pw_d": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}), #"forceInput": True }),
}}
RETURN_TYPES = ("CONDITIONING",)
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/ScheduleNodes"
def animate(self, clip, width, height, crop_w, crop_h, target_width, target_height, text_g, text_l, app_text_G, app_text_L, pre_text_G, pre_text_L, max_frames, current_frame, print_output, pw_a, pw_b, pw_c, pw_d):
current_frame = current_frame % max_frames
inputTextG = str("{" + text_g + "}")
inputTextL = str("{" + text_l + "}")
inputTextG = re.sub(r',\s*}', '}', inputTextG)
inputTextL = re.sub(r',\s*}', '}', inputTextL)
animation_promptsG = json.loads(inputTextG.strip())
animation_promptsL = json.loads(inputTextL.strip())
return (interpolate_prompts_SDXL(animation_promptsG, animation_promptsL, max_frames, current_frame, clip, app_text_G, app_text_L, pre_text_G, pre_text_L, pw_a, pw_b, pw_c, pw_d, width, height, crop_w, crop_h, target_width, target_height, print_output,),)
# This node schedules the prompt using separate nodes as the keyframes.
# The values in the prompt are evaluated in NodeFlowEnd.
class PromptScheduleNodeFlow:
@classmethod
def INPUT_TYPES(s):
return {"required": {"text": ("STRING", {"multiline": True}),
"num_frames": ("INT", {"default": 24.0, "min": 0.0, "max": 9999.0, "step": 1.0}),},
"optional": {"in_text": ("STRING", {"multiline": False, }), # "forceInput": True}),
"max_frames": ("INT", {"default": 0.0, "min": 0.0, "max": 999999.0, "step": 1.0,})}} # "forceInput": True}),}}
RETURN_TYPES = ("INT","STRING",)
FUNCTION = "addString"
CATEGORY = "FizzNodes 📅🅕🅝/ScheduleNodes"
def addString(self, text, in_text='', max_frames=0, num_frames=0):
if in_text:
# Remove trailing comma from in_text if it exists
in_text = in_text.rstrip(',')
new_max = num_frames + max_frames
if max_frames == 0:
# Construct a new JSON object with a single key-value pair
new_text = in_text + (', ' if in_text else '') + f'"{max_frames}": "{text}"'
else:
# Construct a new JSON object with a single key-value pair
new_text = in_text + (', ' if in_text else '') + f'"{new_max}": "{text}"'
return (new_max, new_text,)
#Last node in the Node Flow for evaluating the json produced by the above node.
class PromptScheduleNodeFlowEnd:
@classmethod
def INPUT_TYPES(s):
return {"required": {"text": ("STRING", {"multiline": False, "forceInput": True}),
"clip": ("CLIP", ),
"max_frames": ("INT", {"default": 0.0, "min": 0.0, "max": 999999.0, "step": 1.0,}),
"print_output": ("BOOLEAN", {"default": False}),
"current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 999999.0, "step": 1.0,}),}, #"forceInput": True}),},
"optional": {"pre_text": ("STRING", {"multiline": True, "default": "PRE", }),#"forceInput": True}),
"app_text": ("STRING", {"multiline": True, "default": "APP", }),#"forceInput": True}),
"pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}),# "forceInput": True}),
"pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}),# "forceInput": True}),
"pw_c": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}),# "forceInput": True}),
"pw_d": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}),# "forceInput": True}),
}}
RETURN_TYPES = ("CONDITIONING","CONDITIONING",)
RETURN_NAMES = ("POS", "NEG",)
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/ScheduleNodes"
def animate(self, text, max_frames, print_output, current_frame, clip, pw_a = 0, pw_b = 0, pw_c = 0, pw_d = 0, pre_text = '', app_text = ''):
current_frame = current_frame % max_frames
if text[-1] == ",":
text = text[:-1]
if text[0] == ",":
text = text[:0]
start_frame = 0
inputText = str("{" + text + "}")
inputText = re.sub(r',\s*}', '}', inputText)
animation_prompts = json.loads(inputText.strip())
max_frames += start_frame
pos, neg = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text)
pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a,
pw_b, pw_c, pw_d, print_output)
pc = PoolAnimConditioning(pos_cur_prompt[current_frame], pos_nxt_prompt[current_frame], weight[current_frame],
clip, )
neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a,
pw_b, pw_c, pw_d, print_output)
nc = PoolAnimConditioning(neg_cur_prompt[current_frame], neg_nxt_prompt[current_frame], weight[current_frame],
clip, )
return (pc, nc,)
class BatchPromptScheduleNodeFlowEnd:
@classmethod
def INPUT_TYPES(s):
return {"required": {"text": ("STRING", {"multiline": False, "forceInput": True}),
"clip": ("CLIP", ),
"max_frames": ("INT", {"default": 0.0, "min": 0.0, "max": 999999.0, "step": 1.0,}),
"print_output": ("BOOLEAN", {"default": False}),
},
"optional": {"pre_text": ("STRING", {"multiline": False, }),#"forceInput": True}),
"app_text": ("STRING", {"multiline": False, }),#"forceInput": True}),
"pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}),# "forceInput": True}),
"pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}),# "forceInput": True}),
"pw_c": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}),# "forceInput": True}),
"pw_d": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1,}),# "forceInput": True}),
}}
RETURN_TYPES = ("CONDITIONING",)
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/BatchScheduleNodes"
def animate(self, text, max_frames, start_frame, print_output, clip, pw_a=0, pw_b=0, pw_c=0, pw_d=0, pre_text='', current_frame = 0,
app_text=''):
if text[-1] == ",":
text = text[:-1]
if text[0] == ",":
text = text[:0]
inputText = str("{" + text + "}")
inputText = re.sub(r',\s*}', '}', inputText)
animation_prompts = json.loads(inputText.strip())
max_frames += start_frame
pos, neg = batch_split_weighted_subprompts(animation_prompts, pre_text, app_text)
pos_cur_prompt, pos_nxt_prompt, weight = interpolate_prompt_series(pos, max_frames, start_frame, pre_text, app_text, pw_a,
pw_b, pw_c, pw_d, print_output)
pc = BatchPoolAnimConditioning(pos_cur_prompt[current_frame], pos_nxt_prompt[current_frame], weight[current_frame],
clip, )
neg_cur_prompt, neg_nxt_prompt, weight = interpolate_prompt_series(neg, max_frames, start_frame, pre_text, app_text, pw_a,
pw_b, pw_c, pw_d, print_output)
nc = BatchPoolAnimConditioning(neg_cur_prompt[current_frame], neg_nxt_prompt[current_frame], weight[current_frame],
clip, )
return (pc, nc,)
class BatchGLIGENSchedule:
@classmethod
def INPUT_TYPES(s):
return {"required": {"conditioning_to": ("CONDITIONING",),
"clip": ("CLIP",),
"gligen_textbox_model": ("GLIGEN",),
"text": ("STRING", {"multiline": True, "default":defaultPrompt}),
"width": ("INT", {"default": 64, "min": 8, "max": MAX_RESOLUTION, "step": 8}),
"height": ("INT", {"default": 64, "min": 8, "max": MAX_RESOLUTION, "step": 8}),
"x": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION, "step": 8}),
"y": ("INT", {"default": 0, "min": 0, "max": MAX_RESOLUTION, "step": 8}),
"max_frames": ("INT", {"default": 120.0, "min": 1.0, "max": 999999.0, "step": 1.0}),
"print_output":("BOOLEAN", {"default": False})},
# "forceInput": True}),},
"optional": {"pre_text": ("STRING", {"multiline": True, "default": "PRE", }), # "forceInput": True}),
"app_text": ("STRING", {"multiline": True, "default": "APP", }), # "forceInput": True}),
"pw_a": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_b": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_c": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
"pw_d": ("FLOAT", {"default": 0.0, "min": -9999.0, "max": 9999.0, "step": 0.1, }),
# "forceInput": True }),
}}
RETURN_TYPES = ("CONDITIONING",)
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/BatchScheduleNodes"
def animate(self, conditioning_to, clip, gligen_textbox_model, text, width, height, x, y, max_frames, print_output, pw_a, pw_b, pw_c, pw_d, pre_text='', app_text=''):
inputText = str("{" + text + "}")
inputText = re.sub(r',\s*}', '}', inputText)
animation_prompts = json.loads(inputText.strip())
cur_series, nxt_series, weight_series = interpolate_prompt_series(animation_prompts, max_frames, pre_text, app_text, pw_a, pw_b, pw_c, pw_d, print_output)
out = []
for i in range(0, max_frames - 1):
# Calculate changes in x and y here, based on your logic
x_change = 8
y_change = 0
# Update x and y values
x += x_change
y += y_change
print(x)
print(y)
out.append(self.append(conditioning_to, clip, gligen_textbox_model, pre_text, width, height, x, y))
return (out,)
def append(self, conditioning_to, clip, gligen_textbox_model, text, width, height, x, y):
c = []
cond, cond_pooled = clip.encode_from_tokens(clip.tokenize(text), return_pooled=True)
for t in range(0, len(conditioning_to)):
n = [conditioning_to[t][0], conditioning_to[t][1].copy()]
position_params = [(cond_pooled, height // 8, width // 8, y // 8, x // 8)]
prev = []
if "gligen" in n[1]:
prev = n[1]['gligen'][2]
n[1]['gligen'] = ("position", gligen_textbox_model, prev + position_params)
c.append(n)
return c
#This node parses the user's test input into
#interpolated floats. Expressions can be input
#and evaluated.
class ValueSchedule:
@classmethod
def INPUT_TYPES(s):
return {"required": {"text": ("STRING", {"multiline": True, "default":defaultValue}),
"max_frames": ("INT", {"default": 120.0, "min": 1.0, "max": 999999.0, "step": 1.0}),
"current_frame": ("INT", {"default": 0.0, "min": 0.0, "max": 999999.0, "step": 1.0,}),# "forceInput": True}),
}}
RETURN_TYPES = ("FLOAT", "INT")
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/ScheduleNodes"
def animate(self, text, max_frames, current_frame,):
current_frame = current_frame % max_frames
t = get_inbetweens(parse_key_frames(text, max_frames), max_frames)
cFrame = current_frame
return (t[cFrame],int(t[cFrame]),)
class BatchValueSchedule:
@classmethod
def INPUT_TYPES(s):
return {"required": {"text": ("STRING", {"multiline": True, "default": defaultValue}),
"max_frames": ("INT", {"default": 120.0, "min": 1.0, "max": 999999.0, "step": 1.0}),
}}
RETURN_TYPES = ("FLOAT", "INT")
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/BatchScheduleNodes"
def animate(self, text, max_frames, ):
t = batch_get_inbetweens(batch_parse_key_frames(text, max_frames), max_frames)
return (t, list(map(int,t)),)
class BatchValueScheduleLatentInput:
@classmethod
def INPUT_TYPES(s):
return {"required": {"text": ("STRING", {"multiline": True, "default": defaultValue}),
"num_latents": ("LATENT", ),
}}
RETURN_TYPES = ("FLOAT", "INT", "LATENT", )
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/BatchScheduleNodes"
def animate(self, text, num_latents, ):
num_elements = sum(tensor.size(0) for tensor in num_latents.values())
max_frames = num_elements
t = batch_get_inbetweens(batch_parse_key_frames(text, max_frames), max_frames)
return (t, list(map(int,t)), num_latents, )
# Expects a Batch Value Schedule list input, it exports an image batch with images taken from an input image batch
class ImageBatchFromValueSchedule:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"images": ("IMAGE",),
"values": ("FLOAT", { "default": 1.0, "min": -1.0, "max": 1.0, "label": "values" }),
}
}
RETURN_TYPES = ("IMAGE",)
FUNCTION = "animate"
CATEGORY = "FizzNodes 📅🅕🅝/BatchScheduleNodes"
def animate(self, images, values):
values = [values] * n if isinstance(values, float) else values
min_value, max_value = min(values), max(values)
i = [(x - min_value) / (max_value - min_value) * (images.shape[0] - 1) for x in values]
return (images[i], )
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/custom_nodes_clone/ComfyUI_FizzNodes.git
git@gitee.com:custom_nodes_clone/ComfyUI_FizzNodes.git
custom_nodes_clone
ComfyUI_FizzNodes
ComfyUI_FizzNodes
main

搜索帮助