Image Draw Text
Burn captions, watermarks and timestamps onto frames
- image
- IMAGE
- MASK
The last mile of any video project is captions, and captioning in ComfyUI is usually a search for a node that does text at all. Image Draw Text is the one from WAS Node Suite that takes it seriously: wrapping, alignment, an outline, a background panel, opacity, and a mask output - so a caption can be burned in or kept separate as a blend/inpaint layer. And because it applies the same text to every frame of a batch, one node captions a whole sequence.
It's part of WASasquatch's MIT pack (457 nodes in v3), under WAS Suite/Image/Process.
The inputs that do the heavy lifting
The widget list is long, but a caption workflow only touches a handful:
text- multiline; line breaks are kept. Nice touch: tokens like[time]and[hostname]resolve before drawing, which is how a frame carries the date it was rendered.positionandalign- position places the whole text block (corners, edges, middle center), while align lines the lines up inside the block. They're independent, which is the subtlety: a block anchored bottom-right can still be left-aligned within itself.offset_x/offset_ynudge the block off its anchor;marginholds space back from the edges.wrap_width- wrap the text at a pixel width. 0 disables wrapping and honors only your line breaks. A single word wider than the wrap is left whole and overhangs rather than split mid-word.stroke_width/stroke_color- the outline around each glyph. A stroke of 1–2 is what keeps captions legible over a picture whose brightness changes underneath.background_color/background_padding- a panel behind the text. Empty draws none. A half-transparent black like#000000B4is the standard subtitle treatment and beats an outline over a busy image.opacity- fades text, outline, and panel together, so a faint watermark stays consistent instead of the outline surviving the fade.text_color-#RRGGBB,#RRGGBBAA, or a name likewhite. The eight-digit form carries its own per-text transparency - that's how you make a watermark faint without fading the outline with it.
The mask output
Beyond the composited IMAGE, you get MASK - the text as white where a glyph, outline, or panel was drawn. That's the output people miss. Wire it to a blend node and you can apply the caption as a multiply or screen instead of a hard paste, or use it as an inpaint region or a stylization area. Text drawn once, then reused as a region.
Fonts: the one thing to set up
Fonts load from disk. Drop .ttf, .otf, or .ttc files into the fonts folder beside your config - ComfyUI/user/was-node-suite/fonts - and they appear in the dropdown named after the file. Put them there, not inside the pack, because an update wipes the pack folder. Two bundled families cover most needs: the DejaVu faces handle the widest glyph coverage (the safe pick for text you don't know in advance), and the Liberation faces match Arial, Times New Roman, and Courier New width-for-width - so a caption composed against one of those breaks its lines in the same places. A font that can't be opened falls back to the picked one, then to a small built-in bitmap face that ignores font_size.
Install
Standard WAS Node Suite: ComfyUI Manager, search "WAS Node Suite v3", or git clone https://github.com/WASasquatch/was-node-suite-comfyui into ComfyUI/custom_nodes and restart (ComfyUI 0.14.0+, Python 3.10+). v3 installs no extra Python packages and bundles its fonts, so text drawing works out of the box.
Gotcha to remember: captions and fonts are workflow-independent - the text string travels with the workflow, but the font only exists if that .ttf is on the machine that opens it. Share a graph with a custom font and the receiver falls back to DejaVu. Use the bundled fonts if the workflow will move.
Inputs (17)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | The images to draw on. Every image in the batch gets the same text, so a caption applies across a whole sequence in one node. | |
| text | STRING | The text to draw. Line breaks are kept. Tokens such as `[time]` and `[hostname]` resolve before drawing, which is how a frame carries the date it was rendered. | |
| font_size | INT | 321–1024 | Height of the text in points. A caption on a 1024-pixel image reads at around 24 to 40; a title wants considerably more. |
| text_color | STRING | #FFFFFF | Colour of the glyphs, as #RRGGBB, #RRGGBBAA or a name such as 'white'. The eight-digit form carries its own transparency, which is how a watermark is made faint without fading the outline with it. |
| position | COMBO | Where the block of text sits on the image. The corners and edges hold back by the margin below; 'middle center' ignores it. | |
| align | COMBO | How the lines line up with each other inside the block. Separate from position, which places the block: a block anchored bottom right can still be left-aligned inside itself. | |
| offset_x | INT | 0-16384–16384 | Pixels to move the text right of where position put it. Negative moves it left. For nudging a block off an anchor rather than placing it from scratch. |
| offset_y | INT | 0-16384–16384 | Pixels to move the text down. Negative moves it up. |
| margin | INT | 160–16384 | Space held back from every edge, so an edge-anchored caption does not touch the border. Ignored on whichever axis the position centres on. |
| line_spacing | FLOAT | 1.000.1–5 | Multiplier on the font's own line height. 1.0 is single spaced; 1.2 to 1.5 is easier to read for a paragraph of several lines. |
| wrap_width | INT | 00–16384 | Width in pixels to wrap the text at. 0 turns wrapping off and only the line breaks already in the text are honoured. A word wider than this on its own is left whole and overhangs rather than being split. |
| stroke_width | INT | 00–64 | Width of an outline drawn around every glyph. 1 or 2 is what keeps a caption legible over a picture whose brightness changes underneath it. 0 draws no outline. |
| stroke_color | STRING | #000000 | Colour of the outline. Read only when stroke_width is 1 or more. |
| background_color | STRING | Colour of a panel drawn behind the text. Empty draws no panel. A half-transparent #000000B4 is the usual subtitle treatment, and is more readable than an outline over a busy picture. | |
| background_padding | INT | 80–512 | How far the panel extends past the text on every side. Read only when background_color is set. |
| opacity | FLOAT | 1.000–1 | How much of the finished text shows, 0.0 to 1.0. Applied to the text, its outline and its panel together, so a faint watermark stays consistent instead of the outline surviving the fade. |
| fontopt | COMBO | Which typeface to draw with. The DejaVu faces cover the most ground; `Mono` gives every character the same width, which stops a frame counter jittering. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | The images with the text drawn on them. |
| MASK | MASK | The text as a mask, white where a glyph, outline or panel was drawn. Feeds an inpaint region or a blend factor without drawing the text twice. |