55 Commits
Author SHA1 Message Date
Morgan Johansson f48bed5b8a Removed resampling from Pillow access. 2025-02-16 15:45:39 +01:00
Morgan Johansson b09b8a79eb Removed resampling from Pillow access. 2025-02-16 15:45:15 +01:00
Morgan Johansson 44afbb07c6 Node list fix. 2025-02-15 19:13:25 +01:00
Morgan Johansson a8071b2089 Fix for IS_CHANGED. 2025-02-15 18:49:35 +01:00
Morgan Johansson 12d7ef2a54 Fix for IS_CHANGED 2025-02-12 18:09:16 +01:00
Morgan Johansson a94e21dbdd Fix for IS_CHANGED 2025-02-12 18:03:06 +01:00
Morgan Johansson ae524cd593 Fix for node defaults. 2025-02-11 21:58:33 +01:00
Morgan Johansson d45fffff23 Update check fix. 2025-02-11 21:48:17 +01:00
Morgan Johansson 411948551a Compatibility fix. 2025-02-11 21:41:14 +01:00
Morgan Johansson d87e5d8a7c Compatibility fix. 2025-02-11 21:33:05 +01:00
Morgan Johansson 9e87f209aa Compatibility fix. 2025-02-11 21:27:59 +01:00
Morgan Johansson f09e0f3e36 Compatibility fix. 2025-02-11 21:24:33 +01:00
Morgan Johansson b2dfaea97c Compatibility fix. 2025-02-11 21:18:25 +01:00
Morgan Johansson 1e50facb9e Install fix. 2025-02-11 21:09:48 +01:00
Morgan Johansson b63340f4b7 Version fix. 2025-02-11 21:07:03 +01:00
Morgan Johansson f77719bf34 Version fix. 2025-02-11 21:04:30 +01:00
Morgan Johansson c8fe03350e Version fix. 2025-02-11 20:38:32 +01:00
Morgan Johansson 96258138b6 Re-added random prompt node. 2025-02-11 20:30:11 +01:00
Morgan Johansson 98776cccb6 numpy req versions 2025-02-11 19:47:31 +01:00
Morgan Johansson 942d7d8931 Fix for change check warnings. 2025-02-11 19:46:06 +01:00
Morgan Johansson 1d38975ce3 prompt builder input range fix 2025-01-17 22:00:38 +01:00
Morgan Johansson 403095b513 Random Prompt Words fix. 2025-01-15 21:29:25 +01:00
Morgan Johansson 170664c592 Lazy switches added. 2025-01-15 19:05:13 +01:00
Morgan Johansson 7b73e65cec DreamRandomPromptWords fix. 2025-01-14 17:38:09 +01:00
Morgan Johansson d5c107e541 DreamRandomPromptWords fix. 2025-01-14 17:32:06 +01:00
Morgan Johansson a22b11b43c DreamRandomPromptWords separator added 2025-01-14 17:09:09 +01:00
Morgan Johansson 4b059e5095 DreamRandomPromptWords added 2025-01-14 17:03:29 +01:00
Morgan Johansson b5c804a332 Version bump. 2024-12-07 21:07:28 +01:00
Morgan Johansson 801bcaf1d7 Fixed requirements.txt that could cause parse error on some pip versions 2024-12-07 21:02:26 +01:00
Morgan Johansson b9e6959c1f 14: Switches will now return a None value if there is no valid input. 2024-12-01 10:09:08 +01:00
Morgan Johansson ed2c58cf2f 14: Switches will now return a None value if there is no valid input. 2024-12-01 09:58:49 +01:00
Morgan Johansson f44a70900a Version bump to 1.0.2 2024-12-01 09:50:42 +01:00
Morgan Johansson bff5ca4fbe Version bump to 1.0.1 2024-12-01 09:12:03 +01:00
Morgan Johansson a81c591e9d 14: resolved issue with inf loop in switches when there are inputs but none is valid. 2024-12-01 09:10:09 +01:00
alt-key-project 426a6e85e9 Merge pull request #12 from ComfyNodePRs/licence-update
Update PyProject Toml - License
2024-11-17 07:16:01 +01:00
snomiao e1a7ec58ed chore(licence-update): Update PyProject Toml - License 2024-07-31 15:02:24 +00:00
Morgan Johansson b2ddca87a9 fixed github action branch 2024-07-01 07:34:10 +02:00
Morgan Johansson 6bc4c1616f Merge branch 'master' of https://github.com/alt-key-project/comfyui-dream-project 2024-07-01 07:30:35 +02:00
Morgan Johansson bff8f66047 Version bump 2024-07-01 07:30:30 +02:00
alt-key-project 8babb241dd Merge pull request #10 from haohaocreates/publish
Add Github Action for Publishing to Comfy Registry
2024-07-01 07:27:24 +02:00
Morgan Johansson f456af2ec5 publisher id added 2024-07-01 07:18:55 +02:00
alt-key-project c3c7a4ccfd Merge pull request #11 from haohaocreates/pyproject
Add pyproject.toml for Custom Node Registry
2024-07-01 07:15:25 +02:00
haohaocreates b56e007c57 chore(pyproject): Add pyproject.toml for Custom Node Registry 2024-05-22 16:51:45 -04:00
haohaocreates e6545ec3c9 chore(publish): Add Github Action for Publishing to Comfy Registry 2024-05-22 16:51:43 -04:00
Morgan Johansson 2d642150da 5.0.1 2023-12-21 20:36:49 +01:00
Morgan Johansson c34e9f5213 Fixed issues with big switches. 2023-12-21 20:35:09 +01:00
Morgan Johansson 68246e3adf Added readme notice. 2023-11-25 12:27:15 +01:00
Morgan Johansson ab73436fc2 Added readme notice. 2023-11-25 12:25:42 +01:00
Morgan Johansson d9efc1516a Added readme notice. 2023-11-25 12:25:04 +01:00
Morgan Johansson 6880bde78c Minor update for changed python version. 2023-11-25 12:18:36 +01:00
Morgan Johansson 25cbdff39c Removed mpegCoder encoding as the module does not support newer versions of python. 2023-10-22 18:17:28 +02:00
Morgan Johansson 07bfda783d rename of types.py to dreamtypes.py 2023-10-22 12:08:37 +02:00
alt-key-project d74fdb8de7 Merge pull request #6 from linnkoln/master
Allows to output name of frame file
2023-10-17 21:22:49 +02:00
linnkoln 5def36f87f Allows to output name of frame file 2023-10-12 17:11:54 +03:00
Morgan Johansson 08a0a06820 Removed debug logging. 2023-09-19 20:39:38 +02:00
28 changed files with 812 additions and 1140 deletions
+21
View File
@@ -0,0 +1,21 @@
name: Publish to Comfy registry
on:
workflow_dispatch:
push:
branches:
- master
paths:
- "pyproject.toml"
jobs:
publish-node:
name: Publish Custom Node to registry
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Publish Custom Node
uses: Comfy-Org/publish-node-action@main
with:
## Add your own personal access token to your Github Repository secrets and reference it here.
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
+2 -1
View File
@@ -1,3 +1,4 @@
.idea
__pycache__
config.json
config.json
*.cmd
+7 -3
View File
@@ -1,5 +1,8 @@
# -*- coding: utf-8 -*-
from typing import Type
import sys,os
sys.path.append(str(os.path.dirname(os.path.abspath(__file__))))
from .base import *
from .colors import *
@@ -15,6 +18,7 @@ from .switches import *
from .utility import *
from .calculate import *
from .laboratory import *
#from .lazyswitches import *
_NODE_CLASSES: List[Type] = [DreamSineWave, DreamLinear, DreamCSVCurve, DreamBeatCurve, DreamFrameDimensions,
DreamImageMotion, DreamNoiseFromPalette, DreamAnalyzePalette, DreamColorShift,
@@ -22,7 +26,7 @@ _NODE_CLASSES: List[Type] = [DreamSineWave, DreamLinear, DreamCSVCurve, DreamBea
DreamSimpleFrameCounter, DreamImageSequenceInputWithDefaultFallback,
DreamImageSequenceOutput, DreamCSVGenerator, DreamImageAreaSampler,
DreamVideoEncoder, DreamSequenceTweening, DreamSequenceBlend, DreamColorAlign,
DreamImageSampler, DreamNoiseFromAreaPalettes, DreamVideoEncoderMpegCoder,
DreamImageSampler, DreamNoiseFromAreaPalettes,
DreamInputString, DreamInputFloat, DreamInputInt, DreamInputText, DreamBigLatentSwitch,
DreamFrameCountCalculator, DreamBigImageSwitch, DreamBigTextSwitch, DreamBigFloatSwitch,
DreamBigIntSwitch, DreamBigPaletteSwitch, DreamWeightedPromptBuilder, DreamPromptFinalizer,
@@ -30,12 +34,12 @@ _NODE_CLASSES: List[Type] = [DreamSineWave, DreamLinear, DreamCSVCurve, DreamBea
DreamTriangleEvent, DreamSmoothEvent, DreamCalculation, DreamImageColorShift,
DreamComparePalette, DreamImageContrast, DreamImageBrightness, DreamLogFile,
DreamLaboratory, DreamStringToLog, DreamIntToLog, DreamFloatToLog, DreamJoinLog,
DreamStringTokenizer, DreamWavCurve, DreamFrameCounterTimeOffset]
DreamStringTokenizer, DreamWavCurve, DreamFrameCounterTimeOffset, DreamRandomPromptWords]
_SIGNATURE_SUFFIX = " [Dream]"
MANIFEST = {
"name": "Dream Project Animation",
"version": (4, 3, 0),
"version": (5, 1, 2),
"author": "Dream Project",
"project": "https://github.com/alt-key-project/comfyui-dream-project",
"description": "Various utility nodes for creating animations with ComfyUI",
+17 -26
View File
@@ -3,7 +3,7 @@ import glob
from .categories import NodeCategories
from .shared import *
from .types import *
from .dreamtypes import *
class DreamFrameCounterInfo:
@@ -22,10 +22,6 @@ class DreamFrameCounterInfo:
"elapsed_seconds", "remaining_seconds", "total_seconds", "completion")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *v):
return ALWAYS_CHANGED_FLAG
def result(self, frame_counter: FrameCounter):
return (frame_counter.current_frame,
frame_counter.total_frames,
@@ -56,8 +52,14 @@ class DreamDirectoryFileCount:
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *v):
return ALWAYS_CHANGED_FLAG
def IS_CHANGED(cls, directory_path, patterns):
if not os.path.isdir(directory_path):
return ""
total = 0
for pattern in patterns.split("|"):
files = list(glob.glob(pattern, root_dir=directory_path))
total += len(files)
return total
def result(self, directory_path, patterns):
if not os.path.isdir(directory_path):
@@ -66,7 +68,6 @@ class DreamDirectoryFileCount:
for pattern in patterns.split("|"):
files = list(glob.glob(pattern, root_dir=directory_path))
total += len(files)
print("total " + str(total))
return (total,)
@@ -88,10 +89,6 @@ class DreamFrameCounterOffset:
RETURN_NAMES = ("frame_counter",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, frame_counter, offset):
return hashed_as_strings(frame_counter, offset)
def result(self, frame_counter: FrameCounter, offset):
return (frame_counter.incremented(offset),)
@@ -113,10 +110,6 @@ class DreamFrameCounterTimeOffset:
RETURN_NAMES = ("frame_counter",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, frame_counter, offset):
return hashed_as_strings(frame_counter, offset)
def result(self, frame_counter: FrameCounter, offset_seconds):
offset = offset_seconds * frame_counter.frames_per_second
return (frame_counter.incremented(offset),)
@@ -141,10 +134,6 @@ class DreamSimpleFrameCounter:
RETURN_NAMES = ("frame_counter",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def result(self, frame_index, total_frames, frames_per_second):
n = frame_index
return (FrameCounter(n, total_frames, frames_per_second),)
@@ -172,8 +161,14 @@ class DreamDirectoryBackedFrameCounter:
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def IS_CHANGED(cls, directory_path, patterns, indexing, total_frames, frames_per_second):
if not os.path.isdir(directory_path):
return ""
total = 0
for pattern in patterns.split("|"):
files = list(glob.glob(pattern, root_dir=directory_path))
total += len(files)
return (total, indexing, total_frames, frames_per_second)
def result(self, directory_path, pattern, indexing, total_frames, frames_per_second):
results = list_images_in_directory(directory_path, pattern, indexing == "alphabetic order")
@@ -204,10 +199,6 @@ class DreamFrameCountCalculator:
RETURN_NAMES = ("TOTAL",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *v):
return ALWAYS_CHANGED_FLAG
def result(self, hours, minutes, seconds, milliseconds, frames_per_second):
total_s = seconds + 0.001 * milliseconds + minutes * 60 + hours * 3600
return (round(total_s * frames_per_second),)
-4
View File
@@ -33,10 +33,6 @@ class DreamCalculation:
RETURN_NAMES = ("FLOAT", "INT")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def _make_model(self):
funcs = self._make_functions()
m = base_eval_model.clone()
+1 -37
View File
@@ -2,7 +2,7 @@
from .categories import NodeCategories
from .shared import *
from .types import *
from .dreamtypes import *
class DreamImageAreaSampler:
@@ -26,10 +26,6 @@ class DreamImageAreaSampler:
RETURN_NAMES = ("palette",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def _get_pixel_area(self, img: DreamImage, area):
w = img.width
h = img.height
@@ -102,10 +98,6 @@ class DreamImageSampler:
RETURN_NAMES = ("palette",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def result(self, image, samples, seed):
result = list()
r = random.Random()
@@ -139,10 +131,6 @@ class DreamColorAlign:
RETURN_NAMES = ("palette",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def result(self, palette: Tuple[RGBPalette], target_align: Tuple[RGBPalette], alignment_factor: float):
results = list()
@@ -187,10 +175,6 @@ class DreamColorShift:
RETURN_NAMES = ("palette",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def result(self, palette, red_multiplier, green_multiplier, blue_multiplier, fixed_brightness):
results = list()
@@ -234,10 +218,6 @@ class DreamImageColorShift:
RETURN_NAMES = ("image",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def result(self, image, red_multiplier, green_multiplier, blue_multiplier):
proc = DreamImageProcessor(inputs=image)
@@ -265,10 +245,6 @@ class DreamImageBrightness:
RETURN_NAMES = ("image",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def result(self, image, factor):
proc = DreamImageProcessor(inputs=image)
@@ -296,10 +272,6 @@ class DreamImageContrast:
RETURN_NAMES = ("image",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def result(self, image, factor):
proc = DreamImageProcessor(inputs=image)
@@ -328,10 +300,6 @@ class DreamComparePalette:
"brightness_multiplier", "contrast_multiplier", "red_multiplier", "green_multiplier", "blue_multiplier")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def result(self, a, b):
MIN_VALUE = 1 / 255.0
@@ -372,10 +340,6 @@ class DreamAnalyzePalette:
RETURN_NAMES = ("brightness", "contrast", "redness", "greenness", "blueness")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def result(self, palette):
f = 1.0 / len(palette)
(w, c, r, g, b) = (0, 0, 0, 0, 0)
+4 -45
View File
@@ -8,7 +8,7 @@ from scipy.io.wavfile import read as wav_read
from .categories import NodeCategories
from .shared import hashed_as_strings
from .types import SharedTypes, FrameCounter
from .dreamtypes import SharedTypes, FrameCounter
def _linear_value_calc(x, x_start, x_end, y_start, y_end):
@@ -44,10 +44,6 @@ class DreamSineWave:
RETURN_NAMES = ("FLOAT", "INT")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def result(self, frame_counter: FrameCounter, max_value, min_value, periodicity_seconds, phase):
x = frame_counter.current_time_in_seconds
a = (max_value - min_value) * 0.5
@@ -77,10 +73,6 @@ class DreamSawWave:
RETURN_NAMES = ("FLOAT", "INT")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def result(self, frame_counter: FrameCounter, max_value, min_value, periodicity_seconds, phase):
x = frame_counter.current_time_in_seconds
x = ((x + periodicity_seconds * phase) % periodicity_seconds) / periodicity_seconds
@@ -107,10 +99,6 @@ class DreamTriangleWave:
RETURN_NAMES = ("FLOAT", "INT")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def result(self, frame_counter: FrameCounter, max_value, min_value, periodicity_seconds, phase):
x = frame_counter.current_time_in_seconds
x = ((x + periodicity_seconds * phase) % periodicity_seconds) / periodicity_seconds
@@ -141,7 +129,6 @@ class WavData:
for i in range(self._num_buckets):
self._buckets[i] = float(self._buckets[i]) / self._max_bucket_value
print("Bucket {} = {}".format(i, self._buckets[i]))
def value_at_time(self, second: float) -> float:
if second < 0.0 or second > self._length_in_seconds:
@@ -175,10 +162,6 @@ class DreamWavCurve:
},
}
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def result(self, frame_counter: FrameCounter, wav_path, scale):
if not os.path.isfile(wav_path):
return (0.0, 0)
@@ -207,10 +190,6 @@ class DreamTriangleEvent:
RETURN_NAMES = ("FLOAT", "INT")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def result(self, frame_counter: FrameCounter, max_value, min_value, width_seconds, center_seconds):
x = frame_counter.current_time_in_seconds
start = center_seconds - width_seconds * 0.5
@@ -243,10 +222,6 @@ class DreamSmoothEvent:
RETURN_NAMES = ("FLOAT", "INT")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def result(self, frame_counter: FrameCounter, max_value, min_value, width_seconds, center_seconds):
x = frame_counter.current_time_in_seconds
start = center_seconds - width_seconds * 0.5
@@ -282,9 +257,9 @@ class DreamBeatCurve:
"accent_1": ("INT", {"default": 1, "min": 1, "max": 24}),
},
"optional": {
"accent_2": ("INT", {"default": 3, "min": 1, "max": 24}),
"accent_3": ("INT", {"default": 0}),
"accent_4": ("INT", {"default": 0}),
"accent_2": ("INT", {"default": 0, "min": 0, "max": 24}),
"accent_3": ("INT", {"default": 0, "min": 0, "max": 24}),
"accent_4": ("INT", {"default": 0, "min": 0, "max": 24}),
}
}
@@ -293,10 +268,6 @@ class DreamBeatCurve:
RETURN_NAMES = ("FLOAT", "INT")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def _get_value_for_accent(self, accent, measure_length, bpm, frame_counter: FrameCounter, frame_offset):
current_frame = frame_counter.current_frame + frame_offset
frames_per_minute = frame_counter.frames_per_second * 60.0
@@ -341,10 +312,6 @@ class DreamLinear:
RETURN_NAMES = ("FLOAT", "INT")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def result(self, initial_value, final_value, frame_counter: FrameCounter):
d = final_value - initial_value
v = initial_value + frame_counter.progress * d
@@ -379,10 +346,6 @@ class DreamCSVGenerator:
FUNCTION = "write"
OUTPUT_NODE = True
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def write(self, csvfile, frame_counter: FrameCounter, value, csv_dialect):
if frame_counter.is_first_frame and csvfile:
with open(csvfile, 'w', newline='') as csvfile:
@@ -415,10 +378,6 @@ class DreamCSVCurve:
RETURN_NAMES = ("FLOAT", "INT")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def _row_yield(self, file, csv_dialect):
prev_row = None
for row in csv.reader(file, dialect=csv_dialect):
View File
+64 -139
View File
@@ -1,6 +1,6 @@
{
"last_node_id": 422,
"last_link_id": 5466,
"last_node_id": 423,
"last_link_id": 5467,
"nodes": [
{
"id": 77,
@@ -24,13 +24,7 @@
2312
],
"widget": {
"name": "text_2",
"config": [
"STRING",
{
"multiline": true
}
]
"name": "text"
}
}
],
@@ -65,13 +59,7 @@
],
"slot_index": 0,
"widget": {
"name": "text",
"config": [
"STRING",
{
"multiline": true
}
]
"name": "text"
}
}
],
@@ -1101,15 +1089,7 @@
"type": "INT",
"link": 5351,
"widget": {
"name": "total_frames",
"config": [
"INT",
{
"default": 100,
"min": 2,
"max": 5184000
}
]
"name": "total_frames"
},
"slot_index": 0
},
@@ -1118,14 +1098,7 @@
"type": "STRING",
"link": 5347,
"widget": {
"name": "directory_path",
"config": [
"STRING",
{
"default": "",
"multiline": false
}
]
"name": "directory_path"
}
},
{
@@ -1133,14 +1106,7 @@
"type": "INT",
"link": 5350,
"widget": {
"name": "frames_per_second",
"config": [
"INT",
{
"min": 1,
"default": 25
}
]
"name": "frames_per_second"
}
}
],
@@ -1503,13 +1469,7 @@
"type": "STRING",
"link": 2312,
"widget": {
"name": "text",
"config": [
"STRING",
{
"multiline": true
}
]
"name": "text"
},
"slot_index": 1
}
@@ -1560,13 +1520,7 @@
"type": "STRING",
"link": 2309,
"widget": {
"name": "text",
"config": [
"STRING",
{
"multiline": true
}
]
"name": "text"
}
}
],
@@ -1995,16 +1949,7 @@
"type": "INT",
"link": 5074,
"widget": {
"name": "width",
"config": [
"INT",
{
"default": 512,
"min": 1,
"max": 8192,
"step": 1
}
]
"name": "width"
}
},
{
@@ -2012,16 +1957,7 @@
"type": "INT",
"link": 5075,
"widget": {
"name": "height",
"config": [
"INT",
{
"default": 512,
"min": 1,
"max": 8192,
"step": 1
}
]
"name": "height"
}
}
],
@@ -2462,16 +2398,7 @@
"type": "FLOAT",
"link": 5222,
"widget": {
"name": "x_translation",
"config": [
"FLOAT",
{
"default": 0,
"min": -10,
"max": 10,
"step": 0.01
}
]
"name": "x_translation"
}
},
{
@@ -2479,16 +2406,7 @@
"type": "FLOAT",
"link": 5223,
"widget": {
"name": "y_translation",
"config": [
"FLOAT",
{
"default": 0,
"min": -10,
"max": 10,
"step": 0.01
}
]
"name": "y_translation"
}
},
{
@@ -2496,16 +2414,7 @@
"type": "FLOAT",
"link": 5225,
"widget": {
"name": "zoom",
"config": [
"FLOAT",
{
"default": 0,
"min": -10,
"max": 10,
"step": 0.01
}
]
"name": "zoom"
}
}
],
@@ -2707,14 +2616,7 @@
"type": "STRING",
"link": 5442,
"widget": {
"name": "directory_path",
"config": [
"STRING",
{
"default": "I:\\AI\\ComfyUI\\ComfyUI\\output",
"multiline": false
}
]
"name": "directory_path"
},
"slot_index": 2
}
@@ -2728,6 +2630,12 @@
],
"shape": 3,
"slot_index": 0
},
{
"name": "log_entry",
"type": "LOG_ENTRY",
"links": null,
"shape": 3
}
],
"properties": {
@@ -3206,14 +3114,7 @@
"type": "STRING",
"link": 5348,
"widget": {
"name": "directory_path",
"config": [
"STRING",
{
"default": "",
"multiline": false
}
]
"name": "directory_path"
},
"slot_index": 2
}
@@ -3227,6 +3128,12 @@
],
"shape": 3,
"slot_index": 0
},
{
"name": "frame_name",
"type": "STRING",
"links": null,
"shape": 3
}
],
"properties": {
@@ -4006,7 +3913,7 @@
"name": "sequence",
"type": "ANIMATION_SEQUENCE",
"links": [
5466
5467
],
"shape": 3,
"slot_index": 0
@@ -4022,11 +3929,11 @@
"bgcolor": "#593930"
},
{
"id": 422,
"type": "Video Encoder (mpegCoder) [Dream]",
"id": 423,
"type": "FFMPEG Video Encoder [Dream]",
"pos": [
4785,
561
557
],
"size": {
"0": 315,
@@ -4039,11 +3946,19 @@
{
"name": "sequence",
"type": "ANIMATION_SEQUENCE",
"link": 5466
"link": 5467
}
],
"outputs": [
{
"name": "log_entry",
"type": "LOG_ENTRY",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "Video Encoder (mpegCoder) [Dream]"
"Node name for S&R": "FFMPEG Video Encoder [Dream]"
},
"widgets_values": [
"video",
@@ -4942,10 +4857,10 @@
"*"
],
[
5466,
5467,
281,
0,
422,
423,
0,
"ANIMATION_SEQUENCE"
]
@@ -4959,7 +4874,8 @@
474,
885
],
"color": "#a1309b"
"color": "#a1309b",
"font_size": 24
},
{
"title": "Settings",
@@ -4969,7 +4885,8 @@
482,
742
],
"color": "#b58b2a"
"color": "#b58b2a",
"font_size": 24
},
{
"title": "Inpainting/Outpainting",
@@ -4979,7 +4896,8 @@
1711,
528
],
"color": "#929054"
"color": "#929054",
"font_size": 24
},
{
"title": "Prev Frame Move",
@@ -4989,7 +4907,8 @@
1450,
456
],
"color": "#3f789e"
"color": "#3f789e",
"font_size": 24
},
{
"title": "Full frame sampler",
@@ -4999,7 +4918,8 @@
691,
700
],
"color": "#88A"
"color": "#88A",
"font_size": 24
},
{
"title": "Output",
@@ -5009,7 +4929,8 @@
1458,
381
],
"color": "#b06634"
"color": "#b06634",
"font_size": 24
},
{
"title": "Animation Driver",
@@ -5019,7 +4940,8 @@
336,
373
],
"color": "#3f789e"
"color": "#3f789e",
"font_size": 24
},
{
"title": "Motion Control",
@@ -5029,7 +4951,8 @@
1451,
392
],
"color": "#ef75ff"
"color": "#ef75ff",
"font_size": 24
},
{
"title": "Model selection",
@@ -5039,7 +4962,8 @@
476,
204
],
"color": "#3f789e"
"color": "#3f789e",
"font_size": 24
},
{
"title": "Previews",
@@ -5049,7 +4973,8 @@
6473,
329
],
"color": "#444"
"color": "#444",
"font_size": 24
}
],
"config": {},
+162 -281
View File
@@ -1,6 +1,6 @@
{
"last_node_id": 421,
"last_link_id": 5462,
"last_node_id": 422,
"last_link_id": 5463,
"nodes": [
{
"id": 77,
@@ -24,13 +24,7 @@
2312
],
"widget": {
"name": "text_2",
"config": [
"STRING",
{
"multiline": true
}
]
"name": "text"
}
}
],
@@ -65,13 +59,7 @@
],
"slot_index": 0,
"widget": {
"name": "text",
"config": [
"STRING",
{
"multiline": true
}
]
"name": "text"
}
}
],
@@ -327,7 +315,7 @@
26
],
"flags": {},
"order": 24,
"order": 23,
"mode": 0,
"inputs": [
{
@@ -365,7 +353,7 @@
"1": 130
},
"flags": {},
"order": 49,
"order": 54,
"mode": 0,
"inputs": [
{
@@ -390,7 +378,7 @@
},
"widgets_values": [
256,
183250672320803,
984424700736240,
"randomize",
"center-right"
],
@@ -409,7 +397,7 @@
"1": 130
},
"flags": {},
"order": 50,
"order": 55,
"mode": 0,
"inputs": [
{
@@ -434,7 +422,7 @@
},
"widgets_values": [
256,
57339603779837,
393866830673316,
"randomize",
"bottom-center"
],
@@ -709,7 +697,7 @@
},
"widgets_values": [
256,
902082438494247,
912873459964733,
"randomize",
"bottom-center"
],
@@ -753,7 +741,7 @@
},
"widgets_values": [
256,
638849047502927,
257321647530942,
"randomize",
"center-right"
],
@@ -790,16 +778,7 @@
"type": "FLOAT",
"link": 5334,
"widget": {
"name": "alignment_factor",
"config": [
"FLOAT",
{
"default": 0.5,
"min": 0,
"max": 10,
"step": 0.1
}
]
"name": "alignment_factor"
}
}
],
@@ -818,7 +797,7 @@
"Node name for S&R": "Palette Color Align [Dream]"
},
"widgets_values": [
1.2
1.2000000000000002
],
"color": "#323",
"bgcolor": "#535"
@@ -853,16 +832,7 @@
"type": "FLOAT",
"link": 5325,
"widget": {
"name": "alignment_factor",
"config": [
"FLOAT",
{
"default": 0.5,
"min": 0,
"max": 10,
"step": 0.1
}
]
"name": "alignment_factor"
},
"slot_index": 2
}
@@ -882,7 +852,7 @@
"Node name for S&R": "Palette Color Align [Dream]"
},
"widgets_values": [
1.2
1.2000000000000002
],
"color": "#322",
"bgcolor": "#533"
@@ -917,16 +887,7 @@
"type": "FLOAT",
"link": 5333,
"widget": {
"name": "alignment_factor",
"config": [
"FLOAT",
{
"default": 0.5,
"min": 0,
"max": 10,
"step": 0.1
}
]
"name": "alignment_factor"
}
}
],
@@ -945,7 +906,7 @@
"Node name for S&R": "Palette Color Align [Dream]"
},
"widgets_values": [
1.2
1.2000000000000002
],
"color": "#223",
"bgcolor": "#335"
@@ -980,16 +941,7 @@
"type": "FLOAT",
"link": 5328,
"widget": {
"name": "alignment_factor",
"config": [
"FLOAT",
{
"default": 0.5,
"min": 0,
"max": 10,
"step": 0.1
}
]
"name": "alignment_factor"
}
}
],
@@ -1008,7 +960,7 @@
"Node name for S&R": "Palette Color Align [Dream]"
},
"widgets_values": [
1.2
1.2000000000000002
],
"color": "#432",
"bgcolor": "#653"
@@ -1209,7 +1161,7 @@
"Node name for S&R": "KSampler"
},
"widgets_values": [
586618692559734,
838611060522510,
"randomize",
25,
9,
@@ -1530,15 +1482,7 @@
"type": "INT",
"link": 5351,
"widget": {
"name": "total_frames",
"config": [
"INT",
{
"default": 100,
"min": 2,
"max": 5184000
}
]
"name": "total_frames"
},
"slot_index": 0
},
@@ -1547,14 +1491,7 @@
"type": "STRING",
"link": 5347,
"widget": {
"name": "directory_path",
"config": [
"STRING",
{
"default": "",
"multiline": false
}
]
"name": "directory_path"
}
},
{
@@ -1562,14 +1499,7 @@
"type": "INT",
"link": 5350,
"widget": {
"name": "frames_per_second",
"config": [
"INT",
{
"min": 1,
"default": 25
}
]
"name": "frames_per_second"
}
}
],
@@ -1638,47 +1568,6 @@
"color": "#432",
"bgcolor": "#653"
},
{
"id": 236,
"type": "LoadImage",
"pos": [
-2106,
679
],
"size": {
"0": 430,
"1": 340
},
"flags": {},
"order": 12,
"mode": 0,
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
5313
],
"shape": 3,
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"after (3).jpg",
"image"
],
"color": "#2a363b",
"bgcolor": "#3f5159"
},
{
"id": 373,
"type": "Reroute",
@@ -1691,7 +1580,7 @@
26
],
"flags": {},
"order": 25,
"order": 24,
"mode": 0,
"inputs": [
{
@@ -1878,7 +1767,7 @@
"1": 82
},
"flags": {},
"order": 13,
"order": 12,
"mode": 0,
"outputs": [
{
@@ -1892,16 +1781,7 @@
],
"slot_index": 0,
"widget": {
"name": "alignment_factor",
"config": [
"FLOAT",
{
"default": 0.5,
"min": 0,
"max": 10,
"step": 0.1
}
]
"name": "alignment_factor"
}
}
],
@@ -1965,7 +1845,7 @@
"1": 130
},
"flags": {},
"order": 48,
"order": 53,
"mode": 0,
"inputs": [
{
@@ -1990,7 +1870,7 @@
},
"widgets_values": [
256,
1019724837772866,
919440470904266,
"randomize",
"center-left"
],
@@ -2034,7 +1914,7 @@
},
"widgets_values": [
256,
1014748475294523,
528123820881935,
"randomize",
"center-left"
],
@@ -2055,7 +1935,7 @@
"flags": {
"collapsed": true
},
"order": 34,
"order": 32,
"mode": 0,
"inputs": [
{
@@ -2068,13 +1948,7 @@
"type": "STRING",
"link": 2312,
"widget": {
"name": "text",
"config": [
"STRING",
{
"multiline": true
}
]
"name": "text"
},
"slot_index": 1
}
@@ -2112,7 +1986,7 @@
"flags": {
"collapsed": true
},
"order": 33,
"order": 31,
"mode": 0,
"inputs": [
{
@@ -2125,13 +1999,7 @@
"type": "STRING",
"link": 2309,
"widget": {
"name": "text",
"config": [
"STRING",
{
"multiline": true
}
]
"name": "text"
}
}
],
@@ -2166,7 +2034,7 @@
26
],
"flags": {},
"order": 41,
"order": 40,
"mode": 0,
"inputs": [
{
@@ -2316,7 +2184,7 @@
26
],
"flags": {},
"order": 42,
"order": 41,
"mode": 0,
"inputs": [
{
@@ -2353,7 +2221,7 @@
26
],
"flags": {},
"order": 23,
"order": 22,
"mode": 0,
"inputs": [
{
@@ -2389,7 +2257,7 @@
26
],
"flags": {},
"order": 26,
"order": 25,
"mode": 0,
"inputs": [
{
@@ -2464,7 +2332,7 @@
"Node name for S&R": "KSampler"
},
"widgets_values": [
55143763493153,
700759510514483,
"randomize",
5,
5,
@@ -2523,7 +2391,7 @@
"1": 60
},
"flags": {},
"order": 14,
"order": 13,
"mode": 0,
"title": "Note on full frame sampler",
"properties": {
@@ -2547,7 +2415,7 @@
26
],
"flags": {},
"order": 39,
"order": 44,
"mode": 0,
"inputs": [
{
@@ -2667,7 +2535,7 @@
26
],
"flags": {},
"order": 30,
"order": 35,
"mode": 0,
"inputs": [
{
@@ -2707,7 +2575,7 @@
"1": 270
},
"flags": {},
"order": 15,
"order": 14,
"mode": 0,
"title": "Note on noise",
"properties": {
@@ -2780,16 +2648,7 @@
"type": "INT",
"link": 5074,
"widget": {
"name": "width",
"config": [
"INT",
{
"default": 512,
"min": 1,
"max": 8192,
"step": 1
}
]
"name": "width"
}
},
{
@@ -2797,16 +2656,7 @@
"type": "INT",
"link": 5075,
"widget": {
"name": "height",
"config": [
"INT",
{
"default": 512,
"min": 1,
"max": 8192,
"step": 1
}
]
"name": "height"
}
}
],
@@ -2844,7 +2694,7 @@
"1": 130
},
"flags": {},
"order": 47,
"order": 52,
"mode": 0,
"inputs": [
{
@@ -2869,7 +2719,7 @@
},
"widgets_values": [
256,
309821851176166,
502577689536295,
"randomize",
"top-center"
],
@@ -2913,7 +2763,7 @@
},
"widgets_values": [
256,
973129878717336,
1125637252645999,
"randomize",
"top-center"
],
@@ -2934,7 +2784,7 @@
"flags": {
"collapsed": false
},
"order": 16,
"order": 15,
"mode": 0,
"outputs": [
{
@@ -3007,7 +2857,7 @@
26
],
"flags": {},
"order": 55,
"order": 51,
"mode": 0,
"inputs": [
{
@@ -3083,7 +2933,7 @@
26
],
"flags": {},
"order": 44,
"order": 43,
"mode": 0,
"inputs": [
{
@@ -3119,7 +2969,7 @@
26
],
"flags": {},
"order": 35,
"order": 33,
"mode": 0,
"inputs": [
{
@@ -3156,7 +3006,7 @@
26
],
"flags": {},
"order": 53,
"order": 49,
"mode": 0,
"inputs": [
{
@@ -3196,7 +3046,7 @@
26
],
"flags": {},
"order": 52,
"order": 48,
"mode": 0,
"inputs": [
{
@@ -3335,16 +3185,7 @@
"type": "FLOAT",
"link": 5222,
"widget": {
"name": "x_translation",
"config": [
"FLOAT",
{
"default": 0,
"min": -10,
"max": 10,
"step": 0.01
}
]
"name": "x_translation"
}
},
{
@@ -3352,16 +3193,7 @@
"type": "FLOAT",
"link": 5223,
"widget": {
"name": "y_translation",
"config": [
"FLOAT",
{
"default": 0,
"min": -10,
"max": 10,
"step": 0.01
}
]
"name": "y_translation"
}
},
{
@@ -3369,16 +3201,7 @@
"type": "FLOAT",
"link": 5225,
"widget": {
"name": "zoom",
"config": [
"FLOAT",
{
"default": 0,
"min": -10,
"max": 10,
"step": 0.01
}
]
"name": "zoom"
}
}
],
@@ -3580,14 +3403,7 @@
"type": "STRING",
"link": 5442,
"widget": {
"name": "directory_path",
"config": [
"STRING",
{
"default": "I:\\AI\\ComfyUI\\ComfyUI\\output",
"multiline": false
}
]
"name": "directory_path"
},
"slot_index": 2
}
@@ -3601,6 +3417,12 @@
],
"shape": 3,
"slot_index": 0
},
{
"name": "log_entry",
"type": "LOG_ENTRY",
"links": null,
"shape": 3
}
],
"properties": {
@@ -3664,7 +3486,7 @@
26
],
"flags": {},
"order": 51,
"order": 47,
"mode": 0,
"inputs": [
{
@@ -3700,7 +3522,7 @@
26
],
"flags": {},
"order": 40,
"order": 39,
"mode": 0,
"inputs": [
{
@@ -3737,7 +3559,7 @@
26
],
"flags": {},
"order": 32,
"order": 30,
"mode": 0,
"inputs": [
{
@@ -3773,7 +3595,7 @@
26
],
"flags": {},
"order": 43,
"order": 42,
"mode": 0,
"inputs": [
{
@@ -3809,7 +3631,7 @@
26
],
"flags": {},
"order": 54,
"order": 50,
"mode": 0,
"inputs": [
{
@@ -4079,14 +3901,7 @@
"type": "STRING",
"link": 5348,
"widget": {
"name": "directory_path",
"config": [
"STRING",
{
"default": "",
"multiline": false
}
]
"name": "directory_path"
},
"slot_index": 2
}
@@ -4100,6 +3915,12 @@
],
"shape": 3,
"slot_index": 0
},
{
"name": "frame_name",
"type": "STRING",
"links": null,
"shape": 3
}
],
"properties": {
@@ -4123,7 +3944,7 @@
26
],
"flags": {},
"order": 31,
"order": 36,
"mode": 0,
"inputs": [
{
@@ -4306,7 +4127,7 @@
256,
0.11818237304687501,
0.5,
340337213218643,
855083604429355,
"randomize"
],
"color": "#2a363b",
@@ -4443,7 +4264,7 @@
"flags": {
"collapsed": false
},
"order": 17,
"order": 16,
"mode": 0,
"inputs": [],
"outputs": [
@@ -4493,7 +4314,7 @@
26
],
"flags": {},
"order": 27,
"order": 26,
"mode": 0,
"inputs": [
{
@@ -4529,7 +4350,7 @@
26
],
"flags": {},
"order": 22,
"order": 27,
"mode": 0,
"inputs": [
{
@@ -4607,7 +4428,7 @@
"1": 90
},
"flags": {},
"order": 18,
"order": 17,
"mode": 0,
"title": "Note on motion",
"properties": {
@@ -4705,7 +4526,7 @@
26
],
"flags": {},
"order": 36,
"order": 34,
"mode": 0,
"inputs": [
{
@@ -5031,7 +4852,7 @@
"name": "sequence",
"type": "ANIMATION_SEQUENCE",
"links": [
5462
5463
],
"shape": 3,
"slot_index": 0
@@ -5047,11 +4868,11 @@
"bgcolor": "#593930"
},
{
"id": 421,
"type": "Video Encoder (mpegCoder) [Dream]",
"id": 422,
"type": "FFMPEG Video Encoder [Dream]",
"pos": [
4778,
559
4781,
562
],
"size": {
"0": 315,
@@ -5064,17 +4885,66 @@
{
"name": "sequence",
"type": "ANIMATION_SEQUENCE",
"link": 5462
"link": 5463
}
],
"outputs": [
{
"name": "log_entry",
"type": "LOG_ENTRY",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "Video Encoder (mpegCoder) [Dream]"
"Node name for S&R": "FFMPEG Video Encoder [Dream]"
},
"widgets_values": [
"video",
1,
true
]
},
{
"id": 236,
"type": "LoadImage",
"pos": [
-2106,
679
],
"size": {
"0": 430,
"1": 340
},
"flags": {},
"order": 18,
"mode": 0,
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
5313
],
"shape": 3,
"slot_index": 0
},
{
"name": "MASK",
"type": "MASK",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"7159726-HSC00002-7 (1).jpg",
"image"
],
"color": "#2a363b",
"bgcolor": "#3f5159"
}
],
"links": [
@@ -6223,10 +6093,10 @@
"IMAGE"
],
[
5462,
5463,
281,
0,
421,
422,
0,
"ANIMATION_SEQUENCE"
]
@@ -6240,7 +6110,8 @@
474,
885
],
"color": "#a1309b"
"color": "#a1309b",
"font_size": 24
},
{
"title": "Settings",
@@ -6250,7 +6121,8 @@
482,
742
],
"color": "#b58b2a"
"color": "#b58b2a",
"font_size": 24
},
{
"title": "Inpainting/Outpainting",
@@ -6260,7 +6132,8 @@
1711,
528
],
"color": "#929054"
"color": "#929054",
"font_size": 24
},
{
"title": "Prev Frame Move",
@@ -6270,7 +6143,8 @@
1450,
456
],
"color": "#3f789e"
"color": "#3f789e",
"font_size": 24
},
{
"title": "Full frame sampler",
@@ -6280,7 +6154,8 @@
691,
700
],
"color": "#88A"
"color": "#88A",
"font_size": 24
},
{
"title": "Output",
@@ -6290,7 +6165,8 @@
1458,
381
],
"color": "#b06634"
"color": "#b06634",
"font_size": 24
},
{
"title": "Animation Driver",
@@ -6300,7 +6176,8 @@
336,
373
],
"color": "#3f789e"
"color": "#3f789e",
"font_size": 24
},
{
"title": "Motion Control",
@@ -6310,7 +6187,8 @@
1451,
392
],
"color": "#ef75ff"
"color": "#ef75ff",
"font_size": 24
},
{
"title": "Model selection",
@@ -6320,7 +6198,8 @@
476,
204
],
"color": "#3f789e"
"color": "#3f789e",
"font_size": 24
},
{
"title": "Noise",
@@ -6330,7 +6209,8 @@
1840,
765
],
"color": "#3f789e"
"color": "#3f789e",
"font_size": 24
},
{
"title": "Previews",
@@ -6340,7 +6220,8 @@
6473,
329
],
"color": "#444"
"color": "#444",
"font_size": 24
}
],
"config": {},
+159 -356
View File
@@ -1,6 +1,6 @@
{
"last_node_id": 192,
"last_link_id": 340,
"last_node_id": 193,
"last_link_id": 341,
"nodes": [
{
"id": 62,
@@ -63,13 +63,7 @@
"type": "FLOAT",
"link": 289,
"widget": {
"name": "weight",
"config": [
"FLOAT",
{
"default": 1
}
]
"name": "weight"
},
"slot_index": 1
}
@@ -118,13 +112,7 @@
"type": "FLOAT",
"link": 286,
"widget": {
"name": "weight",
"config": [
"FLOAT",
{
"default": 1
}
]
"name": "weight"
},
"slot_index": 1
}
@@ -173,13 +161,7 @@
"type": "FLOAT",
"link": 283,
"widget": {
"name": "weight",
"config": [
"FLOAT",
{
"default": 1
}
]
"name": "weight"
},
"slot_index": 1
}
@@ -701,14 +683,7 @@
"type": "FLOAT",
"link": 224,
"widget": {
"name": "r_float",
"config": [
"FLOAT",
{
"default": 0,
"multiline": false
}
]
"name": "r_float"
}
},
{
@@ -716,14 +691,7 @@
"type": "FLOAT",
"link": 223,
"widget": {
"name": "s_float",
"config": [
"FLOAT",
{
"default": 0,
"multiline": false
}
]
"name": "s_float"
}
}
],
@@ -851,14 +819,7 @@
"type": "FLOAT",
"link": 227,
"widget": {
"name": "r_float",
"config": [
"FLOAT",
{
"default": 0,
"multiline": false
}
]
"name": "r_float"
}
},
{
@@ -866,14 +827,7 @@
"type": "FLOAT",
"link": 226,
"widget": {
"name": "s_float",
"config": [
"FLOAT",
{
"default": 0,
"multiline": false
}
]
"name": "s_float"
}
}
],
@@ -968,14 +922,7 @@
"type": "FLOAT",
"link": 230,
"widget": {
"name": "factor",
"config": [
"FLOAT",
{
"default": 1,
"min": 0
}
]
"name": "factor"
}
}
],
@@ -1022,14 +969,7 @@
"type": "FLOAT",
"link": 228,
"widget": {
"name": "factor",
"config": [
"FLOAT",
{
"default": 1,
"min": 0
}
]
"name": "factor"
}
}
],
@@ -1096,7 +1036,7 @@
],
"size": {
"0": 315,
"1": 82
"1": 106
},
"flags": {},
"order": 63,
@@ -1124,7 +1064,8 @@
},
"widgets_values": [
5.237730900441297,
0.16363647460937536
0.16363647460937536,
512
]
},
{
@@ -2616,13 +2557,7 @@
"type": "FLOAT",
"link": 279,
"widget": {
"name": "weight",
"config": [
"FLOAT",
{
"default": 1
}
]
"name": "weight"
},
"slot_index": 1
}
@@ -3561,16 +3496,7 @@
"type": "INT",
"link": 314,
"widget": {
"name": "width",
"config": [
"INT",
{
"default": 512,
"min": 1,
"max": 8192,
"step": 1
}
]
"name": "width"
}
},
{
@@ -3578,16 +3504,7 @@
"type": "INT",
"link": 315,
"widget": {
"name": "height",
"config": [
"INT",
{
"default": 512,
"min": 1,
"max": 8192,
"step": 1
}
]
"name": "height"
}
}
],
@@ -3642,14 +3559,7 @@
"type": "STRING",
"link": 257,
"widget": {
"name": "directory_path",
"config": [
"STRING",
{
"default": "",
"multiline": false
}
]
"name": "directory_path"
},
"slot_index": 2
}
@@ -3663,6 +3573,12 @@
],
"shape": 3,
"slot_index": 0
},
{
"name": "frame_name",
"type": "STRING",
"links": null,
"shape": 3
}
],
"properties": {
@@ -3720,7 +3636,7 @@
],
"size": {
"0": 315,
"1": 58
"1": 82
},
"flags": {},
"order": 103,
@@ -3747,7 +3663,8 @@
"Node name for S&R": "LineArtPreprocessor"
},
"widgets_values": [
"disable"
"disable",
512
]
},
{
@@ -3808,16 +3725,7 @@
"type": "INT",
"link": 136,
"widget": {
"name": "width",
"config": [
"INT",
{
"default": 512,
"min": 1,
"max": 8192,
"step": 1
}
]
"name": "width"
},
"slot_index": 1
},
@@ -3826,16 +3734,7 @@
"type": "INT",
"link": 137,
"widget": {
"name": "height",
"config": [
"INT",
{
"default": 512,
"min": 1,
"max": 8192,
"step": 1
}
]
"name": "height"
}
}
],
@@ -3950,15 +3849,7 @@
"type": "FLOAT",
"link": 280,
"widget": {
"name": "width_seconds",
"config": [
"FLOAT",
{
"default": 1,
"multiline": false,
"min": 0.1
}
]
"name": "width_seconds"
}
}
],
@@ -4014,15 +3905,7 @@
"type": "FLOAT",
"link": 281,
"widget": {
"name": "width_seconds",
"config": [
"FLOAT",
{
"default": 1,
"multiline": false,
"min": 0.1
}
]
"name": "width_seconds"
}
}
],
@@ -4078,15 +3961,7 @@
"type": "FLOAT",
"link": 284,
"widget": {
"name": "width_seconds",
"config": [
"FLOAT",
{
"default": 1,
"multiline": false,
"min": 0.1
}
]
"name": "width_seconds"
}
}
],
@@ -4142,15 +4017,7 @@
"type": "FLOAT",
"link": 287,
"widget": {
"name": "width_seconds",
"config": [
"FLOAT",
{
"default": 1,
"multiline": false,
"min": 0.1
}
]
"name": "width_seconds"
}
}
],
@@ -4348,13 +4215,7 @@
"type": "FLOAT",
"link": 319,
"widget": {
"name": "low_value",
"config": [
"FLOAT",
{
"default": 0
}
]
"name": "low_value"
},
"slot_index": 1
},
@@ -4363,13 +4224,7 @@
"type": "FLOAT",
"link": 320,
"widget": {
"name": "high_value",
"config": [
"FLOAT",
{
"default": 1
}
]
"name": "high_value"
},
"slot_index": 2
}
@@ -4538,16 +4393,7 @@
"type": "FLOAT",
"link": 153,
"widget": {
"name": "denoise",
"config": [
"FLOAT",
{
"default": 1,
"min": 0,
"max": 1,
"step": 0.01
}
]
"name": "denoise"
}
}
],
@@ -4656,14 +4502,7 @@
"type": "STRING",
"link": 119,
"widget": {
"name": "directory_path",
"config": [
"STRING",
{
"default": "",
"multiline": false
}
]
"name": "directory_path"
},
"slot_index": 0
},
@@ -4672,15 +4511,7 @@
"type": "INT",
"link": 154,
"widget": {
"name": "total_frames",
"config": [
"INT",
{
"default": 100,
"min": 2,
"max": 5184000
}
]
"name": "total_frames"
}
}
],
@@ -4772,14 +4603,7 @@
"type": "STRING",
"link": 159,
"widget": {
"name": "directory_path",
"config": [
"STRING",
{
"default": "I:\\AI\\ComfyUI\\ComfyUI\\output",
"multiline": false
}
]
"name": "directory_path"
},
"slot_index": 2
}
@@ -4812,83 +4636,6 @@
"jpg"
]
},
{
"id": 37,
"type": "Image Sequence Tweening [Dream]",
"pos": [
8156.282361863093,
-319.08540210493265
],
"size": {
"0": 315,
"1": 58
},
"flags": {},
"order": 135,
"mode": 0,
"inputs": [
{
"name": "sequence",
"type": "ANIMATION_SEQUENCE",
"link": 267
}
],
"outputs": [
{
"name": "sequence",
"type": "ANIMATION_SEQUENCE",
"links": [
327
],
"shape": 3,
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "Image Sequence Tweening [Dream]"
},
"widgets_values": [
4
]
},
{
"id": 187,
"type": "Video Encoder (mpegCoder) [Dream]",
"pos": [
8513,
-320
],
"size": {
"0": 315,
"1": 106
},
"flags": {},
"order": 136,
"mode": 0,
"inputs": [
{
"name": "sequence",
"type": "ANIMATION_SEQUENCE",
"link": 327
}
],
"outputs": [
{
"name": "log_entry",
"type": "LOG_ENTRY",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "Video Encoder (mpegCoder) [Dream]"
},
"widgets_values": [
"video",
1,
true
]
},
{
"id": 59,
"type": "Reroute",
@@ -5064,13 +4811,7 @@
"type": "STRING",
"link": 94,
"widget": {
"name": "text",
"config": [
"STRING",
{
"multiline": true
}
]
"name": "text"
}
}
],
@@ -5120,13 +4861,7 @@
"type": "STRING",
"link": 95,
"widget": {
"name": "text",
"config": [
"STRING",
{
"multiline": true
}
]
"name": "text"
},
"slot_index": 1
}
@@ -5557,10 +5292,10 @@
1318,
-132
],
"size": [
315,
82
],
"size": {
"0": 315,
"1": 82
},
"flags": {},
"order": 94,
"mode": 0,
@@ -5570,13 +5305,7 @@
"type": "STRING",
"link": 338,
"widget": {
"name": "text",
"config": [
"STRING",
{
"default": ""
}
]
"name": "text"
}
}
],
@@ -5606,10 +5335,10 @@
1240,
7
],
"size": [
315,
82
],
"size": {
"0": 315,
"1": 82
},
"flags": {},
"order": 96,
"mode": 0,
@@ -5619,13 +5348,7 @@
"type": "STRING",
"link": 339,
"widget": {
"name": "text",
"config": [
"STRING",
{
"default": ""
}
]
"name": "text"
}
}
],
@@ -5655,10 +5378,10 @@
1676,
-142
],
"size": [
315,
314
],
"size": {
"0": 315,
"1": 314
},
"flags": {},
"order": 101,
"mode": 0,
@@ -5713,13 +5436,7 @@
"type": "STRING",
"link": 336,
"widget": {
"name": "log_directory",
"config": [
"STRING",
{
"default": "I:\\AI\\ComfyUI\\ComfyUI\\output"
}
]
"name": "log_directory"
}
}
],
@@ -5807,6 +5524,83 @@
"showOutputText": true,
"horizontal": false
}
},
{
"id": 37,
"type": "Image Sequence Tweening [Dream]",
"pos": [
8156.282361863093,
-319.08540210493265
],
"size": {
"0": 315,
"1": 58
},
"flags": {},
"order": 135,
"mode": 0,
"inputs": [
{
"name": "sequence",
"type": "ANIMATION_SEQUENCE",
"link": 267
}
],
"outputs": [
{
"name": "sequence",
"type": "ANIMATION_SEQUENCE",
"links": [
341
],
"shape": 3,
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "Image Sequence Tweening [Dream]"
},
"widgets_values": [
4
]
},
{
"id": 193,
"type": "FFMPEG Video Encoder [Dream]",
"pos": [
8506,
-319
],
"size": {
"0": 315,
"1": 106
},
"flags": {},
"order": 136,
"mode": 0,
"inputs": [
{
"name": "sequence",
"type": "ANIMATION_SEQUENCE",
"link": 341
}
],
"outputs": [
{
"name": "log_entry",
"type": "LOG_ENTRY",
"links": null,
"shape": 3
}
],
"properties": {
"Node name for S&R": "FFMPEG Video Encoder [Dream]"
},
"widgets_values": [
"video",
1,
true
]
}
],
"links": [
@@ -7034,14 +6828,6 @@
0,
"*"
],
[
327,
37,
0,
187,
0,
"ANIMATION_SEQUENCE"
],
[
330,
189,
@@ -7121,6 +6907,14 @@
188,
0,
"FRAME_COUNTER"
],
[
341,
37,
0,
193,
0,
"ANIMATION_SEQUENCE"
]
],
"groups": [
@@ -7132,7 +6926,8 @@
2356,
646
],
"color": "#b58b2a"
"color": "#b58b2a",
"font_size": 24
},
{
"title": "ControlNet",
@@ -7142,7 +6937,8 @@
764,
765
],
"color": "#3f789e"
"color": "#3f789e",
"font_size": 24
},
{
"title": "Previous Frame",
@@ -7152,7 +6948,8 @@
748,
385
],
"color": "#a1309b"
"color": "#a1309b",
"font_size": 24
},
{
"title": "Save",
@@ -7162,7 +6959,8 @@
1434,
353
],
"color": "#3f789e"
"color": "#3f789e",
"font_size": 24
},
{
"title": "Diffusion",
@@ -7172,7 +6970,8 @@
805,
853
],
"color": "#88A"
"color": "#88A",
"font_size": 24
},
{
"title": "Denoise curve",
@@ -7182,7 +6981,8 @@
396,
501
],
"color": "#3f789e"
"color": "#3f789e",
"font_size": 24
},
{
"title": "Align brightness/contrast",
@@ -7192,7 +6992,8 @@
860,
767
],
"color": "#8AA"
"color": "#8AA",
"font_size": 24
},
{
"title": "Upscale",
@@ -7202,7 +7003,8 @@
496,
459
],
"color": "#8A8"
"color": "#8A8",
"font_size": 24
},
{
"title": "Basic Settings",
@@ -7212,7 +7014,8 @@
788,
1706
],
"color": "#88A"
"color": "#88A",
"font_size": 24
}
],
"config": {},
+5 -11
View File
@@ -4,13 +4,11 @@ import math
import numpy
import torch
from PIL import Image, ImageDraw
from PIL.Image import Resampling
from .categories import *
from .shared import ALWAYS_CHANGED_FLAG, convertTensorImageToPIL, DreamImageProcessor, \
from .shared import convertTensorImageToPIL, DreamImageProcessor, \
DreamImage, DreamMask
from .types import SharedTypes, FrameCounter
from .dreamtypes import SharedTypes, FrameCounter
class DreamImageMotion:
NODE_NAME = "Image Motion"
@@ -42,10 +40,6 @@ class DreamImageMotion:
RETURN_NAMES = ("image", "mask1", "mask2", "mask3")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def _mk_PIL_image(self, size, color=None, mode="RGB") -> Image:
im = Image.new(mode=mode, size=size)
if color:
@@ -77,7 +71,7 @@ class DreamImageMotion:
return min(max(i, 1), 32767)
if output_resize_height and output_resize_width:
return lambda img: img.resize((bound(output_resize_width), bound(output_resize_height)), Resampling.NEAREST)
return lambda img: img.resize((bound(output_resize_width), bound(output_resize_height)))
else:
return lambda img: img
@@ -98,12 +92,12 @@ class DreamImageMotion:
noise = other.get("noise", None)
multiplier = math.pow(2, zoom)
resized_image = pil_image.resize((round(pil_image.width * multiplier),
round(pil_image.height * multiplier)), Resampling.BILINEAR)
round(pil_image.height * multiplier)))
if noise is None:
base_image = self._mk_PIL_image(pil_image.size, "black")
else:
base_image = convertTensorImageToPIL(noise).resize(pil_image.size, Resampling.BILINEAR)
base_image = convertTensorImageToPIL(noise).resize(pil_image.size)
selection_offset = (round(x_translation * pil_image.width), round(y_translation * pil_image.height))
selection = ((pil_image.width - resized_image.width) // 2 + selection_offset[0],
-16
View File
@@ -18,10 +18,6 @@ class DreamInputText:
RETURN_NAMES = ("STRING",)
FUNCTION = "noop"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def noop(self, value):
return (value,)
@@ -42,10 +38,6 @@ class DreamInputString:
RETURN_NAMES = ("STRING",)
FUNCTION = "noop"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def noop(self, value):
return (value,)
@@ -67,10 +59,6 @@ class DreamInputFloat:
RETURN_NAMES = ("FLOAT",)
FUNCTION = "noop"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def noop(self, value):
return (value,)
@@ -92,9 +80,5 @@ class DreamInputInt:
RETURN_NAMES = ("INT",)
FUNCTION = "noop"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def noop(self, value):
return (value,)
+7 -3
View File
@@ -1,10 +1,14 @@
# -*- coding: utf-8 -*-
from .shared import DreamConfig
import sys, os
#sys.path.append(str(os.path.dirname(os.path.abspath(__file__))))
#from . import shared
def setup_default_config():
DreamConfig()
#shared.DreamConfig()
pass
def run_install():
setup_default_config()
+2 -6
View File
@@ -5,8 +5,8 @@
import json
from .categories import *
from .shared import ALWAYS_CHANGED_FLAG, DreamStateFile
from .types import *
from .shared import DreamStateFile
from .dreamtypes import *
_laboratory_state = DreamStateFile("laboratory")
@@ -36,10 +36,6 @@ class DreamLaboratory:
RETURN_NAMES = ("FLOAT", "INT", "log_entry")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def _generate(self, seed, last_value, min_value, max_value, mode, step_size):
rnd = random.Random()
rnd.seed(seed)
+151
View File
@@ -0,0 +1,151 @@
from .categories import NodeCategories
from .dreamtypes import RGBPalette
_NOT_A_VALUE_I = 9223372036854775807
_NOT_A_VALUE_F = float(_NOT_A_VALUE_I)
_NOT_A_VALUE_S = "⭆"
def _generate_switch_input(type_nm: str, default_value=None):
d = dict()
for i in range(10):
if default_value is None:
d["input_" + str(i)] = (type_nm, {"lazy": True})
else:
d["input_" + str(i)] = (type_nm, {"default": default_value, "forceInput": True, "lazy": True})
return {
"required": {
"select": ("INT", {"default": 0, "min": 0, "max": 9})
},
"optional": d
}
def _check_big_switch_lazy_status(*args, **kwargs):
n = int(kwargs['select'])
input_name = f"input_{n}"
print(f"SELECTED: {input_name}")
if input_name in kwargs:
return [input_name]
else:
return []
class DreamLazyImageSwitch:
_switch_type = "IMAGE"
NODE_NAME = "Lazy Image Switch"
ICON = "⭆"
CATEGORY = NodeCategories.UTILS_SWITCHES
RETURN_TYPES = (_switch_type,)
RETURN_NAMES = ("selected",)
FUNCTION = "pick"
@classmethod
def INPUT_TYPES(cls):
return _generate_switch_input(cls._switch_type)
def check_lazy_status(self, *args, **kwargs):
return _check_big_switch_lazy_status(*args, **kwargs)
def pick(self, select, **args):
return (args.get("input_"+str(select), None),)
class DreamLazyLatentSwitch:
_switch_type = "LATENT"
NODE_NAME = "Lazy Latent Switch"
ICON = "⭆"
CATEGORY = NodeCategories.UTILS_SWITCHES
RETURN_TYPES = (_switch_type,)
RETURN_NAMES = ("selected",)
FUNCTION = "pick"
@classmethod
def INPUT_TYPES(cls):
return _generate_switch_input(cls._switch_type)
def check_lazy_status(self, *args, **kwargs):
return _check_big_switch_lazy_status(*args, **kwargs)
def pick(self, select, **args):
return (args.get("input_" + str(select), None),)
class DreamLazyTextSwitch:
_switch_type = "STRING"
NODE_NAME = "Lazy Text Switch"
ICON = "⭆"
CATEGORY = NodeCategories.UTILS_SWITCHES
RETURN_TYPES = (_switch_type,)
RETURN_NAMES = ("selected",)
FUNCTION = "pick"
@classmethod
def INPUT_TYPES(cls):
return _generate_switch_input(cls._switch_type, _NOT_A_VALUE_S)
def check_lazy_status(self, *args, **kwargs):
return _check_big_switch_lazy_status(*args, **kwargs)
def pick(self, select, **args):
return (args.get("input_" + str(select), None),)
class DreamLazyPaletteSwitch:
_switch_type = RGBPalette.ID
NODE_NAME = "Lazy Palette Switch"
ICON = "⭆"
CATEGORY = NodeCategories.UTILS_SWITCHES
RETURN_TYPES = (_switch_type,)
RETURN_NAMES = ("selected",)
FUNCTION = "pick"
@classmethod
def INPUT_TYPES(cls):
return _generate_switch_input(cls._switch_type)
def check_lazy_status(self, *args, **kwargs):
return _check_big_switch_lazy_status(*args, **kwargs)
def pick(self, select, **args):
return (args.get("input_" + str(select), None),)
class DreamLazyFloatSwitch:
_switch_type = "FLOAT"
NODE_NAME = "Lazy Float Switch"
ICON = "⭆"
CATEGORY = NodeCategories.UTILS_SWITCHES
RETURN_TYPES = (_switch_type,)
RETURN_NAMES = ("selected",)
FUNCTION = "pick"
@classmethod
def INPUT_TYPES(cls):
return _generate_switch_input(cls._switch_type, _NOT_A_VALUE_F)
def check_lazy_status(self, *args, **kwargs):
return _check_big_switch_lazy_status(*args, **kwargs)
def pick(self, select, **args):
return (args.get("input_" + str(select), None),)
class DreamLazyIntSwitch:
_switch_type = "INT"
NODE_NAME = "Lazy Int Switch"
ICON = "⭆"
CATEGORY = NodeCategories.UTILS_SWITCHES
RETURN_TYPES = (_switch_type,)
RETURN_NAMES = ("selected",)
FUNCTION = "pick"
@classmethod
def INPUT_TYPES(cls):
return _generate_switch_input(cls._switch_type, _NOT_A_VALUE_I)
def check_lazy_status(self, *args, **kwargs):
return _check_big_switch_lazy_status(*args, **kwargs)
def pick(self, select, **args):
return (args.get("input_" + str(select), None),)
+9 -7
View File
@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
from .categories import NodeCategories
from .shared import ALWAYS_CHANGED_FLAG, list_images_in_directory, DreamImage
from .types import SharedTypes, FrameCounter
from .shared import list_images_in_directory, DreamImage
from .dreamtypes import SharedTypes, FrameCounter
import os
class DreamImageSequenceInputWithDefaultFallback:
@@ -22,13 +23,13 @@ class DreamImageSequenceInputWithDefaultFallback:
}
CATEGORY = NodeCategories.IMAGE_ANIMATION
RETURN_TYPES = ("IMAGE",)
RETURN_NAMES = ("image",)
RETURN_TYPES = ("IMAGE","STRING")
RETURN_NAMES = ("image","frame_name")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def IS_CHANGED(cls, *values, **kwargs):
return float("NaN")
def result(self, frame_counter: FrameCounter, directory_path, pattern, indexing, **other):
default_image = other.get("default_image", None)
@@ -37,5 +38,6 @@ class DreamImageSequenceInputWithDefaultFallback:
if not entry:
return (default_image, "")
else:
image_names = [os.path.basename(file_path) for file_path in entry]
images = map(lambda f: DreamImage(file_path=f), entry)
return (DreamImage.join_to_tensor_data(images),)
return (DreamImage.join_to_tensor_data(images), image_names[0])
+1 -1
View File
@@ -44,6 +44,7 @@
"Noise from Palette [Dream]": "Generates noise based on the colors in a palette",
"Palette Color Align [Dream]": "Shifts the colors of one palette towards another target palette",
"Palette Color Shift [Dream]": "Multiplies the color values in a palette",
"Random Prompt Words [Dream]": "Picks random words from input",
"Sample Image Area as Palette [Dream]": "Samples a palette from an image based on pre-defined areas",
"Sample Image as Palette [Dream]": "Randomly samples pixel values to build a palette from an image",
"Saw Curve [Dream]": "Saw wave curve",
@@ -55,6 +56,5 @@
"Text Input [Dream]": "Multiline string input (until primitive routing issues are solved)",
"Triangle Curve [Dream]": "Triangle wave curve",
"Triangle Event Curve [Dream]": "Single event/peak curve with triangular shape",
"Video Encoder (mpegCoder) [Dream]": "Post processing for animation sequences using mpegCoder module to generate video file",
"WAV Curve [Dream]": "WAV audio file as a curve"
}
+1 -9
View File
@@ -3,7 +3,7 @@ import math
from .categories import NodeCategories
from .shared import *
from .types import *
from .dreamtypes import *
def _generate_noise(image: DreamImage, color_function, rng: random.Random, block_size, blur_amount,
@@ -44,10 +44,6 @@ class DreamNoiseFromPalette:
RETURN_NAMES = ("image",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def result(self, palette: Tuple[RGBPalette], width, height, seed, blur_amount, density):
outputs = list()
rng = random.Random()
@@ -95,10 +91,6 @@ class DreamNoiseFromAreaPalettes:
RETURN_NAMES = ("image",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def _area_coordinates(self, width, height):
dx = width / 6
dy = height / 6
+3 -7
View File
@@ -6,9 +6,9 @@ import folder_paths as comfy_paths
from PIL.PngImagePlugin import PngInfo
from .categories import NodeCategories
from .shared import hashed_as_strings, DreamImageProcessor, DreamImage, \
from .shared import DreamImageProcessor, DreamImage, \
list_images_in_directory, DreamConfig
from .types import SharedTypes, FrameCounter, AnimationSequence, LogEntry
from .dreamtypes import SharedTypes, FrameCounter, AnimationSequence, LogEntry
CONFIG = DreamConfig()
@@ -57,10 +57,6 @@ class DreamImageSequenceOutput:
RETURN_NAMES = ("sequence", "log_entry")
FUNCTION = "save"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def _get_new_filename(self, current_frame, prefix, digits, filetype):
return prefix + "_" + str(current_frame).zfill(digits) + "." + filetype.split(" ")[0]
@@ -105,7 +101,7 @@ class DreamImageSequenceOutput:
args["logger"] = logger
proc = DreamImageProcessor(image, **args)
proc.process(self._save_single_image)
frame_counter: FrameCounter = args["frame_counter"]
frame_counter = args["frame_counter"]
log_entry = LogEntry([])
for text in log_texts:
log_entry = log_entry.add(text)
+40 -9
View File
@@ -1,6 +1,44 @@
from .categories import NodeCategories
from .shared import hashed_as_strings
from .types import PartialPrompt
from .dreamtypes import PartialPrompt
import random
class DreamRandomPromptWords:
NODE_NAME = "Random Prompt Words"
ICON = "⚅"
@classmethod
def INPUT_TYPES(cls):
return {
"optional": {
"partial_prompt": (PartialPrompt.ID,)
},
"required": {
"words": ("STRING", {"default": "", "multiline": True}),
"separator": ("STRING", {"default": ",", "multiline": False}),
"samples": ("INT", {"default": 1, "min": 1, "max": 100}),
"min_weight": ("FLOAT", {"default": 1.0, "min": -10, "max": 10}),
"max_weight": ("FLOAT", {"default": 1.0, "min": -10, "max": 10}),
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
},
}
CATEGORY = NodeCategories.CONDITIONING
RETURN_TYPES = (PartialPrompt.ID,)
RETURN_NAMES = ("partial_prompt",)
FUNCTION = "result"
def result(self, words: str, separator, samples, min_weight, max_weight, seed, **args):
p = args.get("partial_prompt", PartialPrompt())
rnd = random.Random()
rnd.seed(seed)
words = list(set(map(lambda s: s.strip(), filter(lambda s: s.strip() != "", words.split(separator)))))
samples = min(samples, len(words))
for i in range(samples):
picked_word = words[rnd.randint(0, len(words)-1)]
words = list(filter(lambda s: s!=picked_word, words))
weight = rnd.uniform(min_weight, max_weight)
p = p.add(picked_word, weight)
return (p,)
class DreamWeightedPromptBuilder:
@@ -24,10 +62,6 @@ class DreamWeightedPromptBuilder:
RETURN_NAMES = ("partial_prompt",)
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def result(self, added_prompt, weight, **args):
input = args.get("partial_prompt", PartialPrompt())
p = input.add(added_prompt, weight)
@@ -54,9 +88,6 @@ class DreamPromptFinalizer:
RETURN_NAMES = ("positive", "negative")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def result(self, partial_prompt: PartialPrompt, adjustment, adjustment_reference, clamp):
if adjustment == "raw" or partial_prompt.is_empty():
+15
View File
@@ -0,0 +1,15 @@
[project]
name = "comfyui-dream-project"
description = "This extension offers various nodes that are useful for Deforum-like animations in ComfyUI."
version = "5.1.2"
license = { text = "MIT License" }
dependencies = ["imageio", "pilgram", "scipy", "numpy<2.0,>=1.18", "torchvision", "evalidate"]
[project.urls]
Repository = "https://github.com/alt-key-project/comfyui-dream-project"
# Used by Comfy Registry https://comfyregistry.org
[tool.comfy]
PublisherId = "altkeyproject"
DisplayName = "comfyui-dream-project"
Icon = ""
+18 -3
View File
@@ -7,6 +7,17 @@ and useful to many ComfyUI users.
I have demonstrated the use of these custom nodes in this [youtube video](https://youtu.be/pZ6Li3qF-Kk).
# Notice!
This custom node pack is currently not being updated. Stable Diffusion video generation is moving towards a different
workflow with AnimateDiff and Stable Video Diffusion. I decided to not try to update this node pack, but I am instead
creating a separate custom node pack here:
[github](https://github.com/alt-key-project/comfyui-dream-video-batches)
This new node pack will be getting my attention from now on (at least as long as stable diffusion video generation is done mostly
in batches).
## Installation
### Simple option
@@ -163,9 +174,6 @@ Utility for calculating good width/height based on common video dimensions.
### Video Encoder (FFMPEG) [Dream]
Post processing for animation sequences calling FFMPEG to generate video files.
### Video Encoder (mpegCoder) [Dream]
Post processing for animation sequences using the python module mpegCoder with ffmpeg library to generate video files.
### File Count [Dream]
Finds the number of files in a directory matching specified patterns.
@@ -218,6 +226,10 @@ Post processing for animation sequences generating blended in-between frames.
### Laboratory [Dream]
Super-charged number generator for experimenting with ComfyUI.
### Lazy *** Switch [Dream]
Switch nodes for different type for up to ten inputs. The lazy version only evaluates the
selected input, but first/next of the big switch is unsupported.
### Log Entry Joiner [Dream]
Merges multiple log entries (reduces noodling).
@@ -261,6 +273,9 @@ Single event/peak curve with a slight bell-shape.
### String Tokenizer [Dream]
Splits a text into tokens by a separator and returns one of the tokens based on a given index.
### Random Prompt Words [Dream]
Randomly picks words/tokens/phrases from an input text.
### Triangle Curve [Dream]
Triangle wave curve.
+1 -2
View File
@@ -1,7 +1,6 @@
imageio
pilgram
scipy
numpy<1.24>=1.18
numpy<2.0,>=1.18
torchvision
mpegCoder
evalidate
+64 -63
View File
@@ -9,8 +9,9 @@ from PIL import Image as PilImage
from .categories import NodeCategories
from .err import on_error
from .shared import DreamConfig, MpegEncoderUtility
from .types import *
from .shared import DreamConfig
#from .shared import MpegEncoderUtility
from .dreamtypes import *
CONFIG = DreamConfig()
@@ -131,67 +132,67 @@ def _make_video_filename(name, file_ext):
(b, _) = os.path.splitext(name)
return b + "." + file_ext.strip(".")
class DreamVideoEncoderMpegCoder:
NODE_NAME = "Video Encoder (mpegCoder)"
ICON = "🎬"
CATEGORY = NodeCategories.ANIMATION_POSTPROCESSING
RETURN_TYPES = (LogEntry.ID,)
RETURN_NAMES = ("log_entry",)
OUTPUT_NODE = True
FUNCTION = "encode"
@classmethod
def INPUT_TYPES(cls):
return {
"required": SharedTypes.sequence | {
"name": ("STRING", {"default": 'video', "multiline": False}),
"framerate_factor": ("FLOAT", {"default": 1.0, "min": 0.01, "max": 100.0}),
"remove_images": ("BOOLEAN", {"default": True})
},
}
def _find_free_filename(self, filename, defaultdir):
if os.path.basename(filename) == filename:
filename = os.path.join(defaultdir, filename)
n = 1
tested = filename
while os.path.exists(tested):
n += 1
(b, ext) = os.path.splitext(filename)
tested = b + "_" + str(n) + ext
return tested
def encode(self, sequence, name, framerate_factor, remove_images):
if not sequence.is_defined:
return (LogEntry([]),)
config = DreamConfig()
filename = _make_video_filename(name, config.get("mpeg_coder.file_extension", "mp4"))
log_entry = LogEntry([])
for batch_num in sequence.batches:
try:
images = list(sequence.get_image_files_of_batch(batch_num))
filename = self._find_free_filename(filename, os.path.dirname(images[0]))
first_image = DreamImage.from_file(images[0])
enc = MpegEncoderUtility(video_path=filename,
bit_rate_factor=float(config.get("mpeg_coder.bitrate_factor", 1.0)),
encoding_threads=int(config.get("mpeg_coder.encoding_threads", 4)),
max_b_frame=int(config.get("mpeg_coder.max_b_frame", 2)),
width=first_image.width,
height=first_image.height,
files=images,
fps=sequence.fps * framerate_factor,
codec_name=config.get("mpeg_coder.codec_name", "libx265"))
enc.encode()
log_entry = log_entry.add("Generated video '{}'".format(filename))
if remove_images:
for imagepath in images:
if os.path.isfile(imagepath):
os.unlink(imagepath)
except Exception as e:
on_error(self.__class__, str(e))
return (log_entry,)
#
# class DreamVideoEncoderMpegCoder:
# NODE_NAME = "Video Encoder (mpegCoder)"
# ICON = "🎬"
# CATEGORY = NodeCategories.ANIMATION_POSTPROCESSING
# RETURN_TYPES = (LogEntry.ID,)
# RETURN_NAMES = ("log_entry",)
# OUTPUT_NODE = True
# FUNCTION = "encode"
#
# @classmethod
# def INPUT_TYPES(cls):
# return {
# "required": SharedTypes.sequence | {
# "name": ("STRING", {"default": 'video', "multiline": False}),
# "framerate_factor": ("FLOAT", {"default": 1.0, "min": 0.01, "max": 100.0}),
# "remove_images": ("BOOLEAN", {"default": True})
# },
# }
#
# def _find_free_filename(self, filename, defaultdir):
# if os.path.basename(filename) == filename:
# filename = os.path.join(defaultdir, filename)
# n = 1
# tested = filename
# while os.path.exists(tested):
# n += 1
# (b, ext) = os.path.splitext(filename)
# tested = b + "_" + str(n) + ext
# return tested
#
# def encode(self, sequence, name, framerate_factor, remove_images):
# if not sequence.is_defined:
# return (LogEntry([]),)
# config = DreamConfig()
# filename = _make_video_filename(name, config.get("mpeg_coder.file_extension", "mp4"))
# log_entry = LogEntry([])
# for batch_num in sequence.batches:
# try:
# images = list(sequence.get_image_files_of_batch(batch_num))
# filename = self._find_free_filename(filename, os.path.dirname(images[0]))
# first_image = DreamImage.from_file(images[0])
# enc = MpegEncoderUtility(video_path=filename,
# bit_rate_factor=float(config.get("mpeg_coder.bitrate_factor", 1.0)),
# encoding_threads=int(config.get("mpeg_coder.encoding_threads", 4)),
# max_b_frame=int(config.get("mpeg_coder.max_b_frame", 2)),
# width=first_image.width,
# height=first_image.height,
# files=images,
# fps=sequence.fps * framerate_factor,
# codec_name=config.get("mpeg_coder.codec_name", "libx265"))
# enc.encode()
# log_entry = log_entry.add("Generated video '{}'".format(filename))
# if remove_images:
# for imagepath in images:
# if os.path.isfile(imagepath):
# os.unlink(imagepath)
# except Exception as e:
# on_error(self.__class__, str(e))
# return (log_entry,)
#
class DreamVideoEncoder:
NODE_NAME = "FFMPEG Video Encoder"
+30 -57
View File
@@ -4,10 +4,10 @@ import hashlib
import json
import os
import random
import time
import folder_paths as comfy_paths
import tempfile
import glob
from io import BytesIO
import numpy
import torch
from PIL import Image, ImageFilter, ImageEnhance
@@ -18,10 +18,11 @@ from typing import Dict, Tuple, List
from .dreamlogger import DreamLog
from .embedded_config import EMBEDDED_CONFIGURATION
tmpDir = tempfile.TemporaryDirectory("Dream_Anim")
NODE_FILE = os.path.abspath(__file__)
DREAM_NODES_SOURCE_ROOT = os.path.dirname(NODE_FILE)
TEMP_PATH = os.path.join(os.path.abspath(comfy_paths.temp_directory), "Dream_Anim")
ALWAYS_CHANGED_FLAG = float("NaN")
TEMP_PATH = os.path.join(os.path.abspath(tempfile.gettempdir()), "Dream_Anim")
def convertTensorImageToPIL(tensor_image) -> Image:
@@ -274,7 +275,7 @@ def list_images_in_directory(directory_path: str, pattern: str, alphabetic_index
def _num_from_filename(fn):
(text, _) = os.path.splitext(fn)
token: str = text.split("_")[-1]
token = text.split("_")[-1]
if token.isdigit():
return int(token)
else:
@@ -338,7 +339,7 @@ class DreamStateFile:
if not os.path.isdir(self._dirname):
os.makedirs(self._dirname)
if not os.path.isfile(self._filepath):
self._data: dict = {}
self._data = {}
else:
with open(self._filepath, encoding="utf-8") as f:
self._data = json.load(f)
@@ -361,58 +362,30 @@ class DreamStateFile:
return previous
def hashed_as_strings(*items):
def hash_tensor_data(image, hasher = None):
m = hashlib.sha256() if hasher is None else hasher
if isinstance(image, torch.Tensor):
buff = BytesIO()
torch.save(image, buff)
print("HASHING TENSOR")
m.update(buff.getvalue())
elif isinstance(image, bytes) or isinstance(image, bytearray):
print("HASHING BYTES")
m.update(image)
elif isinstance(image, list) or isinstance(image, tuple):
print("HASHING ITERABLE")
for item in image:
hash_tensor_data(item, m)
else:
print("HASING_AS_TEXT - "+str(type(image)))
m.update(str(image).encode(encoding="utf-8"))
return m.digest().hex()
def hashed_as_strings(*items, **kwargs):
tokens = "|".join(list(map(str, items)))
m = hashlib.sha256()
m.update(tokens.encode(encoding="utf-8"))
for pair in kwargs.items():
m.update(str(pair).encode(encoding="utf-8"))
return m.digest().hex()
class MpegEncoderUtility:
def __init__(self, video_path: str, bit_rate_factor: float, width: int, height: int, files: List[str],
fps: float, encoding_threads: int, codec_name, max_b_frame):
import mpegCoder
self._files = files
self._logger = get_logger()
self._enc = mpegCoder.MpegEncoder()
bit_rate = self._calculate_bit_rate(width, height, fps, bit_rate_factor)
self._logger.info("Bitrate " + str(bit_rate))
self._enc.setParameter(
videoPath=video_path, codecName=codec_name,
nthread=encoding_threads, bitRate=bit_rate, width=width, height=height, widthSrc=width,
heightSrc=height,
GOPSize=len(files), maxBframe=max_b_frame, frameRate=self._fps_to_tuple(fps))
def _calculate_bit_rate(self, width: int, height: int, fps: float, bit_rate_factor: float):
bits_per_pixel_base = 0.5
return round(max(10, float(width * height * fps * bits_per_pixel_base * bit_rate_factor * 0.001)))
def encode(self):
if not self._enc.FFmpegSetup():
raise Exception("Failed to setup MPEG Encoder - check parameters!")
try:
t = time.time()
for filepath in self._files:
self._logger.debug("Encoding frame {}", filepath)
image = DreamImage.from_file(filepath).convert("RGB")
self._enc.EncodeFrame(image.numpy_array())
self._enc.FFmpegClose()
self._logger.info("Completed video encoding of {n} frames in {t} seconds", n=len(self._files),
t=round(time.time() - t))
finally:
self._enc.clear()
def _fps_to_tuple(self, fps: float):
def _is_almost_int(f: float):
return abs(f - int(f)) < 0.001
a = fps
b = 1
while not _is_almost_int(a) and b < 100:
a /= 10
b *= 10
a = round(a)
b = round(b)
self._logger.info("Video specified as {fps} fps - encoder framerate {a}/{b}", fps=fps, a=a, b=b)
return (a, b)
+27 -49
View File
@@ -1,30 +1,40 @@
from .categories import NodeCategories
from .dreamtypes import RGBPalette
from .err import *
from .shared import ALWAYS_CHANGED_FLAG, hashed_as_strings
from .types import RGBPalette
from .shared import hashed_as_strings, hash_tensor_data
_NOT_A_VALUE_I = 9223372036854775807
_NOT_A_VALUE_F = float(_NOT_A_VALUE_I)
_NOT_A_VALUE_S = "⭆"
def _generate_switch_input(type: str):
def _generate_switch_input(type_nm: str, default_value=None):
d = dict()
for i in range(10):
d["input_" + str(i)] = (type,)
if default_value is None:
d["input_" + str(i)] = (type_nm,)
else:
d["input_" + str(i)] = (type_nm, {"default": default_value, "forceInput": True})
return {
"required": {
"select": ("INT", {"defualt": 0, "min": 0, "max": 9}),
"select": ("INT", {"default": 0, "min": 0, "max": 9}),
"on_missing": (["previous", "next"],)
},
"optional": d
}
def _do_pick(cls, select, on_missing, **args):
def _do_pick(cls, select, test_val, on_missing, **args):
direction = 1
if on_missing == "previous":
direction = -1
if len(args) == 0:
on_error(cls, "No inputs provided!")
while args.get("input_" + str(select), None) is None:
n = len(args)
while not test_val(args.get("input_" + str(select), None)):
if n<0:
return (None,)
select = (select + direction) % 10
n = n - 1
return args["input_" + str(select)],
@@ -41,12 +51,8 @@ class DreamBigImageSwitch:
def INPUT_TYPES(cls):
return _generate_switch_input(cls._switch_type)
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def pick(self, select, on_missing, **args):
return _do_pick(self.__class__, select, on_missing, **args)
return _do_pick(self.__class__, select, lambda n: n is not None, on_missing, **args)
class DreamBigLatentSwitch:
@@ -62,12 +68,8 @@ class DreamBigLatentSwitch:
def INPUT_TYPES(cls):
return _generate_switch_input(cls._switch_type)
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def pick(self, select, on_missing, **args):
return _do_pick(self.__class__, select, on_missing, **args)
return _do_pick(self.__class__, select, lambda n: n is not None, on_missing, **args)
class DreamBigTextSwitch:
@@ -81,14 +83,10 @@ class DreamBigTextSwitch:
@classmethod
def INPUT_TYPES(cls):
return _generate_switch_input(cls._switch_type)
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(values)
return _generate_switch_input(cls._switch_type, _NOT_A_VALUE_S)
def pick(self, select, on_missing, **args):
return _do_pick(self.__class__, select, on_missing, **args)
return _do_pick(self.__class__, select, lambda n: (n is not None) and (n != _NOT_A_VALUE_S), on_missing, **args)
class DreamBigPaletteSwitch:
@@ -104,12 +102,8 @@ class DreamBigPaletteSwitch:
def INPUT_TYPES(cls):
return _generate_switch_input(cls._switch_type)
@classmethod
def IS_CHANGED(cls, *values):
return ALWAYS_CHANGED_FLAG
def pick(self, select, on_missing, **args):
return _do_pick(self.__class__, select, on_missing, **args)
return _do_pick(self.__class__, select, lambda n: (n is not None), on_missing, **args)
class DreamBigFloatSwitch:
@@ -123,14 +117,10 @@ class DreamBigFloatSwitch:
@classmethod
def INPUT_TYPES(cls):
return _generate_switch_input(cls._switch_type)
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(values)
return _generate_switch_input(cls._switch_type, _NOT_A_VALUE_F)
def pick(self, select, on_missing, **args):
return _do_pick(self.__class__, select, on_missing, **args)
return _do_pick(self.__class__, select, lambda n: (n is not None) and (n != _NOT_A_VALUE_F), on_missing, **args)
class DreamBigIntSwitch:
@@ -144,14 +134,10 @@ class DreamBigIntSwitch:
@classmethod
def INPUT_TYPES(cls):
return _generate_switch_input(cls._switch_type)
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(values)
return _generate_switch_input(cls._switch_type, _NOT_A_VALUE_I)
def pick(self, select, on_missing, **args):
return _do_pick(self.__class__, select, on_missing, **args)
return _do_pick(self.__class__, select, lambda n: (n is not None) and (n != _NOT_A_VALUE_I), on_missing, **args)
class DreamBoolToFloat:
@@ -172,10 +158,6 @@ class DreamBoolToFloat:
}
}
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(values)
def pick(self, boolean, on_true, on_false):
if boolean:
return (on_true,)
@@ -201,10 +183,6 @@ class DreamBoolToInt:
}
}
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(values)
def pick(self, boolean, on_true, on_false):
if boolean:
return (on_true,)
+1 -5
View File
@@ -7,7 +7,7 @@ import folder_paths as comfy_paths
from .categories import NodeCategories
from .shared import hashed_as_strings, DreamStateFile
from .types import LogEntry, SharedTypes, FrameCounter
from .dreamtypes import LogEntry, SharedTypes, FrameCounter
_logfile_state = DreamStateFile("logging")
@@ -250,10 +250,6 @@ class DreamFrameDimensions:
RETURN_NAMES = ("width", "height", "final_width", "final_height")
FUNCTION = "result"
@classmethod
def IS_CHANGED(cls, *values):
return hashed_as_strings(*values)
def result(self, size, aspect_ratio, orientation, divisor, alignment, alignment_type):
ratio = tuple(map(int, aspect_ratio.split(":")))
final_width = int(size)