Nodes/ComfyUI ASCII Art Nodes/Two-Pass Color Typing (Concurrent)
ComfyUI Node

Two-Pass Color Typing (Concurrent)

Typed white, colored as it goes — the concurrent two-pass trick

By LamEmil·Created about a year ago·Updated about a year ago· 1
Two-Pass Color Typing (Concurrent)
  • image
  • two_pass_animated_frames
char_width80
font_pathcour.ttf
font_size15
ascii_charset .'`^":;Il!i~_?[{1(|/fjxnvzXYJCLQ0Zmwqdkh*#M&8%B@$
background_color#000000
initial_text_color#FFFFFF
invert_brightness_mappingfalse
chars_per_frame1
cursor_char_
cursor_blink_frames5
cursor_color#FFFFFF

Most typing animations in this pack are one-pass: characters appear, done. "Two-Pass Color Typing (Concurrent)" - the display name is doing honest work here - does something weirder and better. As each new character types in, the characters behind it are already transitioning to their image-sampled colors. New glyphs arrive in initial_text_color; older glyphs wear the color of the picture. The two passes run at the same time, which is the "concurrent" in the name.

The signature effect is a wave of color chasing the typing cursor across the image - a logo or portrait that's being "filled in" as it's written. It reads as deliberate and polished, less like a terminal echo and more like an intentional reveal. If you're building a title card and the plain color typing animation felt flat, this is the middle ground before you go full sequential two-pass (the sibling node in this pack, which types everything first and colors in afterward).

How it works

The node builds a flat list of every character in the grid, each with its sampled image color, its pixel width, and its position. Then it keeps a single progress counter: characters before the counter are drawn in their image-sampled color, characters in the current batch (the next chars_per_frame) are drawn in initial_text_color, and everything further along isn't drawn yet. Each frame advances the counter, so the boundary between "just typed" and "already colored" slides across the image. A blinking cursor marks that boundary - cursor_char, cursor_blink_frames, and cursor_color work exactly like the realistic animation node, and the final frame drops the cursor so the reveal ends clean.

The inputs that matter

  • initial_text_color - the color new characters appear in, default #FFFFFF. This one shapes the look more than anything else: white reads as "typing," a gray like #CCCCCC reads as a ghost fill before the color lands.
  • chars_per_frame - controls both speed and the width of the color-wave front (default 1). Higher values mean faster typing and a bigger chunk of newly-typed initial-color characters per frame.
  • cursor_char / cursor_blink_frames / cursor_color - the cursor, tuned the same way as the realistic node.

Plus the shared set: char_width, font_path, font_size, ascii_charset, background_color, invert_brightness_mapping. Output is the IMAGE batch two_pass_animated_frames, same size as the input.

Install and gotchas

ComfyUI Manager (search "ComfyUI ASCII Art Nodes") or:

cd ComfyUI/custom_nodes
git clone https://github.com/LamEmil/ComfyUI_ASCIIArtNode
cd ComfyUI_ASCIIArtNode
pip install -r requirements.txt

Restart after. Only dependency is Pillow - no models, no API keys. The output batch needs a Video Combine or Save Animated WebP/GIF node downstream to become a playable file.

The pack's recurring trap: font_path defaults to cour.ttf, which isn't bundled, and a missing font silently swaps in a chunky bitmap glyph that makes the whole effect fall apart - point it at a real monospace .ttf (e.g. /usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf on Linux). Keep char_width modest or frame count explodes. Don't rename the cloned folder; the README's ComfyUI_ASCIINodes name doesn't match the repo's ComfyUI_ASCIIArtNode. Small single-commit hobby pack, no community support - but the effect is genuinely distinctive and it works as shipped.

Categoryimage/animation

Inputs (12)

NameTypeDefaultDescription
imageIMAGE
char_widthINT8010–1000
font_pathSTRINGcour.ttf
font_sizeINT155–100
ascii_charsetSTRING .'`^":;Il!i~_?[{1(|/fjxnvzXYJCLQ0Zmwqdkh*#M&8%B@$
background_colorSTRING#000000
initial_text_colorSTRING#FFFFFF
invert_brightness_mappingBOOLEANfalse
chars_per_frameINT11–100
cursor_charSTRING_
cursor_blink_framesINT51–60
cursor_colorSTRING#FFFFFF

Outputs (1)

NameTypeDescription
two_pass_animated_framesIMAGE