Vertex Veo Image to Video
Animate a still with Veo — the node that actually uses your image
- image
- videos
- video_path_list
Image-to-video is the community's favorite way to generate, because anchoring the first frame to a real image fixes most of the consistency problems that plague pure text-to-video. Vertex Veo Image to Video is that workflow, pointed at Google's Veo 3.1 - and Veo 3.1 is the release that notably got better at this exact task. If the Text to Video sibling is the pack's flagship, this is the one people actually reach for in production, because it starts from something you control: a product shot, a storyboard frame, a hero image.
Both nodes live in Adforge, Creditas' Vertex AI toolkit for ad creation, and both share the same DNA: paid cloud generation, billed per second, round-tripping through a GCS bucket. Same honest caveat applies - iterate cheap on local models like Wan, bring the budget when the take has to be right.
How it works
Mechanically it's the text-to-video node with a GenerateVideosSource that carries your image alongside the prompt. The interesting bit is how the image gets there. Wire an image into the image input and the node converts the tensor to PNG bytes locally and uploads them with your chosen image_mime_type (PNG default, JPEG available). Or skip the upload entirely: give input_image_gcs_uri as a gs:// path and the API reads it straight from the bucket. You need one or the other - run it with neither and it raises a ValueError before you spend a cent.
From there it's the same pipeline: async generate_videos operation polled every five seconds, Veo writes to GCS, the node downloads it back. Outputs are identical to the text node: videos (a VIDEO-type list) and video_path_list (local paths).
The inputs that matter
prompt- required, describes the motion and the scene. Withenhance_prompton (default), Gemini expands it first.image- required IMAGE input; the node's docstring calls it "Input image to animate." A static product shot in, a slowly orbiting product shot out.input_image_gcs_uri- the alternative to a local image, for when the source is already in your bucket.image_mime_type-image/pngorimage/jpeg; match it to what you're sending.generate_audio- unlike the text node, this defaults to on. Makes sense for a finished ad clip; Veo 3.1's native audio is the capability open models still can't match. Turn it off if you're compositing sound later.duration_seconds- 4 to 8 here (the text node allows 2–8). Sameresolution(1080p/720p, Veo 3 only),seed,number_of_videos(1–4 variations),fps,aspect_ratio,person_generationset as elsewhere.
Installing and authenticating
Search adforge in ComfyUI Manager, or:
cd ComfyUI/custom_nodes
git clone https://github.com/Creditas-labs/ComfyUI-Adforge
cd ComfyUI-Adforge
pip install -r requirements.txt # or: uv sync
Restart, and you'll need Python 3.12+. Authentication is the full Vertex ceremony: copy .env.example to custom_nodes/comfyui_adforge/.env and set GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_STORAGE_BUCKET, GOOGLE_CLOUD_LOCATION, API_KEY (or export them as env vars), and make sure the bucket exists - Veo writes output there before the node pulls it back. Service-account JSON via GOOGLE_APPLICATION_CREDENTIALS works as an alternative to the API key.
Common issues
- "It never starts / hangs." Check
output_gcs_uriand the bucket - a missing bucket or one the credentials can't write to is the classic stall point, since the operation only fails visibly when the node tries to download. - Resolution surprise. Asking for 1080p and getting 720p back is a known Veo 3.1 behavior; if that kills you, it's the model, not the node.
- Prompt fights. Veo can be conservative about faces depending on
person_generation(defaultallow_adult). If the model keeps refusing, that dropdown is the first thing to check.
Inputs (16)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | STRING | The text prompt used to guide video generation. | |
| image | IMAGE | Input image to animate (IMAGE type). | |
| negative_promptopt | STRING | Optional. A text string that describes anything you want to discourage the model from generating. | |
| input_image_gcs_uriopt | STRING | GCS URI of the input image in the format 'gs://BUCKET_NAME/SUBDIRECTORY.'. | |
| output_gcs_uriopt | STRING | None/videos/image-to-video-20260720-202149.mp4 | GCS URI where the generated videos will be stored, in the format 'gs://BUCKET_NAME/SUBDIRECTORY'. |
| modelopt | COMBO | veo-3.1-generate-preview | The Veo model to use for video generation. |
| aspect_ratioopt | COMBO | 16:9 | Optional. Specifies the aspect ratio of generated videos. |
| image_mime_typeopt | COMBO | image/png | Mime type of the input image or video, e.g., 'image/png' or 'video/mp4'. |
| duration_secondsopt | INT | 84–8 | Required. The length in seconds of video files that you want to generate. |
| resolutionopt | COMBO | 1080p | Optional. Veo 3 models only. The resolution of the generated video. |
| fpsopt | INT | 241–60 | Optional. Frames per second for the generated video. |
| number_of_videosopt | INT | 11–4 | Optional. Number of video variations to generate. |
| enhance_promptopt | BOOLEAN | true | Optional. Use Gemini to enhance your prompts. |
| generate_audioopt | BOOLEAN | true | Generate audio for the video. |
| person_generationopt | COMBO | allow_adult | Optional. The safety setting that controls whether people or face generation is allowed. |
| seedopt | INT | 00–2147483647 | Optional. A number to request to make generated videos deterministic. Adding a seed number with your request without changing other parameters will cause the model to produce the same videos. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| videos | VIDEO | A list of generated videos (VIDEO type). |
| video_path_list | STRING | A list of local paths to the generated videos (when output_format=local_file) |