Skip to content

Commit

Permalink
add v0.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Sxela committed Nov 16, 2024
1 parent 513d26d commit 9fe8493
Show file tree
Hide file tree
Showing 6 changed files with 3,290 additions and 23 deletions.
2 changes: 2 additions & 0 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@
NODE_DISPLAY_NAME_MAPPINGS = {**NODE_DISPLAY_NAME_MAPPINGS, **imported_module.NODE_DISPLAY_NAME_MAPPINGS}

__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']

WEB_DIRECTORY = "./js"
45 changes: 36 additions & 9 deletions frame_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ def INPUT_TYPES(self):
{
"file_path": ("STRING", {"multiline": True,
"default":"C:\\code\\warp\\19_cn_venv\\images_out\\stable_warpfusion_0.20.0\\videoFrames\\650571deef_0_0_1"}),
"update_on_frame_load": ("BOOLEAN", {"default": True})
"update_on_frame_load": ("BOOLEAN", {"default": True}),
"start_frame":("INT", {"default": 0, "min": 0, "max": 9999999999}),
"end_frame":("INT", {"default": -1, "min": -1, "max": 9999999999}),
"nth_frame":("INT", {"default": 1, "min": 1, "max": 9999999999}),
},
}

Expand All @@ -95,14 +98,14 @@ def INPUT_TYPES(self):
RETURN_NAMES = ("FRAME_DATASET", "Total_frames")
FUNCTION = "get_frames"

def get_frames(self, file_path, update_on_frame_load):
def get_frames(self, file_path, update_on_frame_load, start_frame, end_frame, nth_frame):
ds = FrameDataset(file_path, outdir_prefix='', videoframes_root=folder_paths.get_output_directory(),
update_on_getitem=update_on_frame_load)
update_on_getitem=update_on_frame_load, start_frame=start_frame, end_frame=end_frame, nth_frame=nth_frame)
return (ds,len(ds))

@classmethod
def VALIDATE_INPUTS(self, file_path, update_on_frame_load):
_, n_frames = self.get_frames(self, file_path, update_on_frame_load)
def VALIDATE_INPUTS(self, file_path, update_on_frame_load, start_frame, end_frame, nth_frame):
_, n_frames = self.get_frames(self, file_path, update_on_frame_load, start_frame, end_frame, nth_frame)
if n_frames==0:
return f"Found 0 frames in path {file_path}"

Expand Down Expand Up @@ -258,10 +261,9 @@ def INPUT_TYPES(self):

CATEGORY = "WarpFusion"

RETURN_TYPES = ()
FUNCTION = "save_img"
RETURN_TYPES = ()
OUTPUT_NODE = True
type = 'output'

def save_img(self, image, output_dir, batch_name, frame_number):
os.makedirs(output_dir, exist_ok=True)
Expand Down Expand Up @@ -370,6 +372,29 @@ def INPUT_TYPES(self):
def get_value(self, schedule, frame_number):
value = get_scheduled_arg(frame_num=frame_number, schedule=schedule, blend_json_schedules=False)
return (str(value),)

"""
inspired by https://github.com/Fannovel16/ComfyUI-Loopchain
"""
class FixedQueue:
@classmethod
def INPUT_TYPES(self):
return {"required":
{
"start": ("INT",{"default": 0, "min": 0, "max": 9999999999}),
"end":("INT",{"default": 1, "min": 0, "max": 9999999999}),
"current_number":("INT",{"default": 0, "min": 0, "max": 9999999999}),
}
}

CATEGORY = "WarpFusion"

RETURN_TYPES = ("INT", "INT", "INT",)
RETURN_NAMES = ("current", "start", "end",)
FUNCTION = "get_value"

def get_value(self, start, end, current_number):
return (current_number, start, end)

NODE_CLASS_MAPPINGS = {
"LoadFrameSequence": LoadFrameSequence,
Expand All @@ -383,7 +408,8 @@ def get_value(self, schedule, frame_number):
"RenderVideo": RenderVideo,
"SchedulerString":SchedulerString,
"SchedulerFloat":SchedulerFloat,
"SchedulerInt":SchedulerInt
"SchedulerInt":SchedulerInt,
"FixedQueue":FixedQueue
}

NODE_DISPLAY_NAME_MAPPINGS = {
Expand All @@ -398,5 +424,6 @@ def get_value(self, schedule, frame_number):
"RenderVideo": "RenderVideo",
"SchedulerString":"SchedulerString",
"SchedulerFloat":"SchedulerFloat",
"SchedulerInt":"SchedulerInt"
"SchedulerInt":"SchedulerInt",
"FixedQueue":"FixedQueue"
}
32 changes: 19 additions & 13 deletions frame_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,31 +45,37 @@ def extractFrames(video_path, output_path, nth_frame, start_frame, end_frame):


class FrameDataset():
def __init__(self, source_path, outdir_prefix='', videoframes_root='', update_on_getitem=False):
def __init__(self, source_path, outdir_prefix='', videoframes_root='', update_on_getitem=False, start_frame=0, end_frame=-1, nth_frame=1):
if end_frame == -1: end_frame = 999999999
self.frame_paths = None
image_extenstions = ['jpeg', 'jpg', 'png', 'tiff', 'bmp', 'webp']
self.update_on_getitem = update_on_getitem
self.source_path = source_path
if not os.path.exists(source_path):
if len(glob.glob(source_path))>0:
self.frame_paths = sorted(glob.glob(source_path))
"""if non-empty glob-pattern"""
self.frame_paths = sorted(glob.glob(source_path))[start_frame:end_frame:nth_frame]
else:
raise FileNotFoundError(f'Frame source for {outdir_prefix} not found at {source_path}\nPlease specify an existing source path.')
if os.path.exists(source_path):
if os.path.isfile(source_path):
if os.path.splitext(source_path)[1][1:].lower() in image_extenstions:
"""if 1 image"""
self.frame_paths = [source_path]
hash = generate_file_hash(source_path)[:10]
out_path = os.path.join(videoframes_root, outdir_prefix+'_'+hash)

extractFrames(source_path, out_path,
nth_frame=1, start_frame=0, end_frame=999999999)
self.frame_paths = glob.glob(os.path.join(out_path, '*.*'))
self.source_path = out_path
if len(self.frame_paths)<1:
else:
"""if 1 video"""
hash = generate_file_hash(source_path)[:10]
out_path = os.path.join(videoframes_root, outdir_prefix+'_'+hash)

extractFrames(source_path, out_path,
nth_frame=nth_frame, start_frame=start_frame, end_frame=end_frame)
self.frame_paths = glob.glob(os.path.join(out_path, '*.*')) #dont apply start-end here as already applied during video extraction
self.source_path = out_path
if len(self.frame_paths)<1:
raise FileNotFoundError(f'Couldn`t extract frames from {source_path}\nPlease specify an existing source path.')
elif os.path.isdir(source_path):
self.frame_paths = glob.glob(os.path.join(source_path, '*.*'))
"""if folder with images"""
self.frame_paths = glob.glob(os.path.join(source_path, '*.*'))[start_frame:end_frame:nth_frame]
if len(self.frame_paths)<1:
raise FileNotFoundError(f'Found 0 frames in {source_path}\nPlease specify an existing source path.')
extensions = []
Expand Down Expand Up @@ -173,8 +179,8 @@ def save_video(indir, video_out, batch_name='', start_frame=1, last_frame=-1, fp
if use_deflicker:
postfix+='_dfl'

indir_stem = indir.replace('\\','/').split('/')[-1]
out_filepath = f"{video_out}/{indir_stem}_{postfix}.{output_format.split('_')[-1]}"
indir_stem = indir.replace('\\','/').strip('/').split('/')[-1]
out_filepath = os.path.join(video_out, f"{indir_stem}_{batch_name}_{postfix}.{output_format.split('_')[-1]}")
if last_frame == -1:
last_frame = len(glob.glob(f"{indir}/*.png"))

Expand Down
54 changes: 54 additions & 0 deletions js/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { app } from "../../scripts/app.js";

class QueueMany {
constructor(node) {
this.serializedCtx = {};
this.node = node;
for (const [i, w] of this.node.widgets.entries()) {
if (w.name === 'start') {
this.start = w;
}
if (w.name === 'end') {
this.end = w;
}
if (w.name === 'current_number') {
this.current_number = w;
}
}
this.current_number.value = this.start.value
console.log(this.start, this.end, this.current_number)

this.QueueButton = this.node.addWidget("button", 'Queue Many', null, () => {
console.log('lolo')
this.current_number.value = this.start.value
for (let i=this.start.value; i<=this.end.value; i++){
console.log('iiii', i)
app.queuePrompt(0, 1)

}
})

this.current_number.serializeValue = async (node, index) => {return this.current_number.value}

this.current_number.afterQueued = () => {
this.current_number.value += 1
if (this.current_number.value > this.end.value) {
this.current_number.value = this.start.value
}
}
}
}

app.registerExtension({
name: "warpfusion.queuemany",
async beforeRegisterNodeDef(nodeType, nodeData, _app) {
// console.log(nodeData.name)
if (nodeData.name === "FixedQueue"){
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function () {
onNodeCreated ? onNodeCreated.apply(this, []) : undefined;
this.queueMany = new QueueMany(this);
}
};
}})

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[project]
name = "comfywarp"
description = "WarpFusion workflow wrapper for ComfyUI"
version = "0.4.0"
version = "0.5.0"
license = {file = "LICENSE"}
dependencies = ["opencv-python", "scikit-image"]

Expand Down
Loading

0 comments on commit 9fe8493

Please sign in to comment.