PNGTuber Image Eye Builder (static, transparent)
Turn one transparent character PNG into a blinking PNGTuber — eyes erased, blink loop rendered
- eyeless_png
- blink_webm
- blink_h264_mp4
- eye_track_json
- eye_open
- eye_half
- eye_closed
- bundle_dir
The classic PNGTuber art asset is one transparent character PNG. The mouth side of that workflow is covered by the image mouth builder; this is the eye side, and it's where "does she blink?" stops being a manual Photoshop chore. PNGTuberImageEyeBuilder takes your transparent PNG, detects the eye band, erases the original eyes into clean facial skin (while preserving the alpha channel - no white matte, no border), generates open/half/closed eye states with the local Qwen/eigen stack, and writes a complete pngtuber.imageEyeBundle.v1 with a pre-rendered blink loop.
What you actually get out
The three outputs worth knowing:
- blink_webm - a transparent blink animation (
blink_loop.webm). This is the file you drop into a PNGTuber app that supports video overlays for blinking. - blink_h264_mp4 - the same blink on an opaque h264 loop. The README's clever move: feed this into the mouth pipeline as your character video, and you get a blink-ready mouthless base for mouth tracking in one pass.
- eyeless_png - the eye-erased transparent character, plus
eye_open.png/eye_half.png/eye_closed.pngsprites andeye_track.jsonfor runtimes that swap eye sprites directly instead of playing a video.
Inputs that matter
- image_path - your transparent character PNG.
- manual_eye_bbox -
x0,y0,x1,y1. Auto-detection uses a multi-scale anime cascade with detail fallback, which is usually right, but for three-quarter or heavily stylized faces you'll sometimes get a band that's off. This is the art-direction override, and it's cheap to test. - blink_fps (24) and blink_frames (96) - the blink loop's length and rate. 96 frames at 24fps is a 4-second loop; longer reads as more natural if the player loops it.
- sprite_size (512), track_quad_scale (1.75), erase_scale (1.7), seed - the geometry and generation controls. Bump
erase_scaleif erased-eye residue bleeds through.
Outputs: eyeless_png, blink_webm, blink_h264_mp4, eye_track_json, eye_open, eye_half, eye_closed, bundle_dir.
Install and what it needs
Standard pack install - Manager search for ComfyUI-PromptMaker-PNGTuber, or:
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/hobi2k/ComfyUI-PromptMaker-PNGTuber.git
cd /path/to/ComfyUI
python -m pip install -r custom_nodes/ComfyUI-PromptMaker-PNGTuber/requirements.txt
Restart after installing. Then the honest part: this node lives and dies by the Qwen/eigen image-edit stack. The eye erase tries _eigen_erase_region (which does have a cv2-inpaint fallback here, unlike the mouth builder), but the open/half/closed eye generation is Qwen, full stop - no fallback. You need the Qwen-Image-Edit model, the Qwen text encoder + VAE, and the TextEncodeQwenImageEditPlus node in ComfyUI's registry. Those are big downloads, and the exact filenames the code loads are specific (qwen-image-edit-2511 GGUF, the Lightning 4-step LoRA, the eigen-banana LoRA), so if you're pointing a different Qwen install at this, expect it to fail until the names match.
Common issues
- "No eyes detected" - usually an anime-cascade miss on a stylized face. Set
manual_eye_bboxrather than re-running; it's deterministic and fast to iterate. - Eyes look wrong in the blink - same story as every Qwen edit job: the model re-emits the crop and identity drifts. The node's prompt side works hard on "same character, same lighting," but if your art style is far from what Qwen knows, the generated
open/half/closedsprites will show it. That's not a node bug; it's the price of the local edit stack. - Blink loop has a hard pop - check
blink_frames; a very short loop makes the blink a stutter.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| image_path | STRING | input.png | — |
| output_dir | STRING | — | |
| asset_id | STRING | pngtuber_image_eyes | — |
| sprite_size | INT | 512128–2048 | — |
| track_quad_scale | FLOAT | 1.751.1–8 | — |
| erase_scale | FLOAT | 1.701–4 | — |
| seed | INT | 420–2147483647 | — |
| manual_eye_bbox | STRING | — | |
| blink_fps | INT | 248–60 | — |
| blink_frames | INT | 968–600 | — |
Outputs (8)
| Name | Type | Description |
|---|---|---|
| eyeless_png | STRING | — |
| blink_webm | STRING | — |
| blink_h264_mp4 | STRING | — |
| eye_track_json | STRING | — |
| eye_open | STRING | — |
| eye_half | STRING | — |
| eye_closed | STRING | — |
| bundle_dir | STRING | — |