{
 "37": {
  "inputs": {
   "source": [
    "91:39",
    0
   ]
  },
  "class_type": "PreviewAny",
  "_meta": {
   "title": "Shot 2: Prompt"
  }
 },
 "46": {
  "inputs": {
   "source": [
    "91:49",
    0
   ]
  },
  "class_type": "PreviewAny",
  "_meta": {
   "title": "Shot 3: Prompt"
  }
 },
 "4": {
  "inputs": {
   "image": "comfy_gpu_angled.png"
  },
  "class_type": "LoadImage",
  "_meta": {
   "title": "Load Start Frame Image"
  }
 },
 "8": {
  "inputs": {
   "image": "comfy_gpu_flat.png"
  },
  "class_type": "LoadImage",
  "_meta": {
   "title": "Load Product Image 1"
  }
 },
 "12": {
  "inputs": {
   "image": "comfy_gpu_close_up.png"
  },
  "class_type": "LoadImage",
  "_meta": {
   "title": "Load Product Image 2"
  }
 },
 "81:76": {
  "inputs": {
   "prefix": "",
   "suffix": "",
   "input": [
    "23",
    0
   ]
  },
  "class_type": "SomethingToString",
  "_meta": {
   "title": "Something To String"
  }
 },
 "81:77": {
  "inputs": {
   "prefix": "",
   "suffix": "",
   "input": [
    "22",
    0
   ]
  },
  "class_type": "SomethingToString",
  "_meta": {
   "title": "Something To String"
  }
 },
 "81:78": {
  "inputs": {
   "regex_pattern": "N_SHOTS",
   "case_insensitive": true,
   "multiline": false,
   "dotall": false,
   "count": 0,
   "string": [
    "81:80",
    0
   ],
   "replace": [
    "81:76",
    0
   ]
  },
  "class_type": "RegexReplace",
  "_meta": {
   "title": "Replace Text (Regex)"
  }
 },
 "81:79": {
  "inputs": {
   "regex_pattern": "N_SECONDS",
   "case_insensitive": true,
   "multiline": false,
   "dotall": false,
   "count": 0,
   "string": [
    "81:78",
    0
   ],
   "replace": [
    "81:77",
    0
   ]
  },
  "class_type": "RegexReplace",
  "_meta": {
   "title": "Replace Text (Regex)"
  }
 },
 "81:80": {
  "inputs": {
   "text": "Use the input image 1, create a prompt that has N_SHOTS distinct shots. The total time for the shots is N_SECONDS. \n\nUSER_STORY."
  },
  "class_type": "Text Multiline",
  "_meta": {
   "title": "Template User Prompt"
  }
 },
 "115:112": {
  "inputs": {
   "mode": "Equal",
   "case_sensitive": false,
   "string_a": [
    "165",
    0
   ],
   "string_b": [
    "115:113",
    0
   ]
  },
  "class_type": "StringCompare",
  "_meta": {
   "title": "Compare Text"
  }
 },
 "115:111": {
  "inputs": {
   "switch": [
    "115:112",
    0
   ],
   "on_false": [
    "165",
    0
   ],
   "on_true": [
    "164",
    0
   ]
  },
  "class_type": "ComfySwitchNode",
  "_meta": {
   "title": "If/Else Switch"
  }
 },
 "115:113": {
  "inputs": {
   "value": ""
  },
  "class_type": "PrimitiveString",
  "_meta": {
   "title": "Empty String"
  }
 },
 "32": {
  "inputs": {
   "source": [
    "91:31",
    0
   ]
  },
  "class_type": "PreviewAny",
  "_meta": {
   "title": "Shot 1: Prompt"
  }
 },
 "38": {
  "inputs": {
   "source": [
    "91:40",
    0
   ]
  },
  "class_type": "PreviewAny",
  "_meta": {
   "title": "Shot 2: # of Seconds"
  }
 },
 "53": {
  "inputs": {
   "source": [
    "91:60",
    0
   ]
  },
  "class_type": "PreviewAny",
  "_meta": {
   "title": "Shot 5: Prompt"
  }
 },
 "52": {
  "inputs": {
   "source": [
    "91:62",
    0
   ]
  },
  "class_type": "PreviewAny",
  "_meta": {
   "title": "Shot 4: # of Seconds"
  }
 },
 "54": {
  "inputs": {
   "source": [
    "91:55",
    0
   ]
  },
  "class_type": "PreviewAny",
  "_meta": {
   "title": "Shot 5: # of Seconds"
  }
 },
 "57": {
  "inputs": {
   "source": [
    "91:58",
    0
   ]
  },
  "class_type": "PreviewAny",
  "_meta": {
   "title": "Shot 6: # of Seconds"
  }
 },
 "35": {
  "inputs": {
   "source": [
    "91:36",
    0
   ]
  },
  "class_type": "PreviewAny",
  "_meta": {
   "title": "Shot 1: # of Seconds"
  }
 },
 "136": {
  "inputs": {
   "data": [
    "91:36",
    0
   ]
  },
  "class_type": "StringToInt",
  "_meta": {
   "title": "Shot 1: Duration"
  }
 },
 "137": {
  "inputs": {
   "data": [
    "91:40",
    0
   ]
  },
  "class_type": "StringToInt",
  "_meta": {
   "title": "Shot 2: Duration"
  }
 },
 "138": {
  "inputs": {
   "data": [
    "91:48",
    0
   ]
  },
  "class_type": "StringToInt",
  "_meta": {
   "title": "Shot 3: Duration"
  }
 },
 "140": {
  "inputs": {
   "data": [
    "91:62",
    0
   ]
  },
  "class_type": "StringToInt",
  "_meta": {
   "title": "Shot 4: Duration"
  }
 },
 "141": {
  "inputs": {
   "data": [
    "91:55",
    0
   ]
  },
  "class_type": "StringToInt",
  "_meta": {
   "title": "Shot 5: Duration"
  }
 },
 "139": {
  "inputs": {
   "data": [
    "91:58",
    0
   ]
  },
  "class_type": "StringToInt",
  "_meta": {
   "title": "Shot 6: Duration"
  }
 },
 "91:40": {
  "inputs": {
   "regex_pattern": "<shot2_duration>(\\d+)</shot2_duration>",
   "mode": "First Group",
   "case_insensitive": true,
   "multiline": true,
   "dotall": false,
   "group_index": 1,
   "string": [
    "115:111",
    0
   ]
  },
  "class_type": "RegexExtract",
  "_meta": {
   "title": "Extract Text"
  }
 },
 "91:48": {
  "inputs": {
   "regex_pattern": "<shot3_duration>(\\d+)</shot3_duration>",
   "mode": "First Group",
   "case_insensitive": true,
   "multiline": true,
   "dotall": false,
   "group_index": 1,
   "string": [
    "115:111",
    0
   ]
  },
  "class_type": "RegexExtract",
  "_meta": {
   "title": "Extract Text"
  }
 },
 "91:31": {
  "inputs": {
   "regex_pattern": "<shot1_prompt>(.+)</shot1_prompt>",
   "mode": "First Group",
   "case_insensitive": true,
   "multiline": true,
   "dotall": false,
   "group_index": 1,
   "string": [
    "115:111",
    0
   ]
  },
  "class_type": "RegexExtract",
  "_meta": {
   "title": "Extract Text"
  }
 },
 "91:39": {
  "inputs": {
   "regex_pattern": "<shot2_prompt>(.+)</shot2_prompt>",
   "mode": "First Group",
   "case_insensitive": true,
   "multiline": true,
   "dotall": false,
   "group_index": 1,
   "string": [
    "115:111",
    0
   ]
  },
  "class_type": "RegexExtract",
  "_meta": {
   "title": "Extract Text"
  }
 },
 "91:49": {
  "inputs": {
   "regex_pattern": "<shot3_prompt>(.+)</shot3_prompt>",
   "mode": "First Group",
   "case_insensitive": true,
   "multiline": true,
   "dotall": false,
   "group_index": 1,
   "string": [
    "115:111",
    0
   ]
  },
  "class_type": "RegexExtract",
  "_meta": {
   "title": "Extract Text"
  }
 },
 "91:62": {
  "inputs": {
   "regex_pattern": "<shot4_duration>(\\d+)</shot4_duration>",
   "mode": "First Group",
   "case_insensitive": true,
   "multiline": true,
   "dotall": false,
   "group_index": 1,
   "string": [
    "115:111",
    0
   ]
  },
  "class_type": "RegexExtract",
  "_meta": {
   "title": "Extract Text"
  }
 },
 "91:55": {
  "inputs": {
   "regex_pattern": "<shot5_duration>(\\d+)</shot5_duration>",
   "mode": "First Group",
   "case_insensitive": true,
   "multiline": true,
   "dotall": false,
   "group_index": 1,
   "string": [
    "115:111",
    0
   ]
  },
  "class_type": "RegexExtract",
  "_meta": {
   "title": "Extract Text"
  }
 },
 "91:58": {
  "inputs": {
   "regex_pattern": "<shot6_duration>(\\d+)</shot6_duration>",
   "mode": "First Group",
   "case_insensitive": true,
   "multiline": true,
   "dotall": false,
   "group_index": 1,
   "string": [
    "115:111",
    0
   ]
  },
  "class_type": "RegexExtract",
  "_meta": {
   "title": "Extract Text"
  }
 },
 "91:61": {
  "inputs": {
   "regex_pattern": "<shot6_prompt>(.+)</shot6_prompt>",
   "mode": "First Group",
   "case_insensitive": true,
   "multiline": true,
   "dotall": false,
   "group_index": 1,
   "string": [
    "115:111",
    0
   ]
  },
  "class_type": "RegexExtract",
  "_meta": {
   "title": "Extract Text"
  }
 },
 "91:60": {
  "inputs": {
   "regex_pattern": "<shot5_prompt>(.+)</shot5_prompt>",
   "mode": "First Group",
   "case_insensitive": true,
   "multiline": true,
   "dotall": false,
   "group_index": 1,
   "string": [
    "115:111",
    0
   ]
  },
  "class_type": "RegexExtract",
  "_meta": {
   "title": "Extract Text"
  }
 },
 "91:59": {
  "inputs": {
   "regex_pattern": "<shot4_prompt>(.+)</shot4_prompt>",
   "mode": "First Group",
   "case_insensitive": true,
   "multiline": true,
   "dotall": false,
   "group_index": 1,
   "string": [
    "115:111",
    0
   ]
  },
  "class_type": "RegexExtract",
  "_meta": {
   "title": "Extract Text"
  }
 },
 "91:36": {
  "inputs": {
   "regex_pattern": "<shot1_duration>(\\d+)</shot1_duration>",
   "mode": "First Group",
   "case_insensitive": true,
   "multiline": true,
   "dotall": false,
   "group_index": 1,
   "string": [
    "115:111",
    0
   ]
  },
  "class_type": "RegexExtract",
  "_meta": {
   "title": "Extract Text"
  }
 },
 "23": {
  "inputs": {
   "value": 2
  },
  "class_type": "PrimitiveInt",
  "_meta": {
   "title": "Number of Shots (1-6)"
  }
 },
 "47": {
  "inputs": {
   "source": [
    "91:48",
    0
   ]
  },
  "class_type": "PreviewAny",
  "_meta": {
   "title": "Shot 3: # of Seconds"
  }
 },
 "22": {
  "inputs": {
   "value": 8
  },
  "class_type": "PrimitiveInt",
  "_meta": {
   "title": "Number of Seconds (3-15)"
  }
 },
 "110:6": {
  "inputs": {
   "images.image0": [
    "4",
    0
   ],
   "images.image1": [
    "110:15",
    0
   ],
   "images.image2": [
    "110:16",
    0
   ]
  },
  "class_type": "BatchImagesNode",
  "_meta": {
   "title": "Batch Images"
  }
 },
 "110:14": {
  "inputs": {
   "image": [
    "4",
    0
   ]
  },
  "class_type": "GetImageSize",
  "_meta": {
   "title": "Get Image Size"
  }
 },
 "110:15": {
  "inputs": {
   "padding_color": "white",
   "interpolation": "area",
   "image": [
    "8",
    0
   ],
   "target_width": [
    "110:14",
    0
   ],
   "target_height": [
    "110:14",
    1
   ]
  },
  "class_type": "ResizeAndPadImage",
  "_meta": {
   "title": "Resize And Pad Image"
  }
 },
 "110:16": {
  "inputs": {
   "padding_color": "white",
   "interpolation": "area",
   "image": [
    "12",
    0
   ],
   "target_width": [
    "110:14",
    0
   ],
   "target_height": [
    "110:14",
    1
   ]
  },
  "class_type": "ResizeAndPadImage",
  "_meta": {
   "title": "Resize And Pad Image"
  }
 },
 "145": {
  "inputs": {
   "source": [
    "91:59",
    0
   ]
  },
  "class_type": "PreviewAny",
  "_meta": {
   "title": "Shot 4: Prompt"
  }
 },
 "148": {
  "inputs": {
   "source": [
    "91:61",
    0
   ]
  },
  "class_type": "PreviewAny",
  "_meta": {
   "title": "Shot 6: Prompt"
  }
 },
 "149": {
  "inputs": {
   "value": "You are a creative director and video prompt specialist. Your job is to analyze a product image and generate a sequence of cinematic video prompts for a multi-shot product advertisement.\n\n---\n\n## INPUT\nYou will receive:\n- A product image (used as the visual start frame for Shot 1 only)\n- {N_SHOTS}: the number of shots to generate (1\u20136)\n- {N_SECONDS}: the total cumulative duration across all shots (max 15 seconds)\n- {USER_STORY}: optional creative direction for vibe, narrative, or tone\n\n---\n\n## STEP 1 \u2014 ANALYZE THE IMAGE\nBefore writing any prompts, internally assess the following from the product image:\n- Product type, shape, color, material, and finish\n- Existing lighting mood (hard/soft, warm/cool, dramatic/flat)\n- Background environment \u2014 describe it precisely and literally: surface type, color, texture, depth, atmospheric elements (e.g. \"matte dark grey surface, no visible background, soft overhead diffusion\"). This description becomes a locked constant for all shots.\n- Implied brand positioning (luxury, minimal, bold, playful, clinical, etc.)\n\nIf {USER_STORY} is provided, let it override or augment your inferred vibe. If it is empty, rely entirely on your image analysis.\n\n---\n\n## STEP 2 \u2014 ASSIGN A SHOT SEQUENCE\nMap {N_SHOTS} to a logical ad narrative arc. Use this as your guide:\n\n| Shot Role     | Purpose                                              |\n|---------------|------------------------------------------------------|\n| Hero (Shot 1) | Product reveal \u2014 slow, confident, visually grounding |\n| Detail        | Extreme close-up of texture, material, or finish     |\n| Feature       | Product in action, reacting to environment or use    |\n| Lifestyle     | Product in its natural world or context              |\n| Outro         | Pull back, final beauty angle, or ambient close      |\n\nCompress or expand the arc based on shot count:\n- 1\u20132 shots: Hero + Outro only\n- 3 shots: Hero, Feature, Outro\n- 4 shots: Hero, Detail, Feature, Outro\n- 5 shots: Hero, Detail, Feature, Lifestyle, Outro\n- 6 shots: Hero, Detail, Detail, Feature, Lifestyle, Outro\n\n---\n\n## STEP 3 \u2014 ALLOCATE DURATIONS\nDistribute seconds across shots. Rules:\n- All durations must be integers (whole seconds)\n- Total must equal exactly {N_SECONDS}\n- Weight durations by shot role and inferred pacing:\n  - Luxury/cinematic vibe: favor longer Hero and Outro, compress middle shots\n  - Energetic/bold vibe: distribute more evenly, keep all shots punchy\n  - Default weighting: Hero gets ~25%, Outro gets ~20%, remaining shots split the rest\n\n---\n\n## STEP 4 \u2014 WRITE THE PROMPTS\n\n**Shot 1 (I2V \u2014 Image to Video):**\nThe product image is the literal start frame. Write a prompt that describes the motion and camera behavior starting from that exact frame. Do not re-describe the product appearance \u2014 describe only what moves and how.\n\n**Shots 2\u2013N (T2V \u2014 Text to Video):**\nEach prompt must be fully self-contained. Describe the product, the scene, the camera, and the motion clearly enough that a video model with no prior context can generate a coherent, on-brand clip. You must preserve the exact environment from the input image \u2014 the same surface, background, depth, and atmosphere. Do not introduce new environments, floors, settings, or atmospheric elements (mist, smoke, reflections, etc.) that were not present in the input image. The environment is a locked constant, not a creative variable.\n\n**Prompt writing rules (apply to all shots):**\n- Write in present tense, descriptive and directive\n- Lead with the most important visual element\n- Specify: camera angle, camera motion, subject action, lighting, mood\n- Keep each prompt between 40\u201380 words \u2014 specific but not overloaded\n- No marketing copy, no voiceover text, no titles or graphics\n- Each shot must feel visually distinct from the others \u2014 vary angle, distance, and motion meaningfully\n\n---\n\n## OUTPUT FORMAT\nOutput only the tagged shot blocks. No preamble, no explanation, no additional text.\n\n<shot1_duration>N</shot1_duration>\n<shot1_prompt>Prompt text here</shot1_prompt>\n\n<shot2_duration>N</shot2_duration>\n<shot2_prompt>Prompt text here</shot2_prompt>\n\n...and so on for all {N_SHOTS} shots."
  },
  "class_type": "PrimitiveStringMultiline",
  "_meta": {
   "title": "System Prompt"
  }
 },
 "164": {
  "inputs": {
   "model": "gemini-3-pro-preview",
   "seed": 11185935742735,
   "prompt": [
    "81:79",
    0
   ],
   "images": [
    "4",
    0
   ],
   "system_prompt": [
    "149",
    0
   ]
  },
  "class_type": "GeminiNode",
  "_meta": {
   "title": "Google Gemini"
  }
 },
 "165": {
  "inputs": {
   "value": ""
  },
  "class_type": "PrimitiveStringMultiline",
  "_meta": {
   "title": "Prompt Input (copy/paste prompt here to lock)"
  }
 },
 "166": {
  "inputs": {
   "source": [
    "164",
    0
   ]
  },
  "class_type": "PreviewAny",
  "_meta": {
   "title": "Preview All Prompts"
  }
 }
}