Adding a first draft of the Pecha Kucha node.
This commit is contained in:
@@ -1,2 +1,25 @@
|
||||
# ComfyUI-PechaKucha
|
||||
Comfy UI nodes to generate pecha kucha presentations
|
||||
|
||||
## Setup:
|
||||
Copy the node in your ComfyUI/custom_nodes directory
|
||||
install the dependencies:
|
||||
```
|
||||
python -m pip install -r requirements.txt
|
||||
```
|
||||
load the example workflow
|
||||
The pecha Kucha pptx will be generated and saved in your `ComfyUI/output/pecha_kucha` folder
|
||||
|
||||
|
||||
## Content:
|
||||
a Node `Split Prompt` to convert a multi-line prompt in an array of prompt
|
||||
a Node `Generate PechaKucha Powerpoint` which generate a PechaKucha presentation from an array of Images.
|
||||
|
||||
## Contribution:
|
||||
Open Source contribution and bug reports are welcome.
|
||||
Please follow the standard open source contribution process.
|
||||
|
||||
## Thanks
|
||||
* ComfyUI Team
|
||||
* ComfyUI-Inspire-Pack
|
||||
* Alexis Rolland for the spot on StackOverflow questions :D
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
from .pecha_kucha import GeneratePowerpoint
|
||||
from .split_prompt import SplitPrompt
|
||||
# A dictionary that contains all nodes you want to export with their names
|
||||
# NOTE: names should be globally unique
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"GeneratePowerpoint": GeneratePowerpoint,
|
||||
"SplitPrompt": SplitPrompt
|
||||
}
|
||||
|
||||
# A dictionary that contains the friendly/humanly readable titles for the nodes
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"GeneratePowerpoint": "Generate PechaKucha Powerpoint",
|
||||
"SplitPrompt": "Split Prompt (To Batch)"
|
||||
}
|
||||
|
||||
__all__ = [NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS]
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 104 KiB |
@@ -0,0 +1,455 @@
|
||||
{
|
||||
"last_node_id": 29,
|
||||
"last_link_id": 31,
|
||||
"nodes": [
|
||||
{
|
||||
"id": 19,
|
||||
"type": "CLIPTextEncode",
|
||||
"pos": [
|
||||
143.13748168945312,
|
||||
333.75732421875
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
200
|
||||
],
|
||||
"flags": {},
|
||||
"order": 3,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "clip",
|
||||
"type": "CLIP",
|
||||
"link": 14
|
||||
},
|
||||
{
|
||||
"name": "text",
|
||||
"type": "STRING",
|
||||
"widget": {
|
||||
"name": "text"
|
||||
},
|
||||
"link": 24
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "CONDITIONING",
|
||||
"type": "CONDITIONING",
|
||||
"links": [
|
||||
17
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CLIPTextEncode"
|
||||
},
|
||||
"widgets_values": [
|
||||
"a pretty girl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"type": "CLIPTextEncode",
|
||||
"pos": [
|
||||
136.04656982421875,
|
||||
592.12109375
|
||||
],
|
||||
"size": [
|
||||
400,
|
||||
200
|
||||
],
|
||||
"flags": {},
|
||||
"order": 4,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "clip",
|
||||
"type": "CLIP",
|
||||
"link": 15
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "CONDITIONING",
|
||||
"type": "CONDITIONING",
|
||||
"links": [
|
||||
16
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CLIPTextEncode"
|
||||
},
|
||||
"widgets_values": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"type": "KSampler",
|
||||
"pos": [
|
||||
696.86474609375,
|
||||
891.57568359375
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
262
|
||||
],
|
||||
"flags": {},
|
||||
"order": 5,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "model",
|
||||
"type": "MODEL",
|
||||
"link": 13
|
||||
},
|
||||
{
|
||||
"name": "positive",
|
||||
"type": "CONDITIONING",
|
||||
"link": 17
|
||||
},
|
||||
{
|
||||
"name": "negative",
|
||||
"type": "CONDITIONING",
|
||||
"link": 16
|
||||
},
|
||||
{
|
||||
"name": "latent_image",
|
||||
"type": "LATENT",
|
||||
"link": 18
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"links": [
|
||||
19
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "KSampler"
|
||||
},
|
||||
"widgets_values": [
|
||||
655165261555852,
|
||||
"randomize",
|
||||
10,
|
||||
8,
|
||||
"euler",
|
||||
"normal",
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"type": "VAEDecode",
|
||||
"pos": [
|
||||
1087.822021484375,
|
||||
903.0579833984375
|
||||
],
|
||||
"size": [
|
||||
210,
|
||||
46
|
||||
],
|
||||
"flags": {},
|
||||
"order": 6,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "samples",
|
||||
"type": "LATENT",
|
||||
"link": 19
|
||||
},
|
||||
{
|
||||
"name": "vae",
|
||||
"type": "VAE",
|
||||
"link": 20
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "IMAGE",
|
||||
"type": "IMAGE",
|
||||
"links": [
|
||||
28
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "VAEDecode"
|
||||
},
|
||||
"widgets_values": []
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"type": "SplitPrompt",
|
||||
"pos": [
|
||||
-576.6425170898438,
|
||||
340.18206787109375
|
||||
],
|
||||
"size": [
|
||||
412,
|
||||
196
|
||||
],
|
||||
"flags": {},
|
||||
"order": 0,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "Split Prompts",
|
||||
"type": "STRING",
|
||||
"shape": 6,
|
||||
"links": [
|
||||
24,
|
||||
31
|
||||
],
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "SplitPrompt"
|
||||
},
|
||||
"widgets_values": [
|
||||
"A rabbit walking with a suitcase\nAn old guy trying to carry a bag of money\nA space view from earth",
|
||||
"\n",
|
||||
true
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"type": "EmptyLatentImage",
|
||||
"pos": [
|
||||
288.1556396484375,
|
||||
1123.75732421875
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
106
|
||||
],
|
||||
"flags": {},
|
||||
"order": 1,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "LATENT",
|
||||
"type": "LATENT",
|
||||
"links": [
|
||||
18
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "EmptyLatentImage"
|
||||
},
|
||||
"widgets_values": [
|
||||
1280,
|
||||
720,
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"type": "CheckpointLoaderSimple",
|
||||
"pos": [
|
||||
-622.9769897460938,
|
||||
888.4140625
|
||||
],
|
||||
"size": [
|
||||
315,
|
||||
98
|
||||
],
|
||||
"flags": {},
|
||||
"order": 2,
|
||||
"mode": 0,
|
||||
"inputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "MODEL",
|
||||
"type": "MODEL",
|
||||
"links": [
|
||||
13
|
||||
],
|
||||
"slot_index": 0
|
||||
},
|
||||
{
|
||||
"name": "CLIP",
|
||||
"type": "CLIP",
|
||||
"links": [
|
||||
14,
|
||||
15
|
||||
],
|
||||
"slot_index": 1
|
||||
},
|
||||
{
|
||||
"name": "VAE",
|
||||
"type": "VAE",
|
||||
"links": [
|
||||
20
|
||||
]
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "CheckpointLoaderSimple"
|
||||
},
|
||||
"widgets_values": [
|
||||
"epicrealismXL_v5Ultimate.safetensors"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"type": "GeneratePowerpoint",
|
||||
"pos": [
|
||||
1417.4892578125,
|
||||
914.5468139648438
|
||||
],
|
||||
"size": [
|
||||
378,
|
||||
130
|
||||
],
|
||||
"flags": {},
|
||||
"order": 7,
|
||||
"mode": 0,
|
||||
"inputs": [
|
||||
{
|
||||
"name": "images",
|
||||
"type": "IMAGE",
|
||||
"link": 28
|
||||
},
|
||||
{
|
||||
"name": "titles",
|
||||
"type": "STRING",
|
||||
"widget": {
|
||||
"name": "titles"
|
||||
},
|
||||
"link": 31
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "filename",
|
||||
"type": "STRING",
|
||||
"links": null,
|
||||
"slot_index": 0
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"Node name for S&R": "GeneratePowerpoint"
|
||||
},
|
||||
"widgets_values": [
|
||||
"My pecha",
|
||||
"",
|
||||
20,
|
||||
true
|
||||
]
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
[
|
||||
13,
|
||||
17,
|
||||
0,
|
||||
18,
|
||||
0,
|
||||
"MODEL"
|
||||
],
|
||||
[
|
||||
14,
|
||||
17,
|
||||
1,
|
||||
19,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
15,
|
||||
17,
|
||||
1,
|
||||
20,
|
||||
0,
|
||||
"CLIP"
|
||||
],
|
||||
[
|
||||
16,
|
||||
20,
|
||||
0,
|
||||
18,
|
||||
2,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
17,
|
||||
19,
|
||||
0,
|
||||
18,
|
||||
1,
|
||||
"CONDITIONING"
|
||||
],
|
||||
[
|
||||
18,
|
||||
21,
|
||||
0,
|
||||
18,
|
||||
3,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
19,
|
||||
18,
|
||||
0,
|
||||
22,
|
||||
0,
|
||||
"LATENT"
|
||||
],
|
||||
[
|
||||
20,
|
||||
17,
|
||||
2,
|
||||
22,
|
||||
1,
|
||||
"VAE"
|
||||
],
|
||||
[
|
||||
24,
|
||||
25,
|
||||
0,
|
||||
19,
|
||||
1,
|
||||
"STRING"
|
||||
],
|
||||
[
|
||||
28,
|
||||
22,
|
||||
0,
|
||||
27,
|
||||
0,
|
||||
"IMAGE"
|
||||
],
|
||||
[
|
||||
31,
|
||||
25,
|
||||
0,
|
||||
27,
|
||||
1,
|
||||
"STRING"
|
||||
]
|
||||
],
|
||||
"groups": [],
|
||||
"config": {},
|
||||
"extra": {
|
||||
"ds": {
|
||||
"scale": 0.9090909090909091,
|
||||
"offset": [
|
||||
812.004781836218,
|
||||
-127.85274297232016
|
||||
]
|
||||
}
|
||||
},
|
||||
"version": 0.4
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,98 @@
|
||||
import io
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import numpy
|
||||
from PIL import Image
|
||||
from PIL.PngImagePlugin import PngInfo
|
||||
|
||||
import folder_paths
|
||||
|
||||
from .presentation_generation.pptx import Pptx
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GeneratePowerpoint:
|
||||
"""
|
||||
A node to generate a PechaKucha presentation
|
||||
"""
|
||||
def __init__(self):
|
||||
self.output_dir = folder_paths.get_output_directory()
|
||||
self.temp_dir = folder_paths.get_temp_directory()
|
||||
self.compress_level = 4
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"images": ("IMAGE",),
|
||||
"title": ("STRING", {
|
||||
"multiline": False,
|
||||
"default": "My pecha",
|
||||
"tooltip": "The title of this Presentation"
|
||||
}),
|
||||
"titles": ("STRING", {
|
||||
"multiline": False,
|
||||
"default": "",
|
||||
"tooltip": "the titles for each slide."
|
||||
}),
|
||||
"slide_duration": ("INT", {
|
||||
"default": 20,
|
||||
"min": 0,
|
||||
"max": 300,
|
||||
"step": 1,
|
||||
"display": "number",
|
||||
"tooltip": "Each slide duration in seconds."
|
||||
}),
|
||||
"show_titles": ("BOOLEAN", {
|
||||
"default": False,
|
||||
"tooltip": "Show each prompt as slide title. Needs to provide the titles input."
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
CATEGORY = "pecha_kucha"
|
||||
DESCRIPTION = "Generates a Pecha Kucha generation from a list of images and prompts"
|
||||
FUNCTION = "generate_pptx"
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_NODE = True
|
||||
RETURN_NAMES = ("filename",)
|
||||
RETURN_TYPES = ("STRING",)
|
||||
|
||||
def save_images(self, images, filename_prefix="PechaKucha"):
|
||||
full_output_folder, filename, counter, subfolder, filename_prefix = folder_paths.get_save_image_path(filename_prefix, self.temp_dir, images[0].shape[1], images[0].shape[0])
|
||||
results = list()
|
||||
log.debug(f"received {len(images)} images")
|
||||
for (batch_number, image) in enumerate(images):
|
||||
log.debug(f"start saving image {batch_number}, shape: {image.shape}")
|
||||
i = 255. * image.cpu().numpy().squeeze()
|
||||
img = Image.fromarray(numpy.clip(i, 0, 255).astype(numpy.uint8))
|
||||
metadata = None
|
||||
metadata = PngInfo()
|
||||
|
||||
filename_with_batch_num = filename.replace("%batch_num%", str(batch_number))
|
||||
file = f"{filename_with_batch_num}_{counter:05}_.png"
|
||||
path = os.path.join(full_output_folder, file)
|
||||
img.save(path, pnginfo=metadata, compress_level=self.compress_level)
|
||||
results.append(path)
|
||||
counter += 1
|
||||
|
||||
return results
|
||||
|
||||
def generate_pptx(self, images, title, titles, slide_duration, show_titles):
|
||||
log.info(f"start pecha_kucha generation")
|
||||
images = self.save_images(images)
|
||||
# The following inputs are also considered as list but only contain a single value
|
||||
title = title[0]
|
||||
slide_duration = slide_duration[0]
|
||||
show_titles = show_titles[0]
|
||||
output_folder = "./output/pecha_kucha"
|
||||
filename = Pptx(output_folder).generate(title, slide_duration, images, show_titles, titles)
|
||||
log.info(f"Generated presentation {filename}")
|
||||
return (filename,)
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(s, images, title, titles, slide_duration, show_titles):
|
||||
return float("NaN")
|
||||
@@ -0,0 +1,10 @@
|
||||
<mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
|
||||
<mc:Choice xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main" Requires="p14">
|
||||
<p:transition xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" spd="slow" advTm="{duration}" p14:dur="1000">
|
||||
</p:transition>
|
||||
</mc:Choice>
|
||||
<mc:Fallback>
|
||||
<p:transition xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" spd="slow" advTm="{duration}">
|
||||
</p:transition>
|
||||
</mc:Fallback>
|
||||
</mc:AlternateContent>
|
||||
Executable
+133
@@ -0,0 +1,133 @@
|
||||
import logging
|
||||
import os
|
||||
import torch
|
||||
|
||||
from pathlib import Path
|
||||
from PIL import Image
|
||||
from pptx import Presentation
|
||||
from pptx.dml.color import RGBColor
|
||||
from pptx.enum.text import PP_ALIGN
|
||||
from pptx.oxml import parse_xml
|
||||
from pptx.util import Inches, Pt
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Pptx:
|
||||
|
||||
duration_template = "oxml_duration_template.xml"
|
||||
pixels_per_inch = 96 # Subjective fixed value
|
||||
|
||||
def __init__(self, output_folder):
|
||||
self.output_folder = output_folder
|
||||
Path(self.output_folder).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def get_next_filepath(self, title):
|
||||
"""
|
||||
Generate the next filepath available by appending `_X`
|
||||
"""
|
||||
extension = 'pptx'
|
||||
filename = title.lower().replace(' ', '_')
|
||||
filepath = f"{self.output_folder}/{filename}.{extension}"
|
||||
if os.path.isfile(filepath):
|
||||
log.info(f"file exsists {filepath}")
|
||||
i = 1
|
||||
filepath = f"{self.output_folder}/{filename}_{i}.{extension}"
|
||||
while os.path.isfile(filepath):
|
||||
log.info(filepath)
|
||||
i = i+1
|
||||
filepath = f"{self.output_folder}/{filename}_{i}.{extension}"
|
||||
return filepath
|
||||
|
||||
def get_duration_fragment(self, duration=20):
|
||||
"""
|
||||
Get the duration xml fragment to add to each slide with automatic transition
|
||||
duration: slide duration in seconds
|
||||
returns: the xml fragment to add to the slide
|
||||
"""
|
||||
template_path = os.path.join(os.path.dirname(__file__), self.duration_template)
|
||||
with open(template_path) as f:
|
||||
xml_fragment = f.read()
|
||||
xml_fragment = xml_fragment.replace("{duration}", str(duration * 1000))
|
||||
return parse_xml(xml_fragment)
|
||||
|
||||
def add_presentation_title(self, root, title):
|
||||
"""
|
||||
Generate the first presentaiton slide
|
||||
"""
|
||||
title_slide = root.slides.add_slide(root.slide_layouts[0])
|
||||
|
||||
main_title = title_slide.shapes.title
|
||||
main_title.width = root.slide_width
|
||||
main_title.left = 0
|
||||
main_title.top = root.slide_height//2
|
||||
main_title.text = title
|
||||
main_title.text_frame.paragraphs[0].font.color.rgb = RGBColor(188, 194, 200)
|
||||
|
||||
sub_title = title_slide.placeholders[1]
|
||||
sub_title.width = root.slide_width
|
||||
sub_title.left = 0
|
||||
sub_title.top = root.slide_height - Pt(12) - Inches(0.2)
|
||||
sub_title.text = "Generated using ComfyUI-PechaKucha"
|
||||
sub_title.text_frame.paragraphs[0].font.color.rgb = RGBColor(188, 194, 200)
|
||||
sub_title.text_frame.paragraphs[0].font.size = Pt(12)
|
||||
|
||||
background = title_slide.background
|
||||
fill = background.fill
|
||||
fill.solid()
|
||||
fill.fore_color.rgb = RGBColor(2, 3, 3)
|
||||
|
||||
def generate(self, title, slide_duration, images, show_titles, titles):
|
||||
"""
|
||||
Generate the powerpoint presentation file
|
||||
Ref for slide types:
|
||||
0 -> title and subtitle
|
||||
1 -> title and content
|
||||
2 -> section header
|
||||
3 -> two content
|
||||
4 -> Comparison
|
||||
5 -> Title only
|
||||
6 -> Blank
|
||||
7 -> Content with caption
|
||||
8 -> Pic with caption
|
||||
"""
|
||||
log.debug(f"{title} Pecha Kucha generation with {len(images)} images and duration {slide_duration}")
|
||||
|
||||
root = Presentation()
|
||||
first_image = Image.open(images[0])
|
||||
width, height = first_image.size
|
||||
root.slide_width = Inches(width//self.pixels_per_inch)
|
||||
root.slide_height = Inches(height//self.pixels_per_inch)
|
||||
|
||||
self.add_presentation_title(root, title)
|
||||
|
||||
if show_titles:
|
||||
assert(len(images) == len(titles))
|
||||
|
||||
slide_layout = root.slide_layouts[0]
|
||||
left = top = Inches(0)
|
||||
width = root.slide_width
|
||||
|
||||
for i, image in enumerate(images):
|
||||
slide = root.slides.add_slide(slide_layout)
|
||||
|
||||
pic = slide.shapes.add_picture(image, left, top, width)
|
||||
# Send picture to background
|
||||
slide.shapes._spTree.remove(pic._element)
|
||||
slide.shapes._spTree.insert(2, pic._element)
|
||||
|
||||
if show_titles:
|
||||
slide.shapes.title.text = titles[i]
|
||||
slide.shapes.title.width = root.slide_width
|
||||
slide.shapes.title.left = 0
|
||||
slide.shapes.title.top = root.slide_height - Pt(16) - Inches(0.5)
|
||||
slide.shapes.title.text_frame.paragraphs[0].font.color.rgb = RGBColor(2, 3, 3)
|
||||
slide.shapes.title.text_frame.paragraphs[0].font.size = Pt(16)
|
||||
|
||||
# Adding automatic transition
|
||||
slide.element.insert(-1, self.get_duration_fragment(slide_duration))
|
||||
|
||||
filepath = self.get_next_filepath(title)
|
||||
root.save(filepath)
|
||||
|
||||
return filepath
|
||||
@@ -0,0 +1,2 @@
|
||||
python-pptx>=1.0.2
|
||||
reportlab>=4.4.0
|
||||
@@ -0,0 +1,48 @@
|
||||
import logging
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SplitPrompt:
|
||||
"""
|
||||
A simple node to split a prompt into a batch of prompt.
|
||||
Inspired from [ComfyUI-Inspire-Pack](https://github.com/ltdrdata/ComfyUI-Inspire-Pack)
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"prompt": (
|
||||
"STRING",
|
||||
{"multiline": True, "default": "First Prompt \nSecond Prompt", "tooltip": "A multiline prompt that will be split to batch generate"}
|
||||
)
|
||||
},
|
||||
"optional": {
|
||||
"split_on": (
|
||||
"STRING",
|
||||
{"default": '\n', "tooltip": "Will split the input prompt on this character"}
|
||||
),
|
||||
"trim": (
|
||||
"BOOLEAN",
|
||||
{"default": True, "tooltip": "Will trim prompts and remove empty ones"}
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
CATEGORY = "pecha_kucha"
|
||||
DESCRIPTION = "Split a prompt in a list of prompts"
|
||||
FUNCTION = "split"
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
RETURN_NAMES = ("Split Prompts",)
|
||||
RETURN_TYPES = ("STRING",)
|
||||
|
||||
@staticmethod
|
||||
def IS_CHANGED(prompt, split_on='\n', trim=True):
|
||||
return f"trim:{trim}_split:{split_on}_prompt:{prompt}"
|
||||
|
||||
@staticmethod
|
||||
def split(prompt, split_on='\n', trim=True):
|
||||
prompts = prompt.split(split_on)
|
||||
if trim:
|
||||
prompts = [prompt.strip() for prompt in prompts]
|
||||
return (prompts,)
|
||||
Reference in New Issue
Block a user