ComfyUI Node

Video to VHS

The node that turns Veo output into frames you can actually use

By GoogleCloudPlatform·Created 8 months ago·Updated about a month ago· 47
Video to VHS
  • video_paths
  • frames

The name is a lie, kind of. "Video to VHS" isn't about adding tracking lines and that grainy camcorder look. It's about making Veo output edible by the rest of ComfyUI - the "VHS" is VideoHelperSuite, the ecosystem's usual way of moving video around as frames. When you've got a Veo video you want to upscale, img2img, or push through a VAE, this is the bridge you'll reach for.

Why this node exists

Every Veo node in this pack (Veo 2, Veo 3.1, reference-to-video, the lot) returns a VEO_VIDEO output. Don't let the fancy name fool you - that's just a list of file paths to MP4s sitting in ComfyUI's temp folder. It's not a tensor, and almost nothing else in ComfyUI can read it. If you want to process what Veo made, you need those files turned into an IMAGE batch. That's the entire job here.

How it works

Under the hood it's OpenCV doing the frame rip. It opens each video with cv2.VideoCapture, figures out the total frame count, then samples intelligently: it computes frame_step = total_frames // 120 and seeks directly to each frame position instead of decoding every single frame sequentially. That keeps it fast even on an 8-second clip. Each frame gets converted from BGR to RGB, scaled to floats in 0–1 range, and stacked into one [N, H, W, 3] torch batch.

Two details worth knowing. First, the 120-frame cap is real - a 24fps, 8-second clip is downsampled to a subset, not ripped frame-perfect. That's fine for img2img or feeding a ControlNet; it's not archival. Second, if nothing valid comes in, it returns a dummy 512×512 black tensor instead of crashing, which is the kind of "better than a hard error" behavior you learn to appreciate.

Inputs and outputs

It's about as minimal as a node gets:

  • video_paths (VEO_VIDEO) - the only input. Wire this straight from any Veo generation node's video_paths output.
  • frames (IMAGE) - the output, a batch of extracted frames. Wire it into any image-processing node: upscalers, ImageToImage, VAE encode, frame-based schedulers, whatever.

That's it. One in, one out. If a Veo node refuses to connect to the rest of your graph, this is usually the missing link.

Installing it

This node ships in the Google GenMedia pack, so it installs like the rest of them. In ComfyUI Manager, search for comfyui-google-genmedia-custom-nodes and hit Install. Or do it by hand:

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

Restart ComfyUI and you'll find it under Google AI/Utils. No model downloads - the heavy lifting (moviepy, opencv-python-headless) is already in the requirements. One catch: every node in this pack needs a GCP project ID and region, because the actual generation happens on Google's Vertex AI, not your GPU. See the pack README for gcloud auth application-default login and you're set.

Gotchas

The frames come out at whatever resolution Veo produced - this node doesn't resize. With the default 720p output on Veo 3.1, your frames are 720p, and the frame cap means you're sampling, not capturing. If you need the full quality and every frame, set output_resolution to 1080p or 4K on the Veo node first. And remember: previewing the video is a separate node's job (VeoVideoSaveAndPreview) - run them in parallel if you want both the player and the frames.

CategoryGoogle AI/Utils

Inputs (1)

NameTypeDefaultDescription
video_pathsVEO_VIDEO

Outputs (1)

NameTypeDescription
framesIMAGE