Vertex Veo Insert Content
Swap anything into a video with a mask — no reshoot required
- video
- mask_image
- videos
- video_path_list
This is the node that makes Adforge feel like an ad toolkit instead of just a wrapper around a video API. Vertex Veo Insert Content takes an existing video and a mask, and replaces whatever's inside the mask with new content - a product dropped into a shelf shot, a logo composited over footage, a new prop where an empty space was. It's video inpainting in the good sense: the masked region gets regenerated from your prompt, and everything outside the mask stays put.
If that sounds like the classic inpainting trade-off, it is, and the KB puts the case for masks well: instruction-based editing models drift on the bits you didn't ask about, while a mask leaves the rest of the frame alone. That "exact placement, boundary you decide" property is precisely what you want when the unmasked footage is expensive-to-reshoot b-roll. Veo 3.1 is the version that got serious about this granular editing.
How it works
The node builds a VideoGenerationMask in INSERT mode and passes it in the generation config. Your video comes from the video input (a VIDEO type, read to bytes and uploaded) or from video_gcs_uri - you need one. Your mask comes from the mask_image input or mask_image_gcs_uri, and you need one of those too. Then it's the same pipeline as the rest of the pack: async generate_videos call, polled every five seconds, Veo writes the edited clip to GCS, and the node downloads it back. Outputs are the standard videos (VIDEO list) and video_path_list (local paths).
The inputs that matter
prompt- required, and it's a description of the new content, not the video. "A matte black espresso machine on the counter," not "edit my kitchen video."mask_image(ormask_image_gcs_uri) - the area of interest, an IMAGE. White or colored region on the area to replace; Veo treats it as the region to regenerate.video(orvideo_gcs_uri) - the footage to edit. This pack's own LoadVideoGCS node is a natural upstream here: bucket footage → local path → into this node'svideoinput.video_mime_type/mask_mime_type-video/mp4andimage/pngby default; match reality.duration_seconds- 1 to 10 here, the widest range in the pack, since you're editing an existing clip rather than inventing one from scratch.generate_audio- defaults to off for editing; you generally want the original clip's sound intact.
The rest of the config - model, aspect_ratio, resolution, fps, seed, number_of_videos, enhance_prompt, person_generation, negative_prompt - is shared across the Veo nodes. Defaults are fine to start.
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; Python 3.12+. Auth is the same Vertex setup as every generation node: copy .env.example to custom_nodes/comfyui_adforge/.env with GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_STORAGE_BUCKET, GOOGLE_CLOUD_LOCATION, API_KEY (or export them), and a bucket that actually exists - Veo writes output there first. GOOGLE_APPLICATION_CREDENTIALS with a service account works instead of the key.
Common issues
- Mask too tight. Veo needs room to blend. A mask that hugs the object exactly gives you seams; a slightly generous mask gives you a believable composite.
- Mask/video mismatch. If the mask doesn't line up with the frame - different resolution, rotated, the video got resized upstream - you'll get garbage in the masked region and it's not the model's fault. Keep the mask on the same canvas as the source frames.
- Cost. It's a paid API call per edit, and iteration is the trap: fine-tuning what goes in the box means paying for the box each time. Batch your prompt ideas, then spend.
Inputs (19)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | STRING | The text prompt used to guide video generation. | |
| videoopt | VIDEO | The video to process. | |
| video_gcs_uriopt | STRING | No documentation available | |
| mask_imageopt | IMAGE | The mask defining the area of interest. | |
| mask_image_gcs_uriopt | STRING | No documentation available | |
| negative_promptopt | STRING | Optional. A text string that describes anything you want to discourage the model from generating. | |
| output_gcs_uriopt | STRING | None/videos/video-insert-content-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 | 7 options: veo-3.1-generate-preview, veo-3.1-fast-generate-preview, veo-3.0-generate-001, veo-3.0-fast-generate-001, veo-2.0-generate-001, veo-2.0-generate-exp, +1 |
| aspect_ratioopt | COMBO | 16:9 | Optional. Specifies the aspect ratio of generated videos. |
| video_mime_typeopt | COMBO | video/mp4 | Mime type of the input image or video, e.g., 'image/png' or 'video/mp4'. |
| mask_mime_typeopt | COMBO | image/png | Mime type of the input image or video, e.g., 'image/png' or 'video/mp4'. |
| duration_secondsopt | INT | 81–10 | — |
| resolutionopt | COMBO | 1080p | 2 options: 1080p, 720p |
| fpsopt | INT | 241–60 | — |
| seedopt | INT | 00–2147483647 | — |
| number_of_videosopt | INT | 11–4 | — |
| enhance_promptopt | BOOLEAN | true | — |
| generate_audioopt | BOOLEAN | false | — |
| person_generationopt | COMBO | allow_adult | 2 options: allow_adult, dont_allow |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| videos | VIDEO | — |
| video_path_list | STRING | — |