ComfyUI Node

TZOOTZ_VHSNode

The VHS filter that's really a duotone demo

By TZOOTZ·Created 2 years ago·Updated about a year ago· 4
TZOOTZ_VHSNode
  • input_image
  • IMAGE
effect_strength0.50

First, the naming trap: in the ComfyUI world "VHS" almost always means VideoHelperSuite, the massively popular video-tooling pack. This is not that. TZOOTZ's "VHS" is the retro-cassette look, and the pack contains exactly one node, TZOOTZ_VHSNode, billed as a way to give images that worn-out analog warmth. It's a tiny experimental one-trick node from a hobbyist research outfit (TZOOTZ Research, tzootz.com), and it has essentially zero community footprint - which should tell you something before you even install it.

What it actually does

The README promises grain, color bleeding, and saturation adjustment. The shipped code does none of that. Open tzoootz_vhs_node.py and the whole "effect" is three Pillow calls: convert the image to grayscale, run ImageOps.colorize with black → purple and white → orange, then nudge brightness by 0.8 + 0.2 * effect_strength. That's it. You get a purple-to-orange duotone with a slightly dimmed exposure - think a '90s TV screen showing a sunset, not tracking lines and head-switch noise. The code even comments "for demonstration," which is the honest description of what this is: a template someone shipped.

Where you'd reach for it: if you want a flat, stylized two-color grade on a still without touching a color-grading pack, it'll do that in one wire. If you want actual VHS - scanlines, chroma bleed, tape dropout - this is not your node. Real analog looks need grain/noise layering and color-channel smearing, and the community has much better places to get that than a 40-line experimental pack.

The inputs and outputs (both of them)

Two required inputs, one output - there's no optional section at all:

  • input_image (IMAGE) - the image you want processed.
  • effect_strength (FLOAT, default 0.5) - despite the name, it only controls that brightness multiplier (0.8–1.0 range). It does not scale the tint. The author's framing says "choose the intensity," but the dial only dims things slightly.
  • Output: IMAGE, wired straight into a SaveImage or anything downstream.

The gotcha that actually bites

Here's where it gets real. ComfyUI passes IMAGE as a torch tensor in float [0, 1]. The node calls .astype(np.uint8) on it - and torch tensors don't have .astype, so on a stock ComfyUI image this throws AttributeError: 'Tensor' object has no attribute 'astype' on first run. And even if it got a numpy float array, casting [0, 1] floats to uint8 without scaling gives you an almost-black image. Either way, the demo effect you were promised mostly doesn't survive contact with a real IMAGE wire. Expect the node to error, or to output garbage if it somehow doesn't.

Installing it

Same drill as any custom node. Via ComfyUI Manager, search "TZOOTZ" and install the TZOOTZ VHS Effect Node. Or manually:

cd ComfyUI/custom_nodes
git clone https://github.com/TZOOTZ/ComfyUI-TZOOTZ_VHS

Restart ComfyUI. Dependencies are just numpy, torch, and Pillow - torch ships with ComfyUI, and you almost certainly already have Pillow, so nothing heavy to download and no model files. Note the README points at a requirements.txt that doesn't actually ship in the repo; the code only needs the three imports above.

Troubleshooting

If ComfyUI reports the node failed to load, check that __init__.py and tzoootz_vhs_node.py both landed inside ComfyUI/custom_nodes/ComfyUI-TZOOTZ_VHS/ (the README's own error-handling tip). If it loads but errors at run time, that's the dtype problem above - there's no slider or setting that fixes it from the UI. My honest advice: treat this as a curiosity, tinker with the source if you like (it's short and readable), and go pick up a real post-processing pack for your VHS aesthetic. This one's a demo, not a daily driver.

CategoryTZOOTZ RESEARCH 2024®

Inputs (2)

NameTypeDefaultDescription
input_imageIMAGE
effect_strengthFLOAT0.50

Outputs (1)

NameTypeDescription
IMAGEIMAGE