Single Image to Multiple Consistent Shots
Upload an input image and automatically generate X prompts for camera angle and shot type.
Inside the workflow
A read-only preview of the source template. Open it in Cloud to explore the nodes and make changes.
Loading the graph
Open full-size workflow preview- Output
- Image
- Author
- Rob
Call this model from your code
The request below uses the same prepared graph and settings as the Playground. Each submission can start a paid run; do not automatically retry a submission whose outcome is unknown.
What you need
- Runs on
- Comfy Cloud
- Key
- COMFY_API_KEY
- Your files
- Uploaded by the code from their urls
Needs a paid Cloud plan and credits.
# Python 3.10+: pip install comfy-sdk==0.4.0
import os
from comfy_sdk import Comfy
api_key = os.environ.get("COMFY_API_KEY", "").strip()
if not api_key: raise RuntimeError("Set COMFY_API_KEY")
os.environ.setdefault("COMFY_BASE_URL", "https://cloud.comfy.org")
client = Comfy(api_key=api_key)
workflow = client.workflows.from_json({
"1": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"2",
0
]
},
"_meta": {
"title": "Preview All Generated Prompts"
}
},
"2": {
"class_type": "GeminiNode",
"inputs": {
"images": [
"6",
0
],
"model": "gemini-3-pro-preview",
"prompt": "Generate 6 different prompts following the instructions below. \nEach prompt idea needs to be 50-80 words max and be separated by *.\nEach prompt should be unique, varying the camera angles and shot type. Add subtle detail and maintain consistent elements.",
"seed": 12345,
"system_prompt": ""
},
"_meta": {
"title": "Google Gemini"
}
},
"5": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "ComfyUI-image_1",
"images": [
"10:9",
0
]
},
"_meta": {
"title": "Save Image 1"
}
},
"6": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_image_FILENAME"
},
"_meta": {
"title": "Load Reference Image"
}
},
"11": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"10:3:1",
0
]
},
"_meta": {
"title": "Preview Prompt 1"
}
},
"18": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "ComfyUI-image_2",
"images": [
"19:9",
0
]
},
"_meta": {
"title": "Save Image 1"
}
},
"20": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"19:3:1",
0
]
},
"_meta": {
"title": "Preview Prompt 2"
}
},
"21": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "ComfyUI-image_3",
"images": [
"22:9",
0
]
},
"_meta": {
"title": "Save Image 3"
}
},
"23": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"22:3:1",
0
]
},
"_meta": {
"title": "Preview Prompt 3"
}
},
"24": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "ComfyUI-image_4",
"images": [
"25:9",
0
]
},
"_meta": {
"title": "Save Image 4"
}
},
"26": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"25:3:1",
0
]
},
"_meta": {
"title": "Preview Prompt 4"
}
},
"27": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "ComfyUI-image_5",
"images": [
"28:9",
0
]
},
"_meta": {
"title": "Save Image 5"
}
},
"29": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"28:3:1",
0
]
},
"_meta": {
"title": "Preview Prompt 5"
}
},
"30": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "ComfyUI-image_6",
"images": [
"31:9",
0
]
},
"_meta": {
"title": "Save Image 6"
}
},
"32": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"31:3:1",
0
]
},
"_meta": {
"title": "Preview Prompt 6"
}
},
"10:3:1": {
"class_type": "RegexExtract",
"inputs": {
"case_insensitive": True,
"dotall": False,
"group_index": 1,
"mode": "First Group",
"multiline": True,
"regex_pattern": [
"10:3:8",
0
],
"string": [
"10:3:7",
0
]
},
"_meta": {
"title": "Extract Text"
}
},
"10:3:2": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"10:3:1",
0
]
},
"_meta": {
"title": "Preview as Text"
}
},
"10:3:3": {
"class_type": "SomethingToString",
"inputs": {
"input": [
"10:3:9",
0
],
"prefix": "",
"suffix": ""
},
"_meta": {
"title": "Something To String"
}
},
"10:3:6": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 1
},
"_meta": {
"title": "Int - Select Prompt Number (not index)"
}
},
"10:3:7": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": [
"2",
0
]
},
"_meta": {
"title": "Text (Multiline)"
}
},
"10:3:8": {
"class_type": "RegexReplace",
"inputs": {
"case_insensitive": True,
"count": 0,
"dotall": False,
"multiline": False,
"regex_pattern": "(?<=\\{)\\d+(?=\\})",
"replace": [
"10:3:3",
0
],
"string": "(?:^(?!\\s*\\*?\\s*$).+$\\n(?:^\\s*\\*?\\s*$\\n)*){0}^(?!\\s*\\*?\\s*$)(.+)$"
},
"_meta": {
"title": "Replace Text (Regex)"
}
},
"10:3:9": {
"class_type": "SimpleMath+",
"inputs": {
"a": [
"10:3:6",
0
],
"b": 0,
"value": "a-1"
},
"_meta": {
"title": "Convert Prompt Number to Index"
}
},
"10:8": {
"class_type": "BatchImagesNode",
"inputs": {
"images.image0": [
"6",
0
],
"images.image1": [
"10:9",
0
]
},
"_meta": {
"title": "Batch Images"
}
},
"10:9": {
"class_type": "GeminiImage2Node",
"inputs": {
"aspect_ratio": "16:9",
"images": [
"6",
0
],
"model": "gemini-3-pro-image-preview",
"prompt": [
"10:3:1",
0
],
"resolution": "2K",
"response_modalities": "IMAGE+TEXT",
"seed": 1,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests."
},
"_meta": {
"title": "Nano Banana Pro (Google Gemini Image)"
}
},
"19:10": {
"class_type": "PreviewImage",
"inputs": {
"images": [
"6",
0
]
},
"_meta": {
"title": "Preview Image"
}
},
"19:11": {
"class_type": "PreviewImage",
"inputs": {
"images": [
"19:8",
0
]
},
"_meta": {
"title": "Preview Image"
}
},
"19:3:1": {
"class_type": "RegexExtract",
"inputs": {
"case_insensitive": True,
"dotall": False,
"group_index": 1,
"mode": "First Group",
"multiline": True,
"regex_pattern": [
"19:3:8",
0
],
"string": [
"19:3:7",
0
]
},
"_meta": {
"title": "Extract Text"
}
},
"19:3:2": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"19:3:1",
0
]
},
"_meta": {
"title": "Preview as Text"
}
},
"19:3:3": {
"class_type": "SomethingToString",
"inputs": {
"input": [
"19:3:9",
0
],
"prefix": "",
"suffix": ""
},
"_meta": {
"title": "Something To String"
}
},
"19:3:6": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 2
},
"_meta": {
"title": "Int - Select Prompt Number (not index)"
}
},
"19:3:7": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": [
"2",
0
]
},
"_meta": {
"title": "Text (Multiline)"
}
},
"19:3:8": {
"class_type": "RegexReplace",
"inputs": {
"case_insensitive": True,
"count": 0,
"dotall": False,
"multiline": False,
"regex_pattern": "(?<=\\{)\\d+(?=\\})",
"replace": [
"19:3:3",
0
],
"string": "(?:^(?!\\s*\\*?\\s*$).+$\\n(?:^\\s*\\*?\\s*$\\n)*){0}^(?!\\s*\\*?\\s*$)(.+)$"
},
"_meta": {
"title": "Replace Text (Regex)"
}
},
"19:3:9": {
"class_type": "SimpleMath+",
"inputs": {
"a": [
"19:3:6",
0
],
"b": 0,
"value": "a-1"
},
"_meta": {
"title": "Convert Prompt Number to Index"
}
},
"19:8": {
"class_type": "BatchImagesNode",
"inputs": {
"images.image0": [
"6",
0
],
"images.image1": [
"19:9",
0
]
},
"_meta": {
"title": "Batch Images"
}
},
"19:9": {
"class_type": "GeminiImage2Node",
"inputs": {
"aspect_ratio": "16:9",
"images": [
"6",
0
],
"model": "gemini-3-pro-image-preview",
"prompt": [
"19:3:1",
0
],
"resolution": "2K",
"response_modalities": "IMAGE+TEXT",
"seed": 2,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests."
},
"_meta": {
"title": "Nano Banana Pro (Google Gemini Image)"
}
},
"22:10": {
"class_type": "PreviewImage",
"inputs": {
"images": [
"6",
0
]
},
"_meta": {
"title": "Preview Image"
}
},
"22:11": {
"class_type": "PreviewImage",
"inputs": {
"images": [
"22:8",
0
]
},
"_meta": {
"title": "Preview Image"
}
},
"22:3:1": {
"class_type": "RegexExtract",
"inputs": {
"case_insensitive": True,
"dotall": False,
"group_index": 1,
"mode": "First Group",
"multiline": True,
"regex_pattern": [
"22:3:8",
0
],
"string": [
"22:3:7",
0
]
},
"_meta": {
"title": "Extract Text"
}
},
"22:3:2": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"22:3:1",
0
]
},
"_meta": {
"title": "Preview as Text"
}
},
"22:3:3": {
"class_type": "SomethingToString",
"inputs": {
"input": [
"22:3:9",
0
],
"prefix": "",
"suffix": ""
},
"_meta": {
"title": "Something To String"
}
},
"22:3:6": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 3
},
"_meta": {
"title": "Int - Select Prompt Number (not index)"
}
},
"22:3:7": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": [
"2",
0
]
},
"_meta": {
"title": "Text (Multiline)"
}
},
"22:3:8": {
"class_type": "RegexReplace",
"inputs": {
"case_insensitive": True,
"count": 0,
"dotall": False,
"multiline": False,
"regex_pattern": "(?<=\\{)\\d+(?=\\})",
"replace": [
"22:3:3",
0
],
"string": "(?:^(?!\\s*\\*?\\s*$).+$\\n(?:^\\s*\\*?\\s*$\\n)*){0}^(?!\\s*\\*?\\s*$)(.+)$"
},
"_meta": {
"title": "Replace Text (Regex)"
}
},
"22:3:9": {
"class_type": "SimpleMath+",
"inputs": {
"a": [
"22:3:6",
0
],
"b": 0,
"value": "a-1"
},
"_meta": {
"title": "Convert Prompt Number to Index"
}
},
"22:8": {
"class_type": "BatchImagesNode",
"inputs": {
"images.image0": [
"6",
0
],
"images.image1": [
"22:9",
0
]
},
"_meta": {
"title": "Batch Images"
}
},
"22:9": {
"class_type": "GeminiImage2Node",
"inputs": {
"aspect_ratio": "16:9",
"images": [
"6",
0
],
"model": "gemini-3-pro-image-preview",
"prompt": [
"22:3:1",
0
],
"resolution": "2K",
"response_modalities": "IMAGE+TEXT",
"seed": 3,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests."
},
"_meta": {
"title": "Nano Banana Pro (Google Gemini Image)"
}
},
"25:3:1": {
"class_type": "RegexExtract",
"inputs": {
"case_insensitive": True,
"dotall": False,
"group_index": 1,
"mode": "First Group",
"multiline": True,
"regex_pattern": [
"25:3:8",
0
],
"string": [
"25:3:7",
0
]
},
"_meta": {
"title": "Extract Text"
}
},
"25:3:2": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"25:3:1",
0
]
},
"_meta": {
"title": "Preview as Text"
}
},
"25:3:3": {
"class_type": "SomethingToString",
"inputs": {
"input": [
"25:3:9",
0
],
"prefix": "",
"suffix": ""
},
"_meta": {
"title": "Something To String"
}
},
"25:3:6": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 4
},
"_meta": {
"title": "Int - Select Prompt Number (not index)"
}
},
"25:3:7": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": [
"2",
0
]
},
"_meta": {
"title": "Text (Multiline)"
}
},
"25:3:8": {
"class_type": "RegexReplace",
"inputs": {
"case_insensitive": True,
"count": 0,
"dotall": False,
"multiline": False,
"regex_pattern": "(?<=\\{)\\d+(?=\\})",
"replace": [
"25:3:3",
0
],
"string": "(?:^(?!\\s*\\*?\\s*$).+$\\n(?:^\\s*\\*?\\s*$\\n)*){0}^(?!\\s*\\*?\\s*$)(.+)$"
},
"_meta": {
"title": "Replace Text (Regex)"
}
},
"25:3:9": {
"class_type": "SimpleMath+",
"inputs": {
"a": [
"25:3:6",
0
],
"b": 0,
"value": "a-1"
},
"_meta": {
"title": "Convert Prompt Number to Index"
}
},
"25:8": {
"class_type": "BatchImagesNode",
"inputs": {
"images.image0": [
"6",
0
],
"images.image1": [
"25:9",
0
]
},
"_meta": {
"title": "Batch Images"
}
},
"25:9": {
"class_type": "GeminiImage2Node",
"inputs": {
"aspect_ratio": "16:9",
"images": [
"6",
0
],
"model": "gemini-3-pro-image-preview",
"prompt": [
"25:3:1",
0
],
"resolution": "2K",
"response_modalities": "IMAGE+TEXT",
"seed": 4,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests."
},
"_meta": {
"title": "Nano Banana Pro (Google Gemini Image)"
}
},
"28:10": {
"class_type": "PreviewImage",
"inputs": {
"images": [
"6",
0
]
},
"_meta": {
"title": "Preview Image"
}
},
"28:11": {
"class_type": "PreviewImage",
"inputs": {
"images": [
"28:8",
0
]
},
"_meta": {
"title": "Preview Image"
}
},
"28:3:1": {
"class_type": "RegexExtract",
"inputs": {
"case_insensitive": True,
"dotall": False,
"group_index": 1,
"mode": "First Group",
"multiline": True,
"regex_pattern": [
"28:3:8",
0
],
"string": [
"28:3:7",
0
]
},
"_meta": {
"title": "Extract Text"
}
},
"28:3:2": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"28:3:1",
0
]
},
"_meta": {
"title": "Preview as Text"
}
},
"28:3:3": {
"class_type": "SomethingToString",
"inputs": {
"input": [
"28:3:9",
0
],
"prefix": "",
"suffix": ""
},
"_meta": {
"title": "Something To String"
}
},
"28:3:6": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 5
},
"_meta": {
"title": "Int - Select Prompt Number (not index)"
}
},
"28:3:7": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": [
"2",
0
]
},
"_meta": {
"title": "Text (Multiline)"
}
},
"28:3:8": {
"class_type": "RegexReplace",
"inputs": {
"case_insensitive": True,
"count": 0,
"dotall": False,
"multiline": False,
"regex_pattern": "(?<=\\{)\\d+(?=\\})",
"replace": [
"28:3:3",
0
],
"string": "(?:^(?!\\s*\\*?\\s*$).+$\\n(?:^\\s*\\*?\\s*$\\n)*){0}^(?!\\s*\\*?\\s*$)(.+)$"
},
"_meta": {
"title": "Replace Text (Regex)"
}
},
"28:3:9": {
"class_type": "SimpleMath+",
"inputs": {
"a": [
"28:3:6",
0
],
"b": 0,
"value": "a-1"
},
"_meta": {
"title": "Convert Prompt Number to Index"
}
},
"28:8": {
"class_type": "BatchImagesNode",
"inputs": {
"images.image0": [
"6",
0
],
"images.image1": [
"28:9",
0
]
},
"_meta": {
"title": "Batch Images"
}
},
"28:9": {
"class_type": "GeminiImage2Node",
"inputs": {
"aspect_ratio": "16:9",
"images": [
"6",
0
],
"model": "gemini-3-pro-image-preview",
"prompt": [
"28:3:1",
0
],
"resolution": "2K",
"response_modalities": "IMAGE+TEXT",
"seed": 5,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests."
},
"_meta": {
"title": "Nano Banana Pro (Google Gemini Image)"
}
},
"31:11": {
"class_type": "PreviewImage",
"inputs": {
"images": [
"31:8",
0
]
},
"_meta": {
"title": "Preview Image"
}
},
"31:3:1": {
"class_type": "RegexExtract",
"inputs": {
"case_insensitive": True,
"dotall": False,
"group_index": 1,
"mode": "First Group",
"multiline": True,
"regex_pattern": [
"31:3:8",
0
],
"string": [
"31:3:7",
0
]
},
"_meta": {
"title": "Extract Text"
}
},
"31:3:2": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"31:3:1",
0
]
},
"_meta": {
"title": "Preview as Text"
}
},
"31:3:3": {
"class_type": "SomethingToString",
"inputs": {
"input": [
"31:3:9",
0
],
"prefix": "",
"suffix": ""
},
"_meta": {
"title": "Something To String"
}
},
"31:3:6": {
"class_type": "PrimitiveInt",
"inputs": {
"value": 6
},
"_meta": {
"title": "Int - Select Prompt Number (not index)"
}
},
"31:3:7": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": [
"2",
0
]
},
"_meta": {
"title": "Text (Multiline)"
}
},
"31:3:8": {
"class_type": "RegexReplace",
"inputs": {
"case_insensitive": True,
"count": 0,
"dotall": False,
"multiline": False,
"regex_pattern": "(?<=\\{)\\d+(?=\\})",
"replace": [
"31:3:3",
0
],
"string": "(?:^(?!\\s*\\*?\\s*$).+$\\n(?:^\\s*\\*?\\s*$\\n)*){0}^(?!\\s*\\*?\\s*$)(.+)$"
},
"_meta": {
"title": "Replace Text (Regex)"
}
},
"31:3:9": {
"class_type": "SimpleMath+",
"inputs": {
"a": [
"31:3:6",
0
],
"b": 0,
"value": "a-1"
},
"_meta": {
"title": "Convert Prompt Number to Index"
}
},
"31:8": {
"class_type": "BatchImagesNode",
"inputs": {
"images.image0": [
"6",
0
],
"images.image1": [
"31:9",
0
]
},
"_meta": {
"title": "Batch Images"
}
},
"31:9": {
"class_type": "GeminiImage2Node",
"inputs": {
"aspect_ratio": "16:9",
"images": [
"6",
0
],
"model": "gemini-3-pro-image-preview",
"prompt": [
"31:3:1",
0
],
"resolution": "2K",
"response_modalities": "IMAGE+TEXT",
"seed": 6,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests."
},
"_meta": {
"title": "Nano Banana Pro (Google Gemini Image)"
}
}
})
workflow.set_input("6", "image", client.assets.from_url("https://comfy.org/catalog-media/388e7cf3-2ed0-4b56-9f3b-41080c2b8025/6b000691-26db-4348-a026-bde146e5bcc7"))
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)
for output in job.get_outputs("5"):
output.to_file(output.name)
for output in job.get_outputs("18"):
output.to_file(output.name)
for output in job.get_outputs("21"):
output.to_file(output.name)
for output in job.get_outputs("24"):
output.to_file(output.name)
for output in job.get_outputs("27"):
output.to_file(output.name)
for output in job.get_outputs("30"):
output.to_file(output.name)Try an example
About this workflow
This ComfyUI workflow, titled 'Single Image to Multiple Consistent Shots,' is designed to transform a single input image into a series of images with varied camera angles and shot types. It leverages the Nano Banana Pro model to ensure high-quality image generation while maintaining consistency across different perspectives.
The workflow utilizes a combination of nodes including PreviewAny, GeminiNode, and SaveImage to process and output the images. Custom nodes from comfyui-kjnodes and comfyui_essentials are also employed to enhance the functionality and flexibility of the workflow. By automating the generation of multiple prompts for camera angles, this workflow is particularly useful for creators who need to produce a variety of shots from a single image source, such as in storyboarding or product photography.
Questions & answers
Images with clear subjects and good lighting tend to yield the best results, as the model can better interpret and generate consistent angles.
Yes, the GeminiNode allows you to define specific parameters for camera angles, giving you control over the output.
While the workflow is efficient, it is primarily designed for pre-production and not optimized for real-time applications.
Consistency is maintained by using the same model settings across all generated images. Ensure that the Nano Banana Pro model is configured uniformly for each output.