Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d783188eeb | ||
|
|
822248eb37 | ||
|
|
07dd99197e | ||
|
|
a53576c98b | ||
|
|
04c8f37f73 | ||
|
|
0a7f4cea0c | ||
|
|
df5efb5b95 | ||
|
|
89dc09b04d | ||
|
|
4cc646b343 | ||
|
|
0264bf9ab5 | ||
|
|
53cf9a8267 | ||
|
|
e6edbc0f97 | ||
|
|
b9ec910206 | ||
|
|
577be739fb | ||
|
|
2c24934900 | ||
|
|
7fb8e6b73c | ||
|
|
4f64a66ba3 |
@@ -4,7 +4,7 @@
|
||||
</p>
|
||||
|
||||
|
||||
This is a custom node for ComfyUI that allows you to use the Luma AI API directly in ComfyUI. Luma AI API is based on top of [Dream Machine](https://lumalabs.ai/dream-machine/api), which is a video generation model developed by Luma. For more information, see [Luma AI API Documentation](https://docs.lumalabs.ai/docs/api).
|
||||
This is a custom node for ComfyUI that allows you to use the Luma AI API directly in ComfyUI. Luma AI API is based on top of [Dream Machine](https://lumalabs.ai/dream-machine/api), which is a complete suite of models for image and video generation. For more information, see [Luma AI API Documentation](https://docs.lumalabs.ai/docs/api).
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -22,7 +22,10 @@ Before using this node, you need to have an LumaAI API key. Get one [here](https
|
||||
```
|
||||
The path should be `ComfyUI/custom_nodes/ComfyUI-LumaAI-API/*`, where `*` represents all the files in this repo.
|
||||
|
||||
3. Run `cd ComfyUI-LumaAI-API && pip install -r requirements.txt` to install the dependencies.
|
||||
3. Install the dependencies:
|
||||
|
||||
- If you are using Windows (ComfyUI portable) run: `.\python_embeded\python.exe -m pip install -r ComfyUI\custom_nodes\ComfyUI-LumaAI-API\requirements.txt`
|
||||
- If you are using Linux or MacOS, run: `cd ComfyUI-LumaAI-API && pip install -r requirements.txt` to install the dependencies.
|
||||
|
||||
4. If you don't want to expose your Luma API key, you can add it to the `config.ini` file and keep it empty in the node.
|
||||
|
||||
@@ -40,25 +43,37 @@ Before using this node, you need to have an LumaAI API key. Get one [here](https
|
||||
|
||||
Most of the nodes allow you to save locally the output video. If you keep the default `filename` (empty string), the video will be saved in the `outputs` folder using the `generation_id` as the name.
|
||||
|
||||
For images, the node will always save the image locally, but you can set the `filename` to save it with a custom name.
|
||||
|
||||
**Notes: Duration and resolution parameters are only supported for Ray 2 and Ray 2 Flash models.**
|
||||
|
||||
### LumaAIClient
|
||||
|
||||
This node is used to create a LumaAI client.
|
||||
|
||||
### LumaText2Video
|
||||
|
||||
This node is used to generate a video from a text prompt.
|
||||
This node is used to generate a video from a text prompt. You can now choose between different models and resolutions.
|
||||
|
||||
### LumaImage2Video
|
||||
|
||||
This node is used to generate a video from an image. The image can be used as the first or last frame.
|
||||
This node is used to generate a video from an image. The image can be used as the first or last frame. You can now choose between different models and resolutions.
|
||||
|
||||
### LumaInterpolateGenerations
|
||||
|
||||
This node is used to interpolate between two generations.
|
||||
This node is used to interpolate between two generations. You can now choose between different models and resolutions.
|
||||
|
||||
### LumaExtendGeneration
|
||||
|
||||
This node is used to extend a generation. You can choose to extend before or after the generation.
|
||||
This node is used to extend a generation. You can choose to extend before or after the generation. You can now choose between different models and resolutions.
|
||||
|
||||
### LumaUpscaleGeneration
|
||||
|
||||
This node is used to upscale a generation.
|
||||
|
||||
### LumaAddAudio2Video
|
||||
|
||||
This node is used to add audio to a video. When using this node with `Preview Video` node, you will notice that the audio won't play in comfy. For that, right click on the video and select `Open Image`, which will open the video in a new tab and you will be able to hear the audio.
|
||||
|
||||
### LumaPreviewVideo
|
||||
|
||||
@@ -69,6 +84,26 @@ This node is used to preview a video. The video is resized to 768px to look bett
|
||||
This node is used to upload an image to ImgBB and return the URL. We need this because Luma API currently only supports image urls as input.
|
||||
To use this node, you need to have an ImgBB API key. Create an account and get one [here](https://api.imgbb.com/).
|
||||
|
||||
### Reference
|
||||
|
||||
This node is used to create a reference from an image URL. It is used for style and image references.
|
||||
|
||||
### ConcatReferences
|
||||
|
||||
This node is used to concatenate a list of references.
|
||||
|
||||
### CharacterReference
|
||||
|
||||
This node is used to create a character reference from a list of image URLs.
|
||||
|
||||
### ImageGeneration
|
||||
|
||||
This node is used to generate an image from a prompt.
|
||||
|
||||
### ModifyImage
|
||||
|
||||
This node is used to modify an image.
|
||||
|
||||
## Examples
|
||||
|
||||
For examples, see [workflows folder](./workflows). To use, just download the workflow json and import it into ComfyUI.
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
from .py.nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
|
||||
from .py.luma_nodes import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
|
||||
|
||||
WEB_DIRECTORY = "./web"
|
||||
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ class ImgBBUpload:
|
||||
result = response.json()
|
||||
|
||||
if result.get("success"):
|
||||
return result["data"]["url"], result["data"]["delete_url"]
|
||||
return (result["data"]["url"],)
|
||||
else:
|
||||
error_message = result.get("error", {}).get("message", "Unknown error")
|
||||
raise ValueError(f"Error: {error_message}")
|
||||
|
||||
@@ -5,6 +5,13 @@ from .lumaai_api_node import (
|
||||
InterpolateGenerations,
|
||||
ExtendGeneration,
|
||||
PreviewVideo,
|
||||
Reference,
|
||||
ConcatReferences,
|
||||
CharacterReference,
|
||||
ImageGeneration,
|
||||
ModifyImage,
|
||||
AddAudio2Video,
|
||||
UpscaleGeneration,
|
||||
)
|
||||
from .imgbb_node import ImgBBUpload
|
||||
|
||||
@@ -16,6 +23,13 @@ NODE_CLASS_MAPPINGS = {
|
||||
"LumaInterpolateGenerations": InterpolateGenerations,
|
||||
"LumaExtendGeneration": ExtendGeneration,
|
||||
"LumaPreviewVideo": PreviewVideo,
|
||||
"Reference": Reference,
|
||||
"ConcatReferences": ConcatReferences,
|
||||
"CharacterReference": CharacterReference,
|
||||
"LumaImageGeneration": ImageGeneration,
|
||||
"LumaModifyImage": ModifyImage,
|
||||
"LumaAddAudio2Video": AddAudio2Video,
|
||||
"LumaUpscaleGeneration": UpscaleGeneration,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
@@ -26,4 +40,11 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"LumaInterpolateGenerations": "Interpolate Generations",
|
||||
"LumaExtendGeneration": "Extend Generation",
|
||||
"LumaPreviewVideo": "LumaAI Preview Video",
|
||||
"LumaReference": "Reference",
|
||||
"LumaConcatReferences": "Concat References",
|
||||
"LumaCharacterReference": "Character Reference",
|
||||
"LumaImageGeneration": "Image Generation",
|
||||
"LumaModifyImage": "Modify Image",
|
||||
"LumaAddAudio2Video": "Add Audio to Video",
|
||||
"LumaUpscaleGeneration": "Upscale Generation",
|
||||
}
|
||||
+447
-74
@@ -5,6 +5,7 @@ import time
|
||||
from lumaai import LumaAI
|
||||
|
||||
import folder_paths
|
||||
import nodes
|
||||
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
parent_dir = os.path.dirname(current_dir)
|
||||
@@ -14,7 +15,7 @@ config = configparser.ConfigParser()
|
||||
config.read(config_path)
|
||||
|
||||
try:
|
||||
luma_api_key = config['API']['LUMAAI_API_KEY']
|
||||
luma_api_key = config["API"]["LUMAAI_API_KEY"]
|
||||
if luma_api_key != "":
|
||||
os.environ["LUMAAI_API_KEY"] = luma_api_key
|
||||
else:
|
||||
@@ -29,6 +30,7 @@ def download_file(url, file_name):
|
||||
file.write(response.content)
|
||||
print(f"File downloaded as {file_name}")
|
||||
|
||||
|
||||
def parse_filename(filename):
|
||||
# Remove file extension if present
|
||||
filename = os.path.splitext(filename)[0]
|
||||
@@ -51,6 +53,27 @@ def parse_filename(filename):
|
||||
return directory, filename
|
||||
|
||||
|
||||
def wait_for_generation(client, generation_id, save, filename, output_dir):
|
||||
completed = False
|
||||
while not completed:
|
||||
generation = client.generations.get(id=generation_id)
|
||||
if generation.state == "completed":
|
||||
completed = True
|
||||
elif generation.state == "failed":
|
||||
raise ValueError(f"Generation failed: {generation.failure_reason}")
|
||||
time.sleep(3)
|
||||
|
||||
video_url = generation.assets.video
|
||||
if save:
|
||||
directory, filename = parse_filename(filename)
|
||||
if filename == "":
|
||||
filename = generation_id
|
||||
download_file(
|
||||
video_url, os.path.join(output_dir, directory, filename + ".mp4")
|
||||
)
|
||||
return video_url
|
||||
|
||||
|
||||
class LumaAIClient:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
@@ -85,19 +108,25 @@ class LumaAIClient:
|
||||
|
||||
return (client,)
|
||||
|
||||
|
||||
class Text2Video:
|
||||
def __init__(self):
|
||||
self.output_dir = folder_paths.get_output_directory()
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, *args, **kwargs):
|
||||
return float("NaN")
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"client": ("LUMACLIENT", {"forceInput": True}),
|
||||
"model": (["ray-flash-2", "ray-2", "ray-1.6"],),
|
||||
"prompt": ("STRING", {"multiline": True, "default": ""}),
|
||||
"duration": (["5s", "9s"],),
|
||||
"loop": ("BOOLEAN", {"default": False}),
|
||||
"aspect_ratio": (["9:16", "3:4", "1:1", "4:3", "16:9", "21:9"],),
|
||||
"resolution": (["540p", "720p"],),
|
||||
"save": ("BOOLEAN", {"default": True}),
|
||||
},
|
||||
"optional": {"filename": ("STRING", {"default": ""})},
|
||||
@@ -107,9 +136,9 @@ class Text2Video:
|
||||
RETURN_NAMES = ("video_url", "generation_id")
|
||||
OUTPUT_NODE = True
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "LumaAI"
|
||||
CATEGORY = "LumaAI/Ray"
|
||||
|
||||
def run(self, client, prompt, loop, aspect_ratio, save, filename):
|
||||
def run(self, client, model, prompt, duration, loop, aspect_ratio, resolution, save, filename):
|
||||
"""
|
||||
Generate a video from a text prompt.
|
||||
"""
|
||||
@@ -117,24 +146,15 @@ class Text2Video:
|
||||
raise ValueError("Prompt is required")
|
||||
|
||||
generation = client.generations.create(
|
||||
prompt=prompt, loop=loop, aspect_ratio=aspect_ratio
|
||||
prompt=prompt,
|
||||
model=model,
|
||||
loop=loop,
|
||||
aspect_ratio=aspect_ratio,
|
||||
duration=duration,
|
||||
resolution=resolution,
|
||||
)
|
||||
generation_id = generation.id
|
||||
completed = False
|
||||
while not completed:
|
||||
generation = client.generations.get(id=generation_id)
|
||||
if generation.state == "completed":
|
||||
completed = True
|
||||
elif generation.state == "failed":
|
||||
raise ValueError(f"Generation failed: {generation.failure_reason}")
|
||||
time.sleep(3)
|
||||
|
||||
video_url = generation.assets.video
|
||||
if save:
|
||||
directory, filename = parse_filename(filename)
|
||||
if filename == "":
|
||||
filename = generation_id
|
||||
download_file(video_url, os.path.join(self.output_dir, directory, filename + ".mp4"))
|
||||
video_url = wait_for_generation(client, generation_id, save, filename, self.output_dir)
|
||||
|
||||
return {
|
||||
"ui": {"text": [generation_id]},
|
||||
@@ -148,6 +168,10 @@ class Text2Video:
|
||||
class Image2Video:
|
||||
def __init__(self):
|
||||
self.output_dir = folder_paths.get_output_directory()
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, *args, **kwargs):
|
||||
return float("NaN")
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
@@ -155,7 +179,10 @@ class Image2Video:
|
||||
"required": {
|
||||
"client": ("LUMACLIENT", {"forceInput": True}),
|
||||
"prompt": ("STRING", {"multiline": True, "default": ""}),
|
||||
"model": (["ray-flash-2", "ray-2", "ray-1.6"],),
|
||||
"duration": (["5s", "9s"],),
|
||||
"loop": ("BOOLEAN", {"default": False}),
|
||||
"resolution": (["540p", "720p"],),
|
||||
"save": ("BOOLEAN", {"default": True}),
|
||||
},
|
||||
"optional": {
|
||||
@@ -168,13 +195,16 @@ class Image2Video:
|
||||
RETURN_TYPES = ("STRING", "STRING")
|
||||
RETURN_NAMES = ("video_url", "generation_id")
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "LumaAI"
|
||||
CATEGORY = "LumaAI/Ray"
|
||||
|
||||
def run(
|
||||
self,
|
||||
client,
|
||||
model,
|
||||
prompt,
|
||||
duration,
|
||||
loop,
|
||||
resolution,
|
||||
save,
|
||||
init_image_url="",
|
||||
final_image_url="",
|
||||
@@ -193,24 +223,15 @@ class Image2Video:
|
||||
keyframes["frame1"] = {"type": "image", "url": final_image_url}
|
||||
|
||||
generation = client.generations.create(
|
||||
prompt=prompt, loop=loop, keyframes=keyframes
|
||||
prompt=prompt,
|
||||
model=model,
|
||||
loop=loop,
|
||||
duration=duration,
|
||||
resolution=resolution,
|
||||
keyframes=keyframes,
|
||||
)
|
||||
generation_id = generation.id
|
||||
completed = False
|
||||
while not completed:
|
||||
generation = client.generations.get(id=generation_id)
|
||||
if generation.state == "completed":
|
||||
completed = True
|
||||
elif generation.state == "failed":
|
||||
raise ValueError(f"Generation failed: {generation.failure_reason}")
|
||||
time.sleep(3)
|
||||
|
||||
video_url = generation.assets.video
|
||||
if save:
|
||||
directory, filename = parse_filename(filename)
|
||||
if filename == "":
|
||||
filename = generation_id
|
||||
download_file(video_url, os.path.join(self.output_dir, directory, filename + ".mp4"))
|
||||
video_url = wait_for_generation(client, generation_id, save, filename, self.output_dir)
|
||||
|
||||
return {
|
||||
"ui": {"text": [generation_id]},
|
||||
@@ -224,6 +245,10 @@ class Image2Video:
|
||||
class InterpolateGenerations:
|
||||
def __init__(self):
|
||||
self.output_dir = folder_paths.get_output_directory()
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, *args, **kwargs):
|
||||
return float("NaN")
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
@@ -231,6 +256,8 @@ class InterpolateGenerations:
|
||||
"required": {
|
||||
"client": ("LUMACLIENT", {"forceInput": True}),
|
||||
"prompt": ("STRING", {"multiline": True, "default": ""}),
|
||||
"model": (["ray-flash-2", "ray-2", "ray-1.6"],),
|
||||
"resolution": (["540p", "720p"],),
|
||||
"save": ("BOOLEAN", {"default": True}),
|
||||
"generation_id_1": ("STRING", {"default": "", "forceInput": True}),
|
||||
"generation_id_2": ("STRING", {"default": "", "forceInput": True}),
|
||||
@@ -241,12 +268,14 @@ class InterpolateGenerations:
|
||||
RETURN_TYPES = ("STRING", "STRING")
|
||||
RETURN_NAMES = ("video_url", "generation_id")
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "LumaAI"
|
||||
CATEGORY = "LumaAI/Ray"
|
||||
|
||||
def run(
|
||||
self,
|
||||
client,
|
||||
model,
|
||||
prompt,
|
||||
resolution,
|
||||
save,
|
||||
generation_id_1,
|
||||
generation_id_2,
|
||||
@@ -264,23 +293,11 @@ class InterpolateGenerations:
|
||||
"frame0": {"type": "generation", "id": generation_id_1},
|
||||
"frame1": {"type": "generation", "id": generation_id_2},
|
||||
},
|
||||
model=model,
|
||||
resolution=resolution,
|
||||
)
|
||||
generation_id = generation.id
|
||||
completed = False
|
||||
while not completed:
|
||||
generation = client.generations.get(id=generation_id)
|
||||
if generation.state == "completed":
|
||||
completed = True
|
||||
elif generation.state == "failed":
|
||||
raise ValueError(f"Generation failed: {generation.failure_reason}")
|
||||
time.sleep(3)
|
||||
|
||||
video_url = generation.assets.video
|
||||
if save:
|
||||
directory, filename = parse_filename(filename)
|
||||
if filename == "":
|
||||
filename = generation_id
|
||||
download_file(video_url, os.path.join(self.output_dir, directory, filename + ".mp4"))
|
||||
video_url = wait_for_generation(client, generation_id, save, filename, self.output_dir)
|
||||
|
||||
return {
|
||||
"ui": {"text": [generation_id]},
|
||||
@@ -294,6 +311,10 @@ class InterpolateGenerations:
|
||||
class ExtendGeneration:
|
||||
def __init__(self):
|
||||
self.output_dir = folder_paths.get_output_directory()
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, *args, **kwargs):
|
||||
return float("NaN")
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
@@ -301,6 +322,9 @@ class ExtendGeneration:
|
||||
"required": {
|
||||
"client": ("LUMACLIENT", {"forceInput": True}),
|
||||
"prompt": ("STRING", {"multiline": True, "default": ""}),
|
||||
"model": (["ray-flash-2", "ray-2", "ray-1.6"],),
|
||||
"loop": ("BOOLEAN", {"default": False}),
|
||||
"resolution": (["540p", "720p"],),
|
||||
"save": ("BOOLEAN", {"default": True}),
|
||||
},
|
||||
"optional": {
|
||||
@@ -315,12 +339,15 @@ class ExtendGeneration:
|
||||
RETURN_TYPES = ("STRING", "STRING")
|
||||
RETURN_NAMES = ("video_url", "generation_id")
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "LumaAI"
|
||||
CATEGORY = "LumaAI/Ray"
|
||||
|
||||
def run(
|
||||
self,
|
||||
client,
|
||||
model,
|
||||
prompt,
|
||||
loop,
|
||||
resolution,
|
||||
save,
|
||||
init_image_url="",
|
||||
final_image_url="",
|
||||
@@ -352,29 +379,121 @@ class ExtendGeneration:
|
||||
if final_generation_id != "":
|
||||
keyframes["frame1"] = {"type": "generation", "id": final_generation_id}
|
||||
|
||||
generation = client.generations.create(prompt=prompt, keyframes=keyframes)
|
||||
new_generation_id = generation.id
|
||||
completed = False
|
||||
while not completed:
|
||||
generation = client.generations.get(id=new_generation_id)
|
||||
if generation.state == "completed":
|
||||
completed = True
|
||||
elif generation.state == "failed":
|
||||
raise ValueError(f"Generation failed: {generation.failure_reason}")
|
||||
time.sleep(3)
|
||||
|
||||
video_url = generation.assets.video
|
||||
if save:
|
||||
directory, filename = parse_filename(filename)
|
||||
if filename == "":
|
||||
filename = new_generation_id
|
||||
download_file(video_url, os.path.join(self.output_dir, directory, filename + ".mp4"))
|
||||
generation = client.generations.create(
|
||||
prompt=prompt,
|
||||
model=model,
|
||||
loop=loop,
|
||||
resolution=resolution,
|
||||
keyframes=keyframes,
|
||||
)
|
||||
generation_id = generation.id
|
||||
video_url = wait_for_generation(client, generation_id, save, filename, self.output_dir)
|
||||
|
||||
return {
|
||||
"ui": {"text": [new_generation_id]},
|
||||
"ui": {"text": [generation_id]},
|
||||
"result": (
|
||||
video_url,
|
||||
new_generation_id,
|
||||
generation_id,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
class UpscaleGeneration:
|
||||
def __init__(self):
|
||||
self.output_dir = folder_paths.get_output_directory()
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"client": ("LUMACLIENT", {"forceInput": True}),
|
||||
"generation_id": ("STRING", {"default": "", "forceInput": True}),
|
||||
"resolution": (["540p", "720p", "1080p", "4k"],),
|
||||
"save": ("BOOLEAN", {"default": True}),
|
||||
},
|
||||
"optional": {
|
||||
"filename": ("STRING", {"default": ""}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING")
|
||||
RETURN_NAMES = ("video_url", "generation_id")
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "LumaAI/Upscale"
|
||||
|
||||
def run(
|
||||
self,
|
||||
client,
|
||||
generation_id,
|
||||
resolution,
|
||||
save,
|
||||
filename="",
|
||||
):
|
||||
"""
|
||||
Upscale a generation.
|
||||
"""
|
||||
generation = client.generations.upscale(id=generation_id, resolution=resolution)
|
||||
upscaled_generation_id = generation.id
|
||||
video_url = wait_for_generation(client, upscaled_generation_id, save, filename, self.output_dir)
|
||||
|
||||
return {
|
||||
"ui": {"text": [upscaled_generation_id]},
|
||||
"result": (
|
||||
video_url,
|
||||
upscaled_generation_id,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
class AddAudio2Video:
|
||||
def __init__(self):
|
||||
self.output_dir = folder_paths.get_output_directory()
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, *args, **kwargs):
|
||||
return float("NaN")
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"client": ("LUMACLIENT", {"forceInput": True}),
|
||||
"generation_id": ("STRING", {"default": "", "forceInput": True}),
|
||||
"prompt": ("STRING", {"multiline": True, "default": ""}),
|
||||
"negative_prompt": ("STRING", {"multiline": True, "default": ""}),
|
||||
"save": ("BOOLEAN", {"default": True}),
|
||||
},
|
||||
"optional": {
|
||||
"filename": ("STRING", {"default": ""}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING")
|
||||
RETURN_NAMES = ("video_url", "generation_id")
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "LumaAI/Audio"
|
||||
|
||||
def run(
|
||||
self,
|
||||
client,
|
||||
generation_id,
|
||||
prompt,
|
||||
negative_prompt,
|
||||
save,
|
||||
filename="",
|
||||
):
|
||||
"""
|
||||
Upscale a generation.
|
||||
"""
|
||||
generation = client.generations.audio(id=generation_id, prompt=prompt, negative_prompt=negative_prompt)
|
||||
with_audio_generation_id = generation.id
|
||||
video_url = wait_for_generation(client, with_audio_generation_id, save, filename, self.output_dir)
|
||||
|
||||
return {
|
||||
"ui": {"text": [with_audio_generation_id]},
|
||||
"result": (
|
||||
video_url,
|
||||
with_audio_generation_id,
|
||||
),
|
||||
}
|
||||
|
||||
@@ -388,10 +507,264 @@ class PreviewVideo:
|
||||
}
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, *args, **kwargs):
|
||||
return float("NaN")
|
||||
|
||||
OUTPUT_NODE = True
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "LumaAI"
|
||||
CATEGORY = "LumaAI/Utils"
|
||||
RETURN_TYPES = ()
|
||||
|
||||
def run(self, video_url):
|
||||
return {"ui": {"video_url": [video_url]}}
|
||||
|
||||
|
||||
class Reference:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"image_url": ("STRING", {"forceInput": True}),
|
||||
"weight": (
|
||||
"FLOAT",
|
||||
{"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01},
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("REFERENCE",)
|
||||
RETURN_NAMES = ("reference",)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "LumaAI/Photon"
|
||||
|
||||
def run(self, image_url, weight):
|
||||
"""
|
||||
Create a reference from an image URL and a weight.
|
||||
"""
|
||||
return ({"url": image_url, "weight": weight},)
|
||||
|
||||
|
||||
class ConcatReferences:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {},
|
||||
"optional": {
|
||||
"reference_1": ("REFERENCE", {"forceInput": True}),
|
||||
"reference_2": ("REFERENCE", {"forceInput": True}),
|
||||
"reference_3": ("REFERENCE", {"forceInput": True}),
|
||||
"reference_4": ("REFERENCE", {"forceInput": True}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONCAT_REFERENCES",)
|
||||
RETURN_NAMES = ("concat_references",)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "LumaAI/Photon"
|
||||
|
||||
def run(
|
||||
self, reference_1=None, reference_2=None, reference_3=None, reference_4=None
|
||||
):
|
||||
"""
|
||||
Concatenate a list of references.
|
||||
"""
|
||||
references = []
|
||||
for reference in [reference_1, reference_2, reference_3, reference_4]:
|
||||
if reference is not None:
|
||||
references.append(reference)
|
||||
if len(references) == 0:
|
||||
raise ValueError("You must provide at least one reference")
|
||||
return (references,)
|
||||
|
||||
|
||||
class CharacterReference:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {},
|
||||
"optional": {
|
||||
"character_image_url_1": ("STRING", {"forceInput": True}),
|
||||
"character_image_url_2": ("STRING", {"forceInput": True}),
|
||||
"character_image_url_3": ("STRING", {"forceInput": True}),
|
||||
"character_image_url_4": ("STRING", {"forceInput": True}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CHARACTER_REFERENCE",)
|
||||
RETURN_NAMES = ("character_reference",)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "LumaAI/Photon"
|
||||
|
||||
def run(
|
||||
self,
|
||||
character_image_url_1=None,
|
||||
character_image_url_2=None,
|
||||
character_image_url_3=None,
|
||||
character_image_url_4=None,
|
||||
):
|
||||
"""
|
||||
Create a character reference from a list of image URLs.
|
||||
"""
|
||||
urls = []
|
||||
for url in [
|
||||
character_image_url_1,
|
||||
character_image_url_2,
|
||||
character_image_url_3,
|
||||
character_image_url_4,
|
||||
]:
|
||||
if url is not None:
|
||||
urls.append(url)
|
||||
if len(urls) == 0:
|
||||
raise ValueError("You must provide at least one character image URL")
|
||||
|
||||
character_reference = {"identity0": {"images": urls}}
|
||||
return (character_reference,)
|
||||
|
||||
|
||||
class ImageGeneration:
|
||||
def __init__(self):
|
||||
self.output_dir = folder_paths.get_output_directory()
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, *args, **kwargs):
|
||||
return float("NaN")
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"client": ("LUMACLIENT", {"forceInput": True}),
|
||||
"model": (["photon-1", "photon-flash-1"],),
|
||||
"prompt": ("STRING", {"forceInput": True, }),
|
||||
"aspect_ratio": (["9:16", "3:4", "1:1", "4:3", "16:9", "21:9"],),
|
||||
},
|
||||
"optional": {
|
||||
"image_ref": ("CONCAT_REFERENCES", {"forceInput": True}),
|
||||
"style_ref": ("REFERENCE", {"forceInput": True}),
|
||||
"character_ref": ("CHARACTER_REFERENCE", {"forceInput": True}),
|
||||
"filename": ("STRING", {"default": ""}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING", "IMAGE")
|
||||
RETURN_NAMES = ("image_url", "generation_id", "image")
|
||||
OUTPUT_NODE = True
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "LumaAI/Photon"
|
||||
|
||||
def run(
|
||||
self,
|
||||
client,
|
||||
model,
|
||||
prompt,
|
||||
aspect_ratio,
|
||||
image_ref=None,
|
||||
style_ref=None,
|
||||
character_ref=None,
|
||||
filename="",
|
||||
):
|
||||
"""
|
||||
Generate an image from a text prompt and optional references.
|
||||
"""
|
||||
if style_ref is not None:
|
||||
style_ref = [style_ref]
|
||||
|
||||
generation = client.generations.image.create(
|
||||
prompt=prompt,
|
||||
model=model,
|
||||
aspect_ratio=aspect_ratio,
|
||||
image_ref=image_ref,
|
||||
style_ref=style_ref,
|
||||
character_ref=character_ref,
|
||||
)
|
||||
|
||||
generation_id = generation.id
|
||||
completed = False
|
||||
while not completed:
|
||||
generation = client.generations.get(id=generation_id)
|
||||
if generation.state == "completed":
|
||||
completed = True
|
||||
elif generation.state == "failed":
|
||||
raise ValueError(f"Generation failed: {generation.failure_reason}")
|
||||
time.sleep(1)
|
||||
|
||||
image_url = generation.assets.image
|
||||
directory, filename = parse_filename(filename)
|
||||
if filename == "":
|
||||
filename = generation_id
|
||||
download_file(
|
||||
image_url, os.path.join(self.output_dir, directory, filename + ".jpg")
|
||||
)
|
||||
|
||||
image, _ = nodes.LoadImage().load_image(
|
||||
os.path.join(self.output_dir, directory, filename + ".jpg")
|
||||
)
|
||||
|
||||
return {
|
||||
"ui": {"text": [generation_id]},
|
||||
"result": (image_url, generation_id, image),
|
||||
}
|
||||
|
||||
|
||||
class ModifyImage:
|
||||
def __init__(self):
|
||||
self.output_dir = folder_paths.get_output_directory()
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, *args, **kwargs):
|
||||
return float("NaN")
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"client": ("LUMACLIENT", {"forceInput": True}),
|
||||
"model": (["photon-1", "photon-flash-1"],),
|
||||
"prompt": ("STRING", {"forceInput": True, }),
|
||||
"modify_image_ref": ("REFERENCE", {"forceInput": True}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING", "STRING", "IMAGE")
|
||||
RETURN_NAMES = ("image_url", "generation_id", "image")
|
||||
OUTPUT_NODE = True
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "LumaAI/Photon"
|
||||
|
||||
def run(self, client, model, prompt, modify_image_ref, filename=""):
|
||||
"""
|
||||
Modify an image.
|
||||
"""
|
||||
generation = client.generations.image.create(
|
||||
prompt=prompt,
|
||||
model=model,
|
||||
modify_image_ref=modify_image_ref,
|
||||
)
|
||||
|
||||
generation_id = generation.id
|
||||
completed = False
|
||||
while not completed:
|
||||
generation = client.generations.get(id=generation_id)
|
||||
if generation.state == "completed":
|
||||
completed = True
|
||||
elif generation.state == "failed":
|
||||
raise ValueError(f"Generation failed: {generation.failure_reason}")
|
||||
time.sleep(3)
|
||||
|
||||
image_url = generation.assets.image
|
||||
directory, filename = parse_filename(filename)
|
||||
if filename == "":
|
||||
filename = generation_id
|
||||
download_file(
|
||||
image_url, os.path.join(self.output_dir, directory, filename + ".jpg")
|
||||
)
|
||||
|
||||
image, _ = nodes.LoadImage().load_image(
|
||||
os.path.join(self.output_dir, directory, filename + ".jpg")
|
||||
)
|
||||
|
||||
return {
|
||||
"ui": {"text": [generation_id]},
|
||||
"result": (image_url, generation_id, image),
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
[project]
|
||||
name = "comfyui-lumaai-api"
|
||||
description = "This custom node allows you to use the LumaAI API."
|
||||
version = "1.0.2"
|
||||
version = "1.1.0"
|
||||
license = {file = "LICENSE"}
|
||||
dependencies = ["lumaai", "requests", "numpy", "Pillow"]
|
||||
dependencies = ["lumaai==1.7.0", "requests", "numpy", "Pillow"]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/lumalabs/ComfyUI-LumaAI-API"
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
lumaai
|
||||
lumaai==1.7.0
|
||||
requests
|
||||
numpy
|
||||
Pillow
|
||||
@@ -7,7 +7,13 @@ import { ComfyWidgets } from "../../../scripts/widgets.js";
|
||||
app.registerExtension({
|
||||
name: "lumaai.showgenerationid",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
if (nodeData.name == "LumaText2Video" || nodeData.name == "LumaImage2Video" || nodeData.name == "LumaInterpolateGenerations" || nodeData.name == "LumaExtendGeneration") {
|
||||
if (nodeData.name == "LumaText2Video"
|
||||
|| nodeData.name == "LumaImage2Video"
|
||||
|| nodeData.name == "LumaInterpolateGenerations"
|
||||
|| nodeData.name == "LumaExtendGeneration"
|
||||
|| nodeData.name == "LumaImageGeneration"
|
||||
|| nodeData.name == "LumaModifyImage"
|
||||
) {
|
||||
function populate(text) {
|
||||
const v = [...text];
|
||||
if (this.widgets) {
|
||||
@@ -31,7 +37,7 @@ app.registerExtension({
|
||||
sz[1] = this.size[1];
|
||||
}
|
||||
this.onResize?.(sz);
|
||||
app.graph.setDirtyCanvas(true, false);
|
||||
app.graph.setDirtyCanvas(true, true);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -49,4 +55,4 @@ app.registerExtension({
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
{
|
||||
"last_node_id": 5,
|
||||
"last_link_id": 5,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 2,
|
||||
"type": "LumaText2Video",
|
||||
"pos": [
|
||||
460.42974853515625,
|
||||
274.5
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
364
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "video_url",
|
||||
"type": "STRING",
|
||||
"links": []
|
||||
},
|
||||
{
|
||||
"name": "generation_id",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
3
|
||||
],
|
||||
"slot_index": 1
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaText2Video"
|
||||
},
|
||||
"widgets_values": [
|
||||
"ray-flash-2",
|
||||
"a car",
|
||||
"5s",
|
||||
false,
|
||||
"9:16",
|
||||
"540p",
|
||||
true,
|
||||
"",
|
||||
"ee4e9dad-9f1e-4e5e-bc37-1b46e9825750",
|
||||
"ee4e9dad-9f1e-4e5e-bc37-1b46e9825750"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"type": "LumaAddAudio2Video",
|
||||
"pos": [
|
||||
1003.0374755859375,
|
||||
442.3060607910156
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
200
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"link": 5
|
||||
},
|
||||
{
|
||||
"name": "generation_id",
|
||||
"type": "STRING",
|
||||
"link": 3,
|
||||
"widget": {
|
||||
"name": "generation_id"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "video_url",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
4
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "generation_id",
|
||||
"type": "STRING",
|
||||
"links": null
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaAddAudio2Video"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
"noise from a car",
|
||||
"",
|
||||
true,
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "LumaPreviewVideo",
|
||||
"pos": [
|
||||
1583.6092529296875,
|
||||
145.96243286132812
|
||||
],
|
||||
"size": [
|
||||
768,
|
||||
768
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "video_url",
|
||||
"type": "STRING",
|
||||
"link": 4,
|
||||
"widget": {
|
||||
"name": "video_url"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaPreviewVideo"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
null
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "LumaAIClient",
|
||||
"pos": [
|
||||
32.32486343383789,
|
||||
344.1593933105469
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"links": [
|
||||
1,
|
||||
5
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaAIClient"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
"LUMACLIENT"
|
||||
],
|
||||
[
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
4,
|
||||
1,
|
||||
0,
|
||||
5,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
5,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
"LUMACLIENT"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 0.5559917313492242,
|
||||
"offset": [
|
||||
230.56296338473092,
|
||||
95.73040355967112
|
||||
]
|
||||
},
|
||||
"node_versions": {
|
||||
"ComfyUI-LumaAI-API": "a53576c98bcffffca5474451a8ca5de4faf92943"
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
{
|
||||
"last_node_id": 31,
|
||||
"last_link_id": 18,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 30,
|
||||
"type": "LumaPreviewVideo",
|
||||
"pos": [
|
||||
1033,
|
||||
378
|
||||
],
|
||||
"size": [
|
||||
768,
|
||||
768
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "video_url",
|
||||
"type": "STRING",
|
||||
"link": 18,
|
||||
"widget": {
|
||||
"name": "video_url"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaPreviewVideo"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 29,
|
||||
"type": "LumaAIClient",
|
||||
"pos": [
|
||||
124,
|
||||
375
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"links": [
|
||||
17
|
||||
],
|
||||
"slot_index": 0,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaAIClient"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 31,
|
||||
"type": "Ray2Text2Video",
|
||||
"pos": [
|
||||
503.9627990722656,
|
||||
379.0370178222656
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
240
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"link": 17
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "video_url",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
18
|
||||
],
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "generation_id",
|
||||
"type": "STRING",
|
||||
"links": null
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Ray2Text2Video"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
"5s",
|
||||
"720p",
|
||||
false,
|
||||
"9:16",
|
||||
true,
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
17,
|
||||
29,
|
||||
0,
|
||||
31,
|
||||
0,
|
||||
"LUMACLIENT"
|
||||
],
|
||||
[
|
||||
18,
|
||||
31,
|
||||
0,
|
||||
30,
|
||||
0,
|
||||
"STRING"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 0.9090909090909091,
|
||||
"offset": [
|
||||
-21.961315505259062,
|
||||
-186.1272521835087
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
{
|
||||
"last_node_id": 6,
|
||||
"last_link_id": 9,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 5,
|
||||
"type": "LumaPreviewVideo",
|
||||
"pos": [
|
||||
1583.6092529296875,
|
||||
145.96243286132812
|
||||
],
|
||||
"size": [
|
||||
768,
|
||||
768
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "video_url",
|
||||
"type": "STRING",
|
||||
"link": 8,
|
||||
"widget": {
|
||||
"name": "video_url"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaPreviewVideo"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
null
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "LumaText2Video",
|
||||
"pos": [
|
||||
460.42974853515625,
|
||||
274.5
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
364
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "video_url",
|
||||
"type": "STRING",
|
||||
"links": []
|
||||
},
|
||||
{
|
||||
"name": "generation_id",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
7
|
||||
],
|
||||
"slot_index": 1
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaText2Video"
|
||||
},
|
||||
"widgets_values": [
|
||||
"ray-flash-2",
|
||||
"a car",
|
||||
"5s",
|
||||
false,
|
||||
"9:16",
|
||||
"540p",
|
||||
true,
|
||||
"",
|
||||
"24ed0260-bc59-419f-8f10-794d291176d0",
|
||||
"24ed0260-bc59-419f-8f10-794d291176d0"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"type": "LumaUpscaleGeneration",
|
||||
"pos": [
|
||||
1056.1300048828125,
|
||||
351.3099365234375
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
150
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"link": 9
|
||||
},
|
||||
{
|
||||
"name": "generation_id",
|
||||
"type": "STRING",
|
||||
"link": 7,
|
||||
"widget": {
|
||||
"name": "generation_id"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "video_url",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
8
|
||||
],
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "generation_id",
|
||||
"type": "STRING",
|
||||
"links": null
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaUpscaleGeneration"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
"1080p",
|
||||
true,
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "LumaAIClient",
|
||||
"pos": [
|
||||
32.32486343383789,
|
||||
344.1593933105469
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
58
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"links": [
|
||||
1,
|
||||
9
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaAIClient"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
"LUMACLIENT"
|
||||
],
|
||||
[
|
||||
7,
|
||||
2,
|
||||
1,
|
||||
6,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
8,
|
||||
6,
|
||||
0,
|
||||
5,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
9,
|
||||
3,
|
||||
0,
|
||||
6,
|
||||
0,
|
||||
"LUMACLIENT"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 0.9849732675807652,
|
||||
"offset": [
|
||||
-92.60513941852872,
|
||||
-55.773528450482495
|
||||
]
|
||||
},
|
||||
"node_versions": {
|
||||
"ComfyUI-LumaAI-API": "a53576c98bcffffca5474451a8ca5de4faf92943"
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,385 @@
|
||||
{
|
||||
"last_node_id": 8,
|
||||
"last_link_id": 8,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 5,
|
||||
"type": "LoadImage",
|
||||
"pos": [
|
||||
-309,
|
||||
482
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
314.00002670288086
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
3
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LoadImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"00014.png",
|
||||
"image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1248,
|
||||
237
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 26
|
||||
},
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"type": "LumaImageGeneration",
|
||||
"pos": [
|
||||
772,
|
||||
199
|
||||
],
|
||||
"size": [
|
||||
342.5999755859375,
|
||||
190
|
||||
],
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"link": 2
|
||||
},
|
||||
{
|
||||
"name": "image_ref",
|
||||
"type": "CONCAT_REFERENCES",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "style_ref",
|
||||
"type": "REFERENCE",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "character_ref",
|
||||
"type": "CHARACTER_REFERENCE",
|
||||
"link": 8
|
||||
},
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "STRING",
|
||||
"link": 6,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image_url",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "generation_id",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
1
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 2
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaImageGeneration"
|
||||
},
|
||||
"widgets_values": [
|
||||
"photon-1",
|
||||
"",
|
||||
"9:16",
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "LumaAIClient",
|
||||
"pos": [
|
||||
380,
|
||||
195
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"links": [
|
||||
2
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaAIClient"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"type": "PrimitiveNode",
|
||||
"pos": [
|
||||
392,
|
||||
318
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
6
|
||||
],
|
||||
"slot_index": 0,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Run widget replace on values": false
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "ImgBBUpload",
|
||||
"pos": [
|
||||
58,
|
||||
482
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 106
|
||||
},
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 3
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image_url",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
7
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ImgBBUpload"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
false,
|
||||
60
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "CharacterReference",
|
||||
"pos": [
|
||||
406,
|
||||
485
|
||||
],
|
||||
"size": [
|
||||
346,
|
||||
94
|
||||
],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "character_image_url_1",
|
||||
"type": "STRING",
|
||||
"link": 7,
|
||||
"widget": {
|
||||
"name": "character_image_url_1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "character_image_url_2",
|
||||
"type": "STRING",
|
||||
"link": null,
|
||||
"widget": {
|
||||
"name": "character_image_url_2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "character_image_url_3",
|
||||
"type": "STRING",
|
||||
"link": null,
|
||||
"widget": {
|
||||
"name": "character_image_url_3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "character_image_url_4",
|
||||
"type": "STRING",
|
||||
"link": null,
|
||||
"widget": {
|
||||
"name": "character_image_url_4"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "character_reference",
|
||||
"type": "CHARACTER_REFERENCE",
|
||||
"links": [
|
||||
8
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CharacterReference"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
2,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
"LUMACLIENT"
|
||||
],
|
||||
[
|
||||
3,
|
||||
5,
|
||||
0,
|
||||
4,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
6,
|
||||
7,
|
||||
0,
|
||||
1,
|
||||
4,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
7,
|
||||
4,
|
||||
0,
|
||||
8,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
8,
|
||||
8,
|
||||
0,
|
||||
1,
|
||||
3,
|
||||
"CHARACTER_REFERENCE"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 0.8264462809917354,
|
||||
"offset": [
|
||||
357.39093750000023,
|
||||
135.43187500000013
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,418 @@
|
||||
{
|
||||
"last_node_id": 10,
|
||||
"last_link_id": 11,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 5,
|
||||
"type": "LoadImage",
|
||||
"pos": [
|
||||
-309,
|
||||
482
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
314.00002670288086
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
3
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LoadImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"00014.png",
|
||||
"image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1248,
|
||||
237
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 26
|
||||
},
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "LumaAIClient",
|
||||
"pos": [
|
||||
380,
|
||||
195
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"links": [
|
||||
2
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaAIClient"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"type": "PrimitiveNode",
|
||||
"pos": [
|
||||
392,
|
||||
318
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
6
|
||||
],
|
||||
"slot_index": 0,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Run widget replace on values": false
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "ImgBBUpload",
|
||||
"pos": [
|
||||
58,
|
||||
482
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 106
|
||||
},
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 3
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image_url",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
9
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ImgBBUpload"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
false,
|
||||
60
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"type": "Reference",
|
||||
"pos": [
|
||||
473,
|
||||
702
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
82
|
||||
],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image_url",
|
||||
"type": "STRING",
|
||||
"link": 9,
|
||||
"widget": {
|
||||
"name": "image_url"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "reference",
|
||||
"type": "REFERENCE",
|
||||
"links": [
|
||||
10
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Reference"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"type": "ConcatReferences",
|
||||
"pos": [
|
||||
437,
|
||||
496
|
||||
],
|
||||
"size": {
|
||||
"0": 367.79998779296875,
|
||||
"1": 86
|
||||
},
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "reference_1",
|
||||
"type": "REFERENCE",
|
||||
"link": 10
|
||||
},
|
||||
{
|
||||
"name": "reference_2",
|
||||
"type": "REFERENCE",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "reference_3",
|
||||
"type": "REFERENCE",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "reference_4",
|
||||
"type": "REFERENCE",
|
||||
"link": null
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "concat_references",
|
||||
"type": "CONCAT_REFERENCES",
|
||||
"links": [
|
||||
11
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ConcatReferences"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"type": "LumaImageGeneration",
|
||||
"pos": [
|
||||
833,
|
||||
197
|
||||
],
|
||||
"size": [
|
||||
342.5999755859375,
|
||||
190
|
||||
],
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"link": 2
|
||||
},
|
||||
{
|
||||
"name": "image_ref",
|
||||
"type": "CONCAT_REFERENCES",
|
||||
"link": 11
|
||||
},
|
||||
{
|
||||
"name": "style_ref",
|
||||
"type": "REFERENCE",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "character_ref",
|
||||
"type": "CHARACTER_REFERENCE",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "STRING",
|
||||
"link": 6,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image_url",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "generation_id",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
1
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 2
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaImageGeneration"
|
||||
},
|
||||
"widgets_values": [
|
||||
"photon-1",
|
||||
"",
|
||||
"9:16",
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
2,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
"LUMACLIENT"
|
||||
],
|
||||
[
|
||||
3,
|
||||
5,
|
||||
0,
|
||||
4,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
6,
|
||||
7,
|
||||
0,
|
||||
1,
|
||||
4,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
9,
|
||||
4,
|
||||
0,
|
||||
9,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
10,
|
||||
9,
|
||||
0,
|
||||
10,
|
||||
0,
|
||||
"REFERENCE"
|
||||
],
|
||||
[
|
||||
11,
|
||||
10,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
"CONCAT_REFERENCES"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 0.8264462809917354,
|
||||
"offset": [
|
||||
357.39093750000023,
|
||||
135.15300781250014
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
{
|
||||
"last_node_id": 11,
|
||||
"last_link_id": 14,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 11,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1127,
|
||||
122
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
246
|
||||
],
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 14,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "LumaModifyImage",
|
||||
"pos": [
|
||||
641,
|
||||
120
|
||||
],
|
||||
"size": [
|
||||
380.4000244140625,
|
||||
122
|
||||
],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"link": 10,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "modify_image_ref",
|
||||
"type": "REFERENCE",
|
||||
"link": 12
|
||||
},
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "STRING",
|
||||
"link": 13,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image_url",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "generation_id",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
14
|
||||
],
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaModifyImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"photon-1",
|
||||
"transform all the flowers to sunflowers"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"type": "Reference",
|
||||
"pos": [
|
||||
248,
|
||||
194
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
82
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image_url",
|
||||
"type": "STRING",
|
||||
"link": 11,
|
||||
"widget": {
|
||||
"name": "image_url"
|
||||
},
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "reference",
|
||||
"type": "REFERENCE",
|
||||
"links": [
|
||||
12
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Reference"
|
||||
},
|
||||
"widgets_values": [
|
||||
"https://staging.storage.cdn-luma.com/dream_machine/400460d3-cc24-47ae-a015-d4d1c6296aba/38cc78d7-95aa-4e6e-b1ac-4123ce24725e_image0c73fa8a463114bf89e30892a301c532e.jpg",
|
||||
0.5
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "PrimitiveNode",
|
||||
"pos": [
|
||||
2,
|
||||
199
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
11
|
||||
],
|
||||
"slot_index": 0,
|
||||
"widget": {
|
||||
"name": "image_url"
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Run widget replace on values": false
|
||||
},
|
||||
"widgets_values": [
|
||||
"https://staging.storage.cdn-luma.com/dream_machine/400460d3-cc24-47ae-a015-d4d1c6296aba/38cc78d7-95aa-4e6e-b1ac-4123ce24725e_image0c73fa8a463114bf89e30892a301c532e.jpg"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"type": "PrimitiveNode",
|
||||
"pos": [
|
||||
120,
|
||||
334
|
||||
],
|
||||
"size": [
|
||||
442.6914007018429,
|
||||
133.1652411475094
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
13
|
||||
],
|
||||
"slot_index": 0,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Run widget replace on values": false
|
||||
},
|
||||
"widgets_values": [
|
||||
"transform all the flowers to sunflowers"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"type": "LumaAIClient",
|
||||
"pos": [
|
||||
246,
|
||||
66
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {
|
||||
"collapsed": false
|
||||
},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"links": [
|
||||
10
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaAIClient"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
10,
|
||||
1,
|
||||
0,
|
||||
8,
|
||||
0,
|
||||
"LUMACLIENT"
|
||||
],
|
||||
[
|
||||
11,
|
||||
5,
|
||||
0,
|
||||
9,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
12,
|
||||
9,
|
||||
0,
|
||||
8,
|
||||
1,
|
||||
"REFERENCE"
|
||||
],
|
||||
[
|
||||
13,
|
||||
10,
|
||||
0,
|
||||
8,
|
||||
2,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
14,
|
||||
8,
|
||||
2,
|
||||
11,
|
||||
0,
|
||||
"IMAGE"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 1.2100000000000002,
|
||||
"offset": [
|
||||
75.7556407983373,
|
||||
175.25858695772177
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,359 @@
|
||||
{
|
||||
"last_node_id": 7,
|
||||
"last_link_id": 6,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 5,
|
||||
"type": "LoadImage",
|
||||
"pos": [
|
||||
-309,
|
||||
482
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
314.00002670288086
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
3
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "MASK",
|
||||
"type": "MASK",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LoadImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
"00014.png",
|
||||
"image"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "ImgBBUpload",
|
||||
"pos": [
|
||||
58,
|
||||
482
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 106
|
||||
},
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"link": 3
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image_url",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
4
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "ImgBBUpload"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
false,
|
||||
60
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1248,
|
||||
237
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 26
|
||||
},
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"type": "LumaImageGeneration",
|
||||
"pos": [
|
||||
772,
|
||||
199
|
||||
],
|
||||
"size": [
|
||||
342.5999755859375,
|
||||
190
|
||||
],
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"link": 2
|
||||
},
|
||||
{
|
||||
"name": "image_ref",
|
||||
"type": "CONCAT_REFERENCES",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "style_ref",
|
||||
"type": "REFERENCE",
|
||||
"link": 5
|
||||
},
|
||||
{
|
||||
"name": "character_ref",
|
||||
"type": "CHARACTER_REFERENCE",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "STRING",
|
||||
"link": 6,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image_url",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "generation_id",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
1
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 2
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaImageGeneration"
|
||||
},
|
||||
"widgets_values": [
|
||||
"photon-1",
|
||||
"",
|
||||
"9:16",
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "LumaAIClient",
|
||||
"pos": [
|
||||
380,
|
||||
195
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"links": [
|
||||
2
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaAIClient"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"type": "Reference",
|
||||
"pos": [
|
||||
400,
|
||||
489
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
82
|
||||
],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "image_url",
|
||||
"type": "STRING",
|
||||
"link": 4,
|
||||
"widget": {
|
||||
"name": "image_url"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "reference",
|
||||
"type": "REFERENCE",
|
||||
"links": [
|
||||
5
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "Reference"
|
||||
},
|
||||
"widgets_values": [
|
||||
"",
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"type": "PrimitiveNode",
|
||||
"pos": [
|
||||
392,
|
||||
318
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
6
|
||||
],
|
||||
"slot_index": 0,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Run widget replace on values": false
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
2,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
"LUMACLIENT"
|
||||
],
|
||||
[
|
||||
3,
|
||||
5,
|
||||
0,
|
||||
4,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
4,
|
||||
4,
|
||||
0,
|
||||
6,
|
||||
0,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
5,
|
||||
6,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
"REFERENCE"
|
||||
],
|
||||
[
|
||||
6,
|
||||
7,
|
||||
0,
|
||||
1,
|
||||
4,
|
||||
"STRING"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 0.8264462809917354,
|
||||
"offset": [
|
||||
357.39093750000023,
|
||||
135.43187500000013
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
{
|
||||
"last_node_id": 10,
|
||||
"last_link_id": 11,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 2,
|
||||
"type": "PreviewImage",
|
||||
"pos": [
|
||||
1248,
|
||||
237
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 26
|
||||
},
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "PreviewImage"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "LumaAIClient",
|
||||
"pos": [
|
||||
380,
|
||||
195
|
||||
],
|
||||
"size": {
|
||||
"0": 315,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"links": [
|
||||
2
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaAIClient"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"type": "PrimitiveNode",
|
||||
"pos": [
|
||||
392,
|
||||
318
|
||||
],
|
||||
"size": {
|
||||
"0": 210,
|
||||
"1": 58
|
||||
},
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"outputs": [
|
||||
{
|
||||
"name": "STRING",
|
||||
"type": "STRING",
|
||||
"links": [
|
||||
6
|
||||
],
|
||||
"slot_index": 0,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Run widget replace on values": false
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"type": "LumaImageGeneration",
|
||||
"pos": [
|
||||
833,
|
||||
197
|
||||
],
|
||||
"size": [
|
||||
342.5999755859375,
|
||||
190
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "client",
|
||||
"type": "LUMACLIENT",
|
||||
"link": 2
|
||||
},
|
||||
{
|
||||
"name": "image_ref",
|
||||
"type": "CONCAT_REFERENCES",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "style_ref",
|
||||
"type": "REFERENCE",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "character_ref",
|
||||
"type": "CHARACTER_REFERENCE",
|
||||
"link": null
|
||||
},
|
||||
{
|
||||
"name": "prompt",
|
||||
"type": "STRING",
|
||||
"link": 6,
|
||||
"widget": {
|
||||
"name": "prompt"
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "image_url",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "generation_id",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"shape": 3
|
||||
},
|
||||
{
|
||||
"name": "image",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
1
|
||||
],
|
||||
"shape": 3,
|
||||
"slot_index": 2
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "LumaImageGeneration"
|
||||
},
|
||||
"widgets_values": [
|
||||
"photon-1",
|
||||
"",
|
||||
"9:16",
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
2,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
"LUMACLIENT"
|
||||
],
|
||||
[
|
||||
6,
|
||||
7,
|
||||
0,
|
||||
1,
|
||||
4,
|
||||
"STRING"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 0.8264462809917354,
|
||||
"offset": [
|
||||
357.39093750000023,
|
||||
135.15300781250014
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
Reference in New Issue
Block a user