From 5b4740d3a25da470a135db76d2d6fbcd6cb381c1 Mon Sep 17 00:00:00 2001 From: DragonDiffusionbyBoyo Date: Sat, 15 Nov 2025 20:32:43 +0000 Subject: [PATCH] Add files via upload --- __init__.py | 177 +++++++++++++++------------- boyo_storyboard_output.py | 93 +++++++++++++++ boyo_storyboard_prompt.py | 241 ++++++++++++++++++++++++++++++++++++++ pyproject.toml | 4 +- readme.md | 128 ++++++++++++++++++-- requirements.txt | 1 + 6 files changed, 550 insertions(+), 94 deletions(-) create mode 100644 boyo_storyboard_output.py create mode 100644 boyo_storyboard_prompt.py diff --git a/__init__.py b/__init__.py index c09b256..8929a84 100644 --- a/__init__.py +++ b/__init__.py @@ -1,82 +1,95 @@ -from .boyolatent import NODE_CLASS_MAPPINGS as BOYOLATENT_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as BOYOLATENT_DISPLAY_NAME_MAPPINGS -from .boyo_vae_decode import BoyoVAEDecode -from .boyo_saver import BoyoSaver -from .boyo_load_image_list import BoyoLoadImageList -from .BoyoAudioEval import BoyoAudioEval -from .boyo_paired_saver import BoyoPairedSaver -from .boyo_tiled_vae_decode import BoyoTiledVAEDecode -from .Boyomandelbrot import NODE_CLASS_MAPPINGS as MANDELBROT_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as MANDELBROT_DISPLAY_NAME_MAPPINGS -from .BoyoBastardLoops import NODE_CLASS_MAPPINGS as BASTARDLOOPS_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as BASTARDLOOPS_DISPLAY_NAME_MAPPINGS -from .BoyoPromptLoop import NODE_CLASS_MAPPINGS as PROMPTLOOP_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as PROMPTLOOP_DISPLAY_NAME_MAPPINGS -from .BoyoLoopCollector import NODE_CLASS_MAPPINGS as LOOPCOLLECTOR_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as LOOPCOLLECTOR_DISPLAY_NAME_MAPPINGS -from .boyo_video_paired_saver import BoyoVideoPairedSaver, BoyoVideoSaver -# Import the existing custom nodes -from .BoyoControl import NODE_CLASS_MAPPINGS as BOYOCONTROL_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as BOYOCONTROL_DISPLAY_NAME_MAPPINGS - -# Import the new BoyoImageGrab node -from .boyo_image_grab import NODE_CLASS_MAPPINGS as BOYOIMAGEGRAB_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as BOYOIMAGEGRAB_DISPLAY_NAME_MAPPINGS - -# Import the paired image saver nodes -from .boyo_paired_image_saver import BoyoPairedImageSaver, BoyoIncontextSaver -from .boyo_qwen_grounding import BoyoQwenVLGrounding -from .boyo_vision import BoyoVision -# Import Lora Loader stuff -from .boyo_lora_json_builder import BoyoLoRAJSONBuilder -from .boyo_lora_paired_loader import BoyoLoRAPairedLoader -from .boyo_lora_config_inspector import BoyoLoRAConfigInspector - -NODE_CLASS_MAPPINGS = { - "BoyoVAEDecode": BoyoVAEDecode, - "BoyoSaver": BoyoSaver, - "BoyoLoadImageList": BoyoLoadImageList, - "BoyoAudioEval": BoyoAudioEval, - "BoyoTiledVAEDecode": BoyoTiledVAEDecode, - "BoyoPairedSaver": BoyoPairedSaver, - "BoyoPairedImageSaver": BoyoPairedImageSaver, - "BoyoVideoPairedSaver": BoyoVideoPairedSaver, - "BoyoVideoSaver": BoyoVideoSaver, - "BoyoQwenVLGrounding": BoyoQwenVLGrounding, - "BoyoVision": BoyoVision, - "BoyoLoRAJSONBuilder": BoyoLoRAJSONBuilder, - "BoyoLoRAPairedLoader": BoyoLoRAPairedLoader, - "BoyoLoRAConfigInspector": BoyoLoRAConfigInspector, - "BoyoIncontextSaver": BoyoIncontextSaver -} - -# Update the mappings with all custom nodes -NODE_CLASS_MAPPINGS.update(BOYOLATENT_CLASS_MAPPINGS) -NODE_CLASS_MAPPINGS.update(MANDELBROT_CLASS_MAPPINGS) -NODE_CLASS_MAPPINGS.update(BOYOCONTROL_CLASS_MAPPINGS) -NODE_CLASS_MAPPINGS.update(BASTARDLOOPS_CLASS_MAPPINGS) -NODE_CLASS_MAPPINGS.update(PROMPTLOOP_CLASS_MAPPINGS) -NODE_CLASS_MAPPINGS.update(LOOPCOLLECTOR_CLASS_MAPPINGS) -NODE_CLASS_MAPPINGS.update(BOYOIMAGEGRAB_CLASS_MAPPINGS) - -NODE_DISPLAY_NAME_MAPPINGS = { - "BoyoVAEDecode": "Boyo VAE Decode", - "BoyoSaver": "Boyo Saver", - "BoyoLoadImageList": "Boyo Load Image List", - "BoyoAudioEval": "Boyo Audio Evaluator", - "BoyoTiledVAEDecode": "Boyo Tiled VAE Decode", - "BoyoPairedSaver": "Boyo Paired Saver", - "BoyoPairedImageSaver": "Boyo Paired Image Saver", - "BoyoVideoPairedSaver": "Boyo Video Paired Saver", - "BoyoVideoSaver": "Boyo Video Saver", - "BoyoLoRAJSONBuilder": "Boyo LoRA JSON Builder", - "BoyoLoRAPairedLoader": "Boyo LoRA Paired Loader", - "BoyoLoRAConfigInspector": "Boyo LoRA Config Inspector", - "BoyoQwenVLGrounding": "Boyo Qwen VL Grounding", - "BoyoVision": "Boyo Vision", - "BoyoIncontextSaver": "Boyo Incontext Saver" -} - -# Update the display name mappings with all custom nodes -NODE_DISPLAY_NAME_MAPPINGS.update(BOYOLATENT_DISPLAY_NAME_MAPPINGS) -NODE_DISPLAY_NAME_MAPPINGS.update(MANDELBROT_DISPLAY_NAME_MAPPINGS) -NODE_DISPLAY_NAME_MAPPINGS.update(BOYOCONTROL_DISPLAY_NAME_MAPPINGS) -NODE_DISPLAY_NAME_MAPPINGS.update(BASTARDLOOPS_DISPLAY_NAME_MAPPINGS) -NODE_DISPLAY_NAME_MAPPINGS.update(PROMPTLOOP_DISPLAY_NAME_MAPPINGS) -NODE_DISPLAY_NAME_MAPPINGS.update(LOOPCOLLECTOR_DISPLAY_NAME_MAPPINGS) -NODE_DISPLAY_NAME_MAPPINGS.update(BOYOIMAGEGRAB_DISPLAY_NAME_MAPPINGS) - -__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] \ No newline at end of file +from .boyolatent import NODE_CLASS_MAPPINGS as BOYOLATENT_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as BOYOLATENT_DISPLAY_NAME_MAPPINGS +from .boyo_vae_decode import BoyoVAEDecode +from .boyo_saver import BoyoSaver +from .boyo_load_image_list import BoyoLoadImageList +from .BoyoAudioEval import BoyoAudioEval +from .boyo_paired_saver import BoyoPairedSaver +from .boyo_tiled_vae_decode import BoyoTiledVAEDecode +from .Boyomandelbrot import NODE_CLASS_MAPPINGS as MANDELBROT_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as MANDELBROT_DISPLAY_NAME_MAPPINGS +from .BoyoBastardLoops import NODE_CLASS_MAPPINGS as BASTARDLOOPS_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as BASTARDLOOPS_DISPLAY_NAME_MAPPINGS +from .BoyoPromptLoop import NODE_CLASS_MAPPINGS as PROMPTLOOP_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as PROMPTLOOP_DISPLAY_NAME_MAPPINGS +from .BoyoLoopCollector import NODE_CLASS_MAPPINGS as LOOPCOLLECTOR_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as LOOPCOLLECTOR_DISPLAY_NAME_MAPPINGS +from .boyo_video_paired_saver import BoyoVideoPairedSaver, BoyoVideoSaver +# Import the existing custom nodes +from .BoyoControl import NODE_CLASS_MAPPINGS as BOYOCONTROL_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as BOYOCONTROL_DISPLAY_NAME_MAPPINGS + +# Import the new BoyoImageGrab node +from .boyo_image_grab import NODE_CLASS_MAPPINGS as BOYOIMAGEGRAB_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS as BOYOIMAGEGRAB_DISPLAY_NAME_MAPPINGS + +# Import the paired image saver nodes +from .boyo_paired_image_saver import BoyoPairedImageSaver, BoyoIncontextSaver +from .boyo_qwen_grounding import BoyoQwenVLGrounding +from .boyo_vision import BoyoVision +# Import Lora Loader stuff +from .boyo_lora_json_builder import BoyoLoRAJSONBuilder +from .boyo_lora_paired_loader import BoyoLoRAPairedLoader +from .boyo_lora_config_inspector import BoyoLoRAConfigInspector + +# Import the BoyoImageCrop node +from .boyo_image_crop import BoyoImageCrop + +#Import the Video-Image-Storyboard Node +from .boyo_storyboard_prompt import BoyoStoryboardPrompt +from .boyo_storyboard_output import BoyoStoryboardOutput + +NODE_CLASS_MAPPINGS = { + "BoyoVAEDecode": BoyoVAEDecode, + "BoyoSaver": BoyoSaver, + "BoyoLoadImageList": BoyoLoadImageList, + "BoyoAudioEval": BoyoAudioEval, + "BoyoTiledVAEDecode": BoyoTiledVAEDecode, + "BoyoPairedSaver": BoyoPairedSaver, + "BoyoPairedImageSaver": BoyoPairedImageSaver, + "BoyoVideoPairedSaver": BoyoVideoPairedSaver, + "BoyoVideoSaver": BoyoVideoSaver, + "BoyoQwenVLGrounding": BoyoQwenVLGrounding, + "BoyoVision": BoyoVision, + "BoyoLoRAJSONBuilder": BoyoLoRAJSONBuilder, + "BoyoLoRAPairedLoader": BoyoLoRAPairedLoader, + "BoyoLoRAConfigInspector": BoyoLoRAConfigInspector, + "BoyoIncontextSaver": BoyoIncontextSaver, + "BoyoStoryboardPrompt": BoyoStoryboardPrompt, + "BoyoStoryboardOutput": BoyoStoryboardOutput, + "BoyoImageCrop": BoyoImageCrop +} + +# Update the mappings with all custom nodes +NODE_CLASS_MAPPINGS.update(BOYOLATENT_CLASS_MAPPINGS) +NODE_CLASS_MAPPINGS.update(MANDELBROT_CLASS_MAPPINGS) +NODE_CLASS_MAPPINGS.update(BOYOCONTROL_CLASS_MAPPINGS) +NODE_CLASS_MAPPINGS.update(BASTARDLOOPS_CLASS_MAPPINGS) +NODE_CLASS_MAPPINGS.update(PROMPTLOOP_CLASS_MAPPINGS) +NODE_CLASS_MAPPINGS.update(LOOPCOLLECTOR_CLASS_MAPPINGS) +NODE_CLASS_MAPPINGS.update(BOYOIMAGEGRAB_CLASS_MAPPINGS) + +NODE_DISPLAY_NAME_MAPPINGS = { + "BoyoVAEDecode": "Boyo VAE Decode", + "BoyoSaver": "Boyo Saver", + "BoyoLoadImageList": "Boyo Load Image List", + "BoyoAudioEval": "Boyo Audio Evaluator", + "BoyoTiledVAEDecode": "Boyo Tiled VAE Decode", + "BoyoPairedSaver": "Boyo Paired Saver", + "BoyoPairedImageSaver": "Boyo Paired Image Saver", + "BoyoVideoPairedSaver": "Boyo Video Paired Saver", + "BoyoVideoSaver": "Boyo Video Saver", + "BoyoLoRAJSONBuilder": "Boyo LoRA JSON Builder", + "BoyoLoRAPairedLoader": "Boyo LoRA Paired Loader", + "BoyoLoRAConfigInspector": "Boyo LoRA Config Inspector", + "BoyoQwenVLGrounding": "Boyo Qwen VL Grounding", + "BoyoVision": "Boyo Vision", + "BoyoIncontextSaver": "Boyo Incontext Saver", + "BoyoStoryboardPrompt": "Boyo Storyboard Prompt", + "BoyoStoryboardOutput": "Boyo Storyboard Output", + "BoyoImageCrop": "Boyo Image Crop" +} + +# Update the display name mappings with all custom nodes +NODE_DISPLAY_NAME_MAPPINGS.update(BOYOLATENT_DISPLAY_NAME_MAPPINGS) +NODE_DISPLAY_NAME_MAPPINGS.update(MANDELBROT_DISPLAY_NAME_MAPPINGS) +NODE_DISPLAY_NAME_MAPPINGS.update(BOYOCONTROL_DISPLAY_NAME_MAPPINGS) +NODE_DISPLAY_NAME_MAPPINGS.update(BASTARDLOOPS_DISPLAY_NAME_MAPPINGS) +NODE_DISPLAY_NAME_MAPPINGS.update(PROMPTLOOP_DISPLAY_NAME_MAPPINGS) +NODE_DISPLAY_NAME_MAPPINGS.update(LOOPCOLLECTOR_DISPLAY_NAME_MAPPINGS) +NODE_DISPLAY_NAME_MAPPINGS.update(BOYOIMAGEGRAB_DISPLAY_NAME_MAPPINGS) + +__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] diff --git a/boyo_storyboard_output.py b/boyo_storyboard_output.py new file mode 100644 index 0000000..4d28446 --- /dev/null +++ b/boyo_storyboard_output.py @@ -0,0 +1,93 @@ +import json + +class BoyoStoryboardOutput: + """ + Output node for parsing structured storyboard JSON from ollama into separate prompt outputs. + Takes JSON input and provides 12 separate text outputs (6 image + 6 video prompts). + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "json_input": ("STRING", { + "multiline": True, + "default": "", + "placeholder": "Paste JSON output from ollama here..." + }), + } + } + + RETURN_TYPES = ("STRING",) * 12 + RETURN_NAMES = ( + "image_scene1", "image_scene2", "image_scene3", "image_scene4", "image_scene5", "image_scene6", + "video_scene1", "video_scene2", "video_scene3", "video_scene4", "video_scene5", "video_scene6" + ) + FUNCTION = "parse_storyboard" + CATEGORY = "Boyo/Storyboard" + + def parse_storyboard(self, json_input): + """ + Parse JSON storyboard into separate prompt outputs. + Returns 12 strings: 6 image prompts + 6 video prompts. + """ + + # Initialize empty outputs + outputs = [""] * 12 + + try: + # Clean and parse the JSON + json_text = json_input.strip() + + # Handle potential markdown code blocks + if json_text.startswith("```json"): + json_text = json_text.replace("```json", "").replace("```", "").strip() + elif json_text.startswith("```"): + json_text = json_text.replace("```", "").strip() + + # Parse the JSON + data = json.loads(json_text) + + # Extract image prompts (outputs 0-5) + if "imagePrompts" in data: + image_prompts = data["imagePrompts"] + for i in range(1, 7): # scene1 through scene6 + scene_key = f"scene{i}" + if scene_key in image_prompts: + outputs[i-1] = image_prompts[scene_key] + else: + outputs[i-1] = f"[Missing image prompt for scene {i}]" + + # Extract video prompts (outputs 6-11) + if "videoPrompts" in data: + video_prompts = data["videoPrompts"] + for i in range(1, 7): # scene1 through scene6 + scene_key = f"scene{i}" + if scene_key in video_prompts: + outputs[5+i] = video_prompts[scene_key] # Start at index 6 + else: + outputs[5+i] = f"[Missing video prompt for scene {i}]" + + except json.JSONDecodeError as e: + # If JSON parsing fails, provide error information + error_msg = f"[JSON Parse Error: {str(e)}]" + for i in range(12): + outputs[i] = error_msg + + except Exception as e: + # Handle any other errors + error_msg = f"[Parse Error: {str(e)}]" + for i in range(12): + outputs[i] = error_msg + + return tuple(outputs) + + +# Node mappings for ComfyUI +NODE_CLASS_MAPPINGS = { + "BoyoStoryboardOutput": BoyoStoryboardOutput +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "BoyoStoryboardOutput": "Boyo Storyboard Output" +} diff --git a/boyo_storyboard_prompt.py b/boyo_storyboard_prompt.py new file mode 100644 index 0000000..3b80969 --- /dev/null +++ b/boyo_storyboard_prompt.py @@ -0,0 +1,241 @@ +class BoyoStoryboardPrompt: + """ + Input node for generating structured storyboard prompts using ollama models. + Provides system prompt selection and user inputs for story generation. + """ + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "story_concept": ("STRING", { + "multiline": True, + "default": "A brave knight embarks on a quest to save a village from an ancient dragon", + "placeholder": "Describe your story concept..." + }), + "main_character": ("STRING", { + "multiline": True, + "default": "A noble knight in gleaming armor with determined eyes", + "placeholder": "Describe the main character..." + }), + "style_setting": ("STRING", { + "multiline": True, + "default": "Medieval fantasy, cinematic lighting, detailed digital art", + "placeholder": "Art style, setting, mood..." + }), + "image_trigger_word": ("STRING", { + "default": "Next Scene:", + "placeholder": "Trigger word for image model (e.g., 'Next Scene:', 'Character:', etc.)" + }), + "video_trigger_word": ("STRING", { + "default": "Next Scene:", + "placeholder": "Trigger word for video model (e.g., 'Motion:', 'Camera:', etc.)" + }), + "system_prompt_type": (["System Prompt 1 (6 Scenes)", "System Prompt 2 (Traveling Prompts)"], { + "default": "System Prompt 1 (6 Scenes)" + }), + "traveling_prompt_count": ("INT", { + "default": 6, + "min": 1, + "max": 20, + "step": 1, + "display": "number" + }), + }, + "optional": { + "additional_details": ("STRING", { + "multiline": True, + "default": "", + "placeholder": "Any additional instructions..." + }), + } + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("formatted_prompt",) + FUNCTION = "generate_prompt" + CATEGORY = "Boyo/Storyboard" + + def generate_prompt(self, story_concept, main_character, style_setting, image_trigger_word, video_trigger_word, system_prompt_type, traveling_prompt_count, additional_details=""): + """ + Generate a formatted prompt for ollama based on the system prompt type and user inputs. + """ + + # System Prompt selection + if system_prompt_type == "System Prompt 1 (6 Scenes)": + system_prompt = self._get_system_prompt_1(image_trigger_word, video_trigger_word) + elif system_prompt_type == "System Prompt 2 (Traveling Prompts)": + system_prompt = self._get_system_prompt_2(image_trigger_word, video_trigger_word, traveling_prompt_count) + else: + system_prompt = self._get_system_prompt_1(image_trigger_word, video_trigger_word) # Default fallback + + # Construct the user input section + user_input = f""" +Story Concept: {story_concept} + +Main Character: {main_character} + +Style & Setting: {style_setting} + +Image Trigger Word: {image_trigger_word} + +Video Trigger Word: {video_trigger_word}""" + + # Add traveling prompt count for System Prompt 2 + if system_prompt_type == "System Prompt 2 (Traveling Prompts)": + user_input += f"\n\nTraveling Prompt Count: {traveling_prompt_count}" + + if additional_details.strip(): + user_input += f"\n\nAdditional Details: {additional_details}" + + # Combine system prompt and user input + formatted_prompt = f"{system_prompt}\n\n{user_input}" + + return (formatted_prompt,) + + def _get_system_prompt_2(self, image_trigger_word, video_trigger_word, traveling_prompt_count): + """ + System Prompt 2: Generates 6 image prompts and 6 video prompts, each containing multiple traveling sub-prompts. + """ + return f"""You are an expert AI storyteller and prompt engineer, tasked with creating a 6-scene visual storyboard with traveling video prompts. Your goal is to break down the provided story concept into 6 distinct scenes for images, plus 6 video scenes where each contains {traveling_prompt_count} traveling sub-prompts. + +For each output, you must provide: +1. 6 IMAGE PROMPTS: Detailed, single-line descriptions focused on composition, lighting, subjects, environment - NO camera movements +2. 6 VIDEO PROMPTS: Each containing {traveling_prompt_count} traveling sub-prompts separated by newlines (\\n), where each sub-prompt represents ~5 seconds of video + +CRITICAL FORMATTING REQUIREMENTS: +- Output ONLY valid JSON format +- No explanatory text outside the JSON structure +- Each image prompt must be a single line with NO line breaks +- Each video prompt contains {traveling_prompt_count} sub-prompts separated by \\n newlines +- Use proper JSON escaping for quotes and special characters +- Start each image prompt with: "{image_trigger_word}" +- Start each video sub-prompt with: "{video_trigger_word}" + +Structure your response as: +{{ + "imagePrompts": {{ + "scene1": "{image_trigger_word} detailed static scene description...", + "scene2": "{image_trigger_word} detailed static scene description...", + "scene3": "{image_trigger_word} detailed static scene description...", + "scene4": "{image_trigger_word} detailed static scene description...", + "scene5": "{image_trigger_word} detailed static scene description...", + "scene6": "{image_trigger_word} detailed static scene description..." + }}, + "videoPrompts": {{ + "scene1": "{video_trigger_word} first sub-prompt for scene 1\\n{video_trigger_word} second sub-prompt for scene 1\\n{video_trigger_word} third sub-prompt for scene 1", + "scene2": "{video_trigger_word} first sub-prompt for scene 2\\n{video_trigger_word} second sub-prompt for scene 2\\n{video_trigger_word} third sub-prompt for scene 2", + "scene3": "{video_trigger_word} first sub-prompt for scene 3\\n{video_trigger_word} second sub-prompt for scene 3\\n{video_trigger_word} third sub-prompt for scene 3", + "scene4": "{video_trigger_word} first sub-prompt for scene 4\\n{video_trigger_word} second sub-prompt for scene 4\\n{video_trigger_word} third sub-prompt for scene 4", + "scene5": "{video_trigger_word} first sub-prompt for scene 5\\n{video_trigger_word} second sub-prompt for scene 5\\n{video_trigger_word} third sub-prompt for scene 5", + "scene6": "{video_trigger_word} first sub-prompt for scene 6\\n{video_trigger_word} second sub-prompt for scene 6\\n{video_trigger_word} third sub-prompt for scene 6" + }} +}} + +SCENE PROGRESSION GUIDELINES (6 image scenes): +- Scene 1: Introduction/Setup - establish character and setting +- Scene 2: Inciting incident - something changes or begins +- Scene 3: Rising action - conflict develops +- Scene 4: Climax - peak of tension/action +- Scene 5: Resolution - conflict resolves +- Scene 6: Conclusion - aftermath/new normal + +IMAGE PROMPT GUIDELINES: +- Focus on static visual composition, lighting, mood, environment, character positioning +- Include artistic style, color palette, atmosphere +- NO camera movements, motion blur, or temporal effects + +VIDEO TRAVELING PROMPT GUIDELINES: +- Each scene gets {traveling_prompt_count} sequential sub-prompts (each ~5 seconds) +- Sub-prompts within a scene should flow smoothly together +- Include camera movements (pan, tilt, zoom, dolly, tracking, handheld) +- Add motion elements, timing effects, cinematic techniques +- Each sub-prompt flows into the next within the scene +- Maintain scene narrative coherence across all {traveling_prompt_count} sub-prompts + +CONSISTENCY REQUIREMENTS: +- Maintain character appearance, clothing, and key features across all scenes +- Keep consistent art style, lighting mood, and color palette +- Each scene should flow logically to the next +- Within each scene, all {traveling_prompt_count} sub-prompts should maintain visual continuity""" + + def _get_system_prompt_1(self, image_trigger_word, video_trigger_word): + """ + System Prompt 1: Generates 6 image prompts and 6 corresponding video prompts with configurable trigger words. + """ + return f"""You are an expert AI storyteller and prompt engineer, tasked with creating a 6-scene visual storyboard for image and video generation. Your goal is to break down the provided story concept into 6 distinct, sequential scenes that tell a complete narrative arc. + +For each scene, you must provide: +1. An IMAGE PROMPT: A detailed, single-line description focused on composition, lighting, subjects, environment, and visual elements - NO camera movements or motion descriptions +2. A VIDEO PROMPT: The same scene but enhanced with camera movements, motion, dynamics, and cinematic techniques + +CRITICAL FORMATTING REQUIREMENTS: +- Output ONLY valid JSON format +- No explanatory text outside the JSON structure +- Each prompt must be a single line with NO line breaks within the prompt text +- Use proper JSON escaping for quotes and special characters +- Start each image prompt with: "{image_trigger_word}" +- Start each video prompt with: "{video_trigger_word}" + +Structure your response as: +{{ + "imagePrompts": {{ + "scene1": "{image_trigger_word} detailed static scene description...", + "scene2": "{image_trigger_word} detailed static scene description...", + "scene3": "{image_trigger_word} detailed static scene description...", + "scene4": "{image_trigger_word} detailed static scene description...", + "scene5": "{image_trigger_word} detailed static scene description...", + "scene6": "{image_trigger_word} detailed static scene description..." + }}, + "videoPrompts": {{ + "scene1": "{video_trigger_word} scene with camera movement and motion...", + "scene2": "{video_trigger_word} scene with camera movement and motion...", + "scene3": "{video_trigger_word} scene with camera movement and motion...", + "scene4": "{video_trigger_word} scene with camera movement and motion...", + "scene5": "{video_trigger_word} scene with camera movement and motion...", + "scene6": "{video_trigger_word} scene with camera movement and motion..." + }} +}} + +SCENE PROGRESSION GUIDELINES: +- Scene 1: Introduction/Setup - establish character and setting +- Scene 2: Inciting incident - something changes or begins +- Scene 3: Rising action - conflict develops +- Scene 4: Climax - peak of tension/action +- Scene 5: Resolution - conflict resolves +- Scene 6: Conclusion - aftermath/new normal + +IMAGE PROMPT GUIDELINES: +- Focus on static visual composition and framing +- Describe lighting, mood, environment, character positioning +- Include artistic style, color palette, atmosphere +- Specify depth of field, focus points, visual hierarchy +- NO camera movements (no pans, zooms, tracks, etc.) +- NO motion blur or temporal effects +- Think like a photographer capturing a single perfect moment + +VIDEO PROMPT GUIDELINES: +- Start with the image prompt foundation +- Add camera movements (pan, tilt, zoom, dolly, tracking shots, handheld) +- Include motion elements (character movement, environmental motion) +- Specify timing (slow-motion, speed ramping, quick cuts) +- Add cinematic techniques (rack focus, whip pans, dramatic angles) +- Include motion blur, depth shifts, dynamic lighting changes +- Think like a cinematographer directing camera movement + +CONSISTENCY REQUIREMENTS: +- Maintain character appearance, clothing, and key features across all scenes +- Keep consistent art style, lighting mood, and color palette +- Ensure environmental/setting continuity unless story requires location change +- Each scene should flow logically to the next +- Character positioning and state should make sense in sequence""" + + +# Node mappings for ComfyUI +NODE_CLASS_MAPPINGS = { + "BoyoStoryboardPrompt": BoyoStoryboardPrompt +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "BoyoStoryboardPrompt": "Boyo Storyboard Prompt" +} diff --git a/pyproject.toml b/pyproject.toml index 641c91c..1f41a3a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "boyonodes" -description = "Essential nodes for semantic image editing workflows with Kontext, Qwen Image Edit, and HiDream E1.1 models. Features automated iterative editing with Boyo Image Grab, organised dataset creation with paired image/prompt savers, and comprehensive file management tools. Perfect for batch processing, training data preparation, and streamlined semantic editing pipelines. Added Uncensored Qwen VL abliterated model node and downloader! Added BoyoLora loader and utils" -version = "3.0.0" +description = "Essential nodes for semantic image editing workflows with Kontext, Qwen Image Edit, and HiDream E1.1 models. Features automated iterative editing with Boyo Image Grab, organised dataset creation with paired image/prompt savers, and comprehensive file management tools. Perfect for batch processing, training data preparation, and streamlined semantic editing pipelines. Added Uncensored Qwen VL abliterated model node and downloader! Added BoyoLora loader and utils. Added Ollama Image and Video Story boards for Qwen edit and Wan video but not limited to." +version = "3.5.0" license = {file = "LICENSE"} dependencies = ["torchvision", "numpy", "pillow"] diff --git a/readme.md b/readme.md index 8a9186a..8475958 100644 --- a/readme.md +++ b/readme.md @@ -28,7 +28,7 @@ Automatically monitors directories and grabs the most recent image file - perfec - `timestamp`: Modification timestamp **Usage:** -Perfect for workflows like: Original → "add a hat" → "make it red" → "change lighting" where each step automatically feeds into the next. +Perfect for workflows like: Original â†' "add a hat" â†' "make it red" â†' "change lighting" where each step automatically feeds into the next. ### Boyo Paired Image Saver Saves original and edited image pairs with organised sequential naming - essential for creating datasets from semantic editing workflows. @@ -153,22 +153,101 @@ Preview LoRA configuration contents before loading for informed decision-making. **Sample Output:** ``` -📋 LoRA Configuration: Character_Cyborg -🎯 LoRA FILES: - 📈 High Noise: ✅ cyborg_char_v2.safetensors - 📉 Low Noise: ✅ cyborg_char_v2_low.safetensors - 🎭 Type: PAIRED LoRA (different high/low files) +ðŸ"‹ LoRA Configuration: Character_Cyborg +🎯 LoRA FILES: + ðŸ"ˆ High Noise: ✅ cyborg_char_v2.safetensors + ðŸ"‰ Low Noise: ✅ cyborg_char_v2_low.safetensors + 🎭 Type: PAIRED LoRA (different high/low files) -💬 PROMPTS (3 total): +ðŸ'¬ PROMPTS (3 total): 1. cyborg woman, metallic skin, glowing eyes 2. android female, chrome details, futuristic 3. robotic humanoid, synthetic appearance -💡 USAGE RECOMMENDATIONS: - • Use 'Cycle Through' for variety - • Use 'Random' for experimentation +ðŸ'¡ USAGE RECOMMENDATIONS: + • Use 'Cycle Through' for variety + • Use 'Random' for experimentation ``` +## AI Storyboard Generation System + +Automated storyboard prompt generation using ollama models for consistent multi-scene video workflows. Perfect for Next Scene LoRA workflows and traveling prompt video generation. + +### Boyo Storyboard Prompt +Intelligent prompt generator that creates structured storyboard sequences using local ollama models. + +**Key Features:** +- **Model-agnostic trigger words** - works with any LoRA or video model +- **Two generation modes**: Standard 6-scene storyboards or traveling prompt sequences +- **Automatic JSON formatting** for clean workflow integration +- **Consistent character/style maintenance** across all scenes +- **Optimised for abliterated coder models** (Qwen 30B A3B Coder recommended) + +**Inputs:** +- `story_concept`: Multi-line story description +- `main_character`: Detailed character description +- `style_setting`: Art style, mood, technical specifications +- `image_trigger_word`: Model-specific trigger (e.g., "Next Scene:", "Character:") +- `video_trigger_word`: Video model trigger (e.g., "Motion:", "Camera:") +- `system_prompt_type`: Choose generation mode +- `traveling_prompt_count`: Number of sub-prompts per scene (System Prompt 2 only) +- `additional_details`: Extra instructions (use for verbosity control) + +**System Prompt 1 (6 Scenes):** +- Generates 6 detailed image prompts for storyboard +- Generates 6 corresponding video prompts with camera movements +- Perfect for Next Scene LoRA workflows requiring scene-by-scene consistency + +**System Prompt 2 (Traveling Prompts):** +- Generates 6 detailed image prompts for storyboard foundation +- Generates 6 video scenes, each containing multiple traveling sub-prompts +- Each sub-prompt ≈ 5 seconds of video content +- Example: 3 traveling prompts = 6 scenes × 3 prompts = 18 total video prompts + +**Outputs:** +- Formatted prompt string ready for ollama integration + +**Recommended Models:** +- **Best quality**: Qwen 30B A3B Coder Abliterated +- **Best speed/efficiency**: Nemo 7B with verbosity nudging +- **Avoid**: Google models (Gemma), Meta coding variants, thinking models + +### Boyo Storyboard Output +Parses ollama JSON responses into separate prompt outputs for direct workflow integration. + +**Key Features:** +- **Robust JSON parsing** with automatic markdown cleanup +- **12 separate outputs** for System Prompt 1 (6 image + 6 video) +- **Multi-line support** for traveling prompts in System Prompt 2 +- **Graceful error handling** with descriptive error messages +- **Direct workflow connection** - outputs connect straight to prompt inputs + +**Input:** +- `json_input`: Raw JSON response from ollama + +**Outputs:** +- `image_scene1` through `image_scene6`: Individual image prompts +- `video_scene1` through `video_scene6`: Individual video prompts (single or multi-line) + +**JSON Structure Handled:** +```json +{ + "imagePrompts": { + "scene1": "Detailed image prompt...", + "scene2": "Detailed image prompt..." + }, + "videoPrompts": { + "scene1": "Video prompt for System Prompt 1 OR multi-line traveling prompts for System Prompt 2", + "scene2": "Video prompt for System Prompt 1 OR multi-line traveling prompts for System Prompt 2" + } +} +``` + +**Integration Workflow:** +1. Boyo Storyboard Prompt → ollama Generate → Boyo Storyboard Output +2. Connect 12 outputs directly to image/video generation workflows +3. Supports both standard scene generation and extended traveling prompt sequences + ## Workflow Enhancement Nodes ### Boyo Empty Latent @@ -280,6 +359,28 @@ Restart ComfyUI after installation. 3. Saves clean images + prompt documentation 4. Ready for sharing without exposing workflows +## Storyboard Generation Workflow Examples + +**Basic Storyboard Creation (System Prompt 1):** +1. Configure story concept, character, and style in Boyo Storyboard Prompt +2. Set trigger words for your specific image/video models +3. Connect to ollama Generate node +4. Parse results with Boyo Storyboard Output +5. Connect 6 image outputs to Next Scene LoRA workflow +6. Connect 6 video outputs to video generation pipeline + +**Extended Video Sequences (System Prompt 2):** +1. Set traveling_prompt_count (e.g., 6 for 30-second scenes) +2. Generate 6 storyboard images + 6 multi-line video prompt sequences +3. Each video scene contains multiple traveling prompts for extended sequences +4. Perfect for longer narrative videos with scene consistency + +**Character Consistency Workflow:** +1. Use detailed character descriptions in main_character field +2. Include style/lighting preferences in style_setting +3. Leverage trigger words optimised for your LoRA models +4. Generate consistent character appearance across all 6 scenes + ## Troubleshooting **LoRA Management issues:** @@ -299,11 +400,18 @@ Restart ComfyUI after installation. - Check file write permissions - Verify input image formats +**Storyboard Generation issues:** +- Use recommended ollama models (Qwen 30B A3B Coder Abliterated) +- Add verbosity instructions in additional_details field +- Verify JSON structure with Boyo Storyboard Output error messages +- Check ollama connectivity and model availability + **Performance tips:** - Large directories may slow Image Grab scanning - Organise files into smaller subdirectories - Use specific file extensions to reduce scanning - LoRA configs are cached for faster loading +- Abliterated coder models perform best for storyboard generation ## Contributing diff --git a/requirements.txt b/requirements.txt index 53c8a2e..85a0975 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,4 @@ qwen-vl-utils qwen-vl-utils bitsandbytes optimum +soundfile