Veo2 Image To Video
Animate a ComfyUI image with Veo 2, without the cloud gymnastics
- image
- last_frame
- video_paths
The tensor-based Veo 2 image-to-video node is the one you'll actually use most: it takes a plain ComfyUI IMAGE - from a Load Image node, a Nano Banana call, an img2img pass, whatever - and animates it with Google's Veo 2. No GCS buckets, no file paths, just wire a tensor in and get a video out. It's the most direct way to bring a still you're happy with to life.
How it works
The node encodes the image tensor, attaches it to a Veo 2 generation request on Vertex AI as the first frame, and polls the long-running operation until the video is ready. The optional last_frame input (another IMAGE tensor) anchors the end of the clip, so the animation interpolates between two images you control instead of wandering. Output comes back as video_paths - a VEO_VIDEO path list pointing at MP4s in ComfyUI's temp folder.
Inputs that matter
- image - the required starting frame tensor.
- last_frame - optional ending frame for interpolation.
- prompt - what happens in the video. An empty prompt is tolerated (Veo interprets the image), but a real description gets you intentional motion.
- image_format -
PNG,JPEG, orMP4, a format hint for the API. - aspect_ratio -
16:9or9:16. - compression_quality -
optimizedorlossless. Lossless requiresoutput_gcs_urior the node throws an interactive error. - person_generation -
allow_adult/dont_allow. - duration_seconds - 5 to 8 seconds (Veo 2's range differs from Veo 3.1's 4–8).
- enhance_prompt - on by default; the model rewrites your prompt, and this disables seed.
- sample_count - up to 4 variations, billed per video.
Optional: negative_prompt, seed, output_gcs_uri, and the pack-standard gcp_project_id / gcp_region.
Gotchas
The seed vs. enhance_prompt interaction is the one that bites: with enhance_prompt on (the default), your seed is ignored. Unlike Veo 3.1 - where you can't turn enhancement off at all - this node lets you flip it, and that's the only way seed reproducibility actually works here. So if you're chasing a repeatable look, disable enhancement and set a seed; if you want the model's prompt polish, accept the randomness. And remember Veo 2 has no native audio and no resolution selector - you get the model's fixed 720p-class output.
Installing and wiring it
Shared pack install:
cd ComfyUI/custom_nodes
git clone https://github.com/GoogleCloudPlatform/comfyui-google-genmedia-custom-nodes
pip install -r comfyui-google-genmedia-custom-nodes/requirements.txt
Or ComfyUI Manager → search comfyui-google-genmedia-custom-nodes. Restart, look under Google AI/Veo2. Set project/region, authenticate, and each video bills to Vertex AI. The video_paths output feeds VeoVideoSaveAndPreview to watch it, or VeoVideoToVHSNode for frames. If you're starting a fresh pipeline today, Veo 3.1's tensor node is the better model - but this one is simpler, cheaper per run, and genuinely toggleable in ways the newer node isn't.
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| image_format | COMBO | PNG | mime type of the image |
| prompt | STRING | — | |
| aspect_ratio | COMBO | 16:9 | 2 options: 16:9, 9:16 |
| compression_quality | COMBO | optimized | 2 options: optimized, lossless |
| person_generation | COMBO | allow_adult | 2 options: dont_allow, allow_adult |
| duration_seconds | INT | 85–8 | — |
| enhance_prompt | BOOLEAN | true | — |
| sample_count | INT | 11–4 | — |
| last_frameopt | IMAGE | — | |
| output_gcs_uriopt | STRING | — | |
| negative_promptopt | STRING | — | |
| seedopt | INT | 00–4294967295 | 0 seed let's Veo API handle randomness. Seed works with enhance_prompt disabled |
| gcp_project_idopt | STRING | GCP project id where Vertex AI API will query Veo | |
| gcp_regionopt | STRING | GCP region for Vertex AI API |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| video_paths | VEO_VIDEO | — |