Text Ovary
Captions, watermarks and credits stamped straight onto images
- image
- IMAGE
Text Ovary overlays styled text on your images - captions, watermarks, frame labels, credits - with fonts, fill and stroke colors, alignment, padding, and per-batch rendering. Plug in an IMAGE and a STRING, pick a font, done. It's the pack's polished in-house merge of the author's own comfyui-textoverlay node, adapted and cleaned up.
When you'd reach for it
You've rendered a batch and want every image stamped with a label - "frame 042", a watermark, a style name, the seed for reproducibility. Pair it with a format node to build the text dynamically from metadata and you get a self-documenting contact sheet. It renders the same text across a whole batch efficiently, which is the part that makes it genuinely useful for video frames or large batches rather than a novelty.
How it works
PIL does the heavy lifting: your tensor gets converted to an image, an RGBA overlay layer is drawn, and the text is composited. The stroke thickness is relative to font size (a 0.2 default means 20% of the font size as outline width), and the stroke has its own opacity slider so you can make captions readable over busy backgrounds without a hard black box.
Colors are flexible: fill and stroke accept hex (#FFFFFF, and short forms like #fff) or named colors via matplotlib's color table - so "white", "red", "yellow" all work.
The inputs that matter
You'll actually touch maybe five of these on day one:
- image (IMAGE, required) - what to stamp on. The node processes it directly, one image or a whole batch.
- text (STRING, multiline) - supports real line breaks, so multi-line captions just work.
- font_size (INT, default 32) - the headline control.
- horizontal_alignment / vertical_alignment - left/center/right, top/middle/bottom (defaults: center, bottom).
- fill_color_hex and stroke_color_hex - text color and outline color.
Beyond those: stroke_thickness, stroke_opacity, padding, x_shift/y_shift for nudges, line_spacing, and font (a dropdown of available fonts). Output is a single IMAGE with the text composited.
Installing it
Part of the comfy-ovum pack:
cd ComfyUI/custom_nodes
git clone https://github.com/sfinktah/comfy-ovum
Restart ComfyUI, or use ComfyUI Manager → search "comfy-ovum" → Install. Text Ovary needs Pillow and numpy, both in the pack's requirements.
Common gotchas
- The font dropdown has a hidden dependency. The pack reads its font list from a sibling
comfyui-textoverlayinstall (custom_nodes/comfyui-textoverlay/fonts). If that's missing, the list falls back toDejaVuSans.ttf, and if even that can't load, you get Pillow's default bitmap font - which looks chunky and low-res. If your fonts look wrong, installcomfyui-textoverlayalongside the pack. - Stroke thickness is relative, not absolute. It's a fraction of font size, so a
0.2stroke on a 32px font and a 96px font are very different widths. That's intentional, but it surprises people at large sizes. - The text input is where the action is. If your caption is coming from upstream, make sure it's a plain STRING - lists or numbers may need a format node first.
Inputs (14)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| text | STRING | Hello | — |
| font_size | INT | 321–9999 | — |
| font | COMBO | 1 options: DejaVuSans.ttf | |
| fill_color_hex | STRING | #FFFFFF | — |
| stroke_color_hex | STRING | #000000 | — |
| stroke_thickness | FLOAT | 0.200–1 | — |
| padding | INT | 160–128 | — |
| horizontal_alignment | COMBO | center | 3 options: left, center, right |
| vertical_alignment | COMBO | bottom | 3 options: top, middle, bottom |
| x_shift | INT | 0-128–128 | — |
| y_shift | INT | 0-128–128 | — |
| line_spacing | FLOAT | 4.00–50 | — |
| stroke_opacity | FLOAT | 0.40–1 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |