* Readme edits * Added docs for v1.1.0 Prompt Sequence JSONs * Improved prompt sequence files can now be used
113 lines
3.6 KiB
Python
113 lines
3.6 KiB
Python
# MBM's Music Visualizer: Prompt Sequence Loader
|
|
# Loads a Prompt Sequence from a JSON input file.
|
|
|
|
# Imports
|
|
import os
|
|
import json
|
|
from typing import Any
|
|
|
|
from nodes import CLIPTextEncode
|
|
|
|
from .mbmMVShared import PROMPT_SEQ_EXTENSIONS, promptSeqInputDir
|
|
from .mbmPrompt import MbmPrompt
|
|
from .mbmPromptSequenceData import PromptSequenceData
|
|
|
|
# Classes
|
|
class PromptSequenceLoader:
|
|
"""
|
|
Loads a Prompt Sequence from a JSON input file.
|
|
"""
|
|
# Class Constants
|
|
KEY_DEFAULTS = "defaults"
|
|
KEY_SEQUENCE = "sequence"
|
|
KEY_POSITIVE = "positive"
|
|
KEY_NEGATIVE = "negative"
|
|
KEY_TIMECODE = "timecode"
|
|
|
|
RETURN_TYPES = ("PROMPT_SEQ", )
|
|
RETURN_NAMES = ("PROMPTS", )
|
|
FUNCTION = "process"
|
|
CATEGORY = "MBMnodes/Prompts"
|
|
|
|
# Constructor
|
|
def __init__(self):
|
|
pass
|
|
|
|
# ComfyUI Functions
|
|
@classmethod
|
|
def INPUT_TYPES(s):
|
|
inputDir = promptSeqInputDir()
|
|
localFiles = [f for f in os.listdir(inputDir) if (os.path.isfile(os.path.join(inputDir, f)) and (os.path.splitext(f)[1].strip(".").lower() in PROMPT_SEQ_EXTENSIONS))]
|
|
|
|
return {
|
|
"required": {
|
|
"filepath": (sorted(localFiles), ),
|
|
"clip": ("CLIP", )
|
|
}
|
|
}
|
|
|
|
def process(self, filepath: str, clip) -> list[MbmPrompt]:
|
|
# Load the prompt sequence data
|
|
jsonPath = os.path.join(promptSeqInputDir(), filepath)
|
|
with open(jsonPath, "r") as file:
|
|
promptData = json.load(file)
|
|
|
|
# Validate the JSON
|
|
self.validateJson(promptData)
|
|
|
|
# Check any prompts were provided
|
|
if len(promptData[self.KEY_SEQUENCE]) == 0:
|
|
# Report and return
|
|
print(f"No prompts provided in the `sequence` for: {jsonPath}")
|
|
return ([], )
|
|
|
|
# Create the text encoder
|
|
textEncoder = CLIPTextEncode()
|
|
|
|
# Loop through the data
|
|
promptsOut: list[MbmPrompt] = []
|
|
promptSet: dict[str, Any]
|
|
for promptSet in promptData[self.KEY_SEQUENCE]:
|
|
# Get the current prompts
|
|
curPosPrompt = promptSet.get(
|
|
self.KEY_POSITIVE,
|
|
promptData[self.KEY_DEFAULTS][self.KEY_POSITIVE]
|
|
)
|
|
curNegPrompt = promptSet.get(
|
|
self.KEY_NEGATIVE,
|
|
promptData[self.KEY_DEFAULTS][self.KEY_NEGATIVE]
|
|
)
|
|
|
|
# Create the packaged prompt
|
|
curPrompt = MbmPrompt.fromComfyUiPrompts(
|
|
textEncoder.encode(clip=clip, text=curPosPrompt)[0],
|
|
textEncoder.encode(clip=clip, text=curNegPrompt)[0]
|
|
)
|
|
|
|
# Add additional data if present
|
|
PromptSequenceData.tryToAddDataFromJson(curPrompt, promptSet)
|
|
|
|
# Record the prompt
|
|
promptsOut.append(curPrompt)
|
|
|
|
return (promptsOut, )
|
|
|
|
# Functions
|
|
def validateJson(self, json):
|
|
"""
|
|
Validates the given JSON data or throws a `ValueError`.
|
|
"""
|
|
# Validate the JSON
|
|
if self.KEY_DEFAULTS not in json:
|
|
raise ValueError("No `defaults` provided in the Prompt Sequence file.")
|
|
else:
|
|
# Check that the defaults have the required keys
|
|
if self.KEY_POSITIVE not in json[self.KEY_DEFAULTS]:
|
|
raise ValueError("No `positive` prompt provided in the defaults of the Prompt Sequence file.")
|
|
|
|
if self.KEY_NEGATIVE not in json[self.KEY_DEFAULTS]:
|
|
raise ValueError("No `negative` prompt provided in the defaults of the Prompt Sequence file.")
|
|
|
|
if self.KEY_SEQUENCE not in json:
|
|
raise ValueError("No `sequence` provided in the Prompt Sequence file.")
|