diff --git a/__init__.py b/__init__.py index 5ddafc3..5740b88 100644 --- a/__init__.py +++ b/__init__.py @@ -278,6 +278,7 @@ from .nodes.preprocessors.pose import PoseInterpolator from .nodes.doom.doom import Doom +from .nodes.misc.misc_nodes import WhisperToPromptTravel HAS_ADVANCED_LIVE_PORTRAIT = os.path.exists(os.path.join(os.path.dirname(os.path.dirname(__file__)), "ComfyUI-AdvancedLivePortrait")) @@ -304,6 +305,7 @@ NODE_CLASS_MAPPINGS = { #"PoseInterpolator": PoseInterpolator, "Doom": Doom, + "WhisperToPromptTravel": WhisperToPromptTravel, "ManualFeaturePipe": ManualFeaturePipe, "ManualFeatureFromPipe": ManualFeatureFromPipe, diff --git a/nodes/misc/misc_nodes.py b/nodes/misc/misc_nodes.py new file mode 100644 index 0000000..7a74179 --- /dev/null +++ b/nodes/misc/misc_nodes.py @@ -0,0 +1,41 @@ +import json +class WhisperToPromptTravel: + """Converts Whisper alignment data to prompt travel format""" + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "segments_alignment": ("STRING", {"multiline": True}), # JSON string of segment alignments + "fps": ("FLOAT", {"default": 24.0, "min": 0.1, "max": 120.0}), + } + } + + RETURN_TYPES = ("STRING",) + FUNCTION = "convert" + CATEGORY = "misc" + + def convert(self, segments_alignment, fps): + import json + + # Parse the alignment data + try: + segments = json.loads(segments_alignment) + except json.JSONDecodeError: + raise ValueError("Invalid segments_alignment JSON format") + + # Create frame-to-prompt mapping + prompt_travel = {} + + for segment in segments: + # Convert time to frame number + frame = int(segment["start"] * fps) + prompt_travel[str(frame)] = segment["value"] + + # Convert to string format + result = "{\n" + for frame, prompt in sorted(prompt_travel.items(), key=lambda x: int(x[0])): + result += f'"{frame}":"{prompt}",\n' + result = result.rstrip(",\n") + "\n}" + + return (result,)